Blame SOURCES/mcelog-update-94d853b2ea81.patch

bb432d
diff -urNp mcelog-d2e13bf0.orig/broadwell_epex.c mcelog-d2e13bf0/broadwell_epex.c
bb432d
--- mcelog-d2e13bf0.orig/broadwell_epex.c	2016-11-30 11:23:54.542909636 -0500
bb432d
+++ mcelog-d2e13bf0/broadwell_epex.c	2016-11-30 11:24:12.203619329 -0500
bb432d
@@ -23,6 +23,11 @@
bb432d
 #include "broadwell_epex.h"
bb432d
 #include "memdb.h"
bb432d
 
bb432d
+/* Memory error was corrected by mirroring with channel failover */
bb432d
+#define BDW_MCI_MISC_FO      (1ULL<<41)
bb432d
+/* Memory error was corrected by mirroring and primary channel scrubbed successfully */
bb432d
+#define BDW_MCI_MISC_MC      (1ULL<<42)
bb432d
+
bb432d
 /* See IA32 SDM Vol3B Table 16-20 */
bb432d
 
bb432d
 static char *pcu_1[] = {
bb432d
@@ -147,3 +152,23 @@ void bdw_epex_decode_model(int cputype,
bb432d
 		break;
bb432d
 	}
bb432d
 }
bb432d
+
bb432d
+/*
bb432d
+ * return: 0 - CE by normal ECC
bb432d
+ *         1 - CE by mirroring with channel failover
bb432d
+ *         2 - CE by mirroring and primary channel scrubbed successfully
bb432d
+ */
bb432d
+int bdw_epex_ce_type(int bank, u64 status, u64 misc)
bb432d
+{
bb432d
+	if (!(bank == 7 || bank == 8))
bb432d
+		return 0;
bb432d
+
bb432d
+	if (status & MCI_STATUS_MISCV) {
bb432d
+		if (misc & BDW_MCI_MISC_FO)
bb432d
+			return 1;
bb432d
+		if (misc & BDW_MCI_MISC_MC)
bb432d
+			return 2;
bb432d
+	}
bb432d
+
bb432d
+	return 0;
bb432d
+}
bb432d
diff -urNp mcelog-d2e13bf0.orig/broadwell_epex.h mcelog-d2e13bf0/broadwell_epex.h
bb432d
--- mcelog-d2e13bf0.orig/broadwell_epex.h	2016-11-30 11:23:54.542909636 -0500
bb432d
+++ mcelog-d2e13bf0/broadwell_epex.h	2016-11-30 11:24:12.203619329 -0500
bb432d
@@ -1 +1,2 @@
bb432d
 void bdw_epex_decode_model(int cputype, int bank, u64 status, u64 misc);
bb432d
+int bdw_epex_ce_type(int bank, u64 status, u64 misc);
bb432d
diff -urNp mcelog-d2e13bf0.orig/client.c mcelog-d2e13bf0/client.c
bb432d
--- mcelog-d2e13bf0.orig/client.c	2016-11-30 11:23:54.530909154 -0500
bb432d
+++ mcelog-d2e13bf0/client.c	2016-11-30 11:24:12.203619329 -0500
bb432d
@@ -67,3 +67,11 @@ void ask_server(char *command)
bb432d
 
bb432d
 	SYSERRprintf("client read");
bb432d
 }
bb432d
+
bb432d
+void client_cleanup(void)
bb432d
+{
bb432d
+	char *path = config_string("server", "socket-path");
bb432d
+	if (!path)
bb432d
+		path = SOCKET_PATH;
bb432d
+	unlink(path);
bb432d
+}
bb432d
diff -urNp mcelog-d2e13bf0.orig/client.h mcelog-d2e13bf0/client.h
bb432d
--- mcelog-d2e13bf0.orig/client.h	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/client.h	2016-11-30 11:24:12.203619329 -0500
bb432d
@@ -1 +1,2 @@
bb432d
 void ask_server(char *command);
