]> www.infradead.org Git - users/mchehab/rasdaemon.git/commitdiff
mce-intel: Enable iMC log where available
authorMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 27 May 2013 19:46:12 +0000 (16:46 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 27 May 2013 19:47:47 +0000 (16:47 -0300)
Add a code to enable iMC log where available.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
mce-intel.c
ras-events.c
ras-mce-handler.c
ras-mce-handler.h

index 34ef709af26d62c201963bfb36bb49d9072ecb6a..9146e24896f809c86a20b2d522d50a4142a04785 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
 
+#include <errno.h>
+#include <fcntl.h>
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
+#include "ras-logger.h"
 #include "ras-mce-handler.h"
 #include "bitfield.h"
 
@@ -384,3 +390,74 @@ int parse_intel_event(struct ras_events *ras, struct mce_event *e)
 
        return 0;
 }
+
+/*
+ * Code to enable iMC logs
+ */
+static int domsr(int cpu, int msr, int bit)
+{
+       char fpath[32];
+       unsigned long long data;
+       int fd;
+
+       sprintf(fpath, "/dev/cpu/%d/msr", cpu);
+       fd = open(fpath, O_RDWR);
+       if (fd == -1) {
+               switch (errno) {
+               case ENOENT:
+                       log(ALL, LOG_ERR,
+                           "Warning: cpu %d offline?, imc_log not set\n", cpu);
+                       return -EINVAL;
+               default:
+                       log(ALL, LOG_ERR,
+                           "Cannot open %s to set imc_log\n", fpath);
+                       return -EINVAL;
+               }
+       }
+       if (pread(fd, &data, sizeof data, msr) != sizeof data) {
+               log(ALL, LOG_ERR,
+                   "Cannot read MSR_ERROR_CONTROL from %s\n", fpath);
+               return -EINVAL;
+       }
+       data |= bit;
+       if (pwrite(fd, &data, sizeof data, msr) != sizeof data) {
+               log(ALL, LOG_ERR,
+                   "Cannot write MSR_ERROR_CONTROL to %s\n", fpath);
+               return -EINVAL;
+       }
+       if (pread(fd, &data, sizeof data, msr) != sizeof data) {
+               log(ALL, LOG_ERR,
+                   "Cannot re-read MSR_ERROR_CONTROL from %s\n", fpath);
+               return -EINVAL;
+       }
+       if ((data & bit) == 0) {
+               log(ALL, LOG_ERR,
+                   "Failed to set imc_log on cpu %d\n", cpu);
+               return -EINVAL;
+       }
+       close(fd);
+       return 0;
+}
+
+int set_intel_imc_log(enum cputype cputype, unsigned ncpus)
+{
+       int cpu, msr, bit, rc;
+
+       switch (cputype) {
+       case CPU_SANDY_BRIDGE_EP:
+       case CPU_IVY_BRIDGE_EPEX:
+               msr = 0x17f;    /* MSR_ERROR_CONTROL */
+               bit = 0x2;      /* MemError Log Enable */
+               break;
+       default:
+               return 0;
+       }
+
+       for (cpu = 0; cpu < ncpus; cpu++) {
+               rc = domsr(cpu, msr, bit);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
index 2926ee51e33b66624287dfa67629492fded00a93..7f500fa8c568bc9ce14ab57f7421ca933de52b9e 100644 (file)
@@ -504,8 +504,9 @@ static int add_event_handler(struct ras_events *ras, struct pevent *pevent,
 
 int handle_ras_events(int record_events)
 {
-       int rc, page_size, i, cpus;
+       int rc, page_size, i;
        int num_events = 0;
+       unsigned cpus;
        struct pevent *pevent = NULL;
        struct pthread_data *data = NULL;
        struct ras_events *ras = NULL;
@@ -559,8 +560,10 @@ int handle_ras_events(int record_events)
                    "ras", "aer_event");
 #endif
 
+       cpus = get_num_cpus(ras);
+
 #ifdef HAVE_MCE
-       rc = register_mce_handler(ras);
+       rc = register_mce_handler(ras, cpus);
        if (rc)
                log(ALL, LOG_INFO, "Can't register mce handler\n");
        if (ras->mce_priv) {
@@ -580,7 +583,6 @@ int handle_ras_events(int record_events)
                return EINVAL;
        }
 
-       cpus = get_num_cpus(ras);
        data = calloc(sizeof(*data), cpus);
        if (!data)
                goto err;
index 991dad901cef7c874b57c89a41815eb1e0ba4405..92ae0e3d5ef897c54573cb32990daa1b2df28af6 100644 (file)
@@ -177,7 +177,7 @@ ret:
        return ret;
 }
 
-int register_mce_handler(struct ras_events *ras)
+int register_mce_handler(struct ras_events *ras, unsigned ncpus)
 {
        int rc;
        struct mce_priv *mce;
@@ -197,6 +197,13 @@ int register_mce_handler(struct ras_events *ras)
                ras->mce_priv = NULL;
                return (rc);
        }
+       switch (mce->cputype) {
+       case CPU_SANDY_BRIDGE_EP:
+       case CPU_IVY_BRIDGE_EPEX:
+               set_intel_imc_log(mce->cputype, ncpus);
+       default:
+               break;
+       }
 
        return rc;
 }
@@ -250,7 +257,7 @@ static void report_mce_event(struct ras_events *ras,
                trace_seq_printf(s, " %s", e->user_action);
 
        if (e->mc_location)
-               trace_seq_printf(s, ", ", e->mc_location);
+               trace_seq_printf(s, ", %s", e->mc_location);
 
 #if 0
        /*
index ffcc1f120edbed60cb19d651d92a33193a687faa..80e9769e9eadd225edbc9d803fd8d0efe894beed 100644 (file)
@@ -97,11 +97,14 @@ struct mce_priv {
 } while (0)
 
 /* register and handling routines */
-int register_mce_handler(struct ras_events *ras);
+int register_mce_handler(struct ras_events *ras, unsigned ncpus);
 int ras_mce_event_handler(struct trace_seq *s,
                          struct pevent_record *record,
                          struct event_format *event, void *context);
 
+/* enables intel iMC logs */
+int set_intel_imc_log(enum cputype cputype, unsigned ncpus);
+
 /* Per-CPU-type decoders for Intel CPUs */
 void p4_decode_model(struct mce_event *e);
 void core2_decode_model(struct mce_event *e);