Blame SOURCES/0019-Fix-handling-of-Machine-Check-Exceptions.patch

a60cd7
From 744e4c6a6cbbb9ba0569bf8e3ab50171e974b2e3 Mon Sep 17 00:00:00 2001
a60cd7
From: Denys Vlasenko <dvlasenk@redhat.com>
a60cd7
Date: Mon, 6 Jan 2014 17:18:31 +0100
a60cd7
Subject: [ABRT PATCH 19/27] Fix handling of Machine Check Exceptions.
a60cd7
a60cd7
Closes #764.
a60cd7
a60cd7
If non-fatal MCE is seen, abrt will detect it as an oops
a60cd7
and alert user in a usual manner. When user opens this
a60cd7
abrt problem for reporting, he will see that "comment"
a60cd7
field is pre-filled with a text.
a60cd7
What it says depends on whether mcelog tool is installed.
a60cd7
If mcelog is installed, the text will say that hardware errors
a60cd7
were detected, and will show the tail of either /var/log/mcelog
a60cd7
or syslog.
a60cd7
Otherwise the text will say that hardware errors
a60cd7
were detected, but they can't be usefully diagnosed,
a60cd7
and user is strongly advised to install mcelog tool.
a60cd7
a60cd7
If fatal MCE is encountered, kernel always panics,
a60cd7
(abrt has no chance of catching the oops),
a60cd7
kdump kicks in, and then after reboot abrt says that new vmcore
a60cd7
is found. When user generates backtrace, he will see oops text
a60cd7
which starts with
a60cd7
"Machine Check Exception: BANK nnn ..." and (hopefully)
a60cd7
is already explanatory enough.
a60cd7
a60cd7
(Yes, it's weird that kernel shows human-readable error messages
a60cd7
on fatal MCEs but doesn't do that for non-fatal ones.
a60cd7
This makes fetching MCE info significantly different...
a60cd7
I wish kernel would show human-readable MCEs in both cases,
a60cd7
we wouldn't need mcelog then... oh well.)
a60cd7
a60cd7
In order to generate meaningful hash for MCE's,
a60cd7
oops hashing was extended for oopses without backtraces.
a60cd7
a60cd7
Since MCEs, unlike regular oopses, don't contain kernel version,
a60cd7
additional magic is added to extract kernel version
a60cd7
in vmcore event handling.
a60cd7
a60cd7
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
a60cd7
a60cd7
Related to rhbz#1032077
a60cd7
a60cd7
Signed-off-by: Jakub Filak <jfilak@redhat.com>
a60cd7
---
a60cd7
 src/lib/kernel.c              | 31 +++++++++++++++++++++++++
a60cd7
 src/plugins/koops_event.conf  | 54 +++++++++++++++++++++++++++++++++++++++++++
a60cd7
 src/plugins/vmcore_event.conf | 18 ++++++++++++++-
a60cd7
 3 files changed, 102 insertions(+), 1 deletion(-)
a60cd7
a60cd7
diff --git a/src/lib/kernel.c b/src/lib/kernel.c
a60cd7
index ce8815b..340ec39 100644
a60cd7
--- a/src/lib/kernel.c
a60cd7
+++ b/src/lib/kernel.c
a60cd7
@@ -115,8 +115,29 @@ static const char *const s_koops_suspicious_strings[] = {
a60cd7
      * arch/x86/kernel/cpu/mcheck/p5.c:		"CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n",
a60cd7
      * arch/x86/kernel/cpu/mcheck/mce.c:	pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
a60cd7
      * drivers/edac/sb_edac.c:			printk("CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
a60cd7
+     *
a60cd7
+     * MCEs can be fatal (they panic kernel) or not.
a60cd7
+     * Fatal MCE are delivered as exception#18 to the CPU.
a60cd7
+     * Non-fatal ones sometimes are delivered as exception#18;
a60cd7
+     * other times they are silently recorded in magic MSRs, CPU is not alerted.
a60cd7
+     * Linux kernel periodically (up to 5 mins interval) reads those MSRs
a60cd7
+     * and if MCE is seen there, it is piped in binary form through
a60cd7
+     * /dev/mcelog to whoever listens on it. (Such as mcelog tool in --daemon
a60cd7
+     * mode; but cat 
a60cd7
+     *
a60cd7
+     * "Machine Check Exception:" message is printed *only*
a60cd7
+     * by fatal MCEs (so far, future kernels may be different).
a60cd7
+     * It will be caught as vmcore if kdump is configured.
a60cd7
+     *
a60cd7
+     * Non-fatal MCEs have "[Hardware Error]: Machine check events logged"
a60cd7
+     * message in kernel log.
a60cd7
+     * When /dev/mcelog is read, *no additional kernel log messages appear*:
a60cd7
+     * if we want more readable data, we must rely on other tools
a60cd7
+     * (such as mcelog daemon consuming binary /dev/mcelog and writing
a60cd7
+     * human-readable /var/log/mcelog).
a60cd7
      */
a60cd7
     "Machine Check Exception:",
a60cd7
+    "Machine check events logged",
a60cd7
 
a60cd7
     /* X86 TRAPs */
a60cd7
     "divide error:",
a60cd7
@@ -299,6 +320,16 @@ next_line:
a60cd7
             if (strcasestr(curline, "Call Trace:")) /* yes, it must be case-insensitive */
a60cd7
                 inbacktrace = 1;
a60cd7
             else
a60cd7
+            /* Fatal MCE's have a few lines of useful information between
a60cd7
+             * first "Machine check exception:" line and the final "Kernel panic"
a60cd7
+             * line. Such oops, of course, is only detectable in kdumps (tested)
a60cd7
+             * or possibly pstore-saved logs (I did not try this yet).
a60cd7
+             * In order to capture all these lines, we treat final line
a60cd7
+             * as "backtrace" (which is admittedly a hack):
a60cd7
+             */
a60cd7
+            if (strstr(curline, "Kernel panic - not syncing"))
a60cd7
+                inbacktrace = 1;
a60cd7
+            else
a60cd7
             if (strnlen(curline, 9) > 8
a60cd7
              && (  (curline[0] == '(' && curline[1] == '[' && curline[2] == '<')
a60cd7
                 || (curline[0] == '[' && curline[1] == '<'))
a60cd7
diff --git a/src/plugins/koops_event.conf b/src/plugins/koops_event.conf
a60cd7
index c0277c8..7dfbe36 100644
a60cd7
--- a/src/plugins/koops_event.conf
a60cd7
+++ b/src/plugins/koops_event.conf
a60cd7
@@ -4,6 +4,60 @@ EVENT=post-create analyzer=Kerneloops
a60cd7
         abrt-action-analyze-oops &&
a60cd7
         dmesg >>dmesg &&
a60cd7
         abrt-action-save-kernel-data
a60cd7
+        abrt-action-save-kernel-data || exit $?
a60cd7
+        #
a60cd7
+        # If it exists, we can save a copy of MCE log here:
a60cd7
+        #test -f /var/log/mcelog && cp /var/log/mcelog .
a60cd7
+        # but in current config, sosreport already does that.
a60cd7
+        #
a60cd7
+        # See if MCEs were seen but mcelog isn't installed or running
a60cd7
+        grep -qFi 'Machine check events logged' dmesg || exit 0
a60cd7
+        #
a60cd7
+        # There was an MCE. IOW: it's not a bug, it's a HW error.
a60cd7
+        # Did mcelog logged it to /var/log/mcelog
a60cd7
+        # (RHEL6 by default does this)?
a60cd7
+        test -f /var/log/mcelog &&
a60cd7
+        {
a60cd7
+                # (Ab)use user comment field to inform user about it.
a60cd7
+                echo "The kernel log indicates that hardware errors were detected."
a60cd7
+                echo "/var/log/mcelog file may have more information."
a60cd7
+                echo "The last 20 lines of /var/log/mcelog are:"
a60cd7
+                echo "========================================="
a60cd7
+                # Redirecting sterr in case selinux makes it unreadable
a60cd7
+                # (annoying anyway, but at least user knows what's going on):
a60cd7
+                tail -n20 /var/log/mcelog 2>&1
a60cd7
+                exit 0
a60cd7
+        } >comment
a60cd7
+        #
a60cd7
+        # On RHEL7, mcelog is run so that its output ends up in syslog.
a60cd7
+        # Do we see that?
a60cd7
+        grep -qFi 'mcelog: Hardware event' /var/log/messages &&
a60cd7
+        {
a60cd7
+                echo "The kernel log indicates that hardware errors were detected."
a60cd7
+                echo "System log may have more information."
a60cd7
+                echo "The last 20 mcelog lines of system log are:"
a60cd7
+                echo "========================================="
a60cd7
+                # Redirecting sterr in case selinux makes it unreadable
a60cd7
+                # (annoying anyway, but at least user knows what's going on):
a60cd7
+                grep -Fi 'mcelog:' /var/log/messages | tail -n20 2>&1
a60cd7
+                exit 0
a60cd7
+        } >comment
a60cd7
+        #
a60cd7
+        # Apparently, there is no running mcelog daemon!
a60cd7
+        # Let user know that he needs one.
a60cd7
+        {
a60cd7
+        echo "The kernel log indicates that hardware errors were detected."
a60cd7
+        echo "The data was saved by kernel for processing by the mcelog tool."
a60cd7
+        echo "However, neither /var/log/mcelog nor system log contain mcelog messages."
a60cd7
+        echo "Most likely reason is that mcelog is not installed or not configured"
a60cd7
+        echo "to be started during boot."
a60cd7
+        echo "Without this tool running, the binary data saved by kernel"
a60cd7
+        echo "is of limited usefulness."
a60cd7
+        echo "(You can save this data anyway by running 'cat </dev/mcelog >FILE')."
a60cd7
+        echo "The recommended course of action is to install mcelog."
a60cd7
+        echo "If another hardware error would occur, a user-readable description"
a60cd7
+        echo "of it will be saved in system log or /var/log/mcelog."
a60cd7
+        } >comment
a60cd7
 
a60cd7
 # If you want behavior similar to one provided by kerneloops daemon
a60cd7
 # distributed by kerneloops.org - that is, if you want
a60cd7
diff --git a/src/plugins/vmcore_event.conf b/src/plugins/vmcore_event.conf
a60cd7
index f8de3c5..655d842 100644
a60cd7
--- a/src/plugins/vmcore_event.conf
a60cd7
+++ b/src/plugins/vmcore_event.conf
a60cd7
@@ -1,6 +1,22 @@
a60cd7
 # analyze
a60cd7
 EVENT=analyze_VMcore analyzer=vmcore
a60cd7
-        abrt-action-analyze-vmcore &&
a60cd7
+        # If kdump machinery already extracted dmesg...
a60cd7
+        if test -f vmcore-dmesg.txt; then
a60cd7
+            # ...use that
a60cd7
+            abrt-dump-oops -o vmcore-dmesg.txt >backtrace || exit $?
a60cd7
+            #
a60cd7
+            # Does "kernel" element exist?
a60cd7
+            test -f kernel && exit 0
a60cd7
+            #
a60cd7
+            # Try creating it from vmcore-dmesg.txt:
a60cd7
+            # MCE oopses don't have kernel version in them,
a60cd7
+            # but it should be specified earlier in the log.
a60cd7
+            k=`sed -n '/Linux version/ s/.*Linux version \([^ ]*\) .*/\1/p' vmcore-dmesg.txt | tail -n1`
a60cd7
+            test "$k" != "" && printf "%s" "$k" >kernel
a60cd7
+        else
a60cd7
+            # No vmcore-dmesg.txt, do it the hard way:
a60cd7
+            abrt-action-analyze-vmcore
a60cd7
+        fi &&
a60cd7
         abrt-action-analyze-oops &&
a60cd7
         abrt-action-save-kernel-data
a60cd7
 
a60cd7
-- 
a60cd7
1.8.3.1
a60cd7