bb432d
+void client_cleanup(void);
bb432d
diff -urNp mcelog-d2e13bf0.orig/db.c mcelog-d2e13bf0/db.c
bb432d
--- mcelog-d2e13bf0.orig/db.c	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/db.c	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,599 +0,0 @@
bb432d
-/* Copyright (C) 2006 Andi Kleen, SuSE Labs.
bb432d
-   Dumb database manager.
bb432d
-   not suitable for large datasets, but human readable files and simple.
bb432d
-   assumes groups and entries-per-group are max low double digits.
bb432d
-   the in memory presentation could be easily optimized with a few
bb432d
-   hashes, but that shouldn't be needed for now.
bb432d
-   Note: obsolete, new design uses in memory databases only
bb432d
-
bb432d
-   mcelog is free software; you can redistribute it and/or
bb432d
-   modify it under the terms of the GNU General Public
bb432d
-   License as published by the Free Software Foundation; version
bb432d
-   2.
bb432d
-
bb432d
-   mcelog is distributed in the hope that it will be useful,
bb432d
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
bb432d
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
bb432d
-   General Public License for more details.
bb432d
-
bb432d
-   You should find a copy of v2 of the GNU General Public License somewhere
bb432d
-   on your Linux system; if not, write to the Free Software Foundation, 
bb432d
-   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
bb432d
-
bb432d
-/* TBD:
bb432d
-   add lock file to protect final rename
bb432d
-   timeout for locks
bb432d
-*/
bb432d
-
bb432d
-#define _GNU_SOURCE 1
bb432d
-#include <stdio.h>
bb432d
-#include <ctype.h>
bb432d
-#include <string.h>
bb432d
-#include <errno.h>
bb432d
-#include <stdlib.h>
bb432d
-#include <unistd.h>
bb432d
-#include <stdarg.h>
bb432d
-#include <sys/fcntl.h>
bb432d
-#include <sys/file.h>
bb432d
-#include <assert.h>
bb432d
-
bb432d
-#include "db.h"
bb432d
-#include "memutil.h"
bb432d
-
bb432d
-/* file format
bb432d
-
bb432d
-# comment
bb432d
-[group1]
bb432d
-entry1: value
bb432d
-entry2: value
bb432d
-
bb432d
-# comment
bb432d
-# comment2
bb432d
-[group2]
bb432d
-entry: value
bb432d
-
bb432d
-value is anything before new line, but first will be skipped
bb432d
-spaces are allowed in entry names or groups
bb432d
-comments are preserved, but moved in front of the group
bb432d
-blank lines allowed.
bb432d
-
bb432d
-code doesnt check for unique records/entries right now. first wins.
bb432d
-
bb432d
-*/
bb432d
-
bb432d
-struct entry { 
bb432d
-	char *name;
bb432d
-	char *val;
bb432d
-};
bb432d
-	
bb432d
-struct group {
bb432d
-	struct group *next;
bb432d
-	char *name;
bb432d
-	struct entry *entries;
bb432d
-	char *comment;
bb432d
-	int numentries;
bb432d
-};	
bb432d
-
bb432d
-#define ENTRY_CHUNK (128 / sizeof(struct entry))
bb432d
-
bb432d
-struct database {
bb432d
-	struct group *groups;
bb432d
-	FILE *fh;
bb432d
-	char *fn;
bb432d
-	int dirty;
bb432d
-}; 	
bb432d
-
bb432d
-static int read_db(struct database *db);
bb432d
-static FILE *open_file(char *fn, int wr);
bb432d
-static void free_group(struct group *g);
bb432d
-
bb432d
-static void DBerror(char *fmt, ...)
bb432d
-{
bb432d
-	va_list ap;
bb432d
-	va_start(ap,fmt);
bb432d
-	vfprintf(stderr, fmt, ap);
bb432d
-	va_end(ap);
bb432d
-	exit(1);
bb432d
-}
bb432d
-
bb432d
-#define DB_NEW(p) ((p) = xalloc(sizeof(*(p))))
bb432d
-
bb432d
-static struct group *alloc_group(char *name)
bb432d
-{
bb432d
-	struct group *g;
bb432d
-	DB_NEW(g);
bb432d
-	g->entries = xalloc(ENTRY_CHUNK * sizeof(struct entry));
bb432d
-	g->name = name;
bb432d
-	return g;
bb432d
-}
bb432d
-
bb432d
-static char *cleanline(char *s)
bb432d
-{
bb432d
-	char *p;
bb432d
-	while (isspace(*s))
bb432d
-		s++;
bb432d
-	if (*s == 0)
bb432d
-		return NULL;
bb432d
-	p = strchr(s, '\n');
bb432d
-	if (p)
bb432d
-		*p = 0;
bb432d
-	return s;	
bb432d
-}
bb432d
-
bb432d
-struct database *open_db(char *fn, int wr)
bb432d
-{
bb432d
-	struct database *db;
bb432d
-
bb432d
-	DB_NEW(db);
bb432d
-	db->fh = open_file(fn, wr);
bb432d
-	if (!db->fh) {
bb432d
-		DBerror("Cannot open database %s\n", fn);
bb432d
-		free(db);
bb432d
-		return NULL;
bb432d
-	}
bb432d
-	db->fn = xstrdup(fn);
bb432d
-	if (read_db(db) < 0) {
bb432d
-		free(db->fn);
bb432d
-		free(db);
bb432d
-		return NULL;
bb432d
-	}
bb432d
-	return db;
bb432d
-}
bb432d
-
bb432d
-static int read_db(struct database *db)
bb432d
-{
bb432d
-	char *line = NULL;
bb432d
-	size_t linesz = 0;
bb432d
-	struct group *group = NULL, **pgroup = &db->groups;
bb432d
-	int linenr = 0;
bb432d
-
bb432d
-	while (getline(&line, &linesz, db->fh) > 0) {
bb432d
-		char *s;
bb432d
-		s = strchr(line, '#');
bb432d
-		if (s) {
bb432d
-			struct group *cmt;
bb432d
-			DB_NEW(cmt);
bb432d
-			*pgroup = cmt;
bb432d
-			pgroup = &cmt->next;
bb432d
-			cmt->comment = xstrdup(s + 1);
bb432d
-			*s = 0;
bb432d
-		} 	
bb432d
-		s = cleanline(line);
bb432d
-		linenr++;
bb432d
-		if (!s) 	
bb432d
-			continue;
bb432d
-		if (*s == '[') {
bb432d
-			int n;
bb432d
-			char *name;
bb432d
-			++s;
bb432d
-			n = strcspn(s, "]");
bb432d
-			if (s[n] == 0)
bb432d
-				goto parse_error;
bb432d
-			name = xalloc(n + 1);
bb432d
-			memcpy(name, s, n);
bb432d
-			group = alloc_group(name);
bb432d
-			*pgroup = group;
bb432d
-			pgroup = &group->next;
bb432d
-		} else {
bb432d
-			char *p;
bb432d
-			if (!group)
bb432d
-				goto parse_error;
bb432d
-			p = s + strcspn(s, ":");
bb432d
-			if (*p != ':')
bb432d
-				goto parse_error;
bb432d
-			*p++ = 0;
bb432d
-			if (*p == ' ')
bb432d
-				p++;
bb432d
-			else
bb432d
-				goto parse_error;
bb432d
-			change_entry(db, group, line, p);
bb432d
-		}
bb432d
-	}								
bb432d
-
bb432d
-	if (ferror(db->fh)) {
bb432d
-		DBerror("IO error while reading database %s: %s\n", db->fn,
bb432d
-			strerror(errno));
bb432d
-		goto error;
bb432d
-	}	
bb432d
-		
bb432d
-	free(line);
bb432d
-	return 0;
bb432d
-
bb432d
-parse_error:
bb432d
-	DBerror("Parse error in database %s at line %d\n", db->fn, linenr);
bb432d
-error: 	
bb432d
-	free(line);
bb432d
-	return -1;
bb432d
-}
bb432d
-
bb432d
-/*
bb432d
-Crash safety strategy:
bb432d
-
bb432d
-While the database is opened hold a exclusive flock on the file
bb432d
-When writing write to a temporary file (.out).  Only when the file
bb432d
-is written rename to another temporary file (.complete).
bb432d
-
bb432d
-Then sync and swap tmp file with main file, then sync directory
bb432d
-(later is linux specific)
bb432d
-
bb432d
-During open if the main file doesn't exist and a .complete file does
bb432d
-rename the .complete file to main first; or open the .complete
bb432d
-file if the file system is read only.
bb432d
-
bb432d
-*/
bb432d
-
bb432d
-/* Flush directory. Useful on ext2, on journaling file systems
bb432d
-   the later fsync would usually force earlier transactions on the
bb432d
-   metadata too. */
bb432d
-static int flush_dir(char *fn)
bb432d
-{
bb432d
-	int err, fd;
bb432d
-	char *p;
bb432d
-	char dir[strlen(fn) + 1];
bb432d
-	strcpy(dir, fn);
bb432d
-	p = strrchr(dir, '/');
bb432d
-	if (p)
bb432d
-		*p = 0;
bb432d
-	else
bb432d
-		strcpy(dir, ".");
bb432d
-	fd = open(dir, O_DIRECTORY|O_RDONLY);
bb432d
-	if (fd < 0)
bb432d
-		return -1;
bb432d
-	err = 0;
bb432d
-	if (fsync(fd) < 0)
bb432d
-		err = -1;
bb432d
-	if (close(fd) < 0)
bb432d
-		err = -1;
bb432d
-	return err;
bb432d
-}
bb432d
-
bb432d
-static int force_rename(char *a, char *b)
bb432d
-{
bb432d
-	unlink(b); /* ignore error */
bb432d
-	return rename(a, b);
bb432d
-}
bb432d
-
bb432d
-static int rewrite_db(struct database *db)
bb432d
-{
bb432d
-	FILE *fhtmp;
bb432d
-	int err;
bb432d
-
bb432d
-	int tmplen = strlen(db->fn) + 10;
bb432d
-	char fn_complete[tmplen], fn_old[tmplen], fn_out[tmplen];
bb432d
-
bb432d
-	sprintf(fn_complete, "%s.complete", db->fn);
bb432d
-	sprintf(fn_old, "%s~", db->fn);
bb432d
-	sprintf(fn_out, "%s.out", db->fn);
bb432d
-
bb432d
-	fhtmp = fopen(fn_out, "w");
bb432d
-	if (!fhtmp) {
bb432d
-		DBerror("Cannot open `%s' output file: %s\n", fn_out,
bb432d
-			strerror(errno));
bb432d
-		return -1;
bb432d
-	}	
bb432d
-	
bb432d
-	dump_database(db, fhtmp);
bb432d
-	
bb432d
-	err = 0;
bb432d
-	/* Finish the output file */
bb432d
-	if (ferror(fhtmp) || fflush(fhtmp) != 0 || fsync(fileno(fhtmp)) != 0 ||
bb432d
-	    fclose(fhtmp))
bb432d
-		err = -1;
bb432d
-	/* Rename to .complete */	
bb432d
-	else if (force_rename(fn_out, fn_complete))
bb432d
-		err = -1;
bb432d
-	/* RED-PEN: need to do retry for race */	
bb432d
-	/* Move to final name */
bb432d
-	else if (force_rename(db->fn, fn_old) || rename(fn_complete, db->fn))
bb432d
-		err = -1;
bb432d
-	/* Hit disk */	
bb432d
-	else if (flush_dir(db->fn))
bb432d
-		err = -1;
bb432d
-		
bb432d
-	if (err) {
bb432d
-		DBerror("Error writing to database %s: %s\n", db->fn,
bb432d
-				strerror(errno));
bb432d
-	}
bb432d
-				
bb432d
-	return err;			
bb432d
-}
bb432d
-
bb432d
-int sync_db(struct database *db)
bb432d
-{
bb432d
-	if (!db->dirty)
bb432d
-		return 0;
bb432d
-	/* RED-PEN window without lock */
bb432d
-	if (rewrite_db(db))
bb432d
-		return -1;
bb432d
-	fclose(db->fh);		
bb432d
-	db->dirty = 0;
bb432d
-	db->fh = open_file(db->fn, 1);
bb432d
-	if (!db->fh)
bb432d
-		return -1;
bb432d
-	return 0;	
bb432d
-}
bb432d
-
bb432d
-static void free_group(struct group *g)
bb432d
-{
bb432d
-	free(g->entries);
bb432d
-	free(g->name);
bb432d
-	free(g->comment);
bb432d
-	free(g); 	
bb432d
-}
bb432d
-
bb432d
-static void free_data(struct database *db)
bb432d
-{
bb432d
-	struct group *g, *gnext;
bb432d
-	for (g = db->groups; g; g = gnext) {
bb432d
-		gnext = g->next;
bb432d
-		free_group(g);
bb432d
-	}
bb432d
-}
bb432d
-
bb432d
-int close_db(struct database *db)
bb432d
-{
bb432d
-	if (db->dirty && rewrite_db(db))
bb432d
-		return -1;
bb432d
-	if (fclose(db->fh))
bb432d
-		return -1;
bb432d
-	free_data(db);
bb432d
-	free(db->fn);
bb432d
-	free(db);
bb432d
-	return 0; 	
bb432d
-}
bb432d
-
bb432d
-static FILE *open_file(char *fn, int wr)
bb432d
-{
bb432d
-	char tmp[strlen(fn) + 10];
bb432d
-	FILE *fh;
bb432d
-	if (access(fn, wr ? (R_OK|W_OK) : R_OK)) {
bb432d
-		switch (errno) {
bb432d
-		case EROFS:
bb432d
-			wr = 0;
bb432d
-			break;
bb432d
-		case ENOENT:	
bb432d
-			/* No main DB file */
bb432d
-			sprintf(tmp, "%s.complete", fn);
bb432d
-			/* Handle race */
bb432d
-			if (!access(tmp, R_OK)) {
bb432d
-				if (rename(tmp, fn) < 0 && errno == EEXIST)
bb432d
-					return open_file(fn, wr);
bb432d
-			} else
bb432d
-				creat(fn, 0644);
bb432d
-			break;
bb432d
-		}
bb432d
-	}
bb432d
-	fh = fopen(fn, wr ? "r+" : "r");
bb432d
-	if (fh) {
bb432d
-		if (flock(fileno(fh), wr ? LOCK_EX : LOCK_SH) < 0) {
bb432d
-			fclose(fh);
bb432d
-			return NULL;
bb432d
-		}
bb432d
-	}	
bb432d
-	return fh;		
bb432d
-}
bb432d
-
bb432d
-void dump_group(struct group *g, FILE *out)
bb432d
-{
bb432d
-	struct entry *e;
bb432d
-	fprintf(out, "[%s]\n", g->name);
bb432d
-	for (e = &g->entries[0]; e->name && !ferror(out); e++)
bb432d
-		fprintf(out, "%s: %s\n", e->name, e->val);
bb432d
-}
bb432d
-
bb432d
-void dump_database(struct database *db, FILE *out)
bb432d
-{
bb432d
-	struct group *g; 	
bb432d
-	for (g = db->groups; g && !ferror(out); g = g->next) {
bb432d
-		if (g->comment) {
bb432d
-			fprintf(out, "#%s", g->comment);
bb432d
-			continue;
bb432d
-		}
bb432d
-		dump_group(g, out);
bb432d
-	}
bb432d
-}
bb432d
-
bb432d
-struct group *find_group(struct database *db, char *name)
bb432d
-{
bb432d
-	struct group *g;
bb432d
-	for (g = db->groups; g; g = g->next)
bb432d
-		if (g->name && !strcmp(g->name, name))
bb432d
-			return g;
bb432d
-	return NULL;		
bb432d
-}
bb432d
-
bb432d
-int delete_group(struct database *db, struct group *group)
bb432d
-{
bb432d
-	struct group *g, **gprev;
bb432d
-	gprev = &db->groups;
bb432d
-	for (g = *gprev; g; gprev = &g->next, g = g->next) {
bb432d
-		if (g == group) {
bb432d
-			*gprev = g->next;
bb432d
-			free_group(g);
bb432d
-			return 0;
bb432d
-		}
bb432d
-	}
bb432d
-	db->dirty = 1;
bb432d
-	return -1;		
bb432d
-}
bb432d
-
bb432d
-char *entry_val(struct group *g, char *entry)
bb432d
-{
bb432d
-	struct entry *e;
bb432d
-	for (e = &g->entries[0]; e->name; e++) 
bb432d
-		if (!strcmp(e->name, entry))
bb432d
-			return e->val;
bb432d
-	return NULL;
bb432d
-}
bb432d
-
bb432d
-struct group *add_group(struct database *db, char *name, int *existed)
bb432d
-{
bb432d
-	struct group *g, **gprev = &db->groups;
bb432d
-	for (g = *gprev; g; gprev = &g->next, g = g->next)
bb432d
-		if (g->name && !strcmp(g->name, name))
bb432d
-			break;
bb432d
-	if (existed)
bb432d
-		*existed = (g != NULL);
bb432d
-	if (!g) {
bb432d
-		g = alloc_group(xstrdup(name));
bb432d
-		g->next = *gprev;
bb432d
-		*gprev = g;
bb432d
-	}
bb432d
-	db->dirty = 1;
bb432d
-	return g;
bb432d
-
bb432d
-}
bb432d
-
bb432d
-void change_entry(struct database *db, struct group *g,
bb432d
-		     char *entry, char *newval)
bb432d
-{
bb432d
-	int i;
bb432d
-	struct entry *e, *entries;
bb432d
-	db->dirty = 1;
bb432d
-	entries = &g->entries[0];
bb432d
-	for (e = entries; e->name; e++) { 
bb432d
-		if (!strcmp(e->name, entry)) { 
bb432d
-			free(e->val);
bb432d
-			e->val = xstrdup(newval);
bb432d
-			return;
bb432d
-		}
bb432d
-	}
bb432d
-	i = e - entries;
bb432d
-	assert(i == g->numentries);
bb432d
-	if (i > 0 && (i % ENTRY_CHUNK) == 0) { 
bb432d
-		int new = (i + ENTRY_CHUNK) * sizeof(struct entry);
bb432d
-		g->entries = xrealloc(g->entries, new);
bb432d
-	} 
bb432d
-	entries = &g->entries[0];
bb432d
-	e = &entries[i];
bb432d
-	e->name = xstrdup(entry);
bb432d
-	e->val = xstrdup(newval);
bb432d
-	g->numentries++;
bb432d
-}
bb432d
-
bb432d
-void delete_entry(struct database *db, struct group *g, char *entry)
bb432d
-{
bb432d
-	struct entry *e;
bb432d
-	for (e = &g->entries[0]; e->name; e++) 
bb432d
-		if (!strcmp(e->name, entry))
bb432d
-			break;
bb432d
-	if (e->name == NULL)
bb432d
-		return;
bb432d
-	while ((++e)->name)
bb432d
-		e[-1] = e[0];
bb432d
-	g->numentries--;
bb432d
-}
bb432d
-
bb432d
-struct group *
bb432d
-clone_group(struct database *db, struct group *gold, char *newname)
bb432d
-{
bb432d
-	struct entry *e;
bb432d
-	struct group *gnew = add_group(db, newname, NULL);
bb432d
-	for (e = &gold->entries[0]; e->name; e++) 
bb432d
-		change_entry(db, gnew, e->name, e->val);
bb432d
-	return gnew;
bb432d
-}
bb432d
-
bb432d
-static char *save_comment(char *c)
bb432d
-{
bb432d
-	int len = strlen(c);
bb432d
-	char *s = xalloc(len + 2); 	
bb432d
-	strcpy(s, c);
bb432d
-	if (len == 0 || c[len - 1] != '\n')
bb432d
-		s[len] = '\n';
bb432d
-	return s;	
bb432d
-}
bb432d
-
bb432d
-void add_comment(struct database *db, struct group *group, char *comment)
bb432d
-{
bb432d
-	struct group *g;
bb432d
-	struct group **gprev = &db->groups;
bb432d
-	for (g = *gprev; g; gprev = &g->next, g = g->next) {
bb432d
-		if ((group && g == group) || (!group && g->comment == NULL))
bb432d
-			break;
bb432d
-	}
bb432d
-	DB_NEW(g);
bb432d
-	g->comment = save_comment(comment);
bb432d
-	g->next = *gprev;
bb432d
-	*gprev = g;
bb432d
-	db->dirty = 1;
bb432d
-}
bb432d
-
bb432d
-struct group *first_group(struct database *db)
bb432d
-{
bb432d
-	return next_group(db->groups);
bb432d
-}
bb432d
-
bb432d
-struct group *next_group(struct group *g)
bb432d
-{
bb432d
-	struct group *n;
bb432d
-	if (!g)
bb432d
-		return NULL;
bb432d
-	n = g->next;
bb432d
-	while (n && n->comment)
bb432d
-		n = n->next;
bb432d
-	return n;
bb432d
-}
bb432d
-
bb432d
-char *group_name(struct group *g)
bb432d
-{
bb432d
-	return g->name;
bb432d
-}
bb432d
-
bb432d
-struct group *find_entry(struct database *db, struct group *prev,
bb432d
-			 char *entry, char *value)
bb432d
-{
bb432d
-	int previ = 0; 
bb432d
-	struct entry *e;
bb432d
-	struct group *g;
bb432d
-	if (prev)
bb432d
-		g = prev->next;
bb432d
-	else
bb432d
-		g = db->groups;
bb432d
-	for (; g; g = g->next) {
bb432d
-		if (g->comment) 
bb432d
-			continue;
bb432d
-		/* Short cut when entry is at the same place as previous */
bb432d
-		if (previ < g->numentries) { 
bb432d
-			e = &g->entries[previ]; 
bb432d
-			if (!strcmp(e->name, entry)) {
bb432d
-				if (!strcmp(e->val, value))
bb432d
-					return g;
bb432d
-				continue;
bb432d
-			}
bb432d
-		}
bb432d
-		for (e = &g->entries[0]; e->name; e++) { 
bb432d
-			if (strcmp(e->name, entry)) 
bb432d
-				continue;
bb432d
-			if (!strcmp(e->val, value))
bb432d
-				return g;
bb432d
-			previ = e - &g->entries[0];
bb432d
-			break;
bb432d
-		}
bb432d
-	}
bb432d
-	return NULL;
bb432d
-}
bb432d
-
bb432d
-void rename_group(struct database *db, struct group *g, char *newname)
bb432d
-{
bb432d
-	free(g->name);
bb432d
-	g->name = xstrdup(newname);
bb432d
-	db->dirty = 1;
bb432d
-}
bb432d
-
bb432d
-unsigned long entry_num(struct group *g, char *entry)
bb432d
-{
bb432d
-	char *e = entry_val(g, entry);
bb432d
-	unsigned long val = 0;
bb432d
-	if (e)
bb432d
-		sscanf(e, "%lu", &val;;
bb432d
-	return val;
bb432d
-}
bb432d
-
bb432d
-void change_entry_num(struct database *db, struct group *g,
bb432d
-		      char *entry, unsigned long val)
bb432d
-{
bb432d
-	char buf[20];
bb432d
-	sprintf(buf, "%lu", val);
bb432d
-	change_entry(db, g, entry, buf);
bb432d
-}
bb432d
diff -urNp mcelog-d2e13bf0.orig/db.h mcelog-d2e13bf0/db.h
bb432d
--- mcelog-d2e13bf0.orig/db.h	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/db.h	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,29 +0,0 @@
bb432d
-#include <stdio.h>
bb432d
-struct database;
bb432d
-struct group;
bb432d
-
bb432d
-struct database *open_db(char *fn, int wr);
bb432d
-int sync_db(struct database *db);
bb432d
-int close_db(struct database *db);
bb432d
-struct group *find_group(struct database *db, char *name);
bb432d
-char *entry_val(struct group *g, char *entry);
bb432d
-struct group *add_group(struct database *db, char *name, int *existed);
bb432d
-int delete_group(struct database *db, struct group *g);
bb432d
-void change_entry(struct database *db, struct group *g,
bb432d
-		  char *entry, char *newval);
bb432d
-void add_comment(struct database *db, struct group *group, char *comment);
bb432d
-struct group *first_group(struct database *db);
bb432d
-struct group *next_group(struct group *g);
bb432d
-void dump_group(struct group *g, FILE *out);
bb432d
-void dump_database(struct database *db, FILE *out);
bb432d
-struct group *find_entry(struct database *db, struct group *prev,
bb432d
-			 char *entry, char *value);
bb432d
-void rename_group(struct database *db, struct group *group, char *newname);
bb432d
-char *group_name(struct group *g);
bb432d
-unsigned long entry_num(struct group *g, char *entry);
bb432d
-void change_entry_num(struct database *db, struct group *g, char *entry,
bb432d
-		      unsigned long val);
bb432d
-void delete_entry(struct database *db, struct group *g, char *entry);
bb432d
-struct group *
bb432d
-clone_group(struct database *db, struct group *gold, char *newname);
bb432d
-
bb432d
diff -urNp mcelog-d2e13bf0.orig/dbquery.c mcelog-d2e13bf0/dbquery.c
bb432d
--- mcelog-d2e13bf0.orig/dbquery.c	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/dbquery.c	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,130 +0,0 @@
bb432d
-/* Access db files. This is for testing and debugging only. */
bb432d
-#define _GNU_SOURCE 1
bb432d
-#include <stdio.h>
bb432d
-#include <string.h>
bb432d
-#include <ctype.h>
bb432d
-#include <stdlib.h>
bb432d
-#include <errno.h>
bb432d
-#include <stdarg.h>
bb432d
-#include "db.h"
bb432d
-
bb432d
-#define C(x) if (x) printf(#x " failed: %s\n", strerror(errno))
bb432d
-#define NEEDGROUP  if (!group) { printf("need group first\n"); break; }
bb432d
-
bb432d
-void Eprintf(char *fmt, ...)
bb432d
-{
bb432d
-	va_list ap;
bb432d
-	va_start(ap, fmt);
bb432d
-	vfprintf(stderr, fmt, ap);
bb432d
-	va_end(ap);
bb432d
-}
bb432d
-
bb432d
-void usage(void)
bb432d
-{
bb432d
-	printf(
bb432d
-	"s sync\n"
bb432d
-	"q close/quit\n"
bb432d
-	"ggroup find group\n"
bb432d
-	"G delete group\n"
bb432d
-	"agroup add group\n" 
bb432d
-	"ventry dump entry\n"
bb432d
-	"centry,val change entry to val\n"
bb432d
-	"fentry,val find entry with value and dump its group\n"
bb432d
-	"Ccomment add comment\n"
bb432d
-	"Lnewname clone group to newname\n"
bb432d
-	"d dump group\n"
bb432d
-	"D dump database\n");
bb432d
-}	
bb432d
-
bb432d
-int main(int ac, char **av)
bb432d
-{
bb432d
-	struct database *db;
bb432d
-	struct group *group = NULL;
bb432d
-	char *line = NULL;
bb432d
-	size_t linesz = 0;
bb432d
-	if (!av[1]) {
bb432d
-		printf("%s database\n", av[0]);
bb432d
-		exit(1);
bb432d
-	}
bb432d
-	printf("dbtest\n");
bb432d
-	db = open_db(av[1], 1);  
bb432d
-	while (printf("> "), 
bb432d
-		fflush(stdout), 
bb432d
-		getline(&line, &linesz, stdin) > 0) { 
bb432d
-		char *p = line + strlen(line) - 1;
bb432d
-		while (p >= line && isspace(*p))
bb432d
-			*p-- = 0; 
bb432d
-		switch (line[0]) { 
bb432d
-		case 's':
bb432d
-			C(sync_db(db));
bb432d
-			break;
bb432d
-		case 'q':
bb432d
-			C(close_db(db)); 
bb432d
-			exit(0);
bb432d
-		case 'g':
bb432d
-			group = find_group(db, line + 1); 
bb432d
-			if (group)
bb432d
-				printf("found\n"); 
bb432d
-			break;
bb432d
-		case 'G':
bb432d
-			NEEDGROUP; 
bb432d
-			C(delete_group(db, group));
bb432d
-			group = NULL;
bb432d
-			break;			
bb432d
-		case 'a': { 
bb432d
-			int existed = 0;
bb432d
-			group = add_group(db, line + 1, &existed);
bb432d
-			if (existed) 
bb432d
-				printf("existed\n");
bb432d
-			break;
bb432d
-		}
bb432d
-		case 'v':
bb432d
-			NEEDGROUP; 
bb432d
-			printf("%s\n", entry_val(group, line + 1)); 
bb432d
-			break;
bb432d
-		case 'c': {
bb432d
-			p = line + 1;
bb432d
-			char *entry = strsep(&p, ","); 
bb432d
-			NEEDGROUP; 
bb432d
-			change_entry(db, group, entry, strsep(&p, ""));
bb432d
-			break;
bb432d
-		} 
bb432d
-		case 'L':
bb432d
-			NEEDGROUP; 
bb432d
-			clone_group(db, group, line + 1); 
bb432d
-			break;
bb432d
-		case 'f': { 
bb432d
-			struct group *g;
bb432d
-			p = line + 1; 
bb432d
-			char *entry = strsep(&p, ",");
bb432d
-			char *val = strsep(&p, "");	
bb432d
-			g = NULL;
bb432d
-			int nr = 0;
bb432d
-			while ((g = find_entry(db, g, entry, val)) != NULL) {
bb432d
-				if (nr == 0)
bb432d
-					group = g;
bb432d
-				nr++;
bb432d
-				dump_group(group, stdout);
bb432d
-			}
bb432d
-			if (nr == 0) 
bb432d
-				printf("not found\n");
bb432d
-			break;
bb432d
-		}
bb432d
-		case 'C':
bb432d
-			NEEDGROUP;
bb432d
-			add_comment(db, group, line + 1); 
bb432d
-			break;
bb432d
-		case 'd':
bb432d
-			NEEDGROUP;
bb432d
-			dump_group(group, stdout); 
bb432d
-			break;
bb432d
-		case 'D':
bb432d
-			dump_database(db, stdout);
bb432d
-			break;
bb432d
-		default:
bb432d
-			usage();
bb432d
-			break;
bb432d
-		}
bb432d
-	}
bb432d
-	return 0;
bb432d
-}
bb432d
diff -urNp mcelog-d2e13bf0.orig/denverton.c mcelog-d2e13bf0/denverton.c
bb432d
--- mcelog-d2e13bf0.orig/denverton.c	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/denverton.c	2016-11-30 11:24:12.204619369 -0500
bb432d
@@ -0,0 +1,45 @@
bb432d
+/* Copyright (C) 2016 Intel Corporation
bb432d
+   Decode Intel Denverton specific machine check errors.
bb432d
+
bb432d
+   mcelog is free software; you can redistribute it and/or
bb432d
+   modify it under the terms of the GNU General Public
bb432d
+   License as published by the Free Software Foundation; version
bb432d
+   2.
bb432d
+
bb432d
+   mcelog is distributed in the hope that it will be useful,
bb432d
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
bb432d
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
bb432d
+   General Public License for more details.
bb432d
+
bb432d
+   You should find a copy of v2 of the GNU General Public License somewhere
bb432d
+   on your Linux system; if not, write to the Free Software Foundation,
bb432d
+   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bb432d
+
bb432d
+   Author: Tony Luck
bb432d
+*/
bb432d
+
bb432d
+#include "mcelog.h"
bb432d
+#include "bitfield.h"
bb432d
+#include "denverton.h"
bb432d
+#include "memdb.h"
bb432d
+
bb432d
+/* See IA32 SDM Vol3B Table 16-33 */
bb432d
+
bb432d
+static struct field mc_bits[] = {
bb432d
+	SBITFIELD(16, "Cmd/Addr parity"),
bb432d
+	SBITFIELD(17, "Corrected Demand/Patrol Scrub Error"),
bb432d
+	SBITFIELD(18, "Uncorrected patrol scrub error"),
bb432d
+	SBITFIELD(19, "Uncorrected demand read error"),
bb432d
+	SBITFIELD(20, "WDB read ECC"),
bb432d
+	{}
bb432d
+};
bb432d
+
bb432d
+void denverton_decode_model(int cputype, int bank, u64 status, u64 misc)
bb432d
+{
bb432d
+	switch (bank) {
bb432d
+	case 6: case 7:
bb432d
+		Wprintf("MemCtrl: ");
bb432d
+		decode_bitfield(status, mc_bits);
bb432d
+		break;
bb432d
+	}
bb432d
+}
bb432d
diff -urNp mcelog-d2e13bf0.orig/denverton.h mcelog-d2e13bf0/denverton.h
bb432d
--- mcelog-d2e13bf0.orig/denverton.h	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/denverton.h	2016-11-30 11:24:12.204619369 -0500
bb432d
@@ -0,0 +1 @@
bb432d
+void denverton_decode_model(int cputype, int bank, u64 status, u64 misc);
bb432d
diff -urNp mcelog-d2e13bf0.orig/diskdb.c mcelog-d2e13bf0/diskdb.c
bb432d
--- mcelog-d2e13bf0.orig/diskdb.c	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/diskdb.c	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,96 +0,0 @@
bb432d
-/* High level interface to disk based DIMM database */
bb432d
-/* Note: obsolete: new design is in memdb.c */
bb432d
-#include <stdlib.h>
bb432d
-#include <getopt.h>
bb432d
-#include <stdio.h>
bb432d
-#include "mcelog.h"
bb432d
-#include "diskdb.h"
bb432d
-#include "paths.h"
bb432d
-#include "dimm.h"
bb432d
-#include "dmi.h"
bb432d
- 
bb432d
-char *error_trigger;
bb432d
-unsigned error_thresh = 20;
bb432d
-char *dimm_db_fn = DIMM_DB_FILENAME;
bb432d
-
bb432d
-static void checkdimmdb(void)
bb432d
-{
bb432d
-	if (open_dimm_db(dimm_db_fn) < 0) 
bb432d
-		exit(1);
bb432d
-}
bb432d
-
bb432d
-int diskdb_modifier(int opt)
bb432d
-{
bb432d
-	char *end;
bb432d
-
bb432d
-	switch (opt) { 
bb432d
-	case O_DATABASE:
bb432d
-		dimm_db_fn = optarg;
bb432d
-		checkdmi();
bb432d
-		checkdimmdb();
bb432d
-		break;
bb432d
-	case O_ERROR_TRIGGER:
bb432d
-		checkdmi();
bb432d
-		open_dimm_db(dimm_db_fn);
bb432d
-		error_thresh = strtoul(optarg, &end, 0);
bb432d
-		if (end == optarg || *end != ',') 
bb432d
-			usage();
bb432d
-		error_trigger = end + 1; 
bb432d
-		break;
bb432d
-	default:
bb432d
-		return 0;
bb432d
-	}
bb432d
-	return 1;
bb432d
-}
bb432d
-
bb432d
-void diskdb_resolve_addr(u64 addr)
bb432d
-{
bb432d
-	if (open_dimm_db(dimm_db_fn) >= 0) 
bb432d
-		new_error(addr, error_thresh, error_trigger);
bb432d
-}
bb432d
-
bb432d
-
bb432d
-void diskdb_usage(void)
bb432d
-{
bb432d
-	fprintf(stderr, 
bb432d
-		"Manage disk DIMM error database\n"
bb432d
-		"  mcelog [options] --drop-old-memory|--reset-memory locator\n"
bb432d
-		"  mcelog --dump-memory locator\n"
bb432d
-		"  old can be either locator or name\n"
bb432d
-		"Disk database options:"
bb432d
-		"--database fn       Set filename of DIMM database (default " DIMM_DB_FILENAME ")\n"
bb432d
-		"--error-trigger cmd,thresh   Run cmd on exceeding thresh errors per DIMM\n");
bb432d
-}
bb432d
-
bb432d
-
bb432d
-static void dimm_common(int ac, char **av)
bb432d
-{
bb432d
-	no_syslog();
bb432d
-	checkdmi();
bb432d
-	checkdimmdb();
bb432d
-	argsleft(ac, av); 
bb432d
-}
bb432d
-
bb432d
-int diskdb_cmd(int opt, int ac, char **av)
bb432d
-{
bb432d
-	char *arg = optarg; 
bb432d
-	
bb432d
-	switch (opt) { 
bb432d
-	case O_DUMP_MEMORY:
bb432d
-		dimm_common(ac, av);
bb432d
-		if (arg)
bb432d
-			dump_dimm(arg);
bb432d
-		else
bb432d
-			dump_all_dimms();
bb432d
-		return 1;
bb432d
-	case O_RESET_MEMORY:
bb432d
-		dimm_common(ac, av);
bb432d
-		reset_dimm(arg);
bb432d
-		return 1;
bb432d
-	case O_DROP_OLD_MEMORY:
bb432d
-		dimm_common(ac, av);
bb432d
-		gc_dimms();
bb432d
-		return 1;
bb432d
-	}
bb432d
-	return 0;	
bb432d
-}
bb432d
diff -urNp mcelog-d2e13bf0.orig/diskdb.h mcelog-d2e13bf0/diskdb.h
bb432d
--- mcelog-d2e13bf0.orig/diskdb.h	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/diskdb.h	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,32 +0,0 @@
bb432d
-
bb432d
-#ifdef CONFIG_DISKDB
bb432d
-enum diskdb_options { 
bb432d
-	O_DATABASE = O_DISKDB,
bb432d
-	O_ERROR_TRIGGER,
bb432d
-	O_DUMP_MEMORY,
bb432d
-	O_RESET_MEMORY,
bb432d
-	O_DROP_OLD_MEMORY,	
bb432d
-};
bb432d
-
bb432d
-void diskdb_resolve_addr(u64 addr);
bb432d
-int diskdb_modifier(int opt);
bb432d
-int diskdb_cmd(int opt, int ac, char **av);
bb432d
-void diskdb_usage(void);
bb432d
-
bb432d
-#define DISKDB_OPTIONS \
bb432d
-	{ "database", 1, NULL, O_DATABASE },	\
bb432d
-	{ "error-trigger", 1, NULL, O_ERROR_TRIGGER },	\
bb432d
-	{ "dump-memory", 2, NULL, O_DUMP_MEMORY },	\
bb432d
-	{ "reset-memory", 2, NULL, O_RESET_MEMORY },	\
bb432d
-	{ "drop-old-memory", 0, NULL, O_DROP_OLD_MEMORY },
bb432d
-
bb432d
-#else
bb432d
-
bb432d
-static inline void diskdb_resolve_addr(u64 addr) {}
bb432d
-static inline int diskdb_modifier(int opt) { return 0; }
bb432d
-static inline int diskdb_cmd(int opt, int ac, char **av) { return 0; }
bb432d
-static inline void diskdb_usage(void) {}
bb432d
-
bb432d
-#define DISKDB_OPTIONS
bb432d
-
bb432d
-#endif
bb432d
diff -urNp mcelog-d2e13bf0.orig/dmi.h mcelog-d2e13bf0/dmi.h
bb432d
--- mcelog-d2e13bf0.orig/dmi.h	2016-11-30 11:23:54.534909314 -0500
bb432d
+++ mcelog-d2e13bf0/dmi.h	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -3,7 +3,7 @@ struct dmi_entry {
bb432d
 	unsigned char type;
bb432d
 	unsigned char length;
bb432d
 	unsigned short handle;
bb432d
-};
bb432d
+} __attribute__((packed));
bb432d
 
