blob: 9c9797e0bdfc2f603e59427a88a98edadbe493d1 [file] [log] [blame]
/*
* Verify MCA grading engine against some examples.
*/
#include <sys/types.h>
#include <stdio.h>
#define __KERNEL__ 1
#include <asm/types.h>
#include <asm/mce.h>
#include <errno.h>
#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;
}