4f63e5
diff -urNp mcelog-d2e13bf0.orig/bitfield.c mcelog-d2e13bf0/bitfield.c
4f63e5
--- mcelog-d2e13bf0.orig/bitfield.c	2016-05-14 08:34:40.434107718 -0400
4f63e5
+++ mcelog-d2e13bf0/bitfield.c	2016-05-14 08:34:58.868975011 -0400
4f63e5
@@ -56,7 +56,7 @@ void decode_numfield(u64 status, struct
4f63e5
 		u64 v = (status >> f->start) & mask;
4f63e5
 		if (v > 0 || f->force) { 
4f63e5
 			char fmt[30];
4f63e5
-			snprintf(fmt, 30, "%%s: %s\n", f->fmt ? f->fmt : "%Lu");
4f63e5
+			snprintf(fmt, 30, "%%s: %s\n", f->fmt ? f->fmt : "%llu");
4f63e5
 			Wprintf(fmt, f->name, v);
4f63e5
 		}
4f63e5
 	}
4f63e5
diff -urNp mcelog-d2e13bf0.orig/bitfield.h mcelog-d2e13bf0/bitfield.h
4f63e5
--- mcelog-d2e13bf0.orig/bitfield.h	2016-05-14 08:34:40.434107718 -0400
4f63e5
+++ mcelog-d2e13bf0/bitfield.h	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -16,10 +16,10 @@ struct numfield {
4f63e5
 #define FIELD(start_bit, name) { start_bit, name, NELE(name) }
4f63e5
 #define SBITFIELD(start_bit, string) { start_bit, ((char * [2]) { NULL, string }), 2 }
4f63e5
 
4f63e5
-#define NUMBER(start, end, name) { start, end, name, "%Lu", 0 }
4f63e5
-#define NUMBERFORCE(start, end, name) { start, end, name, "%Lu", 1 }
4f63e5
-#define HEXNUMBER(start, end, name) { start, end, name, "%Lx", 0 }
4f63e5
-#define HEXNUMBERFORCE(start, end, name) { start, end, name, "%Lx", 1 }
4f63e5
+#define NUMBER(start, end, name) { start, end, name, "%llu", 0 }
4f63e5
+#define NUMBERFORCE(start, end, name) { start, end, name, "%llu", 1 }
4f63e5
+#define HEXNUMBER(start, end, name) { start, end, name, "%llx", 0 }
4f63e5
+#define HEXNUMBERFORCE(start, end, name) { start, end, name, "%llx", 1 }
4f63e5
 
4f63e5
 void decode_bitfield(u64 status, struct field *fields);
4f63e5
 void decode_numfield(u64 status, struct numfield *fields);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/broadwell_de.c mcelog-d2e13bf0/broadwell_de.c
4f63e5
--- mcelog-d2e13bf0.orig/broadwell_de.c	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/broadwell_de.c	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -0,0 +1,104 @@
4f63e5
+/* Copyright (C) 2015 Intel Corporation
4f63e5
+   Decode Intel Broadwell D specific machine check errors.
4f63e5
+
4f63e5
+   mcelog is free software; you can redistribute it and/or
4f63e5
+   modify it under the terms of the GNU General Public
4f63e5
+   License as published by the Free Software Foundation; version
4f63e5
+   2.
4f63e5
+
4f63e5
+   mcelog is distributed in the hope that it will be useful,
4f63e5
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
4f63e5
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4f63e5
+   General Public License for more details.
4f63e5
+
4f63e5
+   You should find a copy of v2 of the GNU General Public License somewhere
4f63e5
+   on your Linux system; if not, write to the Free Software Foundation,
4f63e5
+   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4f63e5
+
4f63e5
+   Author: Tony Luck
4f63e5
+*/
4f63e5
+
4f63e5
+#include "mcelog.h"
4f63e5
+#include "bitfield.h"
4f63e5
+#include "broadwell_de.h"
4f63e5
+#include "memdb.h"
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-24 */
4f63e5
+
4f63e5
+static char *pcu_1[] = {
4f63e5
+	[0x00] = "No Error",
4f63e5
+	[0x09] = "MC_MESSAGE_CHANNEL_TIMEOUT",
4f63e5
+	[0x13] = "MC_DMI_TRAINING_TIMEOUT",
4f63e5
+	[0x15] = "MC_DMI_CPU_RESET_ACK_TIMEOUT",
4f63e5
+	[0x1E] = "MC_VR_ICC_MAX_LT_FUSED_ICC_MAX",
4f63e5
+	[0x25] = "MC_SVID_COMMAN_TIMEOUT",
4f63e5
+	[0x26] = "MCA_PKGC_DIRECT_WAKE_RING_TIMEOUT",
4f63e5
+	[0x29] = "MC_VR_VOUT_MAC_LT_FUSED_SVID",
4f63e5
+	[0x2B] = "MC_PKGC_WATCHDOG_HANG_CBZ_DOWN",
4f63e5
+	[0x2C] = "MC_PKGC_WATCHDOG_HANG_CBZ_UP",
4f63e5
+	[0x44] = "MC_CRITICAL_VR_FAILED",
4f63e5
+	[0x46] = "MC_VID_RAMP_DOWN_FAILED",
4f63e5
+	[0x49] = "MC_SVID_WRITE_REG_VOUT_MAX_FAILED",
4f63e5
+	[0x4B] = "MC_BOOT_VID_TIMEOUT_DRAM_0",
4f63e5
+	[0x4F] = "MC_SVID_COMMAND_ERROR",
4f63e5
+	[0x52] = "MC_FIVR_CATAS_OVERVOL_FAULT",
4f63e5
+	[0x53] = "MC_FIVR_CATAS_OVERCUR_FAULT",
4f63e5
+	[0x57] = "MC_SVID_PKGC_REQUEST_FAILED",
4f63e5
+	[0x58] = "MC_SVID_IMON_REQUEST_FAILED",
4f63e5
+	[0x59] = "MC_SVID_ALERT_REQUEST_FAILED",
4f63e5
+	[0x62] = "MC_INVALID_PKGS_RSP_QPI",
4f63e5
+	[0x64] = "MC_INVALID_PKG_STATE_CONFIG",
4f63e5
+	[0x67] = "MC_HA_IMC_RW_BLOCK_ACK_TIMEOUT",
4f63e5
+	[0x6A] = "MC_MSGCH_PMREQ_CMP_TIMEOUT",
4f63e5
+	[0x72] = "MC_WATCHDOG_TIMEOUT_PKGS_MASTER",
4f63e5
+	[0x81] = "MC_RECOVERABLE_DIE_THERMAL_TOO_HOT"
4f63e5
+};
4f63e5
+
4f63e5
+static struct field pcu_mc4[] = {
4f63e5
+	FIELD(24, pcu_1),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-18 */
4f63e5
+
4f63e5
+static struct field memctrl_mc9[] = {
4f63e5
+	SBITFIELD(16, "Address parity error"),
4f63e5
+	SBITFIELD(17, "HA Wrt buffer Data parity error"),
4f63e5
+	SBITFIELD(18, "HA Wrt byte enable parity error"),
4f63e5
+	SBITFIELD(19, "Corrected patrol scrub error"),
4f63e5
+	SBITFIELD(20, "Uncorrected patrol scrub error"),
4f63e5
+	SBITFIELD(21, "Corrected spare error"),
4f63e5
+	SBITFIELD(22, "Uncorrected spare error"),
4f63e5
+	SBITFIELD(23, "Corrected memory read error"),
4f63e5
+	SBITFIELD(24, "iMC, WDB, parity errors"),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+void bdw_de_decode_model(int cputype, int bank, u64 status, u64 misc)
4f63e5
+{
4f63e5
+	switch (bank) {
4f63e5
+	case 4:
4f63e5
+		Wprintf("PCU: ");
4f63e5
+		switch (EXTRACT(status, 0, 15) & ~(1ull << 12)) {
4f63e5
+		case 0x402: case 0x403:
4f63e5
+			Wprintf("Internal errors ");
4f63e5
+			break;
4f63e5
+		case 0x406:
4f63e5
+			Wprintf("Intel TXT errors ");
4f63e5
+			break;
4f63e5
+		case 0x407:
4f63e5
+			Wprintf("Other UBOX Internal errors ");
4f63e5
+			break;
4f63e5
+		}
4f63e5
+		if (EXTRACT(status, 16, 19) & 3)
4f63e5
+			Wprintf("PCU internal error ");
4f63e5
+		if (EXTRACT(status, 20, 23) & 4)
4f63e5
+			Wprintf("Ubox error ");
4f63e5
+		decode_bitfield(status, pcu_mc4);
4f63e5
+		break;
4f63e5
+	case 9: case 10:
4f63e5
+		Wprintf("MemCtrl: ");
4f63e5
+		decode_bitfield(status, memctrl_mc9);
4f63e5
+		break;
4f63e5
+	}
4f63e5
+}
4f63e5
diff -urNp mcelog-d2e13bf0.orig/broadwell_de.h mcelog-d2e13bf0/broadwell_de.h
4f63e5
--- mcelog-d2e13bf0.orig/broadwell_de.h	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/broadwell_de.h	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -0,0 +1,2 @@
4f63e5
+void bdw_d_decode_model(int cputype, int bank, u64 status, u64 misc);
4f63e5
+void bdw_de_decode_model(int cputype, int bank, u64 status, u64 misc);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/broadwell_epex.c mcelog-d2e13bf0/broadwell_epex.c
4f63e5
--- mcelog-d2e13bf0.orig/broadwell_epex.c	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/broadwell_epex.c	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -0,0 +1,149 @@
4f63e5
+/* Copyright (C) 2015 Intel Corporation
4f63e5
+   Decode Intel Broadwell specific machine check errors.
4f63e5
+
4f63e5
+   mcelog is free software; you can redistribute it and/or
4f63e5
+   modify it under the terms of the GNU General Public
4f63e5
+   License as published by the Free Software Foundation; version
4f63e5
+   2.
4f63e5
+
4f63e5
+   mcelog is distributed in the hope that it will be useful,
4f63e5
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
4f63e5
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4f63e5
+   General Public License for more details.
4f63e5
+
4f63e5
+   You should find a copy of v2 of the GNU General Public License somewhere
4f63e5
+   on your Linux system; if not, write to the Free Software Foundation,
4f63e5
+   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4f63e5
+
4f63e5
+   Author: Tony Luck
4f63e5
+*/
4f63e5
+
4f63e5
+#include "mcelog.h"
4f63e5
+#include "bitfield.h"
4f63e5
+#include "broadwell_epex.h"
4f63e5
+#include "memdb.h"
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-20 */
4f63e5
+
4f63e5
+static char *pcu_1[] = {
4f63e5
+	[0x00] = "No Error",
4f63e5
+	[0x09] = "MC_MESSAGE_CHANNEL_TIMEOUT",
4f63e5
+	[0x0D] = "MC_IMC_FORCE_SR_S3_TIMEOUT",
4f63e5
+	[0x0E] = "MC_CPD_UNCPD_SD_TIMEOUT",
4f63e5
+	[0x13] = "MC_DMI_TRAINING_TIMEOUT",
4f63e5
+	[0x15] = "MC_DMI_CPU_RESET_ACK_TIMEOUT",
4f63e5
+	[0x1E] = "MC_VR_ICC_MAX_LT_FUSED_ICC_MAX",
4f63e5
+	[0x25] = "MC_SVID_COMMAN_TIMEOUT",
4f63e5
+	[0x29] = "MC_VR_VOUT_MAC_LT_FUSED_SVID",
4f63e5
+	[0x2B] = "MC_PKGC_WATCHDOG_HANG_CBZ_DOWN",
4f63e5
+	[0x2C] = "MC_PKGC_WATCHDOG_HANG_CBZ_UP",
4f63e5
+	[0x39] = "MC_PKGC_WATCHDOG_HANG_C3_UP_SF",
4f63e5
+	[0x44] = "MC_CRITICAL_VR_FAILED",
4f63e5
+	[0x45] = "MC_ICC_MAX_NOTSUPPORTED",
4f63e5
+	[0x46] = "MC_VID_RAMP_DOWN_FAILED",
4f63e5
+	[0x47] = "MC_EXCL_MODE_NO_PMREQ_CMP",
4f63e5
+	[0x48] = "MC_SVID_READ_REG_ICC_MAX_FAILED",
4f63e5
+	[0x49] = "MC_SVID_WRITE_REG_VOUT_MAX_FAILED",
4f63e5
+	[0x4B] = "MC_BOOT_VID_TIMEOUT_DRAM_0",
4f63e5
+	[0x4C] = "MC_BOOT_VID_TIMEOUT_DRAM_1",
4f63e5
+	[0x4D] = "MC_BOOT_VID_TIMEOUT_DRAM_2",
4f63e5
+	[0x4E] = "MC_BOOT_VID_TIMEOUT_DRAM_3",
4f63e5
+	[0x4F] = "MC_SVID_COMMAND_ERROR",
4f63e5
+	[0x52] = "MC_FIVR_CATAS_OVERVOL_FAULT",
4f63e5
+	[0x53] = "MC_FIVR_CATAS_OVERCUR_FAULT",
4f63e5
+	[0x57] = "MC_SVID_PKGC_REQUEST_FAILED",
4f63e5
+	[0x58] = "MC_SVID_IMON_REQUEST_FAILED",
4f63e5
+	[0x59] = "MC_SVID_ALERT_REQUEST_FAILED",
4f63e5
+	[0x60] = "MC_INVALID_PKGS_REQ_PCH",
4f63e5
+	[0x61] = "MC_INVALID_PKGS_REQ_QPI",
4f63e5
+	[0x62] = "MC_INVALID_PKGS_RSP_QPI",
4f63e5
+	[0x63] = "MC_INVALID_PKGS_RSP_PCH",
4f63e5
+	[0x64] = "MC_INVALID_PKG_STATE_CONFIG",
4f63e5
+	[0x67] = "MC_HA_IMC_RW_BLOCK_ACK_TIMEOUT",
4f63e5
+	[0x68] = "MC_IMC_RW_SMBUS_TIMEOUT",
4f63e5
+	[0x69] = "MC_HA_FAILSTS_CHANGE_DETECTED",
4f63e5
+	[0x6A] = "MC_MSGCH_PMREQ_CMP_TIMEOUT",
4f63e5
+	[0x70] = "MC_WATCHDOG_TIMEOUT_PKGC_SLAVE",
4f63e5
+	[0x71] = "MC_WATCHDOG_TIMEOUT_PKGC_MASTER",
4f63e5
+	[0x72] = "MC_WATCHDOG_TIMEOUT_PKGS_MASTER",
4f63e5
+	[0x7C] = "MC_BIOS_RST_CPL_INVALID_SEQ",
4f63e5
+	[0x7D] = "MC_MORE_THAN_ONE_TXT_AGENT",
4f63e5
+	[0x81] = "MC_RECOVERABLE_DIE_THERMAL_TOO_HOT"
4f63e5
+};
4f63e5
+
4f63e5
+static struct field pcu_mc4[] = {
4f63e5
+	FIELD(24, pcu_1),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-21 */
4f63e5
+
4f63e5
+static char *qpi[] = {
4f63e5
+	[0x02] = "Intel QPI physical layer detected drift buffer alarm",
4f63e5
+	[0x03] = "Intel QPI physical layer detected latency buffer rollover",
4f63e5
+	[0x10] = "Intel QPI link layer detected control error from R3QPI",
4f63e5
+	[0x11] = "Rx entered LLR abort state on CRC error",
4f63e5
+	[0x12] = "Unsupported or undefined packet",
4f63e5
+	[0x13] = "Intel QPI link layer control error",
4f63e5
+	[0x15] = "RBT used un-initialized value",
4f63e5
+	[0x20] = "Intel QPI physical layer detected a QPI in-band reset but aborted initialization",
4f63e5
+	[0x21] = "Link failover data self healing",
4f63e5
+	[0x22] = "Phy detected in-band reset (no width change)",
4f63e5
+	[0x23] = "Link failover clock failover",
4f63e5
+	[0x30] = "Rx detected CRC error - successful LLR after Phy re-init",
4f63e5
+	[0x31] = "Rx detected CRC error - successful LLR without Phy re-init",
4f63e5
+};
4f63e5
+
4f63e5
+static struct field qpi_mc[] = {
4f63e5
+	FIELD(16, qpi),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-26 */
4f63e5
+
4f63e5
+static struct field memctrl_mc9[] = {
4f63e5
+	SBITFIELD(16, "DDR3 address parity error"),
4f63e5
+	SBITFIELD(17, "Uncorrected HA write data error"),
4f63e5
+	SBITFIELD(18, "Uncorrected HA data byte enable error"),
4f63e5
+	SBITFIELD(19, "Corrected patrol scrub error"),
4f63e5
+	SBITFIELD(20, "Uncorrected patrol scrub error"),
4f63e5
+	SBITFIELD(21, "Corrected spare error"),
4f63e5
+	SBITFIELD(22, "Uncorrected spare error"),
4f63e5
+	SBITFIELD(24, "iMC write data buffer parity error"),
4f63e5
+	SBITFIELD(25, "DDR4 command address parity error"),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+void bdw_epex_decode_model(int cputype, int bank, u64 status, u64 misc)
4f63e5
+{
4f63e5
+	switch (bank) {
4f63e5
+	case 4:
4f63e5
+		Wprintf("PCU: ");
4f63e5
+		switch (EXTRACT(status, 0, 15) & ~(1ull << 12)) {
4f63e5
+		case 0x402: case 0x403:
4f63e5
+			Wprintf("Internal errors ");
4f63e5
+			break;
4f63e5
+		case 0x406:
4f63e5
+			Wprintf("Intel TXT errors ");
4f63e5
+			break;
4f63e5
+		case 0x407:
4f63e5
+			Wprintf("Other UBOX Internal errors ");
4f63e5
+			break;
4f63e5
+		}
4f63e5
+		if (EXTRACT(status, 16, 19))
4f63e5
+			Wprintf("PCU internal error ");
4f63e5
+		decode_bitfield(status, pcu_mc4);
4f63e5
+		break;
4f63e5
+	case 5:
4f63e5
+	case 20:
4f63e5
+	case 21:
4f63e5
+		Wprintf("QPI: ");
4f63e5
+		decode_bitfield(status, qpi_mc);
4f63e5
+		break;
4f63e5
+	case 9: case 10: case 11: case 12:
4f63e5
+	case 13: case 14: case 15: case 16:
4f63e5
+		Wprintf("MemCtrl: ");
4f63e5
+		decode_bitfield(status, memctrl_mc9);
4f63e5
+		break;
4f63e5
+	}
4f63e5
+}
4f63e5
diff -urNp mcelog-d2e13bf0.orig/broadwell_epex.h mcelog-d2e13bf0/broadwell_epex.h
4f63e5
--- mcelog-d2e13bf0.orig/broadwell_epex.h	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/broadwell_epex.h	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -0,0 +1 @@
4f63e5
+void bdw_epex_decode_model(int cputype, int bank, u64 status, u64 misc);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/bus.c mcelog-d2e13bf0/bus.c
4f63e5
--- mcelog-d2e13bf0.orig/bus.c	2016-05-14 08:34:40.446108283 -0400
4f63e5
+++ mcelog-d2e13bf0/bus.c	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -58,6 +58,9 @@ void run_bus_trigger(int socket, int cpu
4f63e5
 	char *msg;
4f63e5
 	char *location;
4f63e5
 
4f63e5
+	if (!bus_trigger)
4f63e5
+		return;
4f63e5
+
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&location, "CPU %d on socket %d", cpu, socket);
4f63e5
 	else
4f63e5
@@ -67,9 +70,6 @@ void run_bus_trigger(int socket, int cpu
4f63e5
 	asprintf(&env[ei++], "LOCATION=%s", location);
4f63e5
 	free(location);
4f63e5
 
4f63e5
-	if (!bus_trigger)
4f63e5
-		goto out;
4f63e5
-
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&env[ei++], "SOCKETID=%d", socket);
4f63e5
 	asprintf(&env[ei++], "MESSAGE=%s", msg);
4f63e5
@@ -85,7 +85,6 @@ void run_bus_trigger(int socket, int cpu
4f63e5
 	run_trigger(bus_trigger, NULL, env);
4f63e5
 	for (i = 0; i < ei; i++)
4f63e5
 		free(env[i]);
4f63e5
-out:
4f63e5
 	free(msg);
4f63e5
 }
4f63e5
 
4f63e5
@@ -97,6 +96,9 @@ void run_iomca_trigger(int socket, int c
4f63e5
 	char *msg;
4f63e5
 	char *location;
4f63e5
 
4f63e5
+	if (!iomca_trigger)
4f63e5
+		return;
4f63e5
+
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&location, "CPU %d on socket %d", cpu, socket);
4f63e5
 	else
4f63e5
@@ -106,9 +108,6 @@ void run_iomca_trigger(int socket, int c
4f63e5
 	asprintf(&env[ei++], "LOCATION=%s", location);
4f63e5
 	free(location);
4f63e5
 
4f63e5
-	if (!iomca_trigger)
4f63e5
-		goto out;
4f63e5
-
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&env[ei++], "SOCKETID=%d", socket);
4f63e5
 	asprintf(&env[ei++], "MESSAGE=%s", msg);
4f63e5
@@ -123,7 +122,6 @@ void run_iomca_trigger(int socket, int c
4f63e5
 	run_trigger(iomca_trigger, NULL, env);
4f63e5
 	for (i = 0; i < ei; i++)
4f63e5
 		free(env[i]);
4f63e5
-out:
4f63e5
 	free(msg);
4f63e5
 
4f63e5
 }
4f63e5
diff -urNp mcelog-d2e13bf0.orig/cache.c mcelog-d2e13bf0/cache.c
4f63e5
--- mcelog-d2e13bf0.orig/cache.c	2016-05-14 08:34:40.434107718 -0400
4f63e5
+++ mcelog-d2e13bf0/cache.c	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -97,9 +97,14 @@ static void parse_cpumap(char *map, unsi
4f63e5
 static void read_cpu_map(struct cache *c, char *cfn)
4f63e5
 {
4f63e5
 	char *map = read_field(cfn, "shared_cpu_map");
4f63e5
+	if (map[0] == 0) {
4f63e5
+		c->cpumap = NULL;
4f63e5
+		goto out;
4f63e5
+	}
4f63e5
 	c->cpumaplen = cpumap_len(map);
4f63e5
 	c->cpumap = xalloc(c->cpumaplen);
4f63e5
 	parse_cpumap(map, c->cpumap, c->cpumaplen);
4f63e5
+out:
4f63e5
 	free(map);
4f63e5
 }
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/core2.c mcelog-d2e13bf0/core2.c
4f63e5
--- mcelog-d2e13bf0.orig/core2.c	2016-05-14 08:34:40.434107718 -0400
4f63e5
+++ mcelog-d2e13bf0/core2.c	2016-05-14 08:34:58.869975058 -0400
4f63e5
@@ -69,7 +69,7 @@ static struct field p6old_status[] = {
4f63e5
 	FIELD(31, reserved_1bit),
4f63e5
 	FIELD(32, reserved_3bits),
4f63e5
 	SBITFIELD(35, "BINIT received from external bus"),
4f63e5
-	SBITFIELD(37, "Received hard error reponse on split transaction (Bus BINIT)"),
4f63e5
+	SBITFIELD(37, "Received hard error response on split transaction (Bus BINIT)"),
4f63e5
 	{}
4f63e5
 };
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/dimm.c mcelog-d2e13bf0/dimm.c
4f63e5
--- mcelog-d2e13bf0.orig/dimm.c	2016-05-14 08:34:40.435107765 -0400
4f63e5
+++ mcelog-d2e13bf0/dimm.c	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -351,14 +351,14 @@ static void run_trigger(char *trigger, c
4f63e5
 		Eprintf("Cannot run error trigger %s for %s\n", trigger, loc);
4f63e5
 	open_dimm_db(NULL);
4f63e5
 }
4f63e5
-void new_error(unsigned long addr, unsigned long max_error, char *trigger)
4f63e5
+void new_error(unsigned long long addr, unsigned long max_error, char *trigger)
4f63e5
 {
4f63e5
 	struct dmi_memdev **devs;
4f63e5
 	int i;
4f63e5
 
4f63e5
 	devs = dmi_find_addr(addr);
4f63e5
 	if (devs[0] == NULL) {
4f63e5
-		Wprintf("No memory found for address %lx\n", addr);
4f63e5
+		Wprintf("No memory found for address %llx\n", addr);
4f63e5
 		exit(1);
4f63e5
 	}
4f63e5
 	for (i = 0; devs[i]; i++) {
4f63e5
@@ -366,7 +366,7 @@ void new_error(unsigned long addr, unsig
4f63e5
 		char *loc = dmi_getstring(&d->header, d->device_locator);
4f63e5
 		struct group *g = find_entry(dimm_db, NULL, "Locator", loc);
4f63e5
 		if (!g) { // shouldn't happen
4f63e5
-			Eprintf("No record found for %lx\n", addr);
4f63e5
+			Eprintf("No record found for %llx\n", addr);
4f63e5
 			return;
4f63e5
 		}
4f63e5
 		unsigned long val = inc_val(g, "corrected errors");
4f63e5
diff -urNp mcelog-d2e13bf0.orig/dimm.h mcelog-d2e13bf0/dimm.h
4f63e5
--- mcelog-d2e13bf0.orig/dimm.h	2016-05-14 08:34:40.435107765 -0400
4f63e5
+++ mcelog-d2e13bf0/dimm.h	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -1,6 +1,6 @@
4f63e5
 void close_dimm_db(void);
4f63e5
 int open_dimm_db(char *fn);
4f63e5
-void new_error(unsigned long addr, unsigned long max_error, char *trigger);
4f63e5
+void new_error(unsigned long long addr, unsigned long max_error, char *trigger);
4f63e5
 void reset_dimm(char *locator);
4f63e5
 void gc_dimms(void);
4f63e5
 void dump_all_dimms(void);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/dmi.c mcelog-d2e13bf0/dmi.c
4f63e5
--- mcelog-d2e13bf0.orig/dmi.c	2016-05-14 08:34:40.446108283 -0400
4f63e5
+++ mcelog-d2e13bf0/dmi.c	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -1,6 +1,8 @@
4f63e5
 /* Copyright (C) 2006 Andi Kleen, SuSE Labs.
4f63e5
+   Portions Copyright (C) 2016 Sergio Gelato.
4f63e5
+
4f63e5
    Use SMBIOS/DMI to map address to DIMM description.
4f63e5
-   For reference see the SMBIOS specification 2.4
4f63e5
+   For reference see the SMBIOS specification 2.4, 3.0
4f63e5
 
4f63e5
    dmi is free software; you can redistribute it and/or
4f63e5
    modify it under the terms of the GNU General Public
4f63e5
@@ -55,9 +57,9 @@ struct anchor {
4f63e5
 } __attribute__((packed));
4f63e5
 
4f63e5
 static struct dmi_entry *entries;
4f63e5
-static int entrieslen;
4f63e5
+static size_t entrieslen;
4f63e5
 static int numentries;
4f63e5
-static int dmi_length;
4f63e5
+static size_t dmi_length;
4f63e5
 static struct dmi_entry **handle_to_entry;
4f63e5
 
4f63e5
 struct dmi_memdev **dmi_dimms; 
4f63e5
@@ -137,6 +139,59 @@ static void fill_handles(void)
4f63e5
 	}
4f63e5
 }
4f63e5
 
4f63e5
+static int append_sysfs_dmi_entry(unsigned char type, int instance)
4f63e5
+{
4f63e5
+	char filename[64];	/* 40 bytes should be enough */
4f63e5
+	char buf[1024];
4f63e5
+	int r;
4f63e5
+	ssize_t nr;
4f63e5
+	size_t l;
4f63e5
+	int fd;
4f63e5
+	r = snprintf(filename, sizeof(filename),
4f63e5
+		     "/sys/firmware/dmi/entries/%hhu-%d/raw",
4f63e5
+		     type, instance);
4f63e5
+	if (r < 0 || (unsigned int)r >= sizeof(filename)) {
4f63e5
+		Eprintf("Can't build pathname for DMI type %hhu instance %d\n",
4f63e5
+			type, instance);
4f63e5
+		return 0;
4f63e5
+	}
4f63e5
+	fd = open(filename, O_RDONLY);
4f63e5
+	if (fd == (-1)) {
4f63e5
+		if (errno != ENOENT)
4f63e5
+			perror(filename);
4f63e5
+		return 0;
4f63e5
+	}
4f63e5
+	l = dmi_length;
4f63e5
+	for (;;) {
4f63e5
+		nr = read(fd, buf, sizeof(buf));
4f63e5
+		if (nr < 0) {
4f63e5
+			if (errno == EINTR)
4f63e5
+				continue;
4f63e5
+			perror(filename);
4f63e5
+			close(fd);
4f63e5
+			return 0;
4f63e5
+		} else if (nr > 0) {
4f63e5
+			while (l + nr > entrieslen) {
4f63e5
+				entrieslen += 4096;
4f63e5
+				entries = xrealloc(entries, entrieslen);
4f63e5
+			}
4f63e5
+			memcpy((char *)entries+l, buf, nr);
4f63e5
+			l += nr;
4f63e5
+		} else {
4f63e5
+			numentries ++;
4f63e5
+			dmi_length = l;
4f63e5
+			close(fd);
4f63e5
+			return 1;
4f63e5
+		}
4f63e5
+	}
4f63e5
+}
4f63e5
+
4f63e5
+static void append_sysfs_dmi_entries(unsigned char type)
4f63e5
+{
4f63e5
+	int i;
4f63e5
+	for (i=0; append_sysfs_dmi_entry(type, i); i++) ;
4f63e5
+}
4f63e5
+
4f63e5
 static int get_efi_base_addr(size_t *address)
4f63e5
 {
4f63e5
 	FILE *efi_systab;
4f63e5
@@ -190,10 +245,12 @@ check_symbol:
4f63e5
 int opendmi(void)
4f63e5
 {
4f63e5
 	struct anchor *a, *abase;
4f63e5
+	void *ebase;
4f63e5
 	void *p, *q;
4f63e5
 	int pagesize = getpagesize();
4f63e5
 	int memfd; 
4f63e5
-	unsigned corr;
4f63e5
+	off_t emapbase, corr;
4f63e5
+	size_t emapsize;
4f63e5
 	int err = -1;
4f63e5
 	const int segsize = 0x10000;
4f63e5
 	size_t entry_point_addr = 0;
4f63e5
@@ -201,6 +258,18 @@ int opendmi(void)
4f63e5
 
4f63e5
 	if (entries)
4f63e5
 		return 0;
4f63e5
+
4f63e5
+	if (access("/sys/firmware/dmi/entries/0-0/raw", R_OK) == 0) {
4f63e5
+		numentries = 0;
4f63e5
+		append_sysfs_dmi_entries(DMI_MEMORY_ARRAY);
4f63e5
+		append_sysfs_dmi_entries(DMI_MEMORY_DEVICE);
4f63e5
+		append_sysfs_dmi_entries(DMI_MEMORY_ARRAY_ADDR);
4f63e5
+		append_sysfs_dmi_entries(DMI_MEMORY_MAPPED_ADDR);
4f63e5
+		fill_handles();
4f63e5
+		collect_dmi_dimms();
4f63e5
+		return 0;
4f63e5
+	}
4f63e5
+
4f63e5
 	memfd = open("/dev/mem", O_RDONLY);
4f63e5
 	if (memfd < 0) { 
4f63e5
 		Eprintf("Cannot open /dev/mem for DMI decoding: %s",
4f63e5
@@ -228,8 +297,6 @@ int opendmi(void)
4f63e5
 		}
4f63e5
 		a = (struct anchor*)((char*)abase + (entry_point_addr - addr_start));
4f63e5
 		goto fill_entries;
4f63e5
-	} else {
4f63e5
-		return -1;
4f63e5
 	}
4f63e5
 
4f63e5
 legacy:
4f63e5
@@ -264,17 +331,18 @@ fill_entries:
4f63e5
 	if (verbose) 
4f63e5
 		printf("DMI tables at %x, %u bytes, %u entries\n", 
4f63e5
 			a->table, a->length, a->numentries);
4f63e5
-	corr = a->table - round_down(a->table, pagesize); 
4f63e5
-	entrieslen = round_up(a->table + a->length, pagesize) -
4f63e5
-		round_down(a->table, pagesize);
4f63e5
- 	entries = mmap(NULL, entrieslen, 
4f63e5
-		       	PROT_READ, MAP_SHARED, memfd, 
4f63e5
-			round_down(a->table, pagesize));
4f63e5
-	if (entries == (struct dmi_entry *)-1) { 
4f63e5
+	emapbase = round_down(a->table, pagesize);
4f63e5
+	corr = a->table - emapbase;
4f63e5
+	emapsize = round_up(a->table + a->length, pagesize) - emapbase;
4f63e5
+	ebase = mmap(NULL, emapsize, PROT_READ, MAP_SHARED, memfd, emapbase);
4f63e5
+	if (ebase == MAP_FAILED) {
4f63e5
 		Eprintf("Cannot mmap SMBIOS tables at %x", a->table);
4f63e5
 		goto out_mmap;
4f63e5
 	}
4f63e5
-	entries = (struct dmi_entry *)(((char *)entries) + corr);
4f63e5
+	entrieslen = a->length;
4f63e5
+	entries = xalloc_nonzero(entrieslen);
4f63e5
+	memcpy(entries, (char *)ebase+corr, entrieslen);
4f63e5
+	munmap(ebase, emapsize);
4f63e5
 	numentries = a->numentries;
4f63e5
 	dmi_length = a->length;
4f63e5
 	fill_handles();
4f63e5
@@ -307,13 +375,15 @@ static char *form_factors[] = {
4f63e5
 	"?",
4f63e5
 	"Other", "Unknown", "SIMM", "SIP", "Chip", "DIP", "ZIP", 
4f63e5
 	"Proprietary Card", "DIMM", "TSOP", "Row of chips", "RIMM",
4f63e5
-	"SODIMM", "SRIMM"
4f63e5
+	"SODIMM", "SRIMM", "FB-DIMM"
4f63e5
 };
4f63e5
 static char *memory_types[] = {
4f63e5
 	"?",
4f63e5
 	"Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
4f63e5
 	"ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM",
4f63e5
-	"SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2"
4f63e5
+	"SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB-DIMM",
4f63e5
+	"Reserved 0x15", "Reserved 0x16", "Reserved 0x17", "DDR3",
4f63e5
+	"FBD2", "DDR4", "LPDDR", "LPDDR2", "LPDDR3", "LPDDR4"
4f63e5
 };
4f63e5
 
4f63e5
 #define LOOKUP(array, val, buf) \
4f63e5
@@ -324,7 +394,8 @@ static char *memory_types[] = {
4f63e5
 static char *type_details[16] = {
4f63e5
 	"Reserved", "Other", "Unknown", "Fast-paged", "Static Column",
4f63e5
 	"Pseudo static", "RAMBUS", "Synchronous", "CMOS", "EDO",
4f63e5
-	"Window DRAM", "Cache DRAM", "Non-volatile", "Res13", "Res14", "Res15"
4f63e5
+	"Window DRAM", "Cache DRAM", "Non-volatile", "Registered",
4f63e5
+	"Unbuffered", "LRDIMM"
4f63e5
 }; 
4f63e5
 
4f63e5
 static void dump_type_details(unsigned short td)
4f63e5
@@ -337,7 +408,7 @@ static void dump_type_details(unsigned s
4f63e5
 			Wprintf("%s ", type_details[i]);
4f63e5
 }
4f63e5
 
4f63e5
-static void dump_memdev(struct dmi_memdev *md, unsigned long addr)
4f63e5
+static void dump_memdev(struct dmi_memdev *md, unsigned long long addr)
4f63e5
 {
4f63e5
 	char tmp[20];
4f63e5
 	char unit[10];
4f63e5
@@ -346,7 +417,7 @@ static void dump_memdev(struct dmi_memde
4f63e5
 	if (md->header.length < 
4f63e5
 			offsetof(struct dmi_memdev, manufacturer)) { 
4f63e5
 		if (verbose > 0)
4f63e5
-			printf("Memory device for address %lx too short %u\n",
4f63e5
+			printf("Memory device for address %llx too short %u\n",
4f63e5
 			       addr, md->header.length);
4f63e5
 		return;
4f63e5
 	}	
4f63e5
@@ -500,7 +571,7 @@ int dmi_sanity_check(void)
4f63e5
 						dmi_dimms[i]->device_locator);
4f63e5
 			if (!strcmp(b, loc)) {
4f63e5
 				if (verbose > 0)
4f63e5
-					printf("Ambigious locators `%s'<->`%s'."
4f63e5
+					printf("Ambiguous locators `%s'<->`%s'."
4f63e5
 					       FAILED, b, loc);
4f63e5
 				return 0;
4f63e5
 			}
4f63e5
@@ -538,7 +609,7 @@ dump_ranges(struct dmi_memdev_addr **ran
4f63e5
 			DMIGET(dmi_dimms[i],device_set));
4f63e5
 }
4f63e5
 
4f63e5
-struct dmi_memdev **dmi_find_addr(unsigned long addr)
4f63e5
+struct dmi_memdev **dmi_find_addr(unsigned long long addr)
4f63e5
 {
4f63e5
 	struct dmi_memdev **devs; 
4f63e5
 	int i, k;
4f63e5
@@ -582,7 +653,7 @@ struct dmi_memdev **dmi_find_addr(unsign
4f63e5
 	return devs;
4f63e5
 }
4f63e5
 
4f63e5
-void dmi_decodeaddr(unsigned long addr)
4f63e5
+void dmi_decodeaddr(unsigned long long addr)
4f63e5
 {
4f63e5
 	struct dmi_memdev **devs = dmi_find_addr(addr);
4f63e5
 	if (devs[0]) { 
4f63e5
@@ -591,7 +662,7 @@ void dmi_decodeaddr(unsigned long addr)
4f63e5
 		for (i = 0; devs[i]; i++) 
4f63e5
 			dump_memdev(devs[i], addr);
4f63e5
 	} else { 
4f63e5
-		Wprintf("No DIMM found for %lx in SMBIOS\n", addr);
4f63e5
+		Wprintf("No DIMM found for %llx in SMBIOS\n", addr);
4f63e5
 	}
4f63e5
 	free(devs);
4f63e5
 } 
4f63e5
@@ -625,11 +696,11 @@ void closedmi(void)
4f63e5
 {
4f63e5
 	if (!entries) 
4f63e5
 		return;
4f63e5
-	munmap(entries, entrieslen);
4f63e5
-	entries = NULL;
4f63e5
 	FREE(dmi_dimms);
4f63e5
 	FREE(dmi_arrays);
4f63e5
 	FREE(dmi_ranges);
4f63e5
 	FREE(dmi_array_ranges);
4f63e5
 	FREE(handle_to_entry);
4f63e5
+	FREE(entries);
4f63e5
+	entrieslen = 0;
4f63e5
 }
4f63e5
diff -urNp mcelog-d2e13bf0.orig/dmi.h mcelog-d2e13bf0/dmi.h
4f63e5
--- mcelog-d2e13bf0.orig/dmi.h	2016-05-14 08:34:40.435107765 -0400
4f63e5
+++ mcelog-d2e13bf0/dmi.h	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -62,10 +62,10 @@ struct dmi_memarray_addr {
4f63e5
 }  __attribute__((packed));
4f63e5
 
4f63e5
 int opendmi(void);
4f63e5
-void dmi_decodeaddr(unsigned long addr);
4f63e5
+void dmi_decodeaddr(unsigned long long addr);
4f63e5
 int dmi_sanity_check(void);
4f63e5
 unsigned dmi_dimm_size(unsigned short size, char *unit);
4f63e5
-struct dmi_memdev **dmi_find_addr(unsigned long addr);
4f63e5
+struct dmi_memdev **dmi_find_addr(unsigned long long addr);
4f63e5
 void dmi_set_verbosity(int v);
4f63e5
 
4f63e5
 char *dmi_getstring(struct dmi_entry *e, unsigned number);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/genconfig.py mcelog-d2e13bf0/genconfig.py
4f63e5
--- mcelog-d2e13bf0.orig/genconfig.py	2016-05-14 08:34:40.436107812 -0400
4f63e5
+++ mcelog-d2e13bf0/genconfig.py	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -66,7 +66,7 @@ def new_option():
4f63e5
 
4f63e5
 
4f63e5
 print """
4f63e5
-.\" Auto generated mcelog.conf manpage. Do not edit.
4f63e5
+.\\" Auto generated mcelog.conf manpage. Do not edit.
4f63e5
 .TH "mcelog.conf" 5 "mcelog"
4f63e5
 """
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/haswell.c mcelog-d2e13bf0/haswell.c
4f63e5
--- mcelog-d2e13bf0.orig/haswell.c	2016-05-14 08:34:40.445108236 -0400
4f63e5
+++ mcelog-d2e13bf0/haswell.c	2016-05-14 08:34:58.870975105 -0400
4f63e5
@@ -91,7 +91,7 @@ static char *qpi[] = {
4f63e5
 	[0x22] = "Phy detected in-band reset (no width change)",
4f63e5
 	[0x23] = "Link failover clock failover",
4f63e5
 	[0x30] = "Rx detected CRC error - successful LLR after Phy re-init",
4f63e5
-	[0x31] = "Rx detected CRC error - successful LLR wihout Phy re-init",
4f63e5
+	[0x31] = "Rx detected CRC error - successful LLR without Phy re-init",
4f63e5
 };
4f63e5
 
4f63e5
 static struct field qpi_mc[] = {
4f63e5
diff -urNp mcelog-d2e13bf0.orig/intel.c mcelog-d2e13bf0/intel.c
4f63e5
--- mcelog-d2e13bf0.orig/intel.c	2016-05-14 08:34:40.434107718 -0400
4f63e5
+++ mcelog-d2e13bf0/intel.c	2016-05-14 08:36:22.435906530 -0400
4f63e5
@@ -35,7 +35,8 @@ void intel_cpu_init(enum cputype cpu)
4f63e5
 	    cpu == CPU_SANDY_BRIDGE || cpu == CPU_SANDY_BRIDGE_EP ||
4f63e5
 	    cpu == CPU_IVY_BRIDGE || cpu == CPU_IVY_BRIDGE_EPEX ||
4f63e5
 	    cpu == CPU_HASWELL || cpu == CPU_HASWELL_EPEX || cpu == CPU_BROADWELL ||
4f63e5
-	    cpu == CPU_KNIGHTS_LANDING)
4f63e5
+	    cpu == CPU_BROADWELL_DE || cpu == CPU_BROADWELL_EPEX ||
4f63e5
+	    cpu == CPU_KNIGHTS_LANDING || cpu == CPU_SKYLAKE || cpu == CPU_SKYLAKE_XEON)
4f63e5
 		memory_error_support = 1;
4f63e5
 }
4f63e5
 
4f63e5
@@ -73,15 +74,23 @@ enum cputype select_intel_cputype(int fa
4f63e5
 			return CPU_HASWELL;
4f63e5
 		else if (model == 0x3f)
4f63e5
 			return CPU_HASWELL_EPEX;
4f63e5
-		else if (model == 0x3d || model == 0x56)
4f63e5
+		else if (model == 0x3d)
4f63e5
 			return CPU_BROADWELL;
4f63e5
-		else if (model == 0x57)
4f63e5
+		else if (model == 0x4f)
4f63e5
+			return CPU_BROADWELL_EPEX;
4f63e5
+		else if (model == 0x56)
4f63e5
+			return CPU_BROADWELL_DE;
4f63e5
+ 		else if (model == 0x57)
4f63e5
 			return CPU_KNIGHTS_LANDING;
4f63e5
 		else if (model == 0x1c || model == 0x26 || model == 0x27 ||
4f63e5
 			 model == 0x35 || model == 0x36 || model == 0x36 ||
4f63e5
 			 model == 0x37 || model == 0x4a || model == 0x4c ||
4f63e5
 			 model == 0x4d || model == 0x5a || model == 0x5d)
4f63e5
 			return CPU_ATOM;
4f63e5
+		else if (model == 0x4e || model == 0x5e)
4f63e5
+			return CPU_SKYLAKE;
4f63e5
+		else if (model == 0x55)
4f63e5
+			return CPU_SKYLAKE_XEON;
4f63e5
 		if (model > 0x1a) {
4f63e5
 			Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n",
4f63e5
 				model);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/intel.h mcelog-d2e13bf0/intel.h
4f63e5
--- mcelog-d2e13bf0.orig/intel.h	2016-05-14 08:34:40.444108189 -0400
4f63e5
+++ mcelog-d2e13bf0/intel.h	2016-05-14 08:34:58.871975152 -0400
4f63e5
@@ -21,5 +21,10 @@ extern int memory_error_support;
4f63e5
 	case CPU_HASWELL: \
4f63e5
 	case CPU_HASWELL_EPEX: \
4f63e5
 	case CPU_BROADWELL: \
4f63e5
-	case CPU_KNIGHTS_LANDING
4f63e5
+	case CPU_BROADWELL_DE: \
4f63e5
+	case CPU_BROADWELL_EPEX: \
4f63e5
+	case CPU_ATOM:	\
4f63e5
+	case CPU_KNIGHTS_LANDING: \
4f63e5
+	case CPU_SKYLAKE: \
4f63e5
+	case CPU_SKYLAKE_XEON
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/k8.c mcelog-d2e13bf0/k8.c
4f63e5
--- mcelog-d2e13bf0.orig/k8.c	2016-05-14 08:34:40.437107859 -0400
4f63e5
+++ mcelog-d2e13bf0/k8.c	2016-05-14 08:34:58.871975152 -0400
4f63e5
@@ -89,7 +89,7 @@ static char *highbits[32] = {
4f63e5
 	[0] = "err cpu0",
4f63e5
 };
4f63e5
 static char *k8threshold[] = {
4f63e5
-	[0 ... K8_MCELOG_THRESHOLD_DRAM_ECC - 1] = "Unknow threshold counter",
4f63e5
+	[0 ... K8_MCELOG_THRESHOLD_DRAM_ECC - 1] = "Unknown threshold counter",
4f63e5
 	[K8_MCELOG_THRESHOLD_DRAM_ECC] = "MC4_MISC0 DRAM threshold",
4f63e5
 	[K8_MCELOG_THRESHOLD_LINK] = "MC4_MISC1 Link threshold",
4f63e5
 	[K8_MCELOG_THRESHOLD_L3_CACHE] = "MC4_MISC2 L3 Cache threshold",
4f63e5
diff -urNp mcelog-d2e13bf0.orig/Makefile mcelog-d2e13bf0/Makefile
4f63e5
--- mcelog-d2e13bf0.orig/Makefile	2016-05-14 08:34:40.447108330 -0400
4f63e5
+++ mcelog-d2e13bf0/Makefile	2016-05-14 08:34:58.868975011 -0400
4f63e5
@@ -30,15 +30,18 @@ TRIGGERS=cache-error-trigger dimm-error-
4f63e5
 
4f63e5
 all: mcelog
4f63e5
 
4f63e5
-.PHONY: install clean depend
4f63e5
+.PHONY: install clean depend FORCE
4f63e5
 
4f63e5
 OBJ := p4.o k8.o mcelog.o dmi.o tsc.o core2.o bitfield.o intel.o \
4f63e5
        nehalem.o dunnington.o tulsa.o config.o memutil.o msg.o   \
4f63e5
        eventloop.o leaky-bucket.o memdb.o server.o trigger.o 	 \
4f63e5
        client.o cache.o sysfs.o yellow.o page.o rbtree.o 	 \
4f63e5
-       xeon75xx.o sandy-bridge.o ivy-bridge.o haswell.o msr.o bus.o unknown.o
4f63e5
+       xeon75xx.o sandy-bridge.o ivy-bridge.o haswell.o		 \
4f63e5
+       broadwell_de.o broadwell_epex.o skylake_xeon.o		 \
4f63e5
+       msr.o bus.o unknown.o
4f63e5
 DISKDB_OBJ := diskdb.o dimm.o db.o
4f63e5
-CLEAN := mcelog dmi tsc dbquery .depend .depend.X dbquery.o ${DISKDB_OBJ}
4f63e5
+CLEAN := mcelog dmi tsc dbquery .depend .depend.X dbquery.o ${DISKDB_OBJ} \
4f63e5
+	version.o version.c version.tmp
4f63e5
 DOC := mce.pdf
4f63e5
 
4f63e5
 ADD_DEFINES :=
4f63e5
@@ -52,7 +55,7 @@ endif
4f63e5
 
4f63e5
 SRC := $(OBJ:.o=.c)
4f63e5
 
4f63e5
-mcelog: ${OBJ}
4f63e5
+mcelog: ${OBJ} version.o
4f63e5
 
4f63e5
 # dbquery intentionally not installed by default
4f63e5
 install: mcelog mcelog.conf mcelog.conf.5 mcelog.triggers.5
4f63e5
@@ -80,7 +83,7 @@ clean: test-clean
4f63e5
 	rm -f ${CLEAN} ${OBJ} 
4f63e5
 
4f63e5
 tsc:    tsc.c
4f63e5
-	gcc -o tsc ${CFLAGS} -DSTANDALONE tsc.c ${LDFLAGS}
4f63e5
+	$(CC) -o tsc ${CFLAGS} -DSTANDALONE tsc.c ${LDFLAGS}
4f63e5
 
4f63e5
 dbquery: db.o dbquery.o memutil.o
4f63e5
 
4f63e5
@@ -89,6 +92,21 @@ depend: .depend
4f63e5
 %.o: %.c
4f63e5
 	$(CC) -c $(CFLAGS) $(CPPFLAGS) $(WARNINGS) $(ADD_DEFINES) -o $@ $<
4f63e5
 
4f63e5
+version.tmp: FORCE
4f63e5
+	( echo -n "char version[] = \"" ; 	\
4f63e5
+	if type -p git >/dev/null; then 	\
4f63e5
+	if [ -d .git ] ; then 			\
4f63e5
+		git describe --tags HEAD | tr -d '\n'; 	\
4f63e5
+	else 					\
4f63e5
+		echo -n "unknown" ; 		\
4f63e5
+	fi ;					\
4f63e5
+	else echo -n "unknown" ; fi ;		\
4f63e5
+	echo '";'				\
4f63e5
+	 ) > version.tmp
4f63e5
+
4f63e5
+version.c: version.tmp
4f63e5
+	cmp version.tmp version.c || mv version.tmp version.c
4f63e5
+
4f63e5
 .depend: ${SRC}
4f63e5
 	${CC} -MM -I. ${SRC} > .depend.X && mv .depend.X .depend
4f63e5
 
4f63e5
@@ -111,7 +129,7 @@ src:
4f63e5
 	echo $(SRC)
4f63e5
 
4f63e5
 config-test: config.c
4f63e5
-	gcc -DTEST=1 config.c -o config-test
4f63e5
+	$(CC) -DTEST=1 config.c -o config-test
4f63e5
 
4f63e5
 test:
4f63e5
 	$(MAKE) -C tests test DEBUG=""
4f63e5
diff -urNp mcelog-d2e13bf0.orig/mcelog.8 mcelog-d2e13bf0/mcelog.8
4f63e5
--- mcelog-d2e13bf0.orig/mcelog.8	2016-05-14 08:34:40.437107859 -0400
4f63e5
+++ mcelog-d2e13bf0/mcelog.8	2016-05-14 08:34:58.871975152 -0400
4f63e5
@@ -16,6 +16,8 @@ mcelog [options] \-\-ascii
4f63e5
 .\".br
4f63e5
 .\"mcelog [options] \-\-dump-memory[=locator]
4f63e5
 .br
4f63e5
+mcelog [options] \-\-is\-cpu\-supported
4f63e5
+.br
4f63e5
 mcelog \-\-version
4f63e5
 .SH DESCRIPTION
4f63e5
 X86 CPUs report errors detected by the CPU as
4f63e5
@@ -81,6 +83,10 @@ store it anymore (different from
4f63e5
 so the output should be always saved somewhere and mcelog
4f63e5
 not run in uncontrolled ways.
4f63e5
 
4f63e5
+When invoked with the
4f63e5
+.I \-\-is\-cpu\-supported
4f63e5
+option mcelog exits with code 0 if the current CPU is supported, 1 otherwise.
4f63e5
+
4f63e5
 .SH OPTIONS
4f63e5
 When the 
4f63e5
 .B \-\-syslog
4f63e5
@@ -294,7 +300,7 @@ For more information on the config file
4f63e5
 The kernel prefers old messages over new. If the log buffer overflows
4f63e5
 only old ones will be kept.
4f63e5
 
4f63e5
-The exact output in the log file depends on the CPU, unless the --raw option is used.
4f63e5
+The exact output in the log file depends on the CPU, unless the \-\-raw option is used.
4f63e5
 
4f63e5
 mcelog will report serious errors to the syslog during decoding.
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/mcelog.c mcelog-d2e13bf0/mcelog.c
4f63e5
--- mcelog-d2e13bf0.orig/mcelog.c	2016-05-14 08:34:40.444108189 -0400
4f63e5
+++ mcelog-d2e13bf0/mcelog.c	2016-05-14 08:37:03.210824839 -0400
4f63e5
@@ -85,6 +85,7 @@ static char *pidfile = pidfile_default;
4f63e5
 static char *logfile;
4f63e5
 static int debug_numerrors;
4f63e5
 int imc_log = -1;
4f63e5
+static int check_only = 0;
4f63e5
 
4f63e5
 static int is_cpu_supported(void);
4f63e5
 
4f63e5
@@ -131,7 +132,7 @@ static char *bankname(unsigned bank)
4f63e5
 	}
4f63e5
 } 
4f63e5
 
4f63e5
-static void resolveaddr(unsigned long addr)
4f63e5
+static void resolveaddr(unsigned long long addr)
4f63e5
 {
4f63e5
 	if (addr && do_dmi && dmi_forced)
4f63e5
 		dmi_decodeaddr(addr);
4f63e5
@@ -232,8 +233,12 @@ static char *cputype_name[] = {
4f63e5
 	[CPU_HASWELL] = "Haswell", /* Fill in better name */
4f63e5
 	[CPU_HASWELL_EPEX] = "Haswell EP/EX", /* Fill in better name */
4f63e5
 	[CPU_BROADWELL] = "Broadwell",
4f63e5
+	[CPU_BROADWELL_DE] = "Intel Xeon (Broadwell) D family",
4f63e5
+	[CPU_BROADWELL_EPEX] = "Intel Xeon v4 (Broadwell) EP/EX",
4f63e5
 	[CPU_KNIGHTS_LANDING] = "Knights Landing",
4f63e5
 	[CPU_ATOM] = "ATOM",
4f63e5
+	[CPU_SKYLAKE] = "Skylake",
4f63e5
+	[CPU_SKYLAKE_XEON] = "Skylake server",
4f63e5
 };
4f63e5
 
4f63e5
 static struct config_choice cpu_choices[] = {
4f63e5
@@ -273,8 +278,14 @@ static struct config_choice cpu_choices[
4f63e5
 	{ "haswell-ep", CPU_HASWELL_EPEX }, /* Fill in better name */
4f63e5
 	{ "haswell-ex", CPU_HASWELL_EPEX }, /* Fill in better name */
4f63e5
 	{ "broadwell", CPU_BROADWELL },
4f63e5
+	{ "broadwell-d", CPU_BROADWELL_DE },
4f63e5
+	{ "broadwell-ep", CPU_BROADWELL_EPEX },
4f63e5
+	{ "broadwell-ex", CPU_BROADWELL_EPEX },
4f63e5
 	{ "knightslanding", CPU_KNIGHTS_LANDING },
4f63e5
+	{ "xeon-v4", CPU_BROADWELL_EPEX },
4f63e5
 	{ "atom", CPU_ATOM },
4f63e5
+	{ "skylake", CPU_SKYLAKE },
4f63e5
+	{ "skylake_server", CPU_SKYLAKE_XEON },
4f63e5
 	{ NULL }
4f63e5
 };
4f63e5
 
4f63e5
@@ -437,7 +448,9 @@ static void dump_mce(struct mce *m, unsi
4f63e5
 	}
4f63e5
 	if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX &&
4f63e5
 	    cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL &&
4f63e5
-	    cputype != CPU_KNIGHTS_LANDING)
4f63e5
+	    cputype != CPU_BROADWELL_DE && cputype != CPU_BROADWELL_EPEX &&
4f63e5
+	    cputype != CPU_KNIGHTS_LANDING && cputype != CPU_SKYLAKE &&
4f63e5
+	    cputype != CPU_SKYLAKE_XEON)
4f63e5
 		resolveaddr(m->addr);
4f63e5
 	if (!ascii_mode && ismemerr && (m->status & MCI_STATUS_ADDRV)) {
4f63e5
 		diskdb_resolve_addr(m->addr);
4f63e5
@@ -916,22 +929,35 @@ void usage(void)
4f63e5
 {
4f63e5
 	fprintf(stderr, 
4f63e5
 "Usage:\n"
4f63e5
+"\n"
4f63e5
 "  mcelog [options]  [mcelogdevice]\n"
4f63e5
 "Decode machine check error records from current kernel.\n"
4f63e5
+"\n"
4f63e5
 "  mcelog [options] --daemon\n"
4f63e5
 "Run mcelog in daemon mode, waiting for errors from the kernel.\n"
4f63e5
+"\n"
4f63e5
 "  mcelog [options] --client\n"
4f63e5
 "Query a currently running mcelog daemon for errors\n"
4f63e5
+"\n"
4f63e5
 "  mcelog [options] --ascii < log\n"
4f63e5
 "  mcelog [options] --ascii --file log\n"
4f63e5
 "Decode machine check ASCII output from kernel logs\n"
4f63e5
+"\n"
4f63e5
 "Options:\n"  
4f63e5
+"--version           Show the version of mcelog and exit\n"
4f63e5
 "--cpu CPU           Set CPU type CPU to decode (see below for valid types)\n"
4f63e5
+"--intel-cpu FAMILY,MODEL  Set CPU type for an Intel CPU based on family and model from cpuid\n"
4f63e5
+"--k8                Set the CPU to be an AMD K8\n"
4f63e5
+"--p4                Set the CPU to be an Intel Pentium4\n"
4f63e5
+"--core2             Set the CPU to be an Intel Core2\n"
4f63e5
+"--generic           Set the CPU to a generic version\n"
4f63e5
 "--cpumhz MHZ        Set CPU Mhz to decode time (output unreliable, not needed on new kernels)\n"
4f63e5
 "--raw		     (with --ascii) Dump in raw ASCII format for machine processing\n"
4f63e5
 "--daemon            Run in background waiting for events (needs newer kernel)\n"
4f63e5
+"--client            Query a currently running mcelog daemon for errors\n"
4f63e5
 "--ignorenodev       Exit silently when the device cannot be opened\n"
4f63e5
 "--file filename     With --ascii read machine check log from filename instead of stdin\n"
4f63e5
+"--logfile filename  Log decoded machine checks in file filename\n"
4f63e5
 "--syslog            Log decoded machine checks in syslog (default stdout or syslog for daemon)\n"	     
4f63e5
 "--syslog-error	     Log decoded machine checks in syslog with error level\n"
4f63e5
 "--no-syslog         Never log anything to syslog\n"
4f63e5
@@ -946,8 +972,10 @@ void usage(void)
4f63e5
 "--num-errors N      Only process N errors (for testing)\n"
4f63e5
 "--pidfile file	     Write pid of daemon into file\n"
4f63e5
 "--no-imc-log	     Disable extended iMC logging\n"
4f63e5
+"--is-cpu-supported  Exit with return code indicating whether the CPU is supported\n"
4f63e5
 		);
4f63e5
 	diskdb_usage();
4f63e5
+	printf("\n");
4f63e5
 	print_cputypes();
4f63e5
 	exit(1);
4f63e5
 }
4f63e5
@@ -980,6 +1008,7 @@ enum options {
4f63e5
 	O_PIDFILE,
4f63e5
 	O_DEBUG_NUMERRORS,
4f63e5
 	O_NO_IMC_LOG,
4f63e5
+	O_IS_CPU_SUPPORTED,
4f63e5
 };
4f63e5
 
4f63e5
 static struct option options[] = {
4f63e5
@@ -1013,6 +1042,7 @@ static struct option options[] = {
4f63e5
 	{ "pidfile", 1, NULL, O_PIDFILE },
4f63e5
 	{ "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */
4f63e5
 	{ "no-imc-log", 0, NULL, O_NO_IMC_LOG },
4f63e5
+	{ "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED },
4f63e5
 	DISKDB_OPTIONS
4f63e5
 	{}
4f63e5
 };
4f63e5
@@ -1115,6 +1145,9 @@ static int modifier(int opt)
4f63e5
 	case O_NO_IMC_LOG:
4f63e5
 		imc_log = 0;
4f63e5
 		break;
4f63e5
+	case O_IS_CPU_SUPPORTED:
4f63e5
+		check_only = 1;
4f63e5
+		break;
4f63e5
 	case 0:
4f63e5
 		break;
4f63e5
 	default:
4f63e5
@@ -1344,15 +1377,19 @@ int main(int ac, char **av)
4f63e5
 
4f63e5
 	/* before doing anything else let's see if the CPUs are supported */
4f63e5
 	if (!cpu_forced && !is_cpu_supported()) {
4f63e5
-		fprintf(stderr, "CPU is unsupported\n");
4f63e5
+		if (!check_only)
4f63e5
+			fprintf(stderr, "CPU is unsupported\n");
4f63e5
 		exit(1);
4f63e5
 	}
4f63e5
+	if (check_only)
4f63e5
+		exit(0);
4f63e5
 
4f63e5
 	/* If the user didn't tell us not to use iMC logging, check if CPU supports it */
4f63e5
 	if (imc_log == -1) {
4f63e5
 		switch (cputype) {
4f63e5
 		case CPU_SANDY_BRIDGE_EP:
4f63e5
 		case CPU_IVY_BRIDGE_EPEX:
4f63e5
+		case CPU_HASWELL_EPEX:
4f63e5
 			imc_log = 1;
4f63e5
 			break;
4f63e5
 		default:
4f63e5
diff -urNp mcelog-d2e13bf0.orig/mcelog.conf mcelog-d2e13bf0/mcelog.conf
4f63e5
--- mcelog-d2e13bf0.orig/mcelog.conf	2016-05-14 08:34:40.445108236 -0400
4f63e5
+++ mcelog-d2e13bf0/mcelog.conf	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -23,7 +23,7 @@
4f63e5
 # If this value is set incorrectly the decoded output will be likely incorrect.
4f63e5
 # By default when this parameter is not set mcelog uses the CPU it is running on
4f63e5
 # on very new kernels the mcelog events reported by the kernel also carry
4f63e5
-# the CPU type which is used too when available and not overriden.
4f63e5
+# the CPU type which is used too when available and not overridden.
4f63e5
 
4f63e5
 # Enable daemon mode:
4f63e5
 #daemon = yes
4f63e5
@@ -132,7 +132,7 @@ mem-ce-error-trigger = socket-memory-err
4f63e5
 
4f63e5
 mem-ce-error-threshold = 100 / 24h
4f63e5
 
4f63e5
-#  Log socket error threshold explicitely?
4f63e5
+#  Log socket error threshold explicitly?
4f63e5
 mem-ce-error-log = yes
4f63e5
 
4f63e5
 # Trigger script for uncorrected bus error events
4f63e5
@@ -148,7 +148,7 @@ unknown-threshold-trigger = unknown-erro
4f63e5
 # Processing of cache error thresholds reported by Intel CPUs.
4f63e5
 cache-threshold-trigger = cache-error-trigger
4f63e5
 
4f63e5
-# Should cache threshold events be logged explicitely?
4f63e5
+# Should cache threshold events be logged explicitly?
4f63e5
 cache-threshold-log = yes
4f63e5
 
4f63e5
 [page]
4f63e5
@@ -159,7 +159,7 @@ memory-ce-threshold = 10 / 24h
4f63e5
 # Trigger script for corrected errors.
4f63e5
 # memory-ce-trigger = page-error-trigger
4f63e5
 
4f63e5
-# Should page threshold events be logged explicitely?
4f63e5
+# Should page threshold events be logged explicitly?
4f63e5
 memory-ce-log = yes
4f63e5
 
4f63e5
 # specify the internal action in mcelog to exceeding a page error threshold
4f63e5
diff -urNp mcelog-d2e13bf0.orig/mcelog.conf.5 mcelog-d2e13bf0/mcelog.conf.5
4f63e5
--- mcelog-d2e13bf0.orig/mcelog.conf.5	2016-05-14 08:34:40.437107859 -0400
4f63e5
+++ mcelog-d2e13bf0/mcelog.conf.5	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -43,7 +43,7 @@ For valid values for type please see mce
4f63e5
 If this value is set incorrectly the decoded output will be likely incorrect.
4f63e5
 By default when this parameter is not set mcelog uses the CPU it is running on
4f63e5
 on very new kernels the mcelog events reported by the kernel also carry
4f63e5
-the CPU type which is used too when available and not overriden.
4f63e5
+the CPU type which is used too when available and not overridden.
4f63e5
 .PP
4f63e5
 .PP
4f63e5
 Enable daemon mode:
4f63e5
@@ -204,7 +204,7 @@ Threshold on when to trigger a correct e
4f63e5
 .B mem-ce-error-threshold = 100 / 24h
4f63e5
 .PP
4f63e5
 .PP
4f63e5
- log socket error threshold explicitely?
4f63e5
+ log socket error threshold explicitly?
4f63e5
 .PP
4f63e5
 .B mem-ce-error-log = yes
4f63e5
 .PP
4f63e5
@@ -230,7 +230,7 @@ Processing of cache error thresholds rep
4f63e5
 .B cache-threshold-trigger = cache-error-trigger
4f63e5
 .PP
4f63e5
 .PP
4f63e5
-Should cache threshold events be logged explicitely?
4f63e5
+Should cache threshold events be logged explicitly?
4f63e5
 .PP
4f63e5
 .B cache-threshold-log = yes
4f63e5
 .PP
4f63e5
@@ -246,7 +246,7 @@ Trigger script for corrected errors.
4f63e5
 memory-ce-trigger = page-error-trigger
4f63e5
 .PP
4f63e5
 .PP
4f63e5
-Should page threshold events be logged explicitely?
4f63e5
+Should page threshold events be logged explicitly?
4f63e5
 .PP
4f63e5
 .B memory-ce-log = yes
4f63e5
 .PP
4f63e5
diff -urNp mcelog-d2e13bf0.orig/mcelog.h mcelog-d2e13bf0/mcelog.h
4f63e5
--- mcelog-d2e13bf0.orig/mcelog.h	2016-05-14 08:34:40.446108283 -0400
4f63e5
+++ mcelog-d2e13bf0/mcelog.h	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -124,8 +124,12 @@ enum cputype {
4f63e5
 	CPU_HASWELL,
4f63e5
 	CPU_HASWELL_EPEX,
4f63e5
 	CPU_BROADWELL,
4f63e5
+	CPU_BROADWELL_DE,
4f63e5
+	CPU_BROADWELL_EPEX,
4f63e5
 	CPU_KNIGHTS_LANDING,
4f63e5
 	CPU_ATOM,
4f63e5
+	CPU_SKYLAKE,
4f63e5
+	CPU_SKYLAKE_XEON,
4f63e5
 };
4f63e5
 
4f63e5
 enum option_ranges {
4f63e5
diff -urNp mcelog-d2e13bf0.orig/memdb.c mcelog-d2e13bf0/memdb.c
4f63e5
--- mcelog-d2e13bf0.orig/memdb.c	2016-05-14 08:34:40.437107859 -0400
4f63e5
+++ mcelog-d2e13bf0/memdb.c	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -379,6 +379,14 @@ parse_dimm_addr(char *bl, unsigned *sock
4f63e5
 		   channel, dimm) == 3)
4f63e5
 		return 1;
4f63e5
 	/* Add more DMI formats here */
4f63e5
+	/* For new AMI BIOS Node0_Bank0 */
4f63e5
+	if (sscanf(bl, "Node%u_Bank%u", socketid, dimm) == 2)
4f63e5
+		return 1;
4f63e5
+
4f63e5
+	/* For old AMI BIOS A1_BANK0*/
4f63e5
+	if (sscanf(bl, "A%u_BANK%u", socketid, dimm) == 2)
4f63e5
+		return 1;
4f63e5
+
4f63e5
 	return 0;		
4f63e5
 }
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/msr.c mcelog-d2e13bf0/msr.c
4f63e5
--- mcelog-d2e13bf0.orig/msr.c	2016-05-14 08:34:40.438107906 -0400
4f63e5
+++ mcelog-d2e13bf0/msr.c	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -20,27 +20,28 @@ static void domsr(int cpu, int msr, int
4f63e5
 			return;
4f63e5
 		default:
4f63e5
 			SYSERRprintf("Cannot open %s to set imc_log\n", fpath);
4f63e5
-			exit(1);
4f63e5
+			return;
4f63e5
 		}
4f63e5
 	}
4f63e5
 	if (pread(fd, &data, sizeof data, msr) != sizeof data) {
4f63e5
 		SYSERRprintf("Cannot read MSR_ERROR_CONTROL from %s\n", fpath);
4f63e5
-		exit(1);
4f63e5
+		return;
4f63e5
 	}
4f63e5
 	data |= bit;
4f63e5
 	if (pwrite(fd, &data, sizeof data, msr) != sizeof data) {
4f63e5
 		SYSERRprintf("Cannot write MSR_ERROR_CONTROL to %s\n", fpath);
4f63e5
-		exit(1);
4f63e5
+		return;
4f63e5
 	}
4f63e5
 	if (pread(fd, &data, sizeof data, msr) != sizeof data) {
4f63e5
 		SYSERRprintf("Cannot re-read MSR_ERROR_CONTROL from %s\n", fpath);
4f63e5
-		exit(1);
4f63e5
+		return;
4f63e5
 	}
4f63e5
 	if ((data & bit) == 0)
4f63e5
 		Lprintf("No DIMM detection available on cpu %d (normal in virtual environments)\n", cpu);
4f63e5
 	close(fd);
4f63e5
 }
4f63e5
 
4f63e5
+/* XXX: assumes all CPUs are already onlined. */
4f63e5
 void set_imc_log(int cputype)
4f63e5
 {
4f63e5
 	int cpu, ncpus = sysconf(_SC_NPROCESSORS_CONF);
4f63e5
@@ -49,6 +50,7 @@ void set_imc_log(int cputype)
4f63e5
 	switch (cputype) {
4f63e5
 	case CPU_SANDY_BRIDGE_EP:
4f63e5
 	case CPU_IVY_BRIDGE_EPEX:
4f63e5
+	case CPU_HASWELL_EPEX:
4f63e5
 		msr = 0x17f;	/* MSR_ERROR_CONTROL */
4f63e5
 		bit = 0x2;	/* MemError Log Enable */
4f63e5
 		break;
4f63e5
diff -urNp mcelog-d2e13bf0.orig/nehalem.c mcelog-d2e13bf0/nehalem.c
4f63e5
--- mcelog-d2e13bf0.orig/nehalem.c	2016-05-14 08:34:40.438107906 -0400
4f63e5
+++ mcelog-d2e13bf0/nehalem.c	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -124,13 +124,17 @@ static char *mmm_desc[] = {
4f63e5
 	"Reserved 7"
4f63e5
 };
4f63e5
 
4f63e5
-void decode_memory_controller(u32 status)
4f63e5
+void decode_memory_controller(u32 status, u8 bank)
4f63e5
 {
4f63e5
 	char channel[30];
4f63e5
 	if ((status & 0xf) == 0xf) 
4f63e5
 		strcpy(channel, "unspecified"); 
4f63e5
-	else
4f63e5
-		sprintf(channel, "%u", status & 0xf);
4f63e5
+	else {
4f63e5
+		if (cputype == CPU_KNIGHTS_LANDING) /* Fix for Knights Landing MIC */
4f63e5
+			sprintf(channel, "%u", (status & 0xf) + 3 * (bank == 15));
4f63e5
+		else
4f63e5
+			sprintf(channel, "%u", status & 0xf);
4f63e5
+	}
4f63e5
 	Wprintf("MEMORY CONTROLLER %s_CHANNEL%s_ERR\n", 
4f63e5
 		mmm_mnemonic[(status >> 4) & 7],
4f63e5
 		channel);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/nehalem.h mcelog-d2e13bf0/nehalem.h
4f63e5
--- mcelog-d2e13bf0.orig/nehalem.h	2016-05-14 08:34:40.438107906 -0400
4f63e5
+++ mcelog-d2e13bf0/nehalem.h	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -1,4 +1,4 @@
4f63e5
 void nehalem_decode_model(u64 status, u64 misc);
4f63e5
 void xeon75xx_decode_model(struct mce *m, unsigned msize);
4f63e5
-void decode_memory_controller(u32 status);
4f63e5
+void decode_memory_controller(u32 status, u8 bank);
4f63e5
 void nehalem_memerr_misc(struct mce *m, int *channel, int *dimm);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/p4.c mcelog-d2e13bf0/p4.c
4f63e5
--- mcelog-d2e13bf0.orig/p4.c	2016-05-14 08:34:40.444108189 -0400
4f63e5
+++ mcelog-d2e13bf0/p4.c	2016-05-14 08:34:58.872975199 -0400
4f63e5
@@ -36,6 +36,9 @@
4f63e5
 #include "sandy-bridge.h"
4f63e5
 #include "ivy-bridge.h"
4f63e5
 #include "haswell.h"
4f63e5
+#include "broadwell_de.h"
4f63e5
+#include "broadwell_epex.h"
4f63e5
+#include "skylake_xeon.h"
4f63e5
 
4f63e5
 /* decode mce for P4/Xeon and Core2 family */
4f63e5
 
4f63e5
@@ -52,7 +55,7 @@ static char* get_TT_str(__u8 t)
4f63e5
 static char* get_LL_str(__u8 ll)
4f63e5
 {
4f63e5
 	static char* LL[] = {"Level-0", "Level-1", "Level-2", "Level-3"};
4f63e5
-	if (ll > NELE(LL)) {
4f63e5
+	if (ll >= NELE(LL)) {
4f63e5
 		return "UNKNOWN";
4f63e5
 	}
4f63e5
 
4f63e5
@@ -118,7 +121,8 @@ static char* get_II_str(__u8 i)
4f63e5
 	return II[i];
4f63e5
 }
4f63e5
 
4f63e5
-static int decode_mca(u64 status, u64 misc, u64 track, int cpu, int *ismemerr, int socket)
4f63e5
+static int decode_mca(u64 status, u64 misc, u64 track, int cpu, int *ismemerr, int socket,
4f63e5
+			u8 bank)
4f63e5
 {
4f63e5
 #define TLB_LL_MASK      0x3  /*bit 0, bit 1*/
4f63e5
 #define TLB_LL_SHIFT     0x0
4f63e5
@@ -231,7 +235,7 @@ static int decode_mca(u64 status, u64 mi
4f63e5
 			run_iomca_trigger(socket, cpu, seg, bus, dev, fn);
4f63e5
 		}
4f63e5
 	} else if (test_prefix(7, mca)) {
4f63e5
-		decode_memory_controller(mca);
4f63e5
+		decode_memory_controller(mca, bank);
4f63e5
 		*ismemerr = 1;
4f63e5
 	} else {
4f63e5
 		Wprintf("Unknown Error %x\n", mca);
4f63e5
@@ -286,7 +290,7 @@ static const char *arstate[4] = {
4f63e5
 };
4f63e5
 
4f63e5
 static int decode_mci(__u64 status, __u64 misc, int cpu, unsigned mcgcap, int *ismemerr,
4f63e5
-		       int socket)
4f63e5
+		       int socket, __u8 bank)
4f63e5
 {
4f63e5
 	u64 track = 0;
4f63e5
 
4f63e5
@@ -326,7 +330,7 @@ static int decode_mci(__u64 status, __u6
4f63e5
 		decode_tracking(track);
4f63e5
 	}
4f63e5
 	Wprintf("MCA: ");
4f63e5
-	return decode_mca(status, misc, track, cpu, ismemerr, socket);
4f63e5
+	return decode_mca(status, misc, track, cpu, ismemerr, socket, bank);
4f63e5
 }
4f63e5
 
4f63e5
 static void decode_mcg(__u64 mcgstatus)
4f63e5
@@ -368,7 +372,7 @@ void decode_intel_mc(struct mce *log, in
4f63e5
 
4f63e5
 	decode_mcg(log->mcgstatus);
4f63e5
 	if (decode_mci(log->status, log->misc, cpu, log->mcgcap, ismemerr,
4f63e5
-		socket))
4f63e5
+		socket, log->bank))
4f63e5
 		run_unknown_trigger(socket, cpu, log);
4f63e5
 
4f63e5
 	if (test_prefix(11, (log->status & 0xffffL))) {
4f63e5
@@ -415,6 +419,15 @@ void decode_intel_mc(struct mce *log, in
4f63e5
 	case CPU_HASWELL_EPEX:
4f63e5
 		hsw_decode_model(cputype, log->bank, log->status, log->misc);
4f63e5
 		break;
4f63e5
+	case CPU_BROADWELL_DE:
4f63e5
+		bdw_de_decode_model(cputype, log->bank, log->status, log->misc);
4f63e5
+		break;
4f63e5
+	case CPU_BROADWELL_EPEX:
4f63e5
+		bdw_epex_decode_model(cputype, log->bank, log->status, log->misc);
4f63e5
+		break;
4f63e5
+	case CPU_SKYLAKE_XEON:
4f63e5
+		skylake_s_decode_model(cputype, log->bank, log->status, log->misc);
4f63e5
+		break;
4f63e5
 	}
4f63e5
 }
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/skylake_xeon.c mcelog-d2e13bf0/skylake_xeon.c
4f63e5
--- mcelog-d2e13bf0.orig/skylake_xeon.c	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/skylake_xeon.c	2016-05-14 08:35:00.556054382 -0400
4f63e5
@@ -0,0 +1,210 @@
4f63e5
+/* Copyright (C) 2016 Intel Corporation
4f63e5
+   Decode Intel Skylake specific machine check errors.
4f63e5
+
4f63e5
+   mcelog is free software; you can redistribute it and/or
4f63e5
+   modify it under the terms of the GNU General Public
4f63e5
+   License as published by the Free Software Foundation; version
4f63e5
+   2.
4f63e5
+
4f63e5
+   mcelog is distributed in the hope that it will be useful,
4f63e5
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
4f63e5
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4f63e5
+   General Public License for more details.
4f63e5
+
4f63e5
+   You should find a copy of v2 of the GNU General Public License somewhere
4f63e5
+   on your Linux system; if not, write to the Free Software Foundation,
4f63e5
+   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4f63e5
+
4f63e5
+   Author: Tony Luck
4f63e5
+*/
4f63e5
+
4f63e5
+#include "mcelog.h"
4f63e5
+#include "bitfield.h"
4f63e5
+#include "skylake_xeon.h"
4f63e5
+#include "memdb.h"
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-27 */
4f63e5
+
4f63e5
+static char *pcu_1[] = {
4f63e5
+	[0x00] = "No Error",
4f63e5
+	[0x0d] = "MCA_DMI_TRAINING_TIMEOUT",
4f63e5
+	[0x0f] = "MCA_DMI_CPU_RESET_ACK_TIMEOUT",
4f63e5
+	[0x10] = "MCA_MORE_THAN_ONE_LT_AGENT",
4f63e5
+	[0x1e] = "MCA_BIOS_RST_CPL_INVALID_SEQ",
4f63e5
+	[0x1f] = "MCA_BIOS_INVALID_PKG_STATE_CONFIG",
4f63e5
+	[0x25] = "MCA_MESSAGE_CHANNEL_TIMEOUT",
4f63e5
+	[0x27] = "MCA_MSGCH_PMREQ_CMP_TIMEOUT",
4f63e5
+	[0x30] = "MCA_PKGC_DIRECT_WAKE_RING_TIMEOUT",
4f63e5
+	[0x31] = "MCA_PKGC_INVALID_RSP_PCH",
4f63e5
+	[0x33] = "MCA_PKGC_WATCHDOG_HANG_CBZ_DOWN",
4f63e5
+	[0x34] = "MCA_PKGC_WATCHDOG_HANG_CBZ_UP",
4f63e5
+	[0x38] = "MCA_PKGC_WATCHDOG_HANG_C3_UP_SF",
4f63e5
+	[0x40] = "MCA_SVID_VCCIN_VR_ICC_MAX_FAILURE",
4f63e5
+	[0x41] = "MCA_SVID_COMMAND_TIMEOUT",
4f63e5
+	[0x42] = "MCA_SVID_VCCIN_VR_VOUT_FAILURE",
4f63e5
+	[0x43] = "MCA_SVID_CPU_VR_CAPABILITY_ERROR",
4f63e5
+	[0x44] = "MCA_SVID_CRITICAL_VR_FAILED",
4f63e5
+	[0x45] = "MCA_SVID_SA_ITD_ERROR",
4f63e5
+	[0x46] = "MCA_SVID_READ_REG_FAILED",
4f63e5
+	[0x47] = "MCA_SVID_WRITE_REG_FAILED",
4f63e5
+	[0x48] = "MCA_SVID_PKGC_INIT_FAILED",
4f63e5
+	[0x49] = "MCA_SVID_PKGC_CONFIG_FAILED",
4f63e5
+	[0x4a] = "MCA_SVID_PKGC_REQUEST_FAILED",
4f63e5
+	[0x4b] = "MCA_SVID_IMON_REQUEST_FAILED",
4f63e5
+	[0x4c] = "MCA_SVID_ALERT_REQUEST_FAILED",
4f63e5
+	[0x4d] = "MCA_SVID_MCP_VR_ABSENT_OR_RAMP_ERROR",
4f63e5
+	[0x4e] = "MCA_SVID_UNEXPECTED_MCP_VR_DETECTED",
4f63e5
+	[0x51] = "MCA_FIVR_CATAS_OVERVOL_FAULT",
4f63e5
+	[0x52] = "MCA_FIVR_CATAS_OVERCUR_FAULT",
4f63e5
+	[0x58] = "MCA_WATCHDOG_TIMEOUT_PKGC_SLAVE",
4f63e5
+	[0x59] = "MCA_WATCHDOG_TIMEOUT_PKGC_MASTER",
4f63e5
+	[0x5a] = "MCA_WATCHDOG_TIMEOUT_PKGS_MASTER",
4f63e5
+	[0x61] = "MCA_PKGS_CPD_UNCPD_TIMEOUT",
4f63e5
+	[0x63] = "MCA_PKGS_INVALID_REQ_PCH",
4f63e5
+	[0x64] = "MCA_PKGS_INVALID_REQ_INTERNAL",
4f63e5
+	[0x65] = "MCA_PKGS_INVALID_RSP_INTERNAL",
4f63e5
+	[0x6b] = "MCA_PKGS_SMBUS_VPP_PAUSE_TIMEOUT",
4f63e5
+	[0x81] = "MCA_RECOVERABLE_DIE_THERMAL_TOO_HOT",
4f63e5
+};
4f63e5
+
4f63e5
+static struct field pcu_mc4[] = {
4f63e5
+	FIELD(24, pcu_1),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-28 */
4f63e5
+
4f63e5
+static char *qpi[] = {
4f63e5
+	[0x00] = "UC Phy Initialization Failure",
4f63e5
+	[0x01] = "UC Phy detected drift buffer alarm",
4f63e5
+	[0x02] = "UC Phy detected latency buffer rollover",
4f63e5
+	[0x10] = "UC LL Rx detected CRC error: unsuccessful LLR: entered abort state",
4f63e5
+	[0x11] = "UC LL Rx unsupported or undefined packet",
4f63e5
+	[0x12] = "UC LL or Phy control error",
4f63e5
+	[0x13] = "UC LL Rx parameter exchange exception",
4f63e5
+	[0x1F] = "UC LL detected control error from the link-mesh interface",
4f63e5
+	[0x20] = "COR Phy initialization abort",
4f63e5
+	[0x21] = "COR Phy reset",
4f63e5
+	[0x22] = "COR Phy lane failure, recovery in x8 width",
4f63e5
+	[0x23] = "COR Phy L0c error corrected without Phy reset",
4f63e5
+	[0x24] = "COR Phy L0c error triggering Phy Reset",
4f63e5
+	[0x25] = "COR Phy L0p exit error corrected with Phy reset",
4f63e5
+	[0x30] = "COR LL Rx detected CRC error - successful LLR without Phy Reinit",
4f63e5
+	[0x31] = "COR LL Rx detected CRC error - successful LLR with Phy Reinit",
4f63e5
+};
4f63e5
+
4f63e5
+static struct field qpi_mc[] = {
4f63e5
+	FIELD(16, qpi),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* These apply to MSCOD 0x12 "UC LL or Phy control error" */
4f63e5
+static struct field qpi_0x12[] = {
4f63e5
+	SBITFIELD(22, "Phy Control Error"),
4f63e5
+	SBITFIELD(23, "Unexpected Retry.Ack flit"),
4f63e5
+	SBITFIELD(24, "Unexpected Retry.Req flit"),
4f63e5
+	SBITFIELD(25, "RF parity error"),
4f63e5
+	SBITFIELD(26, "Routeback Table error"),
4f63e5
+	SBITFIELD(27, "unexpected Tx Protocol flit (EOP, Header or Data)"),
4f63e5
+	SBITFIELD(28, "Rx Header-or-Credit BGF credit overflow/underflow"),
4f63e5
+	SBITFIELD(29, "Link Layer Reset still in progress when Phy enters L0"),
4f63e5
+	SBITFIELD(30, "Link Layer reset initiated while protocol traffic not idle"),
4f63e5
+	SBITFIELD(31, "Link Layer Tx Parity Error"),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-29 */
4f63e5
+
4f63e5
+static struct field mc_bits[] = {
4f63e5
+	SBITFIELD(16, "Address parity error"),
4f63e5
+	SBITFIELD(17, "HA write data parity error"),
4f63e5
+	SBITFIELD(18, "HA write byte enable parity error"),
4f63e5
+	SBITFIELD(19, "Corrected patrol scrub error"),
4f63e5
+	SBITFIELD(20, "Uncorrected patrol scrub error"),
4f63e5
+	SBITFIELD(21, "Corrected spare error"),
4f63e5
+	SBITFIELD(22, "Uncorrected spare error"),
4f63e5
+	SBITFIELD(23, "Any HA read error"),
4f63e5
+	SBITFIELD(24, "WDB read parity error"),
4f63e5
+	SBITFIELD(25, "DDR4 command address parity error"),
4f63e5
+	SBITFIELD(26, "Uncorrected address parity error"),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+static char *mc_0x8xx[] = {
4f63e5
+	[0x0] = "Unrecognized request type",
4f63e5
+	[0x1] = "Read response to an invalid scoreboard entry",
4f63e5
+	[0x2] = "Unexpected read response",
4f63e5
+	[0x3] = "DDR4 completion to an invalid scoreboard entry",
4f63e5
+	[0x4] = "Completion to an invalid scoreboard entry",
4f63e5
+	[0x5] = "Completion FIFO overflow",
4f63e5
+	[0x6] = "Correctable parity error",
4f63e5
+	[0x7] = "Uncorrectable error",
4f63e5
+	[0x8] = "Interrupt received while outstanding interrupt was not ACKed",
4f63e5
+	[0x9] = "ERID FIFO overflow",
4f63e5
+	[0xa] = "Error on Write credits",
4f63e5
+	[0xb] = "Error on Read credits",
4f63e5
+	[0xc] = "Scheduler error",
4f63e5
+	[0xd] = "Error event",
4f63e5
+};
4f63e5
+
4f63e5
+static struct field memctrl_mc13[] = {
4f63e5
+	FIELD(16, mc_0x8xx),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+/* See IA32 SDM Vol3B Table 16-30 */
4f63e5
+
4f63e5
+static struct field m2m[] = {
4f63e5
+	SBITFIELD(16, "MscodDataRdErr"),
4f63e5
+	SBITFIELD(17, "Reserved"),
4f63e5
+	SBITFIELD(18, "MscodPtlWrErr"),
4f63e5
+	SBITFIELD(19, "MscodFullWrErr"),
4f63e5
+	SBITFIELD(20, "MscodBgfErr"),
4f63e5
+	SBITFIELD(21, "MscodTimeout"),
4f63e5
+	SBITFIELD(22, "MscodParErr"),
4f63e5
+	SBITFIELD(23, "MscodBucket1Err"),
4f63e5
+	{}
4f63e5
+};
4f63e5
+
4f63e5
+void skylake_s_decode_model(int cputype, int bank, u64 status, u64 misc)
4f63e5
+{
4f63e5
+	switch (bank) {
4f63e5
+	case 4:
4f63e5
+		Wprintf("PCU: ");
4f63e5
+		switch (EXTRACT(status, 0, 15) & ~(1ull << 12)) {
4f63e5
+		case 0x402: case 0x403:
4f63e5
+			Wprintf("Internal errors ");
4f63e5
+			break;
4f63e5
+		case 0x406:
4f63e5
+			Wprintf("Intel TXT errors ");
4f63e5
+			break;
4f63e5
+		case 0x407:
4f63e5
+			Wprintf("Other UBOX Internal errors ");
4f63e5
+			break;
4f63e5
+		}
4f63e5
+		if (EXTRACT(status, 16, 19))
4f63e5
+			Wprintf("PCU internal error ");
4f63e5
+		decode_bitfield(status, pcu_mc4);
4f63e5
+		break;
4f63e5
+	case 5:
4f63e5
+	case 12:
4f63e5
+	case 19:
4f63e5
+		Wprintf("QPI: ");
4f63e5
+		decode_bitfield(status, qpi_mc);
4f63e5
+		if (EXTRACT(status, 16, 21) == 0x12)
4f63e5
+			decode_bitfield(status, qpi_0x12);
4f63e5
+		break;
4f63e5
+	case 7: case 8:
4f63e5
+		Wprintf("M2M: ");
4f63e5
+		decode_bitfield(status, m2m);
4f63e5
+		break;
4f63e5
+	case 13: case 14: case 15:
4f63e5
+	case 16: case 17: case 18:
4f63e5
+		Wprintf("MemCtrl: ");
4f63e5
+		if (EXTRACT(status, 27, 27))
4f63e5
+			decode_bitfield(status, memctrl_mc13);
4f63e5
+		else
4f63e5
+			decode_bitfield(status, mc_bits);
4f63e5
+		break;
4f63e5
+	}
4f63e5
+}
4f63e5
diff -urNp mcelog-d2e13bf0.orig/skylake_xeon.h mcelog-d2e13bf0/skylake_xeon.h
4f63e5
--- mcelog-d2e13bf0.orig/skylake_xeon.h	1969-12-31 19:00:00.000000000 -0500
4f63e5
+++ mcelog-d2e13bf0/skylake_xeon.h	2016-05-14 08:35:00.557054429 -0400
4f63e5
@@ -0,0 +1 @@
4f63e5
+void skylake_s_decode_model(int cputype, int bank, u64 status, u64 misc);
4f63e5
diff -urNp mcelog-d2e13bf0.orig/trigger.c mcelog-d2e13bf0/trigger.c
4f63e5
--- mcelog-d2e13bf0.orig/trigger.c	2016-05-14 08:34:40.439107953 -0400
4f63e5
+++ mcelog-d2e13bf0/trigger.c	2016-05-14 08:35:00.557054429 -0400
4f63e5
@@ -151,14 +151,11 @@ void trigger_setup(void)
4f63e5
 
4f63e5
 void trigger_wait(void)
4f63e5
 {
4f63e5
-	int sig;
4f63e5
-	sigset_t mask;
4f63e5
-	sigemptyset(&mask);
4f63e5
-	sigaddset(&mask, SIGCHLD);
4f63e5
-	while (num_children > 0) {
4f63e5
-		if (sigwait(&mask, &sig) < 0)
4f63e5
-			SYSERRprintf("sigwait waiting for children");
4f63e5
-	}
4f63e5
+	int status;
4f63e5
+	int pid;
4f63e5
+	
4f63e5
+	while ((pid = waitpid((pid_t)-1, &status, 0)) > 0) 
4f63e5
+		finish_child(pid, status);
4f63e5
 }
4f63e5
 
4f63e5
 int trigger_check(char *s)
4f63e5
diff -urNp mcelog-d2e13bf0.orig/tsc.c mcelog-d2e13bf0/tsc.c
4f63e5
--- mcelog-d2e13bf0.orig/tsc.c	2016-05-14 08:34:40.443108142 -0400
4f63e5
+++ mcelog-d2e13bf0/tsc.c	2016-05-14 08:35:00.557054429 -0400
4f63e5
@@ -161,7 +161,7 @@ int main(void)
4f63e5
 {
4f63e5
 	char *buf;
4f63e5
 	u64 tsc = rdtscll();
4f63e5
-	printf("%Lx tsc\n", tsc);
4f63e5
+	printf("%llx tsc\n", tsc);
4f63e5
 	if (decode_tsc_current(&buf, 0, CPU_CORE2, 0.0, tsc) >= 0)
4f63e5
 		printf("%s\n", buf);
4f63e5
 	else
4f63e5
diff -urNp mcelog-d2e13bf0.orig/unknown.c mcelog-d2e13bf0/unknown.c
4f63e5
--- mcelog-d2e13bf0.orig/unknown.c	2016-05-14 08:34:40.446108283 -0400
4f63e5
+++ mcelog-d2e13bf0/unknown.c	2016-05-14 08:35:00.557054429 -0400
4f63e5
@@ -50,6 +50,9 @@ void run_unknown_trigger(int socket, int
4f63e5
 	char *msg;
4f63e5
 	char *location;
4f63e5
 
4f63e5
+	if (!unknown_trigger)
4f63e5
+		return;
4f63e5
+
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&location, "CPU %d on socket %d", cpu, socket);
4f63e5
 	else
4f63e5
@@ -58,9 +61,6 @@ void run_unknown_trigger(int socket, int
4f63e5
 	asprintf(&env[ei++], "LOCATION=%s", location);
4f63e5
 	free(location);
4f63e5
 
4f63e5
-	if (!unknown_trigger)
4f63e5
-		goto out;
4f63e5
-
4f63e5
 	if (socket >= 0)
4f63e5
 		asprintf(&env[ei++], "SOCKETID=%d", socket);
4f63e5
 	asprintf(&env[ei++], "MESSAGE=%s", msg);
4f63e5
@@ -76,7 +76,6 @@ void run_unknown_trigger(int socket, int
4f63e5
 	run_trigger(unknown_trigger, NULL, env);
4f63e5
 	for (i = 0; i < ei; i++)
4f63e5
 		free(env[i]);
4f63e5
-out:
4f63e5
 	free(msg);
4f63e5
 }
4f63e5
 
4f63e5
diff -urNp mcelog-d2e13bf0.orig/version.h mcelog-d2e13bf0/version.h
4f63e5
--- mcelog-d2e13bf0.orig/version.h	2016-05-14 08:34:40.444108189 -0400
4f63e5
+++ mcelog-d2e13bf0/version.h	2016-05-14 08:35:00.557054429 -0400
4f63e5
@@ -1,2 +1,3 @@
4f63e5
-#define MCELOG_VERSION "1.0pre"
4f63e5
+extern char version[];
4f63e5
+#define MCELOG_VERSION version
4f63e5