bb432d
 enum { 
bb432d
 	DMI_MEMORY_ARRAY = 16,
bb432d
diff -urNp mcelog-d2e13bf0.orig/.gitignore mcelog-d2e13bf0/.gitignore
bb432d
--- mcelog-d2e13bf0.orig/.gitignore	2016-11-30 11:23:54.530909154 -0500
bb432d
+++ mcelog-d2e13bf0/.gitignore	2016-11-30 11:24:12.202619289 -0500
bb432d
@@ -8,3 +8,5 @@ dbquery
bb432d
 .depend
bb432d
 tsc
bb432d
 core
bb432d
+version.c
bb432d
+version.tmp
bb432d
diff -urNp mcelog-d2e13bf0.orig/input/bdw_mirror1 mcelog-d2e13bf0/input/bdw_mirror1
bb432d
--- mcelog-d2e13bf0.orig/input/bdw_mirror1	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/input/bdw_mirror1	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -0,0 +1,6 @@
bb432d
+# Broadwell mirror corrected with mirror failover
bb432d
+CPU 0 7
bb432d
+PROCESSOR 0:0x406f0
bb432d
+STATUS 0x8800000000000080
bb432d
+MISC 20000000000
bb432d
+
bb432d
diff -urNp mcelog-d2e13bf0.orig/input/bdw_mirror2 mcelog-d2e13bf0/input/bdw_mirror2
bb432d
--- mcelog-d2e13bf0.orig/input/bdw_mirror2	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/input/bdw_mirror2	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -0,0 +1,6 @@
bb432d
+# Broadwell mirror corrected with successful scrub
bb432d
+CPU 0 7
bb432d
+PROCESSOR 0:0x406f0
bb432d
+STATUS 0x8800000000000080
bb432d
+MISC 40000000000
bb432d
+
bb432d
diff -urNp mcelog-d2e13bf0.orig/input/GENMEM mcelog-d2e13bf0/input/GENMEM
bb432d
--- mcelog-d2e13bf0.orig/input/GENMEM	2016-11-30 11:23:54.532909234 -0500
bb432d
+++ mcelog-d2e13bf0/input/GENMEM	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -11,7 +11,7 @@ dimm=${3:-0}
bb432d
 corr_err_cnt=${4:-0}
bb432d
 
bb432d
 if [ ! -z "$5" ] ; then
bb432d
-	ucflag=$[1 << (61-32)]
bb432d
+	ucflag=$[(1 << (61-32)) | (1 << (60-32)) | (1 << (56-32))]
bb432d
 else
bb432d
 	ucflag=0
bb432d
 fi
bb432d
diff -urNp mcelog-d2e13bf0.orig/input/skx_mirror1 mcelog-d2e13bf0/input/skx_mirror1
bb432d
--- mcelog-d2e13bf0.orig/input/skx_mirror1	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/input/skx_mirror1	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -0,0 +1,6 @@
bb432d
+# Skylake mirror corrected with mirror failover
bb432d
+CPU 0 7
bb432d
+PROCESSOR 0:0x50650
bb432d
+STATUS 0x8800000000000080
bb432d
+MISC 8000000000000000
bb432d
+
bb432d
diff -urNp mcelog-d2e13bf0.orig/input/skx_mirror2 mcelog-d2e13bf0/input/skx_mirror2
bb432d
--- mcelog-d2e13bf0.orig/input/skx_mirror2	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/input/skx_mirror2	2016-11-30 11:24:12.205619409 -0500
bb432d
@@ -0,0 +1,6 @@
bb432d
+# Skylake mirror corrected with successful scrub
bb432d
+CPU 0 7
bb432d
+PROCESSOR 0:0x50650
bb432d
+STATUS 0x8800000000000080
bb432d
+MISC 4000000000000000
bb432d
+
bb432d
diff -urNp mcelog-d2e13bf0.orig/intel.c mcelog-d2e13bf0/intel.c
bb432d
--- mcelog-d2e13bf0.orig/intel.c	2016-11-30 11:23:54.538909475 -0500
bb432d
+++ mcelog-d2e13bf0/intel.c	2016-11-30 11:24:12.206619450 -0500
bb432d
@@ -25,7 +25,6 @@
bb432d
 #include "sandy-bridge.h"
bb432d
 #include "ivy-bridge.h"
bb432d
 #include "haswell.h"
bb432d
-#include "xeon75xx.h"
bb432d
 
bb432d
 int memory_error_support;
bb432d
 
bb432d
@@ -36,7 +35,9 @@ void intel_cpu_init(enum cputype cpu)
bb432d
 	    cpu == CPU_IVY_BRIDGE || cpu == CPU_IVY_BRIDGE_EPEX ||
bb432d
 	    cpu == CPU_HASWELL || cpu == CPU_HASWELL_EPEX || cpu == CPU_BROADWELL ||
bb432d
 	    cpu == CPU_BROADWELL_DE || cpu == CPU_BROADWELL_EPEX ||
bb432d
-	    cpu == CPU_KNIGHTS_LANDING || cpu == CPU_SKYLAKE || cpu == CPU_SKYLAKE_XEON)
bb432d
+	    cpu == CPU_KNIGHTS_LANDING || cpu == CPU_KNIGHTS_MILL ||
bb432d
+	    cpu == CPU_SKYLAKE || cpu == CPU_SKYLAKE_XEON ||
bb432d
+	    cpu == CPU_KABYLAKE || cpu == CPU_DENVERTON)
bb432d
 		memory_error_support = 1;
