Add a code to enable iMC log where available.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
* 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"
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;
+}
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;
"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) {
return EINVAL;
}
- cpus = get_num_cpus(ras);
data = calloc(sizeof(*data), cpus);
if (!data)
goto err;
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;
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;
}
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
/*
} 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);