x86, mce: add table driven machine check grading
[safe/jmp/linux-2.6] / arch / x86 / kernel / cpu / mcheck / mce-severity.c
1 /*
2  * MCE grading rules.
3  * Copyright 2008, 2009 Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; version 2
8  * of the License.
9  *
10  * Author: Andi Kleen
11  */
12 #include <linux/kernel.h>
13 #include <asm/mce.h>
14
15 #include "mce-internal.h"
16
17 /*
18  * Grade an mce by severity. In general the most severe ones are processed
19  * first. Since there are quite a lot of combinations test the bits in a
20  * table-driven way. The rules are simply processed in order, first
21  * match wins.
22  */
23
24 static struct severity {
25         u64 mask;
26         u64 result;
27         unsigned char sev;
28         unsigned char mcgmask;
29         unsigned char mcgres;
30         char *msg;
31 } severities[] = {
32 #define SEV(s) .sev = MCE_ ## s ## _SEVERITY
33 #define BITCLR(x, s, m, r...) { .mask = x, .result = 0, SEV(s), .msg = m, ## r }
34 #define BITSET(x, s, m, r...) { .mask = x, .result = x, SEV(s), .msg = m, ## r }
35 #define MCGMASK(x, res, s, m, r...) \
36         { .mcgmask = x, .mcgres = res, SEV(s), .msg = m, ## r }
37         BITCLR(MCI_STATUS_VAL, NO, "Invalid"),
38         BITCLR(MCI_STATUS_EN, NO, "Not enabled"),
39         BITSET(MCI_STATUS_PCC, PANIC, "Processor context corrupt"),
40         MCGMASK(MCG_STATUS_RIPV, 0, PANIC, "No restart IP"),
41         BITSET(MCI_STATUS_UC|MCI_STATUS_OVER, PANIC, "Overflowed uncorrected"),
42         BITSET(MCI_STATUS_UC, UC, "Uncorrected"),
43         BITSET(0, SOME, "No match")     /* always matches. keep at end */
44 };
45
46 int mce_severity(struct mce *a, int tolerant, char **msg)
47 {
48         struct severity *s;
49         for (s = severities;; s++) {
50                 if ((a->status & s->mask) != s->result)
51                         continue;
52                 if ((a->mcgstatus & s->mcgmask) != s->mcgres)
53                         continue;
54                 if (s->sev > MCE_NO_SEVERITY && (a->status & MCI_STATUS_UC) &&
55                         tolerant < 1)
56                         return MCE_PANIC_SEVERITY;
57                 if (msg)
58                         *msg = s->msg;
59                 return s->sev;
60         }
61 }