bb432d
 }
bb432d
 
bb432d
@@ -82,6 +83,8 @@ enum cputype select_intel_cputype(int fa
bb432d
 			return CPU_BROADWELL_DE;
bb432d
  		else if (model == 0x57)
bb432d
 			return CPU_KNIGHTS_LANDING;
bb432d
+		else if (model == 0x85)
bb432d
+			return CPU_KNIGHTS_MILL;
bb432d
 		else if (model == 0x1c || model == 0x26 || model == 0x27 ||
bb432d
 			 model == 0x35 || model == 0x36 || model == 0x36 ||
bb432d
 			 model == 0x37 || model == 0x4a || model == 0x4c ||
bb432d
@@ -91,18 +94,22 @@ enum cputype select_intel_cputype(int fa
bb432d
 			return CPU_SKYLAKE;
bb432d
 		else if (model == 0x55)
bb432d
 			return CPU_SKYLAKE_XEON;
bb432d
+		else if (model == 0x8E || model == 0x9E)
bb432d
+			return CPU_KABYLAKE;
bb432d
+		else if (model == 0x5f)
bb432d
+			return CPU_DENVERTON;
bb432d
 		if (model > 0x1a) {
bb432d
-			Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n",
bb432d
+			Eprintf("Family 6 Model %u CPU: only decoding architectural errors\n",
bb432d
 				model);
bb432d
 			return CPU_INTEL; 
bb432d
 		}
bb432d
 	}
bb432d
 	if (family > 6) { 
bb432d
-		Eprintf("Family %u Model %x CPU: only decoding architectural errors\n",
bb432d
+		Eprintf("Family %u Model %u CPU: only decoding architectural errors\n",
bb432d
 				family, model);
bb432d
 		return CPU_INTEL;
bb432d
 	}
bb432d
-	Eprintf("Unknown Intel CPU type family %x model %x\n", family, model);
bb432d
+	Eprintf("Unknown Intel CPU type family %u model %u\n", family, model);
bb432d
 	return family == 6 ? CPU_P6OLD : CPU_GENERIC;
bb432d
 }
bb432d
 
bb432d
@@ -127,9 +134,6 @@ static int intel_memory_error(struct mce
bb432d
 		case CPU_NEHALEM:
bb432d
 			nehalem_memerr_misc(m, channel, dimm);
bb432d
 			break;
bb432d
-		case CPU_XEON75XX:
bb432d
-			xeon75xx_memory_error(m, recordlen, channel, dimm);
bb432d
-			break;
bb432d
 		case CPU_SANDY_BRIDGE_EP:
bb432d
 			sandy_bridge_ep_memerr_misc(m, channel, dimm);
bb432d
 			break;
bb432d
diff -urNp mcelog-d2e13bf0.orig/intel.c.orig mcelog-d2e13bf0/intel.c.orig
bb432d
--- mcelog-d2e13bf0.orig/intel.c.orig	2016-11-30 11:23:54.539909515 -0500
bb432d
+++ mcelog-d2e13bf0/intel.c.orig	2016-11-30 11:23:40.052327334 -0500
bb432d
@@ -35,7 +35,8 @@ void intel_cpu_init(enum cputype cpu)
bb432d
 	    cpu == CPU_SANDY_BRIDGE || cpu == CPU_SANDY_BRIDGE_EP ||
bb432d
 	    cpu == CPU_IVY_BRIDGE || cpu == CPU_IVY_BRIDGE_EPEX ||
bb432d
 	    cpu == CPU_HASWELL || cpu == CPU_HASWELL_EPEX || cpu == CPU_BROADWELL ||
bb432d
-	    cpu == CPU_KNIGHTS_LANDING)
bb432d
+	    cpu == CPU_BROADWELL_DE || cpu == CPU_BROADWELL_EPEX ||
bb432d
+	    cpu == CPU_KNIGHTS_LANDING || cpu == CPU_SKYLAKE || cpu == CPU_SKYLAKE_XEON)
bb432d
 		memory_error_support = 1;
bb432d
 }
