/* * Verify MCA grading engine against some examples. */ #include #include #define __KERNEL__ 1 #include #include #include #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x))) typedef unsigned long long u64; #define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ #define MCI_STATUS_AR (1ULL<<55) /* Action required */ int mce_ser = 1; int tolerant = 1; int panic_on_oops = 0; #include "mce-severity.c" char *resname[] = { #define R(x) [MCE_ ## x ## _SEVERITY] = #x R(NO), R(KEEP), R(SOME), R(AO), R(AR), R(PANIC), }; #define VAL MCI_STATUS_VAL #define EN MCI_STATUS_EN #define PCC MCI_STATUS_PCC #define S MCI_STATUS_S #define AR MCI_STATUS_AR #define UC MCI_STATUS_UC int ring = 3; int fail; void test2(u64 flag, char *flagname, u64 mcg, char *mcgname, int result) { struct mce m = { .ip = 1, .cs = ring, .status = flag, .mcgstatus = mcg, }; int r; char *msg; if ((r = mce_severity(&m, tolerant, &msg)) != result) { printf("%s %s expected %s got %s msg %s\n", flagname, mcgname, resname[result], resname[r], msg); fail++; } } #define TEST(flag, result) \ test2(flag, #flag, MCG_STATUS_MCIP|MCG_STATUS_RIPV, "mcip,ripv", \ MCE_ ## result ## _SEVERITY) void test(void) { // corrected TEST(VAL|EN, KEEP); // uncorrected fatal TEST(VAL|UC|PCC|EN|S|AR, PANIC); TEST(VAL|UC|PCC|EN|S, PANIC); TEST(VAL|UC|PCC|EN, PANIC); // SW recoverable action required // unknown mcacod -> panic TEST(VAL|UC|EN|S|AR, PANIC); // SW recoverable action optional TEST(VAL|UC|EN|S|0xc0, AO); // unknown mcacod TEST(VAL|UC|EN|S|1, SOME); // UCNA TEST(VAL|UC|EN, KEEP); TEST(VAL|UC, NO); // linux clears. correct? } int main(void) { ring = 3; test(); ring = 0; test(); if (fail == 0) printf("SUCCESS\n"); else printf("%d FAILURES\n", fail); return fail; }