From bef63324de7c2f6426ef7525225cc80b3561c74f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 10 2018 05:46:13 +0000 Subject: import mcelog-144-8.94d853b2ea81.el7 --- diff --git a/SOURCES/mcelog-patch-0755b55af.patch b/SOURCES/mcelog-patch-0755b55af.patch new file mode 100644 index 0000000..391ca15 --- /dev/null +++ b/SOURCES/mcelog-patch-0755b55af.patch @@ -0,0 +1,45 @@ +From: Prarit Bhargava + +Subject: Makefile: Make `git` check portable (POSIX compatible) + +commit 0755b55afbf76fcacc31e98bb8c163c8e055ccb2 +Author: Paul Menzel +Date: Mon Jan 30 15:56:41 2017 +0100 + + Makefile: Make `git` check portable (POSIX compatible) + + On systems using not the *GNU Bourne-Again SHell* (bash) as shell, the + git check might fail. This happens on Debian systems where the *Debian + Almquist Shell* (dash) is used by default for `/bin/sh`. + + As a result, after running `make` the file `version.c` always contains + `unknown` instead of the correct version. + + The problem is, that `type -p git` is not portable. Use `command -v` + instead [1][2]. + + > Where bash is your shell/hashbang, consistently use hash (for + > commands) or type (to consider built-ins & keywords). + > + > When writing a POSIX script, use command -v. + + Fixes: #42 + + [1] https://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script + "Check if a program exists from a Bash script" + [2] https://unix.stackexchange.com/questions/85249/why-not-use-which-what-to-use-then + "Why not use “which”? What to use then?" + +diff --git a/Makefile b/Makefile +index 9dbbdbf8eb97e21a6d2efee7f308c1e7e742845b..e4341fceb882597ceebb56883625338c89923ee0 100644 +--- a/Makefile ++++ b/Makefile +@@ -82,7 +82,7 @@ depend: .depend + + version.tmp: FORCE + ( echo -n "char version[] = \"" ; \ +- if type -p git >/dev/null; then \ ++ if command -v git >/dev/null; then \ + if [ -d .git ] ; then \ + git describe --tags HEAD | tr -d '\n'; \ + else \ diff --git a/SOURCES/mcelog-patch-59b8cab3f.patch b/SOURCES/mcelog-patch-59b8cab3f.patch new file mode 100644 index 0000000..bba7666 --- /dev/null +++ b/SOURCES/mcelog-patch-59b8cab3f.patch @@ -0,0 +1,99 @@ +From: Prarit Bhargava + +Subject: mcelog version: Add ability for OS to define version + +commit 59b8cab3f607573cb55b6841ece2f2577be6b419 +Author: Prarit Bhargava +Date: Mon May 22 10:25:57 2017 -0400 + + mcelog version: Add ability for OS to define version + + Example usage of this patch: + + [root@intel-purley-03 mcelog]# cat .os_version + mcelog-144-3.94d853b2ea81.el7 + [root@intel-purley-03 mcelog]# make version.tmp + ( printf "char version[] = \"" ; \ + if test -e .os_version; then \ + cat .os_version | tr -d '\n' ; \ + elif command -v git >/dev/null; then \ + if [ -d .git ] ; then \ + git describe --tags HEAD | tr -d '\n'; \ + else \ + printf "unknown" ; \ + fi ; \ + else \ + printf "unknown" ; \ + fi ; \ + printf '";\n' \ + ) > version.tmp + [root@intel-purley-03 mcelog]# cat version.tmp + char version[] = "mcelog-144-3.94d853b2ea81.el7"; + [root@intel-purley-03 mcelog]# rm .os_version + rm: remove regular file ‘.os_version’? y + [root@intel-purley-03 mcelog]# make version.tmp + ( printf "char version[] = \"" ; \ + if test -e .os_version; then \ + cat .os_version | tr -d '\n' ; \ + elif command -v git >/dev/null; then \ + if [ -d .git ] ; then \ + git describe --tags HEAD | tr -d '\n'; \ + else \ + printf "unknown" ; \ + fi ; \ + else \ + printf "unknown" ; \ + fi ; \ + printf '";\n' \ + ) > version.tmp + [root@intel-purley-03 mcelog]# cat version.tmp + char version[] = "v149-7-g62e645e4c0e9"; + + ----8<---- + + OSes package mcelog (rpm, deb, etc.) and the package version may differ + from the git version. + + Add the ability for the OS to define a version in a local .os_version + file. If the file exists, the version in the file is returned for + 'mcelog --version'. If the file isn't specified the old method of using + git and defaulting to 'unknown' are used. + + Signed-off-by: Prarit Bhargava + Signed-off-by: Andi Kleen + +diff --git a/Makefile b/Makefile +index 864378eb72de315f07d424540509e844241fd932..57373afaf6c77f40d2188dc855c5bc2bd5a02657 100644 +--- a/Makefile ++++ b/Makefile +@@ -81,16 +81,20 @@ depend: .depend + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(WARNINGS) $(ADD_DEFINES) -o $@ $< + + version.tmp: FORCE +- ( echo -n "char version[] = \"" ; \ +- if command -v git >/dev/null; then \ +- if [ -d .git ] ; then \ +- git describe --tags HEAD | tr -d '\n'; \ +- else \ +- echo -n "unknown" ; \ +- fi ; \ +- else echo -n "unknown" ; fi ; \ +- echo '";' \ +- ) > version.tmp ++ ( printf "char version[] = \"" ; \ ++ if test -e .os_version; then \ ++ cat .os_version | tr -d '\n' ; \ ++ elif command -v git >/dev/null; then \ ++ if [ -d .git ] ; then \ ++ git describe --tags HEAD | tr -d '\n'; \ ++ else \ ++ printf "unknown" ; \ ++ fi ; \ ++ else \ ++ printf "unknown" ; \ ++ fi ; \ ++ printf '";\n' \ ++ ) > version.tmp + + version.c: version.tmp + cmp version.tmp version.c || mv version.tmp version.c diff --git a/SOURCES/mcelog-patch-commit-916015663906.patch b/SOURCES/mcelog-patch-commit-916015663906.patch new file mode 100644 index 0000000..518a18c --- /dev/null +++ b/SOURCES/mcelog-patch-commit-916015663906.patch @@ -0,0 +1,157 @@ +From: Prarit Bhargava + +Subject: mcelog: Add --help option. + +commit 91601566390676d3c590bbe4b680f4009b6caa22 +Author: Prarit Bhargava +Date: Thu Oct 12 13:35:33 2017 -0400 + + mcelog: Add --help option. + + The mcelog man page states "See mcelog --help for a list of valid CPUs.". + This command returns 1 because --help is not a valid option. + + Separate the exit(1) from the usage() function and add a --help option. + + Signed-off-by: Prarit Bhargava + Signed-off-by: Andi Kleen + +diff --git a/mcelog.c b/mcelog.c +index 507f11bdbccb87cad45a2f182edd2a8146bd89f3..58a0aac26b53fa382567e034b2e2a8f25735e3aa 100644 +--- a/mcelog.c ++++ b/mcelog.c +@@ -982,10 +982,10 @@ void usage(void) + "--pidfile file Write pid of daemon into file\n" + "--no-imc-log Disable extended iMC logging\n" + "--is-cpu-supported Exit with return code indicating whether the CPU is supported\n" ++"--help Display this message.\n" + ); + printf("\n"); + print_cputypes(); +- exit(1); + } + + enum options { +@@ -1017,6 +1017,7 @@ enum options { + O_DEBUG_NUMERRORS, + O_NO_IMC_LOG, + O_IS_CPU_SUPPORTED, ++ O_HELP, + }; + + static struct option options[] = { +@@ -1050,6 +1051,7 @@ static struct option options[] = { + { "pidfile", 1, NULL, O_PIDFILE }, + { "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */ + { "no-imc-log", 0, NULL, O_NO_IMC_LOG }, ++ { "help", 0, NULL, O_HELP }, + { "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED }, + {} + }; +@@ -1080,12 +1082,15 @@ static int modifier(int opt) + break; + case O_INTEL_CPU: { + unsigned fam, mod; +- if (sscanf(optarg, "%i,%i", &fam, &mod) != 2) ++ if (sscanf(optarg, "%i,%i", &fam, &mod) != 2) { + usage(); ++ exit(1); ++ } + cputype = select_intel_cputype(fam, mod); + if (cputype == CPU_GENERIC) { + fprintf(stderr, "Unknown Intel CPU\n"); + usage(); ++ exit(1); + } + cpu_forced = 1; + break; +@@ -1104,8 +1109,10 @@ static int modifier(int opt) + do_dmi = 0; + break; + case O_DMI_VERBOSE: +- if (sscanf(optarg, "%i", &v) != 1) ++ if (sscanf(optarg, "%i", &v) != 1) { + usage(); ++ exit(1); ++ } + dmi_set_verbosity(v); + break; + case O_SYSLOG: +@@ -1117,8 +1124,10 @@ static int modifier(int opt) + break; + case O_CPUMHZ: + cpumhz_forced = 1; +- if (sscanf(optarg, "%lf", &cpumhz) != 1) ++ if (sscanf(optarg, "%lf", &cpumhz) != 1) { + usage(); ++ exit(1); ++ } + break; + case O_SYSLOG_ERROR: + syslog_level = LOG_ERR; +@@ -1155,6 +1164,10 @@ static int modifier(int opt) + case O_IS_CPU_SUPPORTED: + check_only = 1; + break; ++ case O_HELP: ++ usage(); ++ exit(0); ++ break; + case 0: + break; + default: +@@ -1184,8 +1197,10 @@ void argsleft(int ac, char **av) + int opt; + + while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) { +- if (modifier(opt) != 1) ++ if (modifier(opt) != 1) { + usage(); ++ exit(1); ++ } + } + } + +@@ -1284,16 +1299,20 @@ static void process(int fd, unsigned recordlen, unsigned loglen, char *buf) + + static void noargs(int ac, char **av) + { +- if (getopt_long(ac, av, "", options, NULL) != -1) ++ if (getopt_long(ac, av, "", options, NULL) != -1) { + usage(); ++ exit(1); ++ } + } + + static void parse_config(char **av) + { + static const char config_fn[] = CONFIG_FILENAME; + const char *fn = config_file(av, config_fn); +- if (!fn) ++ if (!fn) { + usage(); ++ exit(1); ++ } + if (parse_config_file(fn) < 0) { + /* If it's the default file don't complain if it isn't there */ + if (fn != config_fn) { +@@ -1362,6 +1381,7 @@ int main(int ac, char **av) + while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) { + if (opt == '?') { + usage(); ++ exit(1); + } else if (combined_modifier(opt) > 0) { + continue; + } else if (opt == O_ASCII) { +@@ -1404,8 +1424,10 @@ int main(int ac, char **av) + modifier_finish(); + if (av[optind]) + logfn = av[optind++]; +- if (av[optind]) ++ if (av[optind]) { + usage(); ++ exit(1); ++ } + checkdmi(); + general_setup(); + diff --git a/SOURCES/mcelog-patch-f8f1490cb.patch b/SOURCES/mcelog-patch-f8f1490cb.patch new file mode 100644 index 0000000..bebb773 --- /dev/null +++ b/SOURCES/mcelog-patch-f8f1490cb.patch @@ -0,0 +1,27 @@ +From: Prarit Bhargava + +Subject: Document .os_release in README + +commit f8f1490cb2c6754aa108779e04fa2f099e394895 +Author: Andi Kleen +Date: Mon May 22 09:38:47 2017 -0700 + + Document .os_release in README + + Signed-off-by: Andi Kleen + +diff --git a/README.md b/README.md +index 7e848a598e40ee4ef7162bbad8c1280d001b9dbd..d47928ff614934730105c314aef1c7a084e16a6a 100644 +--- a/README.md ++++ b/README.md +@@ -55,6 +55,10 @@ error predictive failure analysis) require a continuously running daemon. + You can run mcelog from systemd or similar daemons. An example systemd unit + file is in `mcelog.service`. + ++By default mcelog reports its version as the git tag. This can be overridden ++by setting up a .os_release file in the source directory. A build system ++could write the OS version to this file to mark the binary. ++ + ### For older distributions using init scripts + + Please install an init script by default that runs mcelog in daemon mode. diff --git a/SOURCES/mcelog-update-94d853b2ea81.patch b/SOURCES/mcelog-update-94d853b2ea81.patch index 3b6eecc..741dc58 100644 --- a/SOURCES/mcelog-update-94d853b2ea81.patch +++ b/SOURCES/mcelog-update-94d853b2ea81.patch @@ -1164,45 +1164,6 @@ diff -urNp mcelog-d2e13bf0.orig/intel.c mcelog-d2e13bf0/intel.c case CPU_SANDY_BRIDGE_EP: sandy_bridge_ep_memerr_misc(m, channel, dimm); break; -diff -urNp mcelog-d2e13bf0.orig/intel.c.orig mcelog-d2e13bf0/intel.c.orig ---- mcelog-d2e13bf0.orig/intel.c.orig 2016-11-30 11:23:54.539909515 -0500 -+++ mcelog-d2e13bf0/intel.c.orig 2016-11-30 11:23:40.052327334 -0500 -@@ -35,7 +35,8 @@ void intel_cpu_init(enum cputype cpu) - cpu == CPU_SANDY_BRIDGE || cpu == CPU_SANDY_BRIDGE_EP || - cpu == CPU_IVY_BRIDGE || cpu == CPU_IVY_BRIDGE_EPEX || - cpu == CPU_HASWELL || cpu == CPU_HASWELL_EPEX || cpu == CPU_BROADWELL || -- cpu == CPU_KNIGHTS_LANDING) -+ cpu == CPU_BROADWELL_DE || cpu == CPU_BROADWELL_EPEX || -+ cpu == CPU_KNIGHTS_LANDING || cpu == CPU_SKYLAKE || cpu == CPU_SKYLAKE_XEON) - memory_error_support = 1; - } - -@@ -73,15 +74,23 @@ enum cputype select_intel_cputype(int fa - return CPU_HASWELL; - else if (model == 0x3f) - return CPU_HASWELL_EPEX; -- else if (model == 0x3d || model == 0x56) -+ else if (model == 0x3d) - return CPU_BROADWELL; -- else if (model == 0x57) -+ else if (model == 0x4f) -+ return CPU_BROADWELL_EPEX; -+ else if (model == 0x56) -+ return CPU_BROADWELL_DE; -+ else if (model == 0x57) - return CPU_KNIGHTS_LANDING; - else if (model == 0x1c || model == 0x26 || model == 0x27 || - model == 0x35 || model == 0x36 || model == 0x36 || - model == 0x37 || model == 0x4a || model == 0x4c || - model == 0x4d || model == 0x5a || model == 0x5d) - return CPU_ATOM; -+ else if (model == 0x4e || model == 0x5e) -+ return CPU_SKYLAKE; -+ else if (model == 0x55) -+ return CPU_SKYLAKE_XEON; - if (model > 0x1a) { - Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n", - model); diff -urNp mcelog-d2e13bf0.orig/intel.h mcelog-d2e13bf0/intel.h --- mcelog-d2e13bf0.orig/intel.h 2016-11-30 11:23:54.530909154 -0500 +++ mcelog-d2e13bf0/intel.h 2016-11-30 11:24:12.206619450 -0500 @@ -1378,159 +1339,6 @@ diff -urNp mcelog-d2e13bf0.orig/mcelog.c mcelog-d2e13bf0/mcelog.c } else if (opt == 0) break; } -diff -urNp mcelog-d2e13bf0.orig/mcelog.c.orig mcelog-d2e13bf0/mcelog.c.orig ---- mcelog-d2e13bf0.orig/mcelog.c.orig 2016-11-30 11:23:54.540909556 -0500 -+++ mcelog-d2e13bf0/mcelog.c.orig 2016-11-30 11:23:40.054327414 -0500 -@@ -85,6 +85,7 @@ static char *pidfile = pidfile_default; - static char *logfile; - static int debug_numerrors; - int imc_log = -1; -+static int check_only = 0; - - static int is_cpu_supported(void); - -@@ -131,7 +132,7 @@ static char *bankname(unsigned bank) - } - } - --static void resolveaddr(unsigned long addr) -+static void resolveaddr(unsigned long long addr) - { - if (addr && do_dmi && dmi_forced) - dmi_decodeaddr(addr); -@@ -232,8 +233,12 @@ static char *cputype_name[] = { - [CPU_HASWELL] = "Haswell", /* Fill in better name */ - [CPU_HASWELL_EPEX] = "Haswell EP/EX", /* Fill in better name */ - [CPU_BROADWELL] = "Broadwell", -+ [CPU_BROADWELL_DE] = "Intel Xeon (Broadwell) D family", -+ [CPU_BROADWELL_EPEX] = "Intel Xeon v4 (Broadwell) EP/EX", - [CPU_KNIGHTS_LANDING] = "Knights Landing", - [CPU_ATOM] = "ATOM", -+ [CPU_SKYLAKE] = "Skylake", -+ [CPU_SKYLAKE_XEON] = "Skylake server", - }; - - static struct config_choice cpu_choices[] = { -@@ -273,8 +278,14 @@ static struct config_choice cpu_choices[ - { "haswell-ep", CPU_HASWELL_EPEX }, /* Fill in better name */ - { "haswell-ex", CPU_HASWELL_EPEX }, /* Fill in better name */ - { "broadwell", CPU_BROADWELL }, -+ { "broadwell-d", CPU_BROADWELL_DE }, -+ { "broadwell-ep", CPU_BROADWELL_EPEX }, -+ { "broadwell-ex", CPU_BROADWELL_EPEX }, - { "knightslanding", CPU_KNIGHTS_LANDING }, -+ { "xeon-v4", CPU_BROADWELL_EPEX }, - { "atom", CPU_ATOM }, -+ { "skylake", CPU_SKYLAKE }, -+ { "skylake_server", CPU_SKYLAKE_XEON }, - { NULL } - }; - -@@ -437,7 +448,9 @@ static void dump_mce(struct mce *m, unsi - } - if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX && - cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL && -- cputype != CPU_KNIGHTS_LANDING) -+ cputype != CPU_BROADWELL_DE && cputype != CPU_BROADWELL_EPEX && -+ cputype != CPU_KNIGHTS_LANDING && cputype != CPU_SKYLAKE && -+ cputype != CPU_SKYLAKE_XEON) - resolveaddr(m->addr); - if (!ascii_mode && ismemerr && (m->status & MCI_STATUS_ADDRV)) { - diskdb_resolve_addr(m->addr); -@@ -916,22 +929,35 @@ void usage(void) - { - fprintf(stderr, - "Usage:\n" -+"\n" - " mcelog [options] [mcelogdevice]\n" - "Decode machine check error records from current kernel.\n" -+"\n" - " mcelog [options] --daemon\n" - "Run mcelog in daemon mode, waiting for errors from the kernel.\n" -+"\n" - " mcelog [options] --client\n" - "Query a currently running mcelog daemon for errors\n" -+"\n" - " mcelog [options] --ascii < log\n" - " mcelog [options] --ascii --file log\n" - "Decode machine check ASCII output from kernel logs\n" -+"\n" - "Options:\n" -+"--version Show the version of mcelog and exit\n" - "--cpu CPU Set CPU type CPU to decode (see below for valid types)\n" -+"--intel-cpu FAMILY,MODEL Set CPU type for an Intel CPU based on family and model from cpuid\n" -+"--k8 Set the CPU to be an AMD K8\n" -+"--p4 Set the CPU to be an Intel Pentium4\n" -+"--core2 Set the CPU to be an Intel Core2\n" -+"--generic Set the CPU to a generic version\n" - "--cpumhz MHZ Set CPU Mhz to decode time (output unreliable, not needed on new kernels)\n" - "--raw (with --ascii) Dump in raw ASCII format for machine processing\n" - "--daemon Run in background waiting for events (needs newer kernel)\n" -+"--client Query a currently running mcelog daemon for errors\n" - "--ignorenodev Exit silently when the device cannot be opened\n" - "--file filename With --ascii read machine check log from filename instead of stdin\n" -+"--logfile filename Log decoded machine checks in file filename\n" - "--syslog Log decoded machine checks in syslog (default stdout or syslog for daemon)\n" - "--syslog-error Log decoded machine checks in syslog with error level\n" - "--no-syslog Never log anything to syslog\n" -@@ -946,8 +972,10 @@ void usage(void) - "--num-errors N Only process N errors (for testing)\n" - "--pidfile file Write pid of daemon into file\n" - "--no-imc-log Disable extended iMC logging\n" -+"--is-cpu-supported Exit with return code indicating whether the CPU is supported\n" - ); - diskdb_usage(); -+ printf("\n"); - print_cputypes(); - exit(1); - } -@@ -980,6 +1008,7 @@ enum options { - O_PIDFILE, - O_DEBUG_NUMERRORS, - O_NO_IMC_LOG, -+ O_IS_CPU_SUPPORTED, - }; - - static struct option options[] = { -@@ -1013,6 +1042,7 @@ static struct option options[] = { - { "pidfile", 1, NULL, O_PIDFILE }, - { "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */ - { "no-imc-log", 0, NULL, O_NO_IMC_LOG }, -+ { "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED }, - DISKDB_OPTIONS - {} - }; -@@ -1115,6 +1145,9 @@ static int modifier(int opt) - case O_NO_IMC_LOG: - imc_log = 0; - break; -+ case O_IS_CPU_SUPPORTED: -+ check_only = 1; -+ break; - case 0: - break; - default: -@@ -1344,15 +1377,19 @@ int main(int ac, char **av) - - /* before doing anything else let's see if the CPUs are supported */ - if (!cpu_forced && !is_cpu_supported()) { -- fprintf(stderr, "CPU is unsupported\n"); -+ if (!check_only) -+ fprintf(stderr, "CPU is unsupported\n"); - exit(1); - } -+ if (check_only) -+ exit(0); - - /* If the user didn't tell us not to use iMC logging, check if CPU supports it */ - if (imc_log == -1) { - switch (cputype) { - case CPU_SANDY_BRIDGE_EP: - case CPU_IVY_BRIDGE_EPEX: -+ case CPU_HASWELL_EPEX: - imc_log = 1; - break; - default: diff -urNp mcelog-d2e13bf0.orig/mcelog.h mcelog-d2e13bf0/mcelog.h --- mcelog-d2e13bf0.orig/mcelog.h 2016-11-30 11:23:54.539909515 -0500 +++ mcelog-d2e13bf0/mcelog.h 2016-11-30 11:24:12.207619490 -0500 diff --git a/SOURCES/mcelog-update-e4aca63.patch b/SOURCES/mcelog-update-e4aca63.patch index ea7502c..b3a9636 100644 --- a/SOURCES/mcelog-update-e4aca63.patch +++ b/SOURCES/mcelog-update-e4aca63.patch @@ -758,169 +758,6 @@ diff -urNp mcelog-d2e13bf0.orig/intel.c mcelog-d2e13bf0/intel.c if (model > 0x1a) { Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n", model); -diff -urNp mcelog-d2e13bf0.orig/intel.c.orig mcelog-d2e13bf0/intel.c.orig ---- mcelog-d2e13bf0.orig/intel.c.orig 1969-12-31 19:00:00.000000000 -0500 -+++ mcelog-d2e13bf0/intel.c.orig 2016-05-14 08:34:23.043289544 -0400 -@@ -0,0 +1,159 @@ -+/* Copyright (C) 2009 Intel Corporation -+ Author: Andi Kleen -+ Common Intel CPU code. -+ -+ mcelog is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public -+ License as published by the Free Software Foundation; version -+ 2. -+ -+ mcelog is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should find a copy of v2 of the GNU General Public License somewhere -+ on your Linux system; if not, write to the Free Software Foundation, -+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -+#include -+#include "mcelog.h" -+#include "intel.h" -+#include "bitfield.h" -+#include "nehalem.h" -+#include "memdb.h" -+#include "page.h" -+#include "sandy-bridge.h" -+#include "ivy-bridge.h" -+#include "haswell.h" -+#include "xeon75xx.h" -+ -+int memory_error_support; -+ -+void intel_cpu_init(enum cputype cpu) -+{ -+ if (cpu == CPU_NEHALEM || cpu == CPU_XEON75XX || cpu == CPU_INTEL || -+ cpu == CPU_SANDY_BRIDGE || cpu == CPU_SANDY_BRIDGE_EP || -+ cpu == CPU_IVY_BRIDGE || cpu == CPU_IVY_BRIDGE_EPEX || -+ cpu == CPU_HASWELL || cpu == CPU_HASWELL_EPEX || cpu == CPU_BROADWELL || -+ cpu == CPU_KNIGHTS_LANDING) -+ memory_error_support = 1; -+} -+ -+enum cputype select_intel_cputype(int family, int model) -+{ -+ if (family == 15) { -+ if (model == 6) -+ return CPU_TULSA; -+ return CPU_P4; -+ } -+ if (family == 6) { -+ if (model >= 0x1a && model != 28) -+ memory_error_support = 1; -+ -+ if (model < 0xf) -+ return CPU_P6OLD; -+ else if (model == 0xf || model == 0x17) /* Merom/Penryn */ -+ return CPU_CORE2; -+ else if (model == 0x1d) -+ return CPU_DUNNINGTON; -+ else if (model == 0x1a || model == 0x2c || model == 0x1e || -+ model == 0x25) -+ return CPU_NEHALEM; -+ else if (model == 0x2e || model == 0x2f) -+ return CPU_XEON75XX; -+ else if (model == 0x2a) -+ return CPU_SANDY_BRIDGE; -+ else if (model == 0x2d) -+ return CPU_SANDY_BRIDGE_EP; -+ else if (model == 0x3a) -+ return CPU_IVY_BRIDGE; -+ else if (model == 0x3e) -+ return CPU_IVY_BRIDGE_EPEX; -+ else if (model == 0x3c || model == 0x45 || model == 0x46) -+ return CPU_HASWELL; -+ else if (model == 0x3f) -+ return CPU_HASWELL_EPEX; -+ else if (model == 0x3d || model == 0x56) -+ return CPU_BROADWELL; -+ else if (model == 0x57) -+ return CPU_KNIGHTS_LANDING; -+ else if (model == 0x1c || model == 0x26 || model == 0x27 || -+ model == 0x35 || model == 0x36 || model == 0x36 || -+ model == 0x37 || model == 0x4a || model == 0x4c || -+ model == 0x4d || model == 0x5a || model == 0x5d) -+ return CPU_ATOM; -+ if (model > 0x1a) { -+ Eprintf("Family 6 Model %x CPU: only decoding architectural errors\n", -+ model); -+ return CPU_INTEL; -+ } -+ } -+ if (family > 6) { -+ Eprintf("Family %u Model %x CPU: only decoding architectural errors\n", -+ family, model); -+ return CPU_INTEL; -+ } -+ Eprintf("Unknown Intel CPU type family %x model %x\n", family, model); -+ return family == 6 ? CPU_P6OLD : CPU_GENERIC; -+} -+ -+int is_intel_cpu(int cpu) -+{ -+ switch (cpu) { -+ CASE_INTEL_CPUS: -+ return 1; -+ } -+ return 0; -+} -+ -+static int intel_memory_error(struct mce *m, unsigned recordlen) -+{ -+ u32 mca = m->status & 0xffff; -+ if ((mca >> 7) == 1) { -+ unsigned corr_err_cnt = 0; -+ int channel[2] = { (mca & 0xf) == 0xf ? -1 : (int)(mca & 0xf), -1 }; -+ int dimm[2] = { -1, -1 }; -+ -+ switch (cputype) { -+ case CPU_NEHALEM: -+ nehalem_memerr_misc(m, channel, dimm); -+ break; -+ case CPU_XEON75XX: -+ xeon75xx_memory_error(m, recordlen, channel, dimm); -+ break; -+ case CPU_SANDY_BRIDGE_EP: -+ sandy_bridge_ep_memerr_misc(m, channel, dimm); -+ break; -+ case CPU_IVY_BRIDGE_EPEX: -+ ivy_bridge_ep_memerr_misc(m, channel, dimm); -+ break; -+ default: -+ break; -+ } -+ -+ if (recordlen > offsetof(struct mce, mcgcap) && m->mcgcap & MCG_CMCI_P) -+ corr_err_cnt = EXTRACT(m->status, 38, 52); -+ memory_error(m, channel[0], dimm[0], corr_err_cnt, recordlen); -+ account_page_error(m, channel[0], dimm[0]); -+ -+ /* -+ * When both DIMMs have a error account the error twice to the page. -+ */ -+ if (channel[1] != -1) { -+ memory_error(m, channel[1], dimm[1], corr_err_cnt, recordlen); -+ account_page_error(m, channel[1], dimm[1]); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* No bugs known, but filter out memory errors if the user asked for it */ -+int mce_filter_intel(struct mce *m, unsigned recordlen) -+{ -+ if (intel_memory_error(m, recordlen) == 1) -+ return !filter_memory_errors; -+ return 1; -+} diff -urNp mcelog-d2e13bf0.orig/intel.h mcelog-d2e13bf0/intel.h --- mcelog-d2e13bf0.orig/intel.h 2016-05-14 08:34:40.444108189 -0400 +++ mcelog-d2e13bf0/intel.h 2016-05-14 08:34:58.871975152 -0400 @@ -1285,1419 +1122,6 @@ diff -urNp mcelog-d2e13bf0.orig/mcelog.conf.5 mcelog-d2e13bf0/mcelog.conf.5 .PP .B memory-ce-log = yes .PP -diff -urNp mcelog-d2e13bf0.orig/mcelog.c.orig mcelog-d2e13bf0/mcelog.c.orig ---- mcelog-d2e13bf0.orig/mcelog.c.orig 1969-12-31 19:00:00.000000000 -0500 -+++ mcelog-d2e13bf0/mcelog.c.orig 2016-05-14 08:34:23.044289591 -0400 -@@ -0,0 +1,1409 @@ -+/* Copyright (C) 2004,2005,2006 Andi Kleen, SuSE Labs. -+ Copyright (C) 2008 Intel Corporation -+ Authors: Andi Kleen, Ying Huang -+ Decode IA32/x86-64 machine check events in /dev/mcelog. -+ -+ mcelog is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public -+ License as published by the Free Software Foundation; version -+ 2. -+ -+ mcelog is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should find a copy of v2 of the GNU General Public License somewhere -+ on your Linux system; if not, write to the Free Software Foundation, -+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -+ -+#define _GNU_SOURCE 1 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mcelog.h" -+#include "paths.h" -+#include "k8.h" -+#include "intel.h" -+#include "p4.h" -+#include "dmi.h" -+#include "dimm.h" -+#include "tsc.h" -+#include "version.h" -+#include "config.h" -+#include "diskdb.h" -+#include "memutil.h" -+#include "eventloop.h" -+#include "memdb.h" -+#include "server.h" -+#include "trigger.h" -+#include "client.h" -+#include "msg.h" -+#include "yellow.h" -+#include "page.h" -+#include "bus.h" -+#include "unknown.h" -+ -+enum cputype cputype = CPU_GENERIC; -+ -+char *logfn = LOG_DEV_FILENAME; -+ -+int ignore_nodev; -+int filter_bogus = 1; -+int cpu_forced; -+static double cpumhz; -+static int cpumhz_forced; -+int ascii_mode; -+int dump_raw_ascii; -+int daemon_mode; -+static char *inputfile; -+char *processor_flags; -+static int foreground; -+int filter_memory_errors; -+static struct config_cred runcred = { .uid = -1U, .gid = -1U }; -+static int numerrors; -+static char pidfile_default[] = PID_FILE; -+static char logfile_default[] = LOG_FILE; -+static char *pidfile = pidfile_default; -+static char *logfile; -+static int debug_numerrors; -+int imc_log = -1; -+ -+static int is_cpu_supported(void); -+ -+ -+static void disclaimer(void) -+{ -+ Wprintf("Hardware event. This is not a software error.\n"); -+} -+ -+static char *extended_bankname(unsigned bank) -+{ -+ static char buf[64]; -+ switch (bank) { -+ case MCE_THERMAL_BANK: -+ return "THERMAL EVENT"; -+ case MCE_TIMEOUT_BANK: -+ return "Timeout waiting for exception on other CPUs"; -+ case K8_MCE_THRESHOLD_BASE ... K8_MCE_THRESHOLD_TOP: -+ return k8_bank_name(bank); -+ -+ /* add more extended banks here */ -+ -+ default: -+ sprintf(buf, "Undecoded extended event %x", bank); -+ return buf; -+ } -+} -+ -+static char *bankname(unsigned bank) -+{ -+ static char numeric[64]; -+ if (bank >= MCE_EXTENDED_BANK) -+ return extended_bankname(bank); -+ -+ switch (cputype) { -+ case CPU_K8: -+ return k8_bank_name(bank); -+ CASE_INTEL_CPUS: -+ return intel_bank_name(bank); -+ /* add banks of other cpu types here */ -+ default: -+ sprintf(numeric, "BANK %d", bank); -+ return numeric; -+ } -+} -+ -+static void resolveaddr(unsigned long addr) -+{ -+ if (addr && do_dmi && dmi_forced) -+ dmi_decodeaddr(addr); -+ /* Should check for PCI resources here too */ -+} -+ -+static int mce_filter(struct mce *m, unsigned recordlen) -+{ -+ if (!filter_bogus) -+ return 1; -+ /* Filter out known broken MCEs */ -+ switch (cputype) { -+ case CPU_K8: -+ return mce_filter_k8(m); -+ /* add more buggy CPUs here */ -+ CASE_INTEL_CPUS: -+ return mce_filter_intel(m, recordlen); -+ default: -+ case CPU_GENERIC: -+ return 1; -+ } -+} -+ -+static void print_tsc(int cpunum, __u64 tsc, unsigned long time) -+{ -+ int ret = -1; -+ char *buf = NULL; -+ -+ if (cpumhz_forced) -+ ret = decode_tsc_forced(&buf, cpumhz, tsc); -+ else if (!time) -+ ret = decode_tsc_current(&buf, cpunum, cputype, cpumhz, tsc); -+ Wprintf("TSC %llx %s", tsc, ret >= 0 && buf ? buf : ""); -+ free(buf); -+} -+ -+struct cpuid1 { -+ unsigned stepping : 4; -+ unsigned model : 4; -+ unsigned family : 4; -+ unsigned type : 2; -+ unsigned res1 : 2; -+ unsigned ext_model : 4; -+ unsigned ext_family : 8; -+ unsigned res2 : 4; -+}; -+ -+static void parse_cpuid(u32 cpuid, u32 *family, u32 *model) -+{ -+ union { -+ struct cpuid1 c; -+ u32 v; -+ } c; -+ -+ /* Algorithm from IA32 SDM 2a 3-191 */ -+ c.v = cpuid; -+ *family = c.c.family; -+ if (*family == 0xf) -+ *family += c.c.ext_family; -+ *model = c.c.model; -+ if (*family == 6 || *family == 0xf) -+ *model += c.c.ext_model << 4; -+} -+ -+static u32 unparse_cpuid(unsigned family, unsigned model) -+{ -+ union { -+ struct cpuid1 c; -+ u32 v; -+ } c; -+ -+ c.c.family = family; -+ if (family >= 0xf) { -+ c.c.family = 0xf; -+ c.c.ext_family = family - 0xf; -+ } -+ c.c.model = model & 0xf; -+ if (family == 6 || family == 0xf) -+ c.c.ext_model = model >> 4; -+ return c.v; -+} -+ -+static char *cputype_name[] = { -+ [CPU_GENERIC] = "generic CPU", -+ [CPU_P6OLD] = "Intel PPro/P2/P3/old Xeon", -+ [CPU_CORE2] = "Intel Core", /* 65nm and 45nm */ -+ [CPU_K8] = "AMD K8 and derivates", -+ [CPU_P4] = "Intel P4", -+ [CPU_NEHALEM] = "Intel Xeon 5500 series / Core i3/5/7 (\"Nehalem/Westmere\")", -+ [CPU_DUNNINGTON] = "Intel Xeon 7400 series", -+ [CPU_TULSA] = "Intel Xeon 7100 series", -+ [CPU_INTEL] = "Intel generic architectural MCA", -+ [CPU_XEON75XX] = "Intel Xeon 7500 series", -+ [CPU_SANDY_BRIDGE] = "Sandy Bridge", /* Fill in better name */ -+ [CPU_SANDY_BRIDGE_EP] = "Sandy Bridge EP", /* Fill in better name */ -+ [CPU_IVY_BRIDGE] = "Ivy Bridge", /* Fill in better name */ -+ [CPU_IVY_BRIDGE_EPEX] = "Ivy Bridge EP/EX", /* Fill in better name */ -+ [CPU_HASWELL] = "Haswell", /* Fill in better name */ -+ [CPU_HASWELL_EPEX] = "Haswell EP/EX", /* Fill in better name */ -+ [CPU_BROADWELL] = "Broadwell", -+ [CPU_KNIGHTS_LANDING] = "Knights Landing", -+ [CPU_ATOM] = "ATOM", -+}; -+ -+static struct config_choice cpu_choices[] = { -+ { "generic", CPU_GENERIC }, -+ { "p6old", CPU_P6OLD }, -+ { "core2", CPU_CORE2 }, -+ { "k8", CPU_K8 }, -+ { "p4", CPU_P4 }, -+ { "dunnington", CPU_DUNNINGTON }, -+ { "xeon74xx", CPU_DUNNINGTON }, -+ { "xeon7400", CPU_DUNNINGTON }, -+ { "xeon5500", CPU_NEHALEM }, -+ { "xeon5200", CPU_CORE2 }, -+ { "xeon5000", CPU_P4 }, -+ { "xeon5100", CPU_CORE2 }, -+ { "xeon3100", CPU_CORE2 }, -+ { "xeon3200", CPU_CORE2 }, -+ { "core_i7", CPU_NEHALEM }, -+ { "core_i5", CPU_NEHALEM }, -+ { "core_i3", CPU_NEHALEM }, -+ { "nehalem", CPU_NEHALEM }, -+ { "westmere", CPU_NEHALEM }, -+ { "xeon71xx", CPU_TULSA }, -+ { "xeon7100", CPU_TULSA }, -+ { "tulsa", CPU_TULSA }, -+ { "intel", CPU_INTEL }, -+ { "xeon75xx", CPU_XEON75XX }, -+ { "xeon7500", CPU_XEON75XX }, -+ { "xeon7200", CPU_CORE2 }, -+ { "xeon7100", CPU_P4 }, -+ { "sandybridge", CPU_SANDY_BRIDGE }, /* Fill in better name */ -+ { "sandybridge-ep", CPU_SANDY_BRIDGE_EP }, /* Fill in better name */ -+ { "ivybridge", CPU_IVY_BRIDGE }, /* Fill in better name */ -+ { "ivybridge-ep", CPU_IVY_BRIDGE_EPEX }, /* Fill in better name */ -+ { "ivybridge-ex", CPU_IVY_BRIDGE_EPEX }, /* Fill in better name */ -+ { "haswell", CPU_HASWELL }, /* Fill in better name */ -+ { "haswell-ep", CPU_HASWELL_EPEX }, /* Fill in better name */ -+ { "haswell-ex", CPU_HASWELL_EPEX }, /* Fill in better name */ -+ { "broadwell", CPU_BROADWELL }, -+ { "knightslanding", CPU_KNIGHTS_LANDING }, -+ { "atom", CPU_ATOM }, -+ { NULL } -+}; -+ -+static void print_cputypes(void) -+{ -+ struct config_choice *c; -+ fprintf(stderr, "Valid CPUs:"); -+ for (c = cpu_choices; c->name; c++) -+ fprintf(stderr, " %s", c->name); -+ fputc('\n', stderr); -+} -+ -+static enum cputype lookup_cputype(char *name) -+{ -+ struct config_choice *c; -+ for (c = cpu_choices; c->name; c++) { -+ if (!strcasecmp(name, c->name)) -+ return c->val; -+ } -+ fprintf(stderr, "Unknown CPU type `%s' specified\n", name); -+ print_cputypes(); -+ exit(1); -+} -+ -+static char *vendor[] = { -+ [0] = "Intel", -+ [1] = "Cyrix", -+ [2] = "AMD", -+ [3] = "UMC", -+ [4] = "vendor 4", -+ [5] = "Centaur", -+ [6] = "vendor 6", -+ [7] = "Transmeta", -+ [8] = "NSC" -+}; -+ -+static unsigned cpuvendor_to_num(char *name) -+{ -+ unsigned i; -+ unsigned v; -+ char *end; -+ -+ v = strtoul(name, &end, 0); -+ if (end > name) -+ return v; -+ for (i = 0; i < NELE(vendor); i++) -+ if (!strcmp(name, vendor[i])) -+ return i; -+ return 0; -+} -+ -+static char *cpuvendor_name(u32 cpuvendor) -+{ -+ return (cpuvendor < NELE(vendor)) ? vendor[cpuvendor] : "Unknown vendor"; -+} -+ -+static enum cputype setup_cpuid(u32 cpuvendor, u32 cpuid) -+{ -+ u32 family, model; -+ -+ parse_cpuid(cpuid, &family, &model); -+ -+ switch (cpuvendor) { -+ case X86_VENDOR_INTEL: -+ return select_intel_cputype(family, model); -+ case X86_VENDOR_AMD: -+ if (family >= 15 && family <= 17) -+ return CPU_K8; -+ /* FALL THROUGH */ -+ default: -+ Eprintf("Unknown CPU type vendor %u family %x model %x", -+ cpuvendor, family, model); -+ return CPU_GENERIC; -+ } -+} -+ -+static void mce_cpuid(struct mce *m) -+{ -+ static int warned; -+ if (m->cpuid) { -+ enum cputype t = setup_cpuid(m->cpuvendor, m->cpuid); -+ if (!cpu_forced) -+ cputype = t; -+ else if (t != cputype && t != CPU_GENERIC && !warned) { -+ Eprintf("Forced cputype %s does not match cpu type %s from mcelog\n", -+ cputype_name[cputype], -+ cputype_name[t]); -+ warned = 1; -+ } -+ } else if (cputype == CPU_GENERIC && !cpu_forced) { -+ is_cpu_supported(); -+ } -+} -+ -+static void mce_prepare(struct mce *m) -+{ -+ mce_cpuid(m); -+ if (!m->time) -+ m->time = time(NULL); -+} -+ -+static void dump_mce(struct mce *m, unsigned recordlen) -+{ -+ int n; -+ int ismemerr = 0; -+ unsigned cpu = m->extcpu ? m->extcpu : m->cpu; -+ -+ /* should not happen */ -+ if (!m->finished) -+ Wprintf("not finished?\n"); -+ Wprintf("CPU %d %s ", cpu, bankname(m->bank)); -+ if (m->tsc) -+ print_tsc(cpu, m->tsc, m->time); -+ Wprintf("\n"); -+ if (m->ip) -+ Wprintf("RIP%s %02x:%llx\n", -+ !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", -+ m->cs, m->ip); -+ n = 0; -+ if (m->status & MCI_STATUS_MISCV) -+ n += Wprintf("MISC %llx ", m->misc); -+ if (m->status & MCI_STATUS_ADDRV) -+ n += Wprintf("ADDR %llx ", m->addr); -+ if (n > 0) -+ Wprintf("\n"); -+ if (m->time) { -+ time_t t = m->time; -+ Wprintf("TIME %llu %s", m->time, ctime(&t)); -+ } -+ switch (cputype) { -+ case CPU_K8: -+ decode_k8_mc(m, &ismemerr); -+ break; -+ CASE_INTEL_CPUS: -+ decode_intel_mc(m, cputype, &ismemerr, recordlen); -+ break; -+ /* add handlers for other CPUs here */ -+ default: -+ break; -+ } -+ /* decode all status bits here */ -+ Wprintf("STATUS %llx MCGSTATUS %llx\n", m->status, m->mcgstatus); -+ n = 0; -+ if (recordlen >= offsetof(struct mce, cpuid) && m->mcgcap) -+ n += Wprintf("MCGCAP %llx ", m->mcgcap); -+ if (recordlen >= offsetof(struct mce, apicid)) -+ n += Wprintf("APICID %x ", m->apicid); -+ if (recordlen >= offsetof(struct mce, socketid)) -+ n += Wprintf("SOCKETID %x ", m->socketid); -+ if (n > 0) -+ Wprintf("\n"); -+ -+ if (recordlen >= offsetof(struct mce, cpuid) && m->cpuid) { -+ u32 fam, mod; -+ parse_cpuid(m->cpuid, &fam, &mod); -+ Wprintf("CPUID Vendor %s Family %u Model %u\n", -+ cpuvendor_name(m->cpuvendor), -+ fam, -+ mod); -+ } -+ if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX && -+ cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL && -+ cputype != CPU_KNIGHTS_LANDING) -+ resolveaddr(m->addr); -+ if (!ascii_mode && ismemerr && (m->status & MCI_STATUS_ADDRV)) { -+ diskdb_resolve_addr(m->addr); -+ } -+} -+ -+static void dump_mce_raw_ascii(struct mce *m, unsigned recordlen) -+{ -+ /* should not happen */ -+ if (!m->finished) -+ Wprintf("not finished?\n"); -+ Wprintf("CPU %u\n", m->extcpu ? m->extcpu : m->cpu); -+ Wprintf("BANK %d\n", m->bank); -+ Wprintf("TSC %#llx\n", m->tsc); -+ Wprintf("RIP %#02x:%#llx\n", m->cs, m->ip); -+ Wprintf("MISC %#llx\n", m->misc); -+ Wprintf("ADDR %#llx\n", m->addr); -+ Wprintf("STATUS %#llx\n", m->status); -+ Wprintf("MCGSTATUS %#llx\n", m->mcgstatus); -+ if (recordlen >= offsetof(struct mce, cpuid)) -+ Wprintf("PROCESSOR %u:%#x\n", m->cpuvendor, m->cpuid); -+#define CPRINT(str, field) \ -+ if (recordlen >= offsetof(struct mce, field)) \ -+ Wprintf(str "\n", m->field) -+ CPRINT("TIME %llu", time); -+ CPRINT("SOCKETID %u", socketid); -+ CPRINT("APICID %u", apicid); -+ CPRINT("MCGCAP %#llx", mcgcap); -+#undef CPRINT -+ Wprintf("\n"); -+} -+ -+int is_cpu_supported(void) -+{ -+ enum { -+ VENDOR = 1, -+ FAMILY = 2, -+ MODEL = 4, -+ MHZ = 8, -+ FLAGS = 16, -+ ALL = 0x1f -+ } seen = 0; -+ FILE *f; -+ static int checked; -+ -+ if (checked) -+ return 1; -+ checked = 1; -+ -+ f = fopen("/proc/cpuinfo","r"); -+ if (f != NULL) { -+ int family = 0; -+ int model = 0; -+ char vendor[64] = { 0 }; -+ char *line = NULL; -+ size_t linelen = 0; -+ double mhz; -+ -+ while (getdelim(&line, &linelen, '\n', f) > 0 && seen != ALL) { -+ if (sscanf(line, "vendor_id : %63[^\n]", vendor) == 1) -+ seen |= VENDOR; -+ if (sscanf(line, "cpu family : %d", &family) == 1) -+ seen |= FAMILY; -+ if (sscanf(line, "model : %d", &model) == 1) -+ seen |= MODEL; -+ /* We use only Mhz of the first CPU, assuming they are the same -+ (there are more sanity checks later to make this not as wrong -+ as it sounds) */ -+ if (sscanf(line, "cpu MHz : %lf", &mhz) == 1) { -+ if (!cpumhz_forced) -+ cpumhz = mhz; -+ seen |= MHZ; -+ } -+ if (!strncmp(line, "flags", 5) && isspace(line[6])) { -+ processor_flags = line; -+ line = NULL; -+ linelen = 0; -+ seen |= FLAGS; -+ } -+ -+ } -+ if (seen == ALL) { -+ if (!strcmp(vendor,"AuthenticAMD")) { -+ if (family == 15) { -+ cputype = CPU_K8; -+ } else if (family >= 16) { -+ SYSERRprintf("ERROR: AMD Processor family %d: mcelog does not support this processor. Please use the edac_mce_amd module instead.\n", family); -+ return 0; -+ } -+ } else if (!strcmp(vendor,"GenuineIntel")) -+ cputype = select_intel_cputype(family, model); -+ /* Add checks for other CPUs here */ -+ } else { -+ Eprintf("warning: Cannot parse /proc/cpuinfo\n"); -+ } -+ fclose(f); -+ free(line); -+ } else -+ Eprintf("warning: Cannot open /proc/cpuinfo\n"); -+ -+ return 1; -+} -+ -+static char *skipspace(char *s) -+{ -+ while (isspace(*s)) -+ ++s; -+ return s; -+} -+ -+static char *skip_syslog(char *s) -+{ -+ char *p; -+ -+ /* Handle syslog output */ -+ p = strstr(s, "mcelog: "); -+ if (p) -+ return p + sizeof("mcelog: ") - 1; -+ return s; -+} -+ -+static char *skipgunk(char *s) -+{ -+ s = skip_syslog(s); -+ -+ s = skipspace(s); -+ if (*s == '<') { -+ s += strcspn(s, ">"); -+ if (*s == '>') -+ ++s; -+ } -+ s = skipspace(s); -+ if (*s == '[') { -+ s += strcspn(s, "]"); -+ if (*s == ']') -+ ++s; -+ } -+ -+ s = skipspace(s); -+ -+ if (strncmp(s, "mce: [Hardware Error]:", 22) == 0) -+ s += 22; -+ -+ return skipspace(s); -+} -+ -+static inline int urange(unsigned val, unsigned lo, unsigned hi) -+{ -+ return val >= lo && val <= hi; -+} -+ -+static int is_short(char *name) -+{ -+ return strlen(name) == 3 && -+ isupper(name[0]) && -+ islower(name[1]) && -+ islower(name[2]); -+} -+ -+static unsigned skip_date(char *s) -+{ -+ unsigned day, hour, min, year, sec; -+ char dayname[11]; -+ char month[11]; -+ unsigned next; -+ -+ if (sscanf(s, "%10s %10s %u %u:%u:%u %u%n", -+ dayname, month, &day, &hour, &min, &sec, &year, &next) != 7) -+ return 0; -+ if (!is_short(dayname) || !is_short(month) || !urange(day, 1, 31) || -+ !urange(hour, 0, 24) || !urange(min, 0, 59) || !urange(sec, 0, 59) || -+ year < 1900) -+ return 0; -+ return next; -+} -+ -+static void dump_mce_final(struct mce *m, char *symbol, int missing, int recordlen, -+ int dseen) -+{ -+ m->finished = 1; -+ if (m->cpuid) -+ mce_cpuid(m); -+ if (!dump_raw_ascii) { -+ if (!dseen) -+ disclaimer(); -+ dump_mce(m, recordlen); -+ if (symbol[0]) -+ Wprintf("RIP: %s\n", symbol); -+ if (missing) -+ Wprintf("(Fields were incomplete)\n"); -+ } else -+ dump_mce_raw_ascii(m, recordlen); -+ flushlog(); -+} -+ -+static char *skip_patterns[] = { -+ "MCA:*", -+ "MCi_MISC register valid*", -+ "MC? status*", -+ "Unsupported new Family*", -+ "Kernel does not support page offline interface", -+ NULL -+}; -+ -+static int match_patterns(char *s, char **pat) -+{ -+ for (; *pat; pat++) -+ if (!fnmatch(*pat, s, 0)) -+ return 0; -+ return 1; -+} -+ -+#define FIELD(f) \ -+ if (recordlen < endof_field(struct mce, f)) \ -+ recordlen = endof_field(struct mce, f) -+ -+/* Decode ASCII input for fatal messages */ -+static void decodefatal(FILE *inf) -+{ -+ struct mce m; -+ char *line = NULL; -+ size_t linelen = 0; -+ int missing; -+ char symbol[100]; -+ int data; -+ int next; -+ char *s = NULL; -+ unsigned cpuvendor; -+ unsigned recordlen; -+ int disclaimer_seen; -+ -+ ascii_mode = 1; -+ if (do_dmi && dmi_forced) -+ Wprintf( -+ "WARNING: with --dmi mcelog --ascii must run on the same machine with the\n" -+ " same BIOS/memory configuration as where the machine check occurred.\n"); -+ -+restart: -+ missing = 0; -+ data = 0; -+ next = 0; -+ disclaimer_seen = 0; -+ recordlen = 0; -+ memset(&m, 0, sizeof(struct mce)); -+ symbol[0] = '\0'; -+ while (next > 0 || getdelim(&line, &linelen, '\n', inf) > 0) { -+ int n = 0; -+ char *start; -+ -+ s = next > 0 ? s + next : line; -+ s = skipgunk(s); -+ start = s; -+ next = 0; -+ -+ if (!strncmp(s, "CPU ", 4)) { -+ unsigned cpu = 0, bank = 0; -+ n = sscanf(s, -+ "CPU %u: Machine Check Exception: %16Lx Bank %d: %016Lx%n", -+ &cpu, -+ &m.mcgstatus, -+ &bank, -+ &m.status, -+ &next); -+ if (n == 1) { -+ n = sscanf(s, "CPU %u BANK %u%n", &cpu, &bank, -+ &next); -+ if (n != 2) -+ n = sscanf(s, "CPU %u %u%n", &cpu, -+ &bank, &next); -+ m.cpu = cpu; -+ if (n < 2) -+ missing++; -+ else { -+ m.bank = bank; -+ FIELD(bank); -+ } -+ } else if (n <= 0) { -+ missing++; -+ } else if (n > 1) { -+ FIELD(mcgstatus); -+ m.cpu = cpu; -+ if (n > 2) { -+ m.bank = bank; -+ FIELD(bank); -+ } else if (n > 3) -+ FIELD(status); -+ if (n < 4) -+ missing++; -+ } -+ } -+ else if (!strncmp(s, "STATUS", 6)) { -+ if ((n = sscanf(s,"STATUS %llx%n", &m.status, &next)) < 1) -+ missing++; -+ else -+ FIELD(status); -+ } -+ else if (!strncmp(s, "MCGSTATUS", 6)) { -+ if ((n = sscanf(s,"MCGSTATUS %llx%n", &m.mcgstatus, &next)) < 1) -+ missing++; -+ else -+ FIELD(mcgstatus); -+ } -+ else if (!strncmp(s, "RIP", 3)) { -+ unsigned cs = 0; -+ -+ if (!strncmp(s, "RIP !INEXACT!", 13)) -+ s += 13; -+ else -+ s += 3; -+ -+ n = sscanf(s, "%02x:<%016Lx> {%99s}%n", -+ &cs, -+ &m.ip, -+ symbol, &next); -+ m.cs = cs; -+ if (n < 2) -+ missing++; -+ else -+ FIELD(ip); -+ } -+ else if (!strncmp(s, "TSC",3)) { -+ if ((n = sscanf(s, "TSC %llx%n", &m.tsc, &next)) < 1) -+ missing++; -+ else -+ FIELD(tsc); -+ } -+ else if (!strncmp(s, "ADDR",4)) { -+ if ((n = sscanf(s, "ADDR %llx%n", &m.addr, &next)) < 1) -+ missing++; -+ else -+ FIELD(addr); -+ } -+ else if (!strncmp(s, "MISC",4)) { -+ if ((n = sscanf(s, "MISC %llx%n", &m.misc, &next)) < 1) -+ missing++; -+ else -+ FIELD(misc); -+ } -+ else if (!strncmp(s, "PROCESSOR", 9)) { -+ if ((n = sscanf(s, "PROCESSOR %u:%x%n", &cpuvendor, &m.cpuid, &next)) < 2) -+ missing++; -+ else { -+ m.cpuvendor = cpuvendor; -+ FIELD(cpuid); -+ FIELD(cpuvendor); -+ } -+ } -+ else if (!strncmp(s, "TIME", 4)) { -+ if ((n = sscanf(s, "TIME %llu%n", &m.time, &next)) < 1) -+ missing++; -+ else -+ FIELD(time); -+ -+ next += skip_date(s + next); -+ } -+ else if (!strncmp(s, "MCGCAP", 6)) { -+ if ((n = sscanf(s, "MCGCAP %llx%n", &m.mcgcap, &next)) != 1) -+ missing++; -+ else -+ FIELD(mcgcap); -+ } -+ else if (!strncmp(s, "APICID", 6)) { -+ if ((n = sscanf(s, "APICID %x%n", &m.apicid, &next)) != 1) -+ missing++; -+ else -+ FIELD(apicid); -+ } -+ else if (!strncmp(s, "SOCKETID", 8)) { -+ if ((n = sscanf(s, "SOCKETID %u%n", &m.socketid, &next)) != 1) -+ missing++; -+ else -+ FIELD(socketid); -+ } -+ else if (!strncmp(s, "CPUID", 5)) { -+ unsigned fam, mod; -+ char vendor[31]; -+ -+ if ((n = sscanf(s, "CPUID Vendor %30s Family %u Model %u\n", -+ vendor, &fam, &mod)) < 3) -+ missing++; -+ else { -+ m.cpuvendor = cpuvendor_to_num(vendor); -+ m.cpuid = unparse_cpuid(fam, mod); -+ FIELD(cpuid); -+ FIELD(cpuvendor); -+ } -+ } -+ else if (strstr(s, "HARDWARE ERROR")) -+ disclaimer_seen = 1; -+ else if (!strncmp(s, "(XEN)", 5)) { -+ char *w; -+ unsigned bank, cpu; -+ -+ if (strstr(s, "The hardware reports a non fatal, correctable incident occurred")) { -+ w = strstr(s, "CPU"); -+ if (w && sscanf(w, "CPU %d", &cpu)) { -+ m.cpu = cpu; -+ FIELD(cpu); -+ } -+ } else if ((n = sscanf(s, "(XEN) Bank %d: %llx at %llx", -+ &bank, &m.status, &m.addr) >= 1)) { -+ m.bank = bank; -+ FIELD(bank); -+ if (n >= 2) -+ FIELD(status); -+ if (n >= 3) -+ FIELD(addr); -+ } -+ } -+ else if (!match_patterns(s, skip_patterns)) -+ n = 0; -+ else { -+ s = skipspace(s); -+ if (*s && data) -+ dump_mce_final(&m, symbol, missing, recordlen, disclaimer_seen); -+ if (!dump_raw_ascii) -+ Wprintf("%s", start); -+ if (*s && data) -+ goto restart; -+ } -+ if (n > 0) -+ data = 1; -+ } -+ free(line); -+ if (data) -+ dump_mce_final(&m, symbol, missing, recordlen, disclaimer_seen); -+} -+ -+static void remove_pidfile(void) -+{ -+ unlink(pidfile); -+ if (pidfile != pidfile_default) -+ free(pidfile); -+} -+ -+static void signal_exit(int sig) -+{ -+ remove_pidfile(); -+ _exit(sig); -+} -+ -+static void setup_pidfile(char *s) -+{ -+ char cwd[PATH_MAX]; -+ char *c; -+ -+ if (*s != '/') { -+ c = getcwd(cwd, PATH_MAX); -+ if (!c) -+ return; -+ asprintf(&pidfile, "%s/%s", cwd, s); -+ } else { -+ asprintf(&pidfile, "%s", s); -+ } -+ -+ return; -+} -+ -+static void write_pidfile(void) -+{ -+ FILE *f; -+ atexit(remove_pidfile); -+ signal(SIGTERM, signal_exit); -+ signal(SIGINT, signal_exit); -+ signal(SIGQUIT, signal_exit); -+ f = fopen(pidfile, "w"); -+ if (!f) { -+ Eprintf("Cannot open pidfile `%s'", pidfile); -+ return; -+ } -+ fprintf(f, "%u", getpid()); -+ fclose(f); -+} -+ -+void usage(void) -+{ -+ fprintf(stderr, -+"Usage:\n" -+" mcelog [options] [mcelogdevice]\n" -+"Decode machine check error records from current kernel.\n" -+" mcelog [options] --daemon\n" -+"Run mcelog in daemon mode, waiting for errors from the kernel.\n" -+" mcelog [options] --client\n" -+"Query a currently running mcelog daemon for errors\n" -+" mcelog [options] --ascii < log\n" -+" mcelog [options] --ascii --file log\n" -+"Decode machine check ASCII output from kernel logs\n" -+"Options:\n" -+"--cpu CPU Set CPU type CPU to decode (see below for valid types)\n" -+"--cpumhz MHZ Set CPU Mhz to decode time (output unreliable, not needed on new kernels)\n" -+"--raw (with --ascii) Dump in raw ASCII format for machine processing\n" -+"--daemon Run in background waiting for events (needs newer kernel)\n" -+"--ignorenodev Exit silently when the device cannot be opened\n" -+"--file filename With --ascii read machine check log from filename instead of stdin\n" -+"--syslog Log decoded machine checks in syslog (default stdout or syslog for daemon)\n" -+"--syslog-error Log decoded machine checks in syslog with error level\n" -+"--no-syslog Never log anything to syslog\n" -+"--logfile filename Append log output to logfile instead of stdout\n" -+"--dmi Use SMBIOS information to decode DIMMs (needs root)\n" -+"--no-dmi Don't use SMBIOS information\n" -+"--dmi-verbose Dump SMBIOS information (for debugging)\n" -+"--filter Inhibit known bogus events (default on)\n" -+"--no-filter Don't inhibit known broken events\n" -+"--config-file filename Read config information from config file instead of " CONFIG_FILENAME "\n" -+"--foreground Keep in foreground (for debugging)\n" -+"--num-errors N Only process N errors (for testing)\n" -+"--pidfile file Write pid of daemon into file\n" -+"--no-imc-log Disable extended iMC logging\n" -+ ); -+ diskdb_usage(); -+ print_cputypes(); -+ exit(1); -+} -+ -+enum options { -+ O_LOGFILE = O_COMMON, -+ O_K8, -+ O_P4, -+ O_GENERIC, -+ O_CORE2, -+ O_INTEL_CPU, -+ O_FILTER, -+ O_DMI, -+ O_NO_DMI, -+ O_DMI_VERBOSE, -+ O_SYSLOG, -+ O_NO_SYSLOG, -+ O_CPUMHZ, -+ O_SYSLOG_ERROR, -+ O_RAW, -+ O_DAEMON, -+ O_ASCII, -+ O_CLIENT, -+ O_VERSION, -+ O_CONFIG_FILE, -+ O_CPU, -+ O_FILE, -+ O_FOREGROUND, -+ O_NUMERRORS, -+ O_PIDFILE, -+ O_DEBUG_NUMERRORS, -+ O_NO_IMC_LOG, -+}; -+ -+static struct option options[] = { -+ { "logfile", 1, NULL, O_LOGFILE }, -+ { "k8", 0, NULL, O_K8 }, -+ { "p4", 0, NULL, O_P4 }, -+ { "generic", 0, NULL, O_GENERIC }, -+ { "core2", 0, NULL, O_CORE2 }, -+ { "intel-cpu", 1, NULL, O_INTEL_CPU }, -+ { "ignorenodev", 0, &ignore_nodev, 1 }, -+ { "filter", 0, &filter_bogus, 1 }, -+ { "no-filter", 0, &filter_bogus, 0 }, -+ { "dmi", 0, NULL, O_DMI }, -+ { "no-dmi", 0, NULL, O_NO_DMI }, -+ { "dmi-verbose", 1, NULL, O_DMI_VERBOSE }, -+ { "syslog", 0, NULL, O_SYSLOG }, -+ { "cpumhz", 1, NULL, O_CPUMHZ }, -+ { "syslog-error", 0, NULL, O_SYSLOG_ERROR }, -+ { "dump-raw-ascii", 0, &dump_raw_ascii, 1 }, -+ { "raw", 0, &dump_raw_ascii, 1 }, -+ { "no-syslog", 0, NULL, O_NO_SYSLOG }, -+ { "daemon", 0, NULL, O_DAEMON }, -+ { "ascii", 0, NULL, O_ASCII }, -+ { "file", 1, NULL, O_FILE }, -+ { "version", 0, NULL, O_VERSION }, -+ { "config-file", 1, NULL, O_CONFIG_FILE }, -+ { "cpu", 1, NULL, O_CPU }, -+ { "foreground", 0, NULL, O_FOREGROUND }, -+ { "client", 0, NULL, O_CLIENT }, -+ { "num-errors", 1, NULL, O_NUMERRORS }, -+ { "pidfile", 1, NULL, O_PIDFILE }, -+ { "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */ -+ { "no-imc-log", 0, NULL, O_NO_IMC_LOG }, -+ DISKDB_OPTIONS -+ {} -+}; -+ -+static int modifier(int opt) -+{ -+ int v; -+ -+ switch (opt) { -+ case O_LOGFILE: -+ logfile = optarg; -+ break; -+ case O_K8: -+ cputype = CPU_K8; -+ cpu_forced = 1; -+ break; -+ case O_P4: -+ cputype = CPU_P4; -+ cpu_forced = 1; -+ break; -+ case O_GENERIC: -+ cputype = CPU_GENERIC; -+ cpu_forced = 1; -+ break; -+ case O_CORE2: -+ cputype = CPU_CORE2; -+ cpu_forced = 1; -+ break; -+ case O_INTEL_CPU: { -+ unsigned fam, mod; -+ if (sscanf(optarg, "%i,%i", &fam, &mod) != 2) -+ usage(); -+ cputype = select_intel_cputype(fam, mod); -+ if (cputype == CPU_GENERIC) { -+ fprintf(stderr, "Unknown Intel CPU\n"); -+ usage(); -+ } -+ cpu_forced = 1; -+ break; -+ } -+ case O_CPU: -+ cputype = lookup_cputype(optarg); -+ cpu_forced = 1; -+ intel_cpu_init(cputype); -+ break; -+ case O_DMI: -+ do_dmi = 1; -+ dmi_forced = 1; -+ break; -+ case O_NO_DMI: -+ dmi_forced = 1; -+ do_dmi = 0; -+ break; -+ case O_DMI_VERBOSE: -+ if (sscanf(optarg, "%i", &v) != 1) -+ usage(); -+ dmi_set_verbosity(v); -+ break; -+ case O_SYSLOG: -+ openlog("mcelog", 0, LOG_DAEMON); -+ syslog_opt = SYSLOG_ALL|SYSLOG_FORCE; -+ break; -+ case O_NO_SYSLOG: -+ syslog_opt = SYSLOG_FORCE; -+ break; -+ case O_CPUMHZ: -+ cpumhz_forced = 1; -+ if (sscanf(optarg, "%lf", &cpumhz) != 1) -+ usage(); -+ break; -+ case O_SYSLOG_ERROR: -+ syslog_level = LOG_ERR; -+ syslog_opt = SYSLOG_ALL|SYSLOG_FORCE; -+ break; -+ case O_DAEMON: -+ daemon_mode = 1; -+ if (!(syslog_opt & SYSLOG_FORCE)) -+ syslog_opt = SYSLOG_REMARK|SYSLOG_ERROR; -+ break; -+ case O_FILE: -+ inputfile = optarg; -+ break; -+ case O_FOREGROUND: -+ foreground = 1; -+ if (!(syslog_opt & SYSLOG_FORCE)) -+ syslog_opt = SYSLOG_FORCE; -+ break; -+ case O_NUMERRORS: -+ numerrors = atoi(optarg); -+ break; -+ case O_PIDFILE: -+ setup_pidfile(optarg); -+ break; -+ case O_CONFIG_FILE: -+ /* parsed in config.c */ -+ break; -+ case O_DEBUG_NUMERRORS: -+ debug_numerrors = 1; -+ break; -+ case O_NO_IMC_LOG: -+ imc_log = 0; -+ break; -+ case 0: -+ break; -+ default: -+ return 0; -+ } -+ return 1; -+} -+ -+static void modifier_finish(void) -+{ -+ if(!foreground && daemon_mode && !logfile && !(syslog_opt & SYSLOG_LOG)) { -+ logfile = logfile_default; -+ } -+ if (logfile) { -+ if (open_logfile(logfile) < 0) { -+ if (daemon_mode && !(syslog_opt & SYSLOG_FORCE)) -+ syslog_opt = SYSLOG_ALL; -+ SYSERRprintf("Cannot open logfile %s", logfile); -+ if (!daemon_mode) -+ exit(1); -+ } -+ } -+} -+ -+void argsleft(int ac, char **av) -+{ -+ int opt; -+ -+ while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) { -+ if (modifier(opt) != 1) -+ usage(); -+ } -+} -+ -+void no_syslog(void) -+{ -+ if (!(syslog_opt & SYSLOG_FORCE)) -+ syslog_opt = 0; -+} -+ -+static int combined_modifier(int opt) -+{ -+ int r = modifier(opt); -+ if (r == 0) -+ r = diskdb_modifier(opt); -+ return r; -+} -+ -+static void general_setup(void) -+{ -+ trigger_setup(); -+ yellow_setup(); -+ bus_setup(); -+ unknown_setup(); -+ config_cred("global", "run-credentials", &runcred); -+ if (config_bool("global", "filter-memory-errors") == 1) -+ filter_memory_errors = 1; -+} -+ -+static void drop_cred(void) -+{ -+ if (runcred.uid != -1U && runcred.gid == -1U) { -+ struct passwd *pw = getpwuid(runcred.uid); -+ if (pw) -+ runcred.gid = pw->pw_gid; -+ } -+ if (runcred.gid != -1U) { -+ if (setgid(runcred.gid) < 0) -+ SYSERRprintf("Cannot change group to %d", runcred.gid); -+ } -+ if (runcred.uid != -1U) { -+ if (setuid(runcred.uid) < 0) -+ SYSERRprintf("Cannot change user to %d", runcred.uid); -+ } -+} -+ -+static void process(int fd, unsigned recordlen, unsigned loglen, char *buf) -+{ -+ int i; -+ int len, count; -+ int finish = 0, flags; -+ -+ if (recordlen == 0) { -+ Wprintf("no data in mce record\n"); -+ return; -+ } -+ -+ len = read(fd, buf, recordlen * loglen); -+ if (len < 0) { -+ SYSERRprintf("mcelog read"); -+ return; -+ } -+ -+ count = len / (int)recordlen; -+ if (count == (int)loglen) { -+ if ((ioctl(fd, MCE_GETCLEAR_FLAGS, &flags) == 0) && -+ (flags & (1 << MCE_OVERFLOW))) -+ Eprintf("Warning: MCE buffer is overflowed.\n"); -+ } -+ -+ for (i = 0; (i < count) && !finish; i++) { -+ struct mce *mce = (struct mce *)(buf + i*recordlen); -+ mce_prepare(mce); -+ if (numerrors > 0 && --numerrors == 0) -+ finish = 1; -+ if (!mce_filter(mce, recordlen)) -+ continue; -+ if (!dump_raw_ascii) { -+ disclaimer(); -+ Wprintf("MCE %d\n", i); -+ dump_mce(mce, recordlen); -+ } else -+ dump_mce_raw_ascii(mce, recordlen); -+ flushlog(); -+ } -+ -+ if (debug_numerrors && numerrors <= 0) -+ finish = 1; -+ -+ if (recordlen > sizeof(struct mce)) { -+ Eprintf("warning: %lu bytes ignored in each record\n", -+ (unsigned long)recordlen - sizeof(struct mce)); -+ Eprintf("consider an update\n"); -+ } -+ -+ if (finish) -+ exit(0); -+} -+ -+static void noargs(int ac, char **av) -+{ -+ if (getopt_long(ac, av, "", options, NULL) != -1) -+ usage(); -+} -+ -+static void parse_config(char **av) -+{ -+ static const char config_fn[] = CONFIG_FILENAME; -+ const char *fn = config_file(av, config_fn); -+ if (!fn) -+ usage(); -+ if (parse_config_file(fn) < 0) { -+ /* If it's the default file don't complain if it isn't there */ -+ if (fn != config_fn) { -+ fprintf(stderr, "Cannot open config file %s\n", fn); -+ exit(1); -+ } -+ return; -+ } -+ config_options(options, combined_modifier); -+} -+ -+static void ascii_command(int ac, char **av) -+{ -+ FILE *f = stdin; -+ -+ argsleft(ac, av); -+ if (inputfile) { -+ f = fopen(inputfile, "r"); -+ if (!f) { -+ fprintf(stderr, "Cannot open input file `%s': %s\n", -+ inputfile, strerror(errno)); -+ exit(1); -+ } -+ /* f closed by exit */ -+ } -+ no_syslog(); -+ checkdmi(); -+ decodefatal(f); -+} -+ -+static void client_command(int ac, char **av) -+{ -+ argsleft(ac, av); -+ no_syslog(); -+ // XXX modifiers -+ ask_server("dump all bios\n"); -+ ask_server("pages\n"); -+} -+ -+struct mcefd_data { -+ unsigned loglen; -+ unsigned recordlen; -+ char *buf; -+}; -+ -+static void process_mcefd(struct pollfd *pfd, void *data) -+{ -+ struct mcefd_data *d = (struct mcefd_data *)data; -+ assert((pfd->revents & POLLIN) != 0); -+ process(pfd->fd, d->recordlen, d->loglen, d->buf); -+} -+ -+static void handle_sigusr1(int sig) -+{ -+ reopenlog(); -+} -+ -+int main(int ac, char **av) -+{ -+ struct mcefd_data d = {}; -+ int opt; -+ int fd; -+ -+ parse_config(av); -+ -+ while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) { -+ if (opt == '?') { -+ usage(); -+ } else if (combined_modifier(opt) > 0) { -+ continue; -+ } else if (opt == O_ASCII) { -+ ascii_command(ac, av); -+ exit(0); -+ } else if (opt == O_CLIENT) { -+ client_command(ac, av); -+ exit(0); -+ } else if (opt == O_VERSION) { -+ noargs(ac, av); -+ fprintf(stderr, "mcelog %s\n", MCELOG_VERSION); -+ exit(0); -+ } else if (diskdb_cmd(opt, ac, av)) { -+ exit(0); -+ } else if (opt == 0) -+ break; -+ } -+ -+ /* before doing anything else let's see if the CPUs are supported */ -+ if (!cpu_forced && !is_cpu_supported()) { -+ fprintf(stderr, "CPU is unsupported\n"); -+ exit(1); -+ } -+ -+ /* If the user didn't tell us not to use iMC logging, check if CPU supports it */ -+ if (imc_log == -1) { -+ switch (cputype) { -+ case CPU_SANDY_BRIDGE_EP: -+ case CPU_IVY_BRIDGE_EPEX: -+ imc_log = 1; -+ break; -+ default: -+ imc_log = 0; -+ break; -+ } -+ } -+ -+ modifier_finish(); -+ if (av[optind]) -+ logfn = av[optind++]; -+ if (av[optind]) -+ usage(); -+ checkdmi(); -+ general_setup(); -+ -+ fd = open(logfn, O_RDONLY); -+ if (fd < 0) { -+ if (ignore_nodev) -+ exit(0); -+ SYSERRprintf("Cannot open `%s'", logfn); -+ exit(1); -+ } -+ -+ if (ioctl(fd, MCE_GET_RECORD_LEN, &d.recordlen) < 0) -+ err("MCE_GET_RECORD_LEN"); -+ if (ioctl(fd, MCE_GET_LOG_LEN, &d.loglen) < 0) -+ err("MCE_GET_LOG_LEN"); -+ -+ d.buf = xalloc(d.recordlen * d.loglen); -+ if (daemon_mode) { -+ prefill_memdb(do_dmi); -+ if (!do_dmi) -+ closedmi(); -+ server_setup(); -+ page_setup(); -+ if (imc_log) -+ set_imc_log(cputype); -+ drop_cred(); -+ register_pollcb(fd, POLLIN, process_mcefd, &d); -+ if (!foreground && daemon(0, need_stdout()) < 0) -+ err("daemon"); -+ if (pidfile) -+ write_pidfile(); -+ signal(SIGUSR1, handle_sigusr1); -+ event_signal(SIGUSR1); -+ eventloop(); -+ } else { -+ process(fd, d.recordlen, d.loglen, d.buf); -+ } -+ trigger_wait(); -+ -+ exit(0); -+} diff -urNp mcelog-d2e13bf0.orig/mcelog.h mcelog-d2e13bf0/mcelog.h --- mcelog-d2e13bf0.orig/mcelog.h 2016-05-14 08:34:40.446108283 -0400 +++ mcelog-d2e13bf0/mcelog.h 2016-05-14 08:34:58.872975199 -0400 diff --git a/SPECS/mcelog.spec b/SPECS/mcelog.spec index 952b3eb..844b6bc 100644 --- a/SPECS/mcelog.spec +++ b/SPECS/mcelog.spec @@ -4,7 +4,7 @@ Summary: Tool to translate x86-64 CPU Machine Check Exception data Name: mcelog Version: 144 -Release: 3.%{last_git_commit}%{?dist} +Release: 8.%{last_git_commit}%{?dist} Epoch: 3 Group: System Environment/Base License: GPLv2 @@ -26,6 +26,11 @@ Patch7: mcelog-update-e4aca63.patch Patch8: mcelog-update-94d853b2ea81.patch Patch9: mcelog-patch-e9aeed03f3d1.patch Patch10: mcelog-patch-cfa11588ad8b.patch +# Patches 11-14 below can be removed on the next full code update. +Patch11: mcelog-patch-commit-916015663906.patch +Patch12: mcelog-patch-0755b55af.patch +Patch13: mcelog-patch-59b8cab3f.patch +Patch14: mcelog-patch-f8f1490cb.patch URL: https://github.com/andikleen/mcelog.git Buildroot: %{_tmppath}/%{name}-%{version}-root ExclusiveArch: i686 x86_64 @@ -40,23 +45,30 @@ on x86-32 and x86-64 systems. It can be run either as a daemon, or by cron. %prep %setup -q -n %{name}-%{last_tar_git_commit} -%patch0 -p1 -b .fix-triggers-and-cacheing -%patch1 -p1 -b .mcelog-update-2577aeb -%patch2 -p1 -b .mcelog-update-f30da3d -%patch3 -p1 -b .mcelog-haswell-support -%patch4 -p1 -b .mcelog-update-9de4924 -%patch5 -p1 -b .mcelog-update-e7e0ac1 -%patch6 -p1 -b .mcelog-patch-1bd2984 -%patch7 -p1 -b .mcelog-update-e4aca63 -%patch8 -p1 -b .mcelog-update-94d853b2ea81 -%patch9 -p1 -b .mcelog-patch-e9aeed03f3d1 -%patch10 -p1 -b .mcelog-patch-e9aeed03f3d1 +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 %build mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir} mkdir -p $RPM_BUILD_ROOT/%{_sbindir} mkdir -p $RPM_BUILD_ROOT/%{_mandir} +# Make sure mcelog --version and 'rpm -q mcelog' are consistent +echo "%{name}-%{version}-%{release}" > .os_version + make CFLAGS="$RPM_OPT_FLAGS -Wl,-z,relro,-z,now -fpie" LDFLAGS="-Wl,-z,relro,-z,now -fpie -pie" %install @@ -84,8 +96,14 @@ install -p -m644 mcelog.triggers.5 $RPM_BUILD_ROOT/%{_mandir}/man5 rm -rf $RPM_BUILD_ROOT %post -systemctl enable mcelog.service &> /dev/null || -systemctl daemon-reload &> /dev/null +case "$1" in + 1) # This is an initial installation + systemctl enable mcelog.service &> /dev/null || systemctl daemon-reload &> /dev/null + ;; + 2) # This is an upgrade - don't reactivate the service again + : + ;; +esac %preun # Handle removing mcelog @@ -113,6 +131,16 @@ fi %attr(0644,root,root) %{_mandir}/*/* %changelog +* Tue Oct 17 2017 Prarit Bhargava - 3:144.8.94d853b2ea81 +- Fix typo in spec file for .os_version[1454419] +* Tue Oct 17 2017 Prarit Bhargava - 3:144.7.94d853b2ea81 +- Fix mcelog --version [1454419] +* Mon Oct 16 2017 Prarit Bhargava - 3:144.6.94d853b2ea81 +- Fix return value from 'mcelog --help' [1481421] +* Thu Oct 5 2017 Prarit Bhargava - 3:144.5.94d853b2ea81 +- Fix mcelog.service file enable/disable after install & upgrade [1413284] +* Tue Sep 19 2017 Prarit Bhargava - 3:144.4.94d853b2ea81 +- Cleanup spec and patch files [1493151] * Thu Apr 27 2017 Prarit Bhargava - 3:144.3.94d853b2ea81 - Fix "warning: 16 bytes ignored in each record" warning [1445809] * Thu Feb 2 2017 Prarit Bhargava - 3:144.2.94d853b2ea81