bb432d
 
bb432d
@@ -73,15 +74,23 @@ enum cputype select_intel_cputype(int fa
bb432d
 			return CPU_HASWELL;
bb432d
 		else if (model == 0x3f)
bb432d
 			return CPU_HASWELL_EPEX;
bb432d
-		else if (model == 0x3d || model == 0x56)
bb432d
+		else if (model == 0x3d)
bb432d
 			return CPU_BROADWELL;
bb432d
-		else if (model == 0x57)
bb432d
+		else if (model == 0x4f)
bb432d
+			return CPU_BROADWELL_EPEX;
bb432d
+		else if (model == 0x56)
bb432d
+			return CPU_BROADWELL_DE;
bb432d
+ 		else if (model == 0x57)
bb432d
 			return CPU_KNIGHTS_LANDING;
bb432d
 		else if (model == 0x1c || model == 0x26 || model == 0x27 ||
bb432d
 			 model == 0x35 || model == 0x36 || model == 0x36 ||
bb432d
 			 model == 0x37 || model == 0x4a || model == 0x4c ||
bb432d
 			 model == 0x4d || model == 0x5a || model == 0x5d)
bb432d
 			return CPU_ATOM;
bb432d
+		else if (model == 0x4e || model == 0x5e)
bb432d
+			return CPU_SKYLAKE;
bb432d
+		else if (model == 0x55)
bb432d
+			return CPU_SKYLAKE_XEON;
bb432d
 		if (model > 0x1a) {
bb432d
 			Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n",
bb432d
 				model);
bb432d
diff -urNp mcelog-d2e13bf0.orig/intel.h mcelog-d2e13bf0/intel.h
bb432d
--- mcelog-d2e13bf0.orig/intel.h	2016-11-30 11:23:54.530909154 -0500
bb432d
+++ mcelog-d2e13bf0/intel.h	2016-11-30 11:24:12.206619450 -0500
bb432d
@@ -25,6 +25,9 @@ extern int memory_error_support;
bb432d
 	case CPU_BROADWELL_EPEX: \
bb432d
 	case CPU_ATOM:	\
bb432d
 	case CPU_KNIGHTS_LANDING: \
bb432d
+	case CPU_KNIGHTS_MILL: \
bb432d
 	case CPU_SKYLAKE: \
bb432d
-	case CPU_SKYLAKE_XEON
bb432d
+	case CPU_SKYLAKE_XEON: \
bb432d
+	case CPU_KABYLAKE: \
bb432d
+	case CPU_DENVERTON
bb432d
 
bb432d
diff -urNp mcelog-d2e13bf0.orig/leaky-bucket.c mcelog-d2e13bf0/leaky-bucket.c
bb432d
--- mcelog-d2e13bf0.orig/leaky-bucket.c	2016-11-30 11:23:54.537909435 -0500
bb432d
+++ mcelog-d2e13bf0/leaky-bucket.c	2016-11-30 11:24:12.206619450 -0500
bb432d
@@ -72,7 +72,9 @@ static int timeconv(char unit, int *out)
bb432d
 	case 'h': corr *= 60;
bb432d
 	case 'm': corr *= 60;
bb432d
 	case 0:   break;
bb432d
-	default: return -1;
bb432d
+	default:
bb432d
+		*out = 1;
bb432d
+		return -1;
bb432d
 	}
bb432d
 	*out = corr;
bb432d
 	return 0;
bb432d
diff -urNp mcelog-d2e13bf0.orig/Makefile mcelog-d2e13bf0/Makefile
bb432d
--- mcelog-d2e13bf0.orig/Makefile	2016-11-30 11:23:54.538909475 -0500
bb432d
+++ mcelog-d2e13bf0/Makefile	2016-11-30 11:24:12.202619289 -0500
bb432d
@@ -17,11 +17,6 @@ WARNINGS := -Wall -Wextra -Wno-missing-f
bb432d
 	    -Wstrict-prototypes -Wformat-security -Wmissing-declarations \
bb432d
 	    -Wdeclaration-after-statement
bb432d
 
bb432d
-# The on disk database has still many problems (partly in this code and partly
bb432d
-# due to missing support from BIOS), so it's disabled by default. You can 
bb432d
-# enable it here by uncommenting the following line
bb432d
-# CONFIG_DISKDB = 1
bb432d
-
bb432d
 TRIGGERS=cache-error-trigger dimm-error-trigger page-error-trigger \
bb432d
 	 socket-memory-error-trigger \
bb432d
 	 bus-error-trigger \
bb432d
@@ -36,23 +31,16 @@ OBJ := p4.o k8.o mcelog.o dmi.o tsc.o co
bb432d
        nehalem.o dunnington.o tulsa.o config.o memutil.o msg.o   \
bb432d
        eventloop.o leaky-bucket.o memdb.o server.o trigger.o 	 \
bb432d
        client.o cache.o sysfs.o yellow.o page.o rbtree.o 	 \
bb432d
-       xeon75xx.o sandy-bridge.o ivy-bridge.o haswell.o		 \
bb432d
+       sandy-bridge.o ivy-bridge.o haswell.o		 	 \
bb432d
        broadwell_de.o broadwell_epex.o skylake_xeon.o		 \
bb432d
+       denverton.o						 \
bb432d
        msr.o bus.o unknown.o
bb432d
-DISKDB_OBJ := diskdb.o dimm.o db.o
bb432d
-CLEAN := mcelog dmi tsc dbquery .depend .depend.X dbquery.o ${DISKDB_OBJ} \
bb432d
+CLEAN := mcelog dmi tsc dbquery .depend .depend.X dbquery.o \
bb432d
 	version.o version.c version.tmp
bb432d
 DOC := mce.pdf
bb432d
 
bb432d
 ADD_DEFINES :=
bb432d
 
bb432d
-ifdef CONFIG_DISKDB
bb432d
-ADD_DEFINES := -DCONFIG_DISKDB=1
bb432d
-OBJ += ${DISKDB_OBJ}
bb432d
-
bb432d
-all: dbquery
bb432d
-endif
bb432d
-
bb432d
 SRC := $(OBJ:.o=.c)
bb432d
 
bb432d
 mcelog: ${OBJ} version.o
bb432d
diff -urNp mcelog-d2e13bf0.orig/mcelog.c mcelog-d2e13bf0/mcelog.c
bb432d
--- mcelog-d2e13bf0.orig/mcelog.c	2016-11-30 11:23:54.531909194 -0500
bb432d
+++ mcelog-d2e13bf0/mcelog.c	2016-11-30 11:25:24.563516902 -0500
bb432d
@@ -48,7 +48,6 @@
bb432d
 #include "tsc.h"
bb432d
 #include "version.h"
bb432d
 #include "config.h"
bb432d
-#include "diskdb.h"
bb432d
 #include "memutil.h"
bb432d
 #include "eventloop.h"
bb432d
 #include "memdb.h"
bb432d
@@ -236,9 +235,12 @@ static char *cputype_name[] = {
bb432d
 	[CPU_BROADWELL_DE] = "Intel Xeon (Broadwell) D family",
bb432d
 	[CPU_BROADWELL_EPEX] = "Intel Xeon v4 (Broadwell) EP/EX",
bb432d
 	[CPU_KNIGHTS_LANDING] = "Knights Landing",
bb432d
+	[CPU_KNIGHTS_MILL] = "Knights Mill",
bb432d
 	[CPU_ATOM] = "ATOM",
bb432d
 	[CPU_SKYLAKE] = "Skylake",
bb432d
 	[CPU_SKYLAKE_XEON] = "Skylake server",
bb432d
+	[CPU_KABYLAKE] = "Kabylake",
bb432d
+	[CPU_DENVERTON] = "Denverton",
bb432d
 };
bb432d
 
bb432d
 static struct config_choice cpu_choices[] = {
bb432d
@@ -282,10 +284,13 @@ static struct config_choice cpu_choices[
bb432d
 	{ "broadwell-ep", CPU_BROADWELL_EPEX },
bb432d
 	{ "broadwell-ex", CPU_BROADWELL_EPEX },
bb432d
 	{ "knightslanding", CPU_KNIGHTS_LANDING },
bb432d
+	{ "knightsmill", CPU_KNIGHTS_MILL },
bb432d
 	{ "xeon-v4", CPU_BROADWELL_EPEX },
bb432d
 	{ "atom", CPU_ATOM },
bb432d
 	{ "skylake", CPU_SKYLAKE },
bb432d
 	{ "skylake_server", CPU_SKYLAKE_XEON },
bb432d
+	{ "kabylake", CPU_KABYLAKE },
bb432d
+	{ "denverton", CPU_DENVERTON },
bb432d
 	{ NULL }
bb432d
 };
bb432d
 
bb432d
@@ -356,7 +361,7 @@ static enum cputype setup_cpuid(u32 cpuv
bb432d
 			return CPU_K8;
bb432d
 		/* FALL THROUGH */
bb432d
 	default:
bb432d
-		Eprintf("Unknown CPU type vendor %u family %x model %x", 
bb432d
+		Eprintf("Unknown CPU type vendor %u family %u model %u",
bb432d
 			cpuvendor, family, model);
bb432d
 		return CPU_GENERIC;
bb432d
 	}
bb432d
@@ -449,12 +454,10 @@ static void dump_mce(struct mce *m, unsi
bb432d
 	if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX &&
bb432d
 	    cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL &&
bb432d
 	    cputype != CPU_BROADWELL_DE && cputype != CPU_BROADWELL_EPEX &&
bb432d
-	    cputype != CPU_KNIGHTS_LANDING && cputype != CPU_SKYLAKE &&
bb432d
-	    cputype != CPU_SKYLAKE_XEON)
bb432d
+	    cputype != CPU_KNIGHTS_LANDING && cputype != CPU_KNIGHTS_MILL &&
bb432d
+	    cputype != CPU_SKYLAKE && cputype != CPU_SKYLAKE_XEON &&
bb432d
+	    cputype != CPU_KABYLAKE && cputype != CPU_DENVERTON)
bb432d
 		resolveaddr(m->addr);
bb432d
-	if (!ascii_mode && ismemerr && (m->status & MCI_STATUS_ADDRV)) {
bb432d
-		diskdb_resolve_addr(m->addr);
bb432d
-	}
bb432d
 }
bb432d
 
bb432d
 static void dump_mce_raw_ascii(struct mce *m, unsigned recordlen)
bb432d
@@ -889,6 +892,7 @@ static void remove_pidfile(void)
bb432d
 static void signal_exit(int sig)
bb432d
 {
bb432d
 	remove_pidfile();
bb432d
+	client_cleanup();
bb432d
 	_exit(sig);
bb432d
 }
bb432d
 
bb432d
@@ -974,7 +978,6 @@ void usage(void)
bb432d
 "--no-imc-log	     Disable extended iMC logging\n"
bb432d
 "--is-cpu-supported  Exit with return code indicating whether the CPU is supported\n"
bb432d
 		);
bb432d
-	diskdb_usage();
bb432d
 	printf("\n");
bb432d
 	print_cputypes();
bb432d
 	exit(1);
bb432d
@@ -1043,7 +1046,6 @@ static struct option options[] = {
bb432d
 	{ "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */
bb432d
 	{ "no-imc-log", 0, NULL, O_NO_IMC_LOG },
bb432d
 	{ "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED },
bb432d
-	DISKDB_OPTIONS
bb432d
 	{}
bb432d
 };
bb432d
 
bb432d
@@ -1191,8 +1193,6 @@ void no_syslog(void)
bb432d
 static int combined_modifier(int opt)
bb432d
 {
bb432d
 	int r = modifier(opt);
bb432d
-	if (r == 0)
bb432d
-		r = diskdb_modifier(opt);
bb432d
 	return r;
bb432d
 }
bb432d
 
bb432d
@@ -1369,8 +1369,6 @@ int main(int ac, char **av)
bb432d
 			noargs(ac, av);
bb432d
 			fprintf(stderr, "mcelog %s\n", MCELOG_VERSION);
bb432d
 			exit(0);
bb432d
-		} else if (diskdb_cmd(opt, ac, av)) {
bb432d
-			exit(0);
bb432d
 		} else if (opt == 0)
bb432d
 			break;		    
bb432d
 	} 
