blob: 0ce3913f4af5a1f08261ea156ee713576f4c1d19 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
/* Grammar for machine check injection. Follows the format printed out
by the kernel on panics with some extensions. See SPEC. */
%{
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "parser.h"
#include "mce.h"
#include "inject.h"
static struct mce m;
enum mceflags mce_flags;
static void init(void);
%}
%token STATUS RIP TSC ADDR MISC CPU BANK MCGSTATUS NOBROADCAST HOLD IN_IRQ
%token CORRECTED UNCORRECTED FATAL MCE
%token NUMBER
%token SYMBOL
%token MACHINE CHECK EXCEPTION
%token RIPV EIPV MCIP
%token VAL OVER UC EN PCC
%%
input: /* empty */
| input mce_start mce { submit_mce(&m); } ;
mce_start: CPU NUMBER { init(); m.cpu = $2; }
| CPU NUMBER NUMBER { init(); m.cpu = $2; m.bank = $3; }
| MCE { init(); }
| CPU NUMBER ':'
MACHINE CHECK EXCEPTION ':' NUMBER BANK NUMBER ':'
NUMBER { init();
m.cpu = $2; m.mcgstatus = $6;
m.bank = $8; m.status = $10; }
;
mce: mce_term
| mce mce_term
;
mce_term: STATUS status_list { m.status = $2; }
| STATUS NUMBER { m.status = $2; }
| MCGSTATUS mcgstatus_list { m.mcgstatus = $2; }
| MCGSTATUS NUMBER { m.mcgstatus = $2; }
| BANK NUMBER { m.bank = $2; }
| TSC NUMBER { m.tsc = $2; }
| RIP NUMBER { m.ip = $2; }
| RIP NUMBER ':' NUMBER { m.ip = $4; m.cs = $2; }
| RIP NUMBER ':' '<' NUMBER '>' '{' SYMBOL '}'
{ m.ip = $5; m.cs = $2; }
| ADDR NUMBER { m.addr = $2; m.status |= MCI_STATUS_ADDRV; }
| MISC NUMBER { m.misc = $2; m.status |= MCI_STATUS_MISCV; }
| NOBROADCAST { mce_flags |= MCE_NOBROADCAST; }
| HOLD { mce_flags |= MCE_HOLD; }
| IN_IRQ { m.pad = MCEC_IRQ; }
;
mcgstatus_list: /* empty */
| mcgstatus_list mcgstatus { $$ = $1 | $2; }
;
mcgstatus : RIPV | EIPV | MCIP | NUMBER ;
status_list: /* empty */ { $$ = 0; }
| status_list status { $$ = $1 | $2; }
status: UC | EN | VAL | OVER | PCC | NUMBER | CORRECTED | UNCORRECTED |
FATAL
;
%%
static void init(void)
{
init_mce(&m);
mce_flags = 0;
}
void yyerror(char const *msg, ...)
{
va_list ap;
va_start(ap, msg);
fprintf(stderr, "%s:%d: ", filename, yylineno);
vfprintf(stderr, msg, ap);
fputc('\n', stderr);
va_end(ap);
exit(1);
}
|