1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Verify MCA grading engine against some examples.
3f08c3bdfSopenharmony_ci */
4f08c3bdfSopenharmony_ci#include <sys/types.h>
5f08c3bdfSopenharmony_ci#include <stdio.h>
6f08c3bdfSopenharmony_ci#define __KERNEL__ 1
7f08c3bdfSopenharmony_ci#include <asm/types.h>
8f08c3bdfSopenharmony_ci#include <asm/mce.h>
9f08c3bdfSopenharmony_ci#include <errno.h>
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ci#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x)))
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_citypedef unsigned long long u64;
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#define MCI_STATUS_S	 (1ULL<<56)  /* Signaled machine check */
16f08c3bdfSopenharmony_ci#define MCI_STATUS_AR	 (1ULL<<55)  /* Action required */
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ciint mce_ser = 1;
19f08c3bdfSopenharmony_ciint tolerant = 1;
20f08c3bdfSopenharmony_ciint panic_on_oops = 0;
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci#include "mce-severity.c"
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cichar *resname[] = {
25f08c3bdfSopenharmony_ci#define R(x) [MCE_ ## x ## _SEVERITY] = #x
26f08c3bdfSopenharmony_ci	R(NO),
27f08c3bdfSopenharmony_ci	R(KEEP),
28f08c3bdfSopenharmony_ci	R(SOME),
29f08c3bdfSopenharmony_ci	R(AO),
30f08c3bdfSopenharmony_ci	R(AR),
31f08c3bdfSopenharmony_ci	R(PANIC),
32f08c3bdfSopenharmony_ci};
33f08c3bdfSopenharmony_ci#define VAL MCI_STATUS_VAL
34f08c3bdfSopenharmony_ci#define EN MCI_STATUS_EN
35f08c3bdfSopenharmony_ci#define PCC MCI_STATUS_PCC
36f08c3bdfSopenharmony_ci#define S MCI_STATUS_S
37f08c3bdfSopenharmony_ci#define AR MCI_STATUS_AR
38f08c3bdfSopenharmony_ci#define UC MCI_STATUS_UC
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ciint ring = 3;
41f08c3bdfSopenharmony_ciint fail;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_civoid test2(u64 flag, char *flagname, u64 mcg, char *mcgname, int result)
44f08c3bdfSopenharmony_ci{
45f08c3bdfSopenharmony_ci	struct mce m = {
46f08c3bdfSopenharmony_ci		.ip = 1,
47f08c3bdfSopenharmony_ci		.cs = ring,
48f08c3bdfSopenharmony_ci		.status = flag,
49f08c3bdfSopenharmony_ci		.mcgstatus = mcg,
50f08c3bdfSopenharmony_ci	};
51f08c3bdfSopenharmony_ci	int r;
52f08c3bdfSopenharmony_ci	char *msg;
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci	if ((r = mce_severity(&m, tolerant, &msg)) != result) {
55f08c3bdfSopenharmony_ci		printf("%s %s expected %s got %s msg %s\n",
56f08c3bdfSopenharmony_ci		       flagname, mcgname, resname[result], resname[r], msg);
57f08c3bdfSopenharmony_ci		fail++;
58f08c3bdfSopenharmony_ci	}
59f08c3bdfSopenharmony_ci}
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci#define TEST(flag, result) \
63f08c3bdfSopenharmony_ci	test2(flag, #flag, MCG_STATUS_MCIP|MCG_STATUS_RIPV, "mcip,ripv", \
64f08c3bdfSopenharmony_ci		MCE_ ## result ## _SEVERITY)
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_civoid test(void)
67f08c3bdfSopenharmony_ci{
68f08c3bdfSopenharmony_ci	// corrected
69f08c3bdfSopenharmony_ci	TEST(VAL|EN, KEEP);
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ci	// uncorrected fatal
72f08c3bdfSopenharmony_ci	TEST(VAL|UC|PCC|EN|S|AR, PANIC);
73f08c3bdfSopenharmony_ci	TEST(VAL|UC|PCC|EN|S, PANIC);
74f08c3bdfSopenharmony_ci	TEST(VAL|UC|PCC|EN, PANIC);
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci	// SW recoverable action required
77f08c3bdfSopenharmony_ci	// unknown mcacod -> panic
78f08c3bdfSopenharmony_ci	TEST(VAL|UC|EN|S|AR, PANIC);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	// SW recoverable action optional
81f08c3bdfSopenharmony_ci	TEST(VAL|UC|EN|S|0xc0, AO);
82f08c3bdfSopenharmony_ci	// unknown mcacod
83f08c3bdfSopenharmony_ci	TEST(VAL|UC|EN|S|1, SOME);
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci	// UCNA
86f08c3bdfSopenharmony_ci	TEST(VAL|UC|EN, KEEP);
87f08c3bdfSopenharmony_ci	TEST(VAL|UC, NO);	// linux clears. correct?
88f08c3bdfSopenharmony_ci}
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ciint main(void)
91f08c3bdfSopenharmony_ci{
92f08c3bdfSopenharmony_ci	ring = 3;
93f08c3bdfSopenharmony_ci	test();
94f08c3bdfSopenharmony_ci	ring = 0;
95f08c3bdfSopenharmony_ci	test();
96f08c3bdfSopenharmony_ci	if (fail == 0)
97f08c3bdfSopenharmony_ci		printf("SUCCESS\n");
98f08c3bdfSopenharmony_ci	else
99f08c3bdfSopenharmony_ci		printf("%d FAILURES\n", fail);
100f08c3bdfSopenharmony_ci	return fail;
101f08c3bdfSopenharmony_ci}
102