bb432d
diff -urNp mcelog-d2e13bf0.orig/mcelog.c.orig mcelog-d2e13bf0/mcelog.c.orig
bb432d
--- mcelog-d2e13bf0.orig/mcelog.c.orig	2016-11-30 11:23:54.540909556 -0500
bb432d
+++ mcelog-d2e13bf0/mcelog.c.orig	2016-11-30 11:23:40.054327414 -0500
bb432d
@@ -85,6 +85,7 @@ static char *pidfile = pidfile_default;
bb432d
 static char *logfile;
bb432d
 static int debug_numerrors;
bb432d
 int imc_log = -1;
bb432d
+static int check_only = 0;
bb432d
 
bb432d
 static int is_cpu_supported(void);
bb432d
 
bb432d
@@ -131,7 +132,7 @@ static char *bankname(unsigned bank)
bb432d
 	}
bb432d
 } 
bb432d
 
bb432d
-static void resolveaddr(unsigned long addr)
bb432d
+static void resolveaddr(unsigned long long addr)
bb432d
 {
bb432d
 	if (addr && do_dmi && dmi_forced)
bb432d
 		dmi_decodeaddr(addr);
bb432d
@@ -232,8 +233,12 @@ static char *cputype_name[] = {
bb432d
 	[CPU_HASWELL] = "Haswell", /* Fill in better name */
bb432d
 	[CPU_HASWELL_EPEX] = "Haswell EP/EX", /* Fill in better name */
bb432d
 	[CPU_BROADWELL] = "Broadwell",
bb432d
+	[CPU_BROADWELL_DE] = "Intel Xeon (Broadwell) D family",
bb432d
+	[CPU_BROADWELL_EPEX] = "Intel Xeon v4 (Broadwell) EP/EX",
bb432d
 	[CPU_KNIGHTS_LANDING] = "Knights Landing",
bb432d
 	[CPU_ATOM] = "ATOM",
bb432d
+	[CPU_SKYLAKE] = "Skylake",
bb432d
+	[CPU_SKYLAKE_XEON] = "Skylake server",
bb432d
 };
bb432d
 
bb432d
 static struct config_choice cpu_choices[] = {
bb432d
@@ -273,8 +278,14 @@ static struct config_choice cpu_choices[
bb432d
 	{ "haswell-ep", CPU_HASWELL_EPEX }, /* Fill in better name */
bb432d
 	{ "haswell-ex", CPU_HASWELL_EPEX }, /* Fill in better name */
bb432d
 	{ "broadwell", CPU_BROADWELL },
bb432d
+	{ "broadwell-d", CPU_BROADWELL_DE },
bb432d
+	{ "broadwell-ep", CPU_BROADWELL_EPEX },
bb432d
+	{ "broadwell-ex", CPU_BROADWELL_EPEX },
bb432d
 	{ "knightslanding", CPU_KNIGHTS_LANDING },
bb432d
+	{ "xeon-v4", CPU_BROADWELL_EPEX },
bb432d
 	{ "atom", CPU_ATOM },
bb432d
+	{ "skylake", CPU_SKYLAKE },
bb432d
+	{ "skylake_server", CPU_SKYLAKE_XEON },
bb432d
 	{ NULL }
bb432d
 };
bb432d
 
bb432d
@@ -437,7 +448,9 @@ static void dump_mce(struct mce *m, unsi
bb432d
 	}
bb432d
 	if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX &&
bb432d
 	    cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL &&
bb432d
-	    cputype != CPU_KNIGHTS_LANDING)
bb432d
+	    cputype != CPU_BROADWELL_DE && cputype != CPU_BROADWELL_EPEX &&
bb432d
+	    cputype != CPU_KNIGHTS_LANDING && cputype != CPU_SKYLAKE &&
bb432d
+	    cputype != CPU_SKYLAKE_XEON)
bb432d
 		resolveaddr(m->addr);
bb432d
 	if (!ascii_mode && ismemerr && (m->status & MCI_STATUS_ADDRV)) {
bb432d
 		diskdb_resolve_addr(m->addr);
bb432d
@@ -916,22 +929,35 @@ void usage(void)
bb432d
 {
bb432d
 	fprintf(stderr, 
bb432d
 "Usage:\n"
bb432d
+"\n"
bb432d
 "  mcelog [options]  [mcelogdevice]\n"
bb432d
 "Decode machine check error records from current kernel.\n"
bb432d
+"\n"
bb432d
 "  mcelog [options] --daemon\n"
bb432d
 "Run mcelog in daemon mode, waiting for errors from the kernel.\n"
bb432d
+"\n"
bb432d
 "  mcelog [options] --client\n"
bb432d
 "Query a currently running mcelog daemon for errors\n"
bb432d
+"\n"
bb432d
 "  mcelog [options] --ascii < log\n"
bb432d
 "  mcelog [options] --ascii --file log\n"
bb432d
 "Decode machine check ASCII output from kernel logs\n"
bb432d
+"\n"
bb432d
 "Options:\n"  
bb432d
+"--version           Show the version of mcelog and exit\n"
bb432d
 "--cpu CPU           Set CPU type CPU to decode (see below for valid types)\n"
bb432d
+"--intel-cpu FAMILY,MODEL  Set CPU type for an Intel CPU based on family and model from cpuid\n"
bb432d
+"--k8                Set the CPU to be an AMD K8\n"
bb432d
+"--p4                Set the CPU to be an Intel Pentium4\n"
bb432d
+"--core2             Set the CPU to be an Intel Core2\n"
bb432d
+"--generic           Set the CPU to a generic version\n"
bb432d
 "--cpumhz MHZ        Set CPU Mhz to decode time (output unreliable, not needed on new kernels)\n"
bb432d
 "--raw		     (with --ascii) Dump in raw ASCII format for machine processing\n"
bb432d
 "--daemon            Run in background waiting for events (needs newer kernel)\n"
bb432d
+"--client            Query a currently running mcelog daemon for errors\n"
bb432d
 "--ignorenodev       Exit silently when the device cannot be opened\n"
bb432d
 "--file filename     With --ascii read machine check log from filename instead of stdin\n"
bb432d
+"--logfile filename  Log decoded machine checks in file filename\n"
bb432d
 "--syslog            Log decoded machine checks in syslog (default stdout or syslog for daemon)\n"	     
bb432d
 "--syslog-error	     Log decoded machine checks in syslog with error level\n"
bb432d
 "--no-syslog         Never log anything to syslog\n"
bb432d
@@ -946,8 +972,10 @@ void usage(void)
bb432d
 "--num-errors N      Only process N errors (for testing)\n"
bb432d
 "--pidfile file	     Write pid of daemon into file\n"
bb432d
 "--no-imc-log	     Disable extended iMC logging\n"
bb432d
+"--is-cpu-supported  Exit with return code indicating whether the CPU is supported\n"
bb432d
 		);
bb432d
 	diskdb_usage();
bb432d
+	printf("\n");
bb432d
 	print_cputypes();
bb432d
 	exit(1);
bb432d
 }
bb432d
@@ -980,6 +1008,7 @@ enum options {
bb432d
 	O_PIDFILE,
bb432d
 	O_DEBUG_NUMERRORS,
bb432d
 	O_NO_IMC_LOG,
bb432d
+	O_IS_CPU_SUPPORTED,
bb432d
 };
bb432d
 
bb432d
 static struct option options[] = {
bb432d
@@ -1013,6 +1042,7 @@ static struct option options[] = {
bb432d
 	{ "pidfile", 1, NULL, O_PIDFILE },
bb432d
 	{ "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */
bb432d
 	{ "no-imc-log", 0, NULL, O_NO_IMC_LOG },
bb432d
+	{ "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED },
bb432d
 	DISKDB_OPTIONS
bb432d
 	{}
bb432d
 };
bb432d
@@ -1115,6 +1145,9 @@ static int modifier(int opt)
bb432d
 	case O_NO_IMC_LOG:
bb432d
 		imc_log = 0;
bb432d
 		break;
bb432d
+	case O_IS_CPU_SUPPORTED:
bb432d
+		check_only = 1;
bb432d
+		break;
bb432d
 	case 0:
bb432d
 		break;
bb432d
 	default:
bb432d
@@ -1344,15 +1377,19 @@ int main(int ac, char **av)
bb432d
 
bb432d
 	/* before doing anything else let's see if the CPUs are supported */
bb432d
 	if (!cpu_forced && !is_cpu_supported()) {
bb432d
-		fprintf(stderr, "CPU is unsupported\n");
bb432d
+		if (!check_only)
bb432d
+			fprintf(stderr, "CPU is unsupported\n");
bb432d
 		exit(1);
bb432d
 	}
bb432d
+	if (check_only)
bb432d
+		exit(0);
bb432d
 
bb432d
 	/* If the user didn't tell us not to use iMC logging, check if CPU supports it */
bb432d
 	if (imc_log == -1) {
bb432d
 		switch (cputype) {
bb432d
 		case CPU_SANDY_BRIDGE_EP:
bb432d
 		case CPU_IVY_BRIDGE_EPEX:
bb432d
+		case CPU_HASWELL_EPEX:
bb432d
 			imc_log = 1;
bb432d
 			break;
bb432d
 		default:
bb432d
diff -urNp mcelog-d2e13bf0.orig/mcelog.h mcelog-d2e13bf0/mcelog.h
bb432d
--- mcelog-d2e13bf0.orig/mcelog.h	2016-11-30 11:23:54.539909515 -0500
bb432d
+++ mcelog-d2e13bf0/mcelog.h	2016-11-30 11:24:12.207619490 -0500
bb432d
@@ -127,9 +127,12 @@ enum cputype {
bb432d
 	CPU_BROADWELL_DE,
bb432d
 	CPU_BROADWELL_EPEX,
bb432d
 	CPU_KNIGHTS_LANDING,
bb432d
+	CPU_KNIGHTS_MILL,
bb432d
 	CPU_ATOM,
bb432d
 	CPU_SKYLAKE,
bb432d
 	CPU_SKYLAKE_XEON,
bb432d
+	CPU_KABYLAKE,
bb432d
+	CPU_DENVERTON,
bb432d
 };
bb432d
 
bb432d
 enum option_ranges {
bb432d
diff -urNp mcelog-d2e13bf0.orig/mcelog.service mcelog-d2e13bf0/mcelog.service
bb432d
--- mcelog-d2e13bf0.orig/mcelog.service	2016-11-30 11:23:54.540909556 -0500
bb432d
+++ mcelog-d2e13bf0/mcelog.service	2016-11-30 11:24:12.207619490 -0500
bb432d
@@ -5,6 +5,7 @@ After=syslog.target
bb432d
 [Service] 
bb432d
 ExecStart=/usr/sbin/mcelog --ignorenodev --daemon --foreground
bb432d
 StandardOutput=syslog 
bb432d
+SuccessExitStatus=0 15
bb432d
 
bb432d
 [Install]
bb432d
 WantedBy=multi-user.target
bb432d
diff -urNp mcelog-d2e13bf0.orig/msr.c mcelog-d2e13bf0/msr.c
bb432d
--- mcelog-d2e13bf0.orig/msr.c	2016-11-30 11:23:54.538909475 -0500
bb432d
+++ mcelog-d2e13bf0/msr.c	2016-11-30 11:24:12.207619490 -0500
bb432d
@@ -25,19 +25,20 @@ static void domsr(int cpu, int msr, int
bb432d
 	}
bb432d
 	if (pread(fd, &data, sizeof data, msr) != sizeof data) {
bb432d
 		SYSERRprintf("Cannot read MSR_ERROR_CONTROL from %s\n", fpath);
bb432d
-		return;
bb432d
+		goto out;
bb432d
 	}
bb432d
 	data |= bit;
bb432d
 	if (pwrite(fd, &data, sizeof data, msr) != sizeof data) {
bb432d
 		SYSERRprintf("Cannot write MSR_ERROR_CONTROL to %s\n", fpath);
bb432d
-		return;
bb432d
+		goto out;
bb432d
 	}
bb432d
 	if (pread(fd, &data, sizeof data, msr) != sizeof data) {
bb432d
 		SYSERRprintf("Cannot re-read MSR_ERROR_CONTROL from %s\n", fpath);
bb432d
-		return;
bb432d
+		goto out;
bb432d
 	}
bb432d
 	if ((data & bit) == 0)
bb432d
 		Lprintf("No DIMM detection available on cpu %d (normal in virtual environments)\n", cpu);
bb432d
+out:
bb432d
 	close(fd);
bb432d
 }
bb432d
 
bb432d
diff -urNp mcelog-d2e13bf0.orig/nehalem.c mcelog-d2e13bf0/nehalem.c
bb432d
--- mcelog-d2e13bf0.orig/nehalem.c	2016-11-30 11:23:54.537909435 -0500
bb432d
+++ mcelog-d2e13bf0/nehalem.c	2016-11-30 11:24:12.207619490 -0500
bb432d
@@ -24,7 +24,6 @@
bb432d
 #include "nehalem.h"
bb432d
 #include "bitfield.h"
bb432d
 #include "memdb.h"
bb432d
-#include "xeon75xx.h"
bb432d
 
bb432d
 /* See IA32 SDM Vol3B Appendix E.3.2 ff */
bb432d
 
bb432d
@@ -130,7 +129,8 @@ void decode_memory_controller(u32 status
bb432d
 	if ((status & 0xf) == 0xf) 
bb432d
 		strcpy(channel, "unspecified"); 
bb432d
 	else {
bb432d
-		if (cputype == CPU_KNIGHTS_LANDING) /* Fix for Knights Landing MIC */
bb432d
+        /* Fix for Knights Landing/Mill MIC */
bb432d
+		if (cputype == CPU_KNIGHTS_LANDING || cputype == CPU_KNIGHTS_MILL)
bb432d
 			sprintf(channel, "%u", (status & 0xf) + 3 * (bank == 15));
bb432d
 		else
bb432d
 			sprintf(channel, "%u", status & 0xf);
bb432d
@@ -170,7 +170,6 @@ void xeon75xx_decode_model(struct mce *m
bb432d
 		decode_bitfield(status, internal_error_status);
bb432d
 		decode_numfield(status, internal_error_numbers);
bb432d
 	}
bb432d
-	xeon75xx_decode_dimm(m, msize);
bb432d
 }
bb432d
 
bb432d
 /* Nehalem-EP specific DIMM decoding */
bb432d
diff -urNp mcelog-d2e13bf0.orig/p4.c mcelog-d2e13bf0/p4.c
bb432d
--- mcelog-d2e13bf0.orig/p4.c	2016-11-30 11:23:54.534909314 -0500
bb432d
+++ mcelog-d2e13bf0/p4.c	2016-11-30 11:24:12.208619530 -0500
bb432d
@@ -39,6 +39,7 @@
bb432d
 #include "broadwell_de.h"
bb432d
 #include "broadwell_epex.h"
bb432d
 #include "skylake_xeon.h"
bb432d
+#include "denverton.h"
bb432d
 
bb432d
 /* decode mce for P4/Xeon and Core2 family */
bb432d
 
bb432d
@@ -289,10 +290,29 @@ static const char *arstate[4] = {
bb432d
 	[3] = "SRAR"
bb432d
 };
bb432d
 
bb432d
+static const char *ce_types[] = {
bb432d
+	[0] = "ecc",
bb432d
+	[1] = "mirroring with channel failover",
bb432d
+	[2] = "mirroring. Primary channel scrubbed successfully"
bb432d
+};
bb432d
+
bb432d
+static int check_for_mirror(__u8 bank, __u64  status, __u64 misc)
bb432d
+{
bb432d
+	switch (cputype) {
bb432d
+	case CPU_BROADWELL_EPEX:
bb432d
+		return bdw_epex_ce_type(bank, status, misc);
bb432d
+	case CPU_SKYLAKE_XEON:
bb432d
+		return skylake_s_ce_type(bank, status, misc);
bb432d
+	default:
bb432d
+		return 0;
bb432d
+	}
bb432d
+}
bb432d
+
bb432d
 static int decode_mci(__u64 status, __u64 misc, int cpu, unsigned mcgcap, int *ismemerr,
bb432d
 		       int socket, __u8 bank)
bb432d
 {
bb432d
 	u64 track = 0;
bb432d
+	int i;
bb432d
 
bb432d
 	Wprintf("MCi status:\n");
bb432d
 	if (!(status & MCI_STATUS_VAL))
bb432d
@@ -303,6 +323,8 @@ static int decode_mci(__u64 status, __u6
bb432d
 	
bb432d
 	if (status & MCI_STATUS_UC) 
bb432d
 		Wprintf("Uncorrected error\n");
bb432d
+	else if ((i = check_for_mirror(bank, status, misc)))
bb432d
+		Wprintf("Corrected error by %s\n", ce_types[i]);
bb432d
 	else
bb432d
 		Wprintf("Corrected error\n");
bb432d
 
bb432d
@@ -428,6 +450,9 @@ void decode_intel_mc(struct mce *log, in
bb432d
 	case CPU_SKYLAKE_XEON:
bb432d
 		skylake_s_decode_model(cputype, log->bank, log->status, log->misc);
bb432d
 		break;
bb432d
+	case CPU_DENVERTON:
bb432d
+		denverton_decode_model(cputype, log->bank, log->status, log->misc);
bb432d
+		break;
bb432d
 	}
bb432d
 }
bb432d
 
bb432d
diff -urNp mcelog-d2e13bf0.orig/README mcelog-d2e13bf0/README
bb432d
--- mcelog-d2e13bf0.orig/README	2016-11-30 11:23:54.538909475 -0500
bb432d
+++ mcelog-d2e13bf0/README	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,119 +0,0 @@
bb432d
-mcelog is the user space backend for logging machine check errors
bb432d
-reported by the hardware to the kernel. The kernel does the immediate
bb432d
-actions (like killing processes etc.) and mcelog decodes the errors
bb432d
-and manages various other advanced error responses like
bb432d
-offlining memory, CPUs or triggering events. In addition
bb432d
-mcelog also handles corrected errors, by logging and accounting them.
bb432d
-
bb432d
-It primarily handles machine checks and thermal events, which
bb432d
-are reported for errors detected by the CPU.
bb432d
-
bb432d
-For more details on what mcelog can do and the underlying theory
bb432d
-see http://www.mcelog.org
bb432d
-
bb432d
-It is recommended that mcelog runs on all x86 machines, both
bb432d
-64bit (since early 2.6) and 32bit (since 2.6.32)
bb432d
-
bb432d
-mcelog can run in several modi: cronjob, trigger, daemon
bb432d
-
bb432d
-cronjob is the old method. mcelog runs every 5 minutes from cron and checks
bb432d
-for errors. Disadvantage of this is that it can delay error reporting 
bb432d
-significantly (upto 10 minutes) and does not allow mcelog to keep extended state.
bb432d
-
bb432d
-trigger is a newer method where the kernel runs mcelog on a error.
bb432d
-This is configured with 
bb432d
-echo /usr/sbin/mcelog > /sys/devices/system/machinecheck/machinecheck0/trigger
bb432d
-This is faster, but still doesn't allow mcelog to keep state,
bb432d
-and has relatively high overhead for each error because a program has
bb432d
-to be initialized from scratch.
bb432d
-
bb432d
-In daemon mode mcelog runs continuously as a daemon in the background
bb432d
-and wait for errors. It is enabled by running mcelog --daemon & 
bb432d
-from a init script. This is the fastest and most feature-ful.
bb432d
-
bb432d
-The recommended mode is daemon, because several new functions (like page error
bb432d
-predictive failure analysis) require a continuously running daemon.
bb432d
-
bb432d
-Documentation:
bb432d
-
bb432d
-The primary reference documentation are the man pages.
bb432d
-lk10-mcelog.pdf has a overview over the errors mcelog handles
bb432d
-(originally from Linux Kongress 2010)
bb432d
-mce.pdf is a very old paper describing the first releases of mcelog
bb432d
-(some parts are obsolete)
bb432d
-
bb432d
-For distributors:
bb432d
-
bb432d
-You can run mcelog from systemd or similar daemons. An example
bb432d
-systemd unit file is in mcelog.service.
bb432d
-
bb432d
-For older distributions using init scripts:
bb432d
-
bb432d
-Please install a init script by default that runs mcelog in daemon mode.
bb432d
-The mcelog.init script is a good starting point.
bb432d
-
bb432d
-Also install a logrotated file (mcelog.logrotate) or equivalent 
bb432d
-when mcelog is running in daemon mode. 
bb432d
-
bb432d
-These two are not in make install.
bb432d
-
bb432d
-The installation also requires a config file (/etc/mcelog.conf) and
bb432d
-the default triggers. These are all installed by "make install"
bb432d
-
bb432d
-/dev/mcelog is needed for mcelog operation
bb432d
-If it's not there it can be created with mknod /dev/mcelog c 10 227
bb432d
-Normally it should be created automatically in udev.
bb432d
-
bb432d
-Security:
bb432d
-
bb432d
-mcelog needs to run as root because it might trigger actions like
bb432d
-page-offlining, which require CAP_SYS_ADMIN. Also it opens /dev/mcelog
bb432d
-and a unix socket for client support.
bb432d
-
bb432d
-It also opens /dev/mem to parse the BIOS DMI tables. It is careful
bb432d
-to close the file descriptor and unmap any mappings after using them.
bb432d
-
bb432d
-There is support for changing the user in daemon mode after opening
bb432d
-the device and the sockets, but that would stop triggers from
bb432d
-doing corrective action that require root.
bb432d
-
bb432d
-In principle it would be possible to only keep CAP_SYS_ADMIN
bb432d
-for page-offling, but that would prevent triggers from doing root
bb432d
-only actions not covered by it (and CAP_SYS_ADMIN is not that different 
bb432d
-from full root)
bb432d
-
bb432d
-In daemon mode mcelog listens to a unix socket and processes
bb432d
-requests from mcelog --client. This can be disabled in the configuration file.
bb432d
-The uid/gid of the requestor is checked on access and is configurable
bb432d
-(default 0/0 only). The command parsing code is very straight forward
bb432d
-(server.c) The client parsing/reply is currently done with full privileges
bb432d
-of the daemon.
bb432d
-
bb432d
-Testing:
bb432d
-
bb432d
-There is a simple test suite in tests/. The test suite requires root to 
bb432d
-run and access to mce-inject and a kernel with MCE injection support 
bb432d
-(CONFIG_X86_MCE_INJECT).  It will kill any running mcelog daemon.
bb432d
-
bb432d
-Run it with "make test"
bb432d
-
bb432d
-The test suite requires the mce-inject tool, available from
bb432d
-git://git.kernel.org/pub/utils/cpu/mce/mce-inject.git
bb432d
-The mce-inject executable must be either in $PATH or in the
bb432d
-../mce-inject directory.
bb432d
-
bb432d
-You can also test under valgrind with "make valgrind-test". For 
bb432d
-this valgrind needs to be installed of course.  Advanced
bb432d
-valgrind options can be specified with 
bb432d
-make VALGRIND="valgrind --option" valgrind-test
bb432d
-
bb432d
-Other checks:
bb432d
-
bb432d
-make iccverify and make clangverify run the static verifiers
bb432d
-in clang and icc respectively.
bb432d
-
bb432d
-License:
bb432d
-
bb432d
-This program is licensed under the subject of the GNU Public General
bb432d
-License, v.2
bb432d
-
bb432d
diff -urNp mcelog-d2e13bf0.orig/README.md mcelog-d2e13bf0/README.md
bb432d
--- mcelog-d2e13bf0.orig/README.md	1969-12-31 19:00:00.000000000 -0500
bb432d
+++ mcelog-d2e13bf0/README.md	2016-11-30 11:24:12.202619289 -0500
bb432d
@@ -0,0 +1,129 @@
bb432d
+# mcelog
bb432d
+
bb432d
+mcelog is the user space backend for logging machine check errors reported
bb432d
+by the hardware to the kernel. The kernel does the immediate actions
bb432d
+(like killing processes etc.) and mcelog decodes the errors and manages
bb432d
+various other advanced error responses like offlining memory, CPUs or triggering
bb432d
+events. In addition mcelog also handles corrected errors, by logging and
bb432d
+accounting them.
bb432d
+It primarily handles machine checks and thermal events, which are reported
bb432d
+for errors detected by the CPU.
bb432d
+
bb432d
+For more details on what mcelog can do and the underlying theory
bb432d
+see [mcelog.org](http://www.mcelog.org).
bb432d
+
bb432d
+It is recommended that mcelog runs on all x86 machines, both 64bit
bb432d
+(since early 2.6) and 32bit (since 2.6.32).
bb432d
+
bb432d
+mcelog can run in several modes:
bb432d
+
bb432d
+- cronjob
bb432d
+- trigger
bb432d
+- daemon
bb432d
+
bb432d
+**cronjob** is the old method. mcelog runs every 5 minutes from cron and checks
bb432d
+for errors. Disadvantage of this is that it can delay error reporting
bb432d
+significantly (upto 10 minutes) and does not allow mcelog to keep extended state.
bb432d
+
bb432d
+**trigger** is a newer method where the kernel runs mcelog on a error.
bb432d
+
bb432d
+This is configured with:
bb432d
+```sh
bb432d
+echo /usr/sbin/mcelog > /sys/devices/system/machinecheck/machinecheck0/trigger
bb432d
+```
bb432d
+This is faster, but still doesn't allow mcelog to keep state,
bb432d
+and has relatively high overhead for each error because a program has
bb432d
+to be initialized from scratch.
bb432d
+
bb432d
+In **daemon** mode mcelog runs continuously as a daemon in the background and
bb432d
+wait for errors. It is enabled by running `mcelog --daemon &`
bb432d
+from a init script. This is the fastest and most feature-ful.
bb432d
+
bb432d
+The recommended mode is **daemon**, because several new functions (like page
bb432d
+error predictive failure analysis) require a continuously running daemon.
bb432d
+
bb432d
+## Documentation
bb432d
+
bb432d
+- The primary reference documentation are the man pages.
bb432d
+- [lk10-mcelog.pdf](https://github.com/andikleen/mcelog/blob/master/lk10-mcelog.pdf)
bb432d
+  has a overview over the errors mcelog handles (originally from Linux Kongress 2010).
bb432d
+- [mce.pdf](https://github.com/mjtrangoni/mcelog/blob/README.md/mce.pdf)
bb432d
+  is a very old paper describing the first releases of mcelog (some parts are obsolete).
bb432d
+
bb432d
+## For distributors
bb432d
+
bb432d
+You can run mcelog from systemd or similar daemons. An example systemd unit
bb432d
+file is in `mcelog.service`.
bb432d
+
bb432d
+### For older distributions using init scripts
bb432d
+
bb432d
+Please install an init script by default that runs mcelog in daemon mode.
bb432d
+The `mcelog.init` script is a good starting point. Also install a
bb432d
+logrotated file (mcelog.logrotate) or equivalent when mcelog is running
bb432d
+in daemon mode.
bb432d
+These two are not in make install.
bb432d
+
bb432d
+The installation also requires a config file `/etc/mcelog.conf` and the default
bb432d
+triggers. These are all installed by `make install`
bb432d
+
bb432d
+`/dev/mcelog` is needed for mcelog operation. If it's not there it can be
bb432d
+created with:
bb432d
+```sh
bb432d
+mknod /dev/mcelog c 10 227
bb432d
+```
bb432d
+
bb432d
+Normally it should be created automatically in udev.
bb432d
+
bb432d
+## Security
bb432d
+
bb432d
+mcelog needs to run as root because it might trigger actions like
bb432d
+page-offlining, which require `CAP_SYS_ADMIN`. Also it opens `/dev/mcelog`
bb432d
+and an UNIX socket for client support.
bb432d
+
bb432d
+It also opens `/dev/mem` to parse the BIOS DMI tables. It is careful to close
bb432d
+the file descriptor and unmap any mappings after using them.
bb432d
+
bb432d
+There is support for changing the user in daemon mode after opening the device
bb432d
+and the sockets, but that would stop triggers from doing corrective action
bb432d
+that require `root`.
bb432d
+
bb432d
+In principle it would be possible to only keep `CAP_SYS_ADMIN` for page-offling,
bb432d
+but that would prevent triggers from doing root-only actions not covered by
bb432d
+it (and `CAP_SYS_ADMIN` is not that different from full root)
bb432d
+
bb432d
+In `daemon` mode mcelog listens to a UNIX socket and processes requests from
bb432d
+`sh mcelog --client`. This can be disabled in the configuration file.
bb432d
+The uid/gid of the requestor is checked on access and is configurable
bb432d
+(default 0/0 only). The command parsing code is very straight forward
bb432d
+(server.c). The client parsing/reply is currently done with full privileges
bb432d
+of the `daemon`.
bb432d
+
bb432d
+## Testing
bb432d
+
bb432d
+There is a simple test suite in `sh tests/`. The test suite requires root to
bb432d
+run and access to mce-inject and a kernel with MCE injection support
bb432d
+`CONFIG_X86_MCE_INJECT`.  It will kill any running mcelog daemon.
bb432d
+
bb432d
+Run it with `sh make test`.
bb432d
+
bb432d
+The test suite requires the
bb432d
+[mce-inject](git://git.kernel.org/pub/utils/cpu/mce/mce-inject.git) tool.
bb432d
+The `mce-inject` executable must be either in `$PATH` or in the
bb432d
+`../mce-inject` directory.
bb432d
+
bb432d
+You can also test under **valgrind** with `sh make valgrind-test`. For this
bb432d
+valgrind needs to be installed of course. Advanced valgrind options can be
bb432d
+specified with:
bb432d
+```sh
bb432d
+make VALGRIND="valgrind --option" valgrind-test
bb432d
+```
bb432d
+
bb432d
+### Other checks
bb432d
+
bb432d
+`make iccverify` and `make clangverify` run the static verifiers in *clang*
bb432d
+and *icc* respectively.
bb432d
+
bb432d
+## License
bb432d
+
bb432d
+This program is licensed under the subject of the GNU Public General
bb432d
+License, v.2
bb432d
diff -urNp mcelog-d2e13bf0.orig/skylake_xeon.c mcelog-d2e13bf0/skylake_xeon.c
bb432d
--- mcelog-d2e13bf0.orig/skylake_xeon.c	2016-11-30 11:23:54.538909475 -0500
bb432d
+++ mcelog-d2e13bf0/skylake_xeon.c	2016-11-30 11:24:12.208619530 -0500
bb432d
@@ -23,6 +23,11 @@
bb432d
 #include "skylake_xeon.h"
bb432d
 #include "memdb.h"
bb432d
 
bb432d
+/* Memory error was corrected by mirroring with channel failover */
bb432d
+#define SKX_MCI_MISC_FO      (1ULL<<63)
bb432d
+/* Memory error was corrected by mirroring and primary channel scrubbed successfully */
bb432d
+#define SKX_MCI_MISC_MC      (1ULL<<62)
bb432d
+
bb432d
 /* See IA32 SDM Vol3B Table 16-27 */
bb432d
 
bb432d
 static char *pcu_1[] = {
bb432d
@@ -208,3 +213,18 @@ void skylake_s_decode_model(int cputype,
bb432d
 		break;
bb432d
 	}
bb432d
 }
bb432d
+
bb432d
+int skylake_s_ce_type(int bank, u64 status, u64 misc)
bb432d
+{
bb432d
+	if (!(bank == 7 || bank == 8))
bb432d
+		return 0;
bb432d
+
bb432d
+	if (status & MCI_STATUS_MISCV) {
bb432d
+		if (misc & SKX_MCI_MISC_FO)
bb432d
+			return 1;
bb432d
+		if (misc & SKX_MCI_MISC_MC)
bb432d
+			return 2;
bb432d
+	}
bb432d
+
bb432d
+	return 0;
bb432d
+}
bb432d
diff -urNp mcelog-d2e13bf0.orig/skylake_xeon.h mcelog-d2e13bf0/skylake_xeon.h
bb432d
--- mcelog-d2e13bf0.orig/skylake_xeon.h	2016-11-30 11:23:54.539909515 -0500
bb432d
+++ mcelog-d2e13bf0/skylake_xeon.h	2016-11-30 11:24:12.208619530 -0500
bb432d
@@ -1 +1,2 @@
bb432d
 void skylake_s_decode_model(int cputype, int bank, u64 status, u64 misc);
bb432d
+int skylake_s_ce_type(int bank, u64 status, u64 misc);
bb432d
diff -urNp mcelog-d2e13bf0.orig/sysfs.c mcelog-d2e13bf0/sysfs.c
bb432d
--- mcelog-d2e13bf0.orig/sysfs.c	2016-11-30 11:23:54.534909314 -0500
bb432d
+++ mcelog-d2e13bf0/sysfs.c	2016-11-30 11:24:12.208619530 -0500
bb432d
@@ -37,10 +37,10 @@ char *read_field(char *base, char *name)
bb432d
 
bb432d
 	asprintf(&fn, "%s/%s", base, name);
bb432d
 	fd = open(fn, O_RDONLY);
bb432d
+	free(fn);
bb432d
 	if (fstat(fd, &st) < 0)
bb432d
 		goto bad;		
bb432d
 	buf = xalloc(st.st_size);
bb432d
-	free(fn);
bb432d
 	if (fd < 0) 
bb432d
 		goto bad;
bb432d
 	n = read(fd, buf, st.st_size);
bb432d
@@ -81,10 +81,12 @@ unsigned read_field_map(char *base, char
bb432d
 		if (!strcmp(val, map->name))
bb432d
 			break;
bb432d
 	}
bb432d
-	free(val);
bb432d
-	if (map->name)
bb432d
+	if (map->name) {
bb432d
+		free(val);
bb432d
 		return map->value;
bb432d
+	}
bb432d
 	Eprintf("sysfs field %s/%s has unknown string value `%s'\n", base, name, val);
bb432d
+	free(val);
bb432d
 	return -1;
bb432d
 }
bb432d
 
bb432d
diff -urNp mcelog-d2e13bf0.orig/TODO-diskdb mcelog-d2e13bf0/TODO-diskdb
bb432d
--- mcelog-d2e13bf0.orig/TODO-diskdb	2016-11-30 11:23:54.530909154 -0500
bb432d
+++ mcelog-d2e13bf0/TODO-diskdb	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,31 +0,0 @@
bb432d
-
bb432d
-diskdb was a experimental attempt to track errors per DIMM
bb432d
-on disk. It ran into problems unfortunately.
bb432d
-
bb432d
-diskdb is not compiled by default now. It can be enabled with 
bb432d
-make CONFIG_DISKDB=1
bb432d
-
bb432d
-It is replaced with a new memory only database now that
bb432d
-relies on daemon mode.
bb432d
-
bb432d
-Open fundamental issues:
bb432d
-- DIMM tracking over boot doesn't work due to SMBIOS not reporting
bb432d
-serial numbers
bb432d
-
bb432d
-Code problems:
bb432d
-- Missing aging
bb432d
-- For Intel Nehalem CE errors need reverse smbios translation
bb432d
-- SMBIOS interleaving decoding missing
bb432d
-- Some crash races in db.c (see comments there)
bb432d
-- Need lock timeout
bb432d
-- Default enable/disable heuristics (smbios check etc.)
bb432d
-- write db test suite (with crash)
bb432d
-
bb432d
-General:
bb432d
-- Missing CPU database
bb432d
-
bb432d
-Missing:
bb432d
-- rename to different name without memory
bb432d
-
bb432d
-Old:
bb432d
-- add ifdef for memory because it's broken
bb432d
diff -urNp mcelog-d2e13bf0.orig/xeon75xx.c mcelog-d2e13bf0/xeon75xx.c
bb432d
--- mcelog-d2e13bf0.orig/xeon75xx.c	2016-11-30 11:23:54.537909435 -0500
bb432d
+++ mcelog-d2e13bf0/xeon75xx.c	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,39 +0,0 @@
bb432d
-/* Copyright (C) 2009/2010 Intel Corporation
bb432d
-
bb432d
-   Decode Intel Xeon75xx memory errors. Requires the mce-75xx.ko driver
bb432d
-   load. The core errors are the same as Nehalem.
bb432d
-
bb432d
-   mcelog is free software; you can redistribute it and/or
bb432d
-   modify it under the terms of the GNU General Public
bb432d
-   License as published by the Free Software Foundation; version
bb432d
-   2.
bb432d
-
bb432d
-   mcelog is distributed in the hope that it will be useful,
bb432d
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
bb432d
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
bb432d
-   General Public License for more details.
bb432d
-
bb432d
-   You should find a copy of v2 of the GNU General Public License somewhere
bb432d
-   on your Linux system; if not, write to the Free Software Foundation, 
bb432d
-   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
bb432d
-
bb432d
-   Author: Andi Kleen 
bb432d
-*/
bb432d
-
bb432d
-#include <stdio.h>
bb432d
-#include <stddef.h>
bb432d
-#include "mcelog.h"
bb432d
-#include "xeon75xx.h"
bb432d
-
bb432d
-/* This used to decode the old xeon 75xx memory error aux format. But that has never
bb432d
-   been merged into mainline kernels, so removed it again. */
bb432d
-
bb432d
-void 
bb432d
-xeon75xx_memory_error(struct mce *m, unsigned msize, int *channel, int *dimm)
bb432d
-{
bb432d
-}
bb432d
-
bb432d
-
bb432d
-void xeon75xx_decode_dimm(struct mce *m, unsigned msize)
bb432d
-{
bb432d
-}
bb432d
diff -urNp mcelog-d2e13bf0.orig/xeon75xx.h mcelog-d2e13bf0/xeon75xx.h
bb432d
--- mcelog-d2e13bf0.orig/xeon75xx.h	2016-11-30 11:23:54.537909435 -0500
bb432d
+++ mcelog-d2e13bf0/xeon75xx.h	1969-12-31 19:00:00.000000000 -0500
bb432d
@@ -1,2 +0,0 @@
bb432d
-void xeon75xx_memory_error(struct mce *m, unsigned msize, int *channel, int *dimm);
bb432d
-void xeon75xx_decode_dimm(struct mce *m, unsigned msize);