rasdaemon: add support for ARM events
PATCH v3 2/2 rasdaemon: add support for ARM events
Em Mon, 12 Jun 2017 16:16:05 -0600
Tyler Baicar <[email protected]> escreveu:
Quoted 2 lines
Add support to handle the ARM kernel trace events which cover RAS ARM processor errors.
I'm getting this gcc 7.1 warning with this patch applied:
ras-record.c:227:41: warning: ‘arm_event_tab’ defined but not used [-Wunused-const-variable=]
static const struct db_table_descriptor arm_event_tab = {
^~~~~~~~~~~~~Quoted 461 lines
Signed-off-by Tyler Baicar <[email protected]>--- Makefile.am | 3 ++ configure.ac | 9 ++++++ ras-arm-handler.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ras-arm-handler.h | 24 +++++++++++++++ ras-events.c | 15 ++++++++++ ras-record.c | 52 ++++++++++++++++++++++++++++++++ ras-record.h | 16 ++++++++++ ras-report.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ ras-report.h | 5 +++- 9 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 ras-arm-handler.c create mode 100644 ras-arm-handler.hMakefile.am +3
-0@@ -27,6 +27,9 @@ endif if WITH_NON_STANDARD rasdaemon_SOURCES += ras-non-standard-handler.c endif +if WITH_ARM + rasdaemon_SOURCES += ras-arm-handler.c +endif if WITH_MCE rasdaemon_SOURCES += ras-mce-handler.c mce-intel.c mce-amd-k8.c \ mce-intel-p4-p6.c mce-intel-nehalem.c \configure.ac +9
-0@@ -53,6 +53,15 @@ AS_IF([test "x$enable_non_standard" = "xyes"], [ ]) AM_CONDITIONAL([WITH_NON_STANDARD], [test x$enable_non_standard = xyes]) +AC_ARG_ENABLE([arm], + AS_HELP_STRING([--enable-arm], [enable ARM events (currently experimental)])) + +AS_IF([test "x$enable_arm" = "xyes"], [ + AC_DEFINE(HAVE_ARM,1,"have ARM events collect") + AC_SUBST([WITH_ARM]) +]) +AM_CONDITIONAL([WITH_ARM], [test x$enable_arm = xyes]) + AC_ARG_ENABLE([mce], AS_HELP_STRING([--enable-mce], [enable MCE events (currently experimental)]))ras-arm-handler.c new file +90
-0@@ -0,0 +1,90 @@ +/* +* Copyright (c) 2016, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "libtrace/kbuffer.h" +#include "ras-arm-handler.h" +#include "ras-record.h" +#include "ras-logger.h" +#include "ras-report.h" + +int ras_arm_event_handler (struct trace_seq *s, +struct pevent_record *record, +struct event_format *event,void *context) +{ +unsigned long long val; +struct ras_events *ras = context; +time_t now; +struct tm *tm; +struct ras_arm_event ev; + +/* +* Newer kernels (3.10-rc1 or upper) provide an uptime clock. +* On previous kernels, the way to properly generate an event would +* be to inject a fake one, measure its timestamp and diff it against +* gettimeofday. We won't do it here. Instead, let's use uptime, +* falling-back to the event report's time, if "uptime" clock is +* not available (legacy kernels). +*/ + +if (ras->use_uptime) + now = record->ts/user_hz + ras->uptime_diff; +else + now =time (NULL ); + + tm =localtime (&now); +if (tm) +strftime (ev.timestamp,sizeof (ev.timestamp), +"%Y-%m-%d %H:%M:%S %z" , tm); +trace_seq_printf (s,"%s\n" , ev.timestamp); + +if (pevent_get_field_val (s, event,"affinity" , record, &val,1 ) <0 ) +return -1 ; + ev.affinity = val; +trace_seq_printf (s," affinity: %d" , ev.affinity); + +if (pevent_get_field_val (s, event,"mpidr" , record, &val,1 ) <0 ) +return -1 ; + ev.mpidr = val; +trace_seq_printf (s,"\n MPIDR: 0x%llx" , (unsigned long long )ev.mpidr); + +if (pevent_get_field_val (s, event,"midr" , record, &val,1 ) <0 ) +return -1 ; + ev.midr = val; +trace_seq_printf (s,"\n MIDR: 0x%llx" , (unsigned long long )ev.midr); + +if (pevent_get_field_val (s, event,"running_state" , record, &val,1 ) <0 ) +return -1 ; + ev.running_state = val; +trace_seq_printf (s,"\n running_state: %d" , ev.running_state); + +if (pevent_get_field_val (s, event,"psci_state" , record, &val,1 ) <0 ) +return -1 ; + ev.psci_state = val; +trace_seq_printf (s,"\n psci_state: %d" , ev.psci_state); + +/* Insert data into the SGBD */ +#ifdef HAVE_SQLITE3 +ras_store_arm_record (ras, &ev); +#endif + +#ifdef HAVE_ABRT_REPORT +/* Report event to ABRT */ +ras_report_arm_event (ras, &ev); +#endif + +return 0 ; +}ras-arm-handler.h new file +24
-0@@ -0,0 +1,24 @@ +/* +* Copyright (c) 2016, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __RAS_ARM_HANDLER_H +#define __RAS_ARM_HANDLER_H + +#include "ras-events.h" +#include "libtrace/event-parse.h" + +int ras_arm_event_handler (struct trace_seq *s, +struct pevent_record *record, +struct event_format *event,void *context); + +#endif ras-events.c +15
-0@@ -30,6 +30,7 @@#include "ras-mc-handler.h" #include "ras-aer-handler.h" #include "ras-non-standard-handler.h" +#include "ras-arm-handler.h" #include "ras-mce-handler.h" #include "ras-extlog-handler.h" #include "ras-record.h" @@ -213,6 +214,10 @@ int toggle_ras_mc_event(int enable) rc |=__toggle_ras_mc_event (ras,"ras" ,"non_standard_event" , enable);#endif +#ifdef HAVE_ARM + rc |=__toggle_ras_mc_event (ras,"ras" ,"arm_event" , enable); +#endif + free_ras:free (ras);return rc;@@ -691,6 +696,16 @@ int handle_ras_events(int record_events) "ras", "non_standard_event");#endif +#ifdef HAVE_ARM + rc =add_event_handler (ras, pevent, page_size,"ras" ,"arm_event" , + ras_arm_event_handler); +if (!rc) + num_events++; +else +log (ALL ,LOG_ERR ,"Can't get traces from %s:%s\n" , +"ras" ,"arm_event" ); +#endif + cpus =get_num_cpus (ras);#ifdef HAVE_MCE ras-record.c +52
-0@@ -209,6 +209,58 @@ int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standar }#endif +/* +* Table and functions to handle ras:arm +*/ + +#ifdef HAVE_ARM +static const struct db_fields arm_event_fields[] = { + { .name="id" , .type="INTEGER PRIMARY KEY" }, + { .name="timestamp" , .type="TEXT" }, + { .name="error_count" , .type="INTEGER" }, + { .name="affinity" , .type="INTEGER" }, + { .name="mpidr" , .type="INTEGER" }, + { .name="running_state" , .type="INTEGER" }, + { .name="psci_state" , .type="INTEGER" }, +}; + +static const struct db_table_descriptor arm_event_tab = { + .name ="arm_event" , + .fields = arm_event_fields, + .num_fields =ARRAY_SIZE (arm_event_fields), +}; + +int ras_store_arm_record (struct ras_events *ras,struct ras_arm_event *ev) +{ +int rc; +struct sqlite3_priv *priv = ras->db_priv; + +if (!priv || !priv->stmt_arm_record) +return 0 ; +log (TERM ,LOG_INFO ,"arm_event store: %p\n" , priv->stmt_arm_record); + +sqlite3_bind_text (priv->stmt_arm_record,1 , ev->timestamp,-1 ,NULL ); +sqlite3_bind_int (priv->stmt_arm_record,2 , ev->error_count); +sqlite3_bind_int (priv->stmt_arm_record,3 , ev->affinity); +sqlite3_bind_int (priv->stmt_arm_record,4 , ev->mpidr); +sqlite3_bind_int (priv->stmt_arm_record,5 , ev->running_state); +sqlite3_bind_int (priv->stmt_arm_record,6 , ev->psci_state); + + rc =sqlite3_step (priv->stmt_arm_record); +if (rc !=SQLITE_OK && rc !=SQLITE_DONE ) +log (TERM ,LOG_ERR , +"Failed to do arm_event step on sqlite: error = %d\n" , rc); + rc =sqlite3_reset (priv->stmt_arm_record); +if (rc !=SQLITE_OK && rc !=SQLITE_DONE ) +log (TERM ,LOG_ERR , +"Failed reset arm_event on sqlite: error = %d\n" , + rc); +log (TERM ,LOG_INFO ,"register inserted at db\n" ); + +return rc; +} +#endif +#ifdef HAVE_EXTLOG static const struct db_fields extlog_event_fields[] = { { .name="id", .type="INTEGER PRIMARY KEY" },ras-record.h +16
-0@@ -65,10 +65,21 @@ struct ras_non_standard_event {uint32_t length; }; +struct ras_arm_event { +char timestamp[64 ]; +int32_t error_count; +int8_t affinity; +int64_t mpidr; +int64_t midr; +int32_t running_state; +int32_t psci_state; +}; +struct ras_mc_event ;struct ras_aer_event ;struct ras_extlog_event ;struct ras_non_standard_event ; +struct ras_arm_event ;struct mce_event ;#ifdef HAVE_SQLITE3 @@ -90,6 +101,9 @@ struct sqlite3_priv {#ifdef HAVE_NON_STANDARD sqlite3_stmt *stmt_non_standard_record;#endif +#ifdef HAVE_ARM +sqlite3_stmt *stmt_arm_record; +#endif };int ras_mc_event_opendb (unsigned cpu,struct ras_events *ras);@@ -98,6 +112,7 @@ int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev);int ras_store_mce_record (struct ras_events *ras,struct mce_event *ev);int ras_store_extlog_mem_record (struct ras_events *ras,struct ras_extlog_event *ev);int ras_store_non_standard_record (struct ras_events *ras,struct ras_non_standard_event *ev); +int ras_store_arm_record (struct ras_events *ras,struct ras_arm_event *ev);#else static inline int ras_mc_event_opendb (unsigned cpu,struct ras_events *ras) {return 0 ; };@@ -106,6 +121,7 @@ static inline int ras_store_aer_event(struct ras_events *ras, struct ras_aer_evestatic inline int ras_store_mce_record (struct ras_events *ras,struct mce_event *ev) {return 0 ; };static inline int ras_store_extlog_mem_record (struct ras_events *ras,struct ras_extlog_event *ev) {return 0 ; };static inline int ras_store_non_standard_record (struct ras_events *ras,struct ras_non_standard_event *ev) {return 0 ; }; +static inline int ras_store_arm_record (struct ras_events *ras,struct ras_arm_event *ev) {return 0 ; };#endif ras-report.c +75
-0@@ -228,6 +228,33 @@ static int set_non_standard_event_backtrace(char *buf, struct ras_non_standard_ereturn 0 ; } +static int set_arm_event_backtrace (char *buf,struct ras_arm_event *ev){ +char bt_buf[MAX_BACKTRACE_SIZE ]; + +if (!buf || !ev) +return -1 ; + +sprintf (bt_buf,"BACKTRACE=" \ +"timestamp=%s\n" \ +"error_count=%d\n" \ +"affinity=%d\n" \ +"mpidr=0x%lx\n" \ +"midr=0x%lx\n" \ +"running_state=%d\n" \ +"psci_state=%d\n" , \ + ev->timestamp, \ + ev->error_count, \ + ev->affinity, \ + ev->mpidr, \ + ev->midr, \ + ev->running_state, \ + ev->psci_state); + +strcat (buf, bt_buf); + +return 0 ; +} +static int commit_report_backtrace (int sockfd,int type,void *ev){char buf[MAX_BACKTRACE_SIZE ];char *pbuf = buf;@@ -253,6 +280,9 @@ static int commit_report_backtrace(int sockfd, int type, void *ev){case NON_STANDARD_EVENT : rc =set_non_standard_event_backtrace (buf, (struct ras_non_standard_event *)ev);break ; +case ARM_EVENT : + rc =set_arm_event_backtrace (buf, (struct ras_arm_event *)ev); +break ;default :return -1 ; }@@ -425,6 +455,51 @@ non_standard_fail:return rc; } +int ras_report_arm_event (struct ras_events *ras,struct ras_arm_event *ev){ +char buf[MAX_MESSAGE_SIZE ]; +int sockfd =0 ; +int rc =-1 ; + +memset (buf,0 ,sizeof (buf)); + + sockfd =setup_report_socket (); +if (sockfd <0 ){ +return rc; + } + + rc =commit_report_basic (sockfd); +if (rc <0 ){ + goto arm_fail; + } + + rc =commit_report_backtrace (sockfd,ARM_EVENT , ev); +if (rc <0 ){ + goto arm_fail; + } + +sprintf (buf,"ANALYZER=%s" ,"rasdaemon-arm" ); + rc =write (sockfd, buf,strlen (buf) +1 ); +if (rc <strlen (buf) +1 ){ + goto arm_fail; + } + +sprintf (buf,"REASON=%s" ,"ARM CPU report problem" ); + rc =write (sockfd, buf,strlen (buf) +1 ); +if (rc <strlen (buf) +1 ){ + goto arm_fail; + } + + rc =0 ; + +arm_fail: + +if (sockfd >0 ){ +close (sockfd); + } + +return rc; +} +int ras_report_mce_event (struct ras_events *ras,struct mce_event *ev){char buf[MAX_MESSAGE_SIZE ];int sockfd =0 ;ras-report.h +4
-1@@ -33,7 +33,8 @@ enum {MC_EVENT ,MCE_EVENT ,AER_EVENT , - NON_STANDARD_EVENT +NON_STANDARD_EVENT , + ARM_EVENT };#ifdef HAVE_ABRT_REPORT @@ -42,6 +43,7 @@ int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev);int ras_report_aer_event (struct ras_events *ras,struct ras_aer_event *ev);int ras_report_mce_event (struct ras_events *ras,struct mce_event *ev);int ras_report_non_standard_event (struct ras_events *ras,struct ras_non_standard_event *ev); +int ras_report_arm_event (struct ras_events *ras,struct ras_arm_event *ev);#else @@ -49,6 +51,7 @@ static inline int ras_report_mc_event(struct ras_events *ras, struct ras_mc_evenstatic inline int ras_report_aer_event (struct ras_events *ras,struct ras_aer_event *ev) {return 0 ; };static inline int ras_report_mce_event (struct ras_events *ras,struct mce_event *ev) {return 0 ; };static inline int ras_report_non_standard_event (struct ras_events *ras,struct ras_non_standard_event *ev) {return 0 ; }; +static inline int ras_report_arm_event (struct ras_events *ras,struct ras_arm_event *ev) {return 0 ; };#endif