1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018, Advanced Micro Devices, Inc.
3
4 #include <linux/cper.h>
5
6 /*
7 * We don't need a "CPER_IA" prefix since these are all locally defined.
8 * This will save us a lot of line space.
9 */
10 #define VALID_LAPIC_ID BIT_ULL(0)
11 #define VALID_CPUID_INFO BIT_ULL(1)
12 #define VALID_PROC_ERR_INFO_NUM(bits) (((bits) & GENMASK_ULL(7, 2)) >> 2)
13 #define VALID_PROC_CXT_INFO_NUM(bits) (((bits) & GENMASK_ULL(13, 8)) >> 8)
14
15 #define INFO_ERR_STRUCT_TYPE_CACHE \
16 GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B, \
17 0x57, 0x3F, 0xAD, 0x2C)
18 #define INFO_ERR_STRUCT_TYPE_TLB \
19 GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B, \
20 0x9A, 0xDB, 0x63, 0xC3)
21 #define INFO_ERR_STRUCT_TYPE_BUS \
22 GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF, \
23 0x92, 0xFF, 0xA6, 0x3C)
24 #define INFO_ERR_STRUCT_TYPE_MS \
25 GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5, \
26 0xB0, 0xA7, 0x43, 0x14)
27
28 #define INFO_VALID_CHECK_INFO BIT_ULL(0)
29 #define INFO_VALID_TARGET_ID BIT_ULL(1)
30 #define INFO_VALID_REQUESTOR_ID BIT_ULL(2)
31 #define INFO_VALID_RESPONDER_ID BIT_ULL(3)
32 #define INFO_VALID_IP BIT_ULL(4)
33
34 #define CHECK_VALID_TRANS_TYPE BIT_ULL(0)
35 #define CHECK_VALID_OPERATION BIT_ULL(1)
36 #define CHECK_VALID_LEVEL BIT_ULL(2)
37 #define CHECK_VALID_PCC BIT_ULL(3)
38 #define CHECK_VALID_UNCORRECTED BIT_ULL(4)
39 #define CHECK_VALID_PRECISE_IP BIT_ULL(5)
40 #define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
41 #define CHECK_VALID_OVERFLOW BIT_ULL(7)
42
43 #define CHECK_VALID_BUS_PART_TYPE BIT_ULL(8)
44 #define CHECK_VALID_BUS_TIME_OUT BIT_ULL(9)
45 #define CHECK_VALID_BUS_ADDR_SPACE BIT_ULL(10)
46
47 #define CHECK_VALID_BITS(check) (((check) & GENMASK_ULL(15, 0)))
48 #define CHECK_TRANS_TYPE(check) (((check) & GENMASK_ULL(17, 16)) >> 16)
49 #define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)
50 #define CHECK_LEVEL(check) (((check) & GENMASK_ULL(24, 22)) >> 22)
51 #define CHECK_PCC BIT_ULL(25)
52 #define CHECK_UNCORRECTED BIT_ULL(26)
53 #define CHECK_PRECISE_IP BIT_ULL(27)
54 #define CHECK_RESTARTABLE_IP BIT_ULL(28)
55 #define CHECK_OVERFLOW BIT_ULL(29)
56
57 #define CHECK_BUS_PART_TYPE(check) (((check) & GENMASK_ULL(31, 30)) >> 30)
58 #define CHECK_BUS_TIME_OUT BIT_ULL(32)
59 #define CHECK_BUS_ADDR_SPACE(check) (((check) & GENMASK_ULL(34, 33)) >> 33)
60
61 #define CHECK_VALID_MS_ERR_TYPE BIT_ULL(0)
62 #define CHECK_VALID_MS_PCC BIT_ULL(1)
63 #define CHECK_VALID_MS_UNCORRECTED BIT_ULL(2)
64 #define CHECK_VALID_MS_PRECISE_IP BIT_ULL(3)
65 #define CHECK_VALID_MS_RESTARTABLE_IP BIT_ULL(4)
66 #define CHECK_VALID_MS_OVERFLOW BIT_ULL(5)
67
68 #define CHECK_MS_ERR_TYPE(check) (((check) & GENMASK_ULL(18, 16)) >> 16)
69 #define CHECK_MS_PCC BIT_ULL(19)
70 #define CHECK_MS_UNCORRECTED BIT_ULL(20)
71 #define CHECK_MS_PRECISE_IP BIT_ULL(21)
72 #define CHECK_MS_RESTARTABLE_IP BIT_ULL(22)
73 #define CHECK_MS_OVERFLOW BIT_ULL(23)
74
75 #define CTX_TYPE_MSR 1
76 #define CTX_TYPE_MMREG 7
77
78 enum err_types {
79 ERR_TYPE_CACHE = 0,
80 ERR_TYPE_TLB,
81 ERR_TYPE_BUS,
82 ERR_TYPE_MS,
83 N_ERR_TYPES
84 };
85
cper_get_err_type(const guid_t * err_type)86 static enum err_types cper_get_err_type(const guid_t *err_type)
87 {
88 if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_CACHE))
89 return ERR_TYPE_CACHE;
90 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_TLB))
91 return ERR_TYPE_TLB;
92 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_BUS))
93 return ERR_TYPE_BUS;
94 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_MS))
95 return ERR_TYPE_MS;
96 else
97 return N_ERR_TYPES;
98 }
99
100 static const char * const ia_check_trans_type_strs[] = {
101 "Instruction",
102 "Data Access",
103 "Generic",
104 };
105
106 static const char * const ia_check_op_strs[] = {
107 "generic error",
108 "generic read",
109 "generic write",
110 "data read",
111 "data write",
112 "instruction fetch",
113 "prefetch",
114 "eviction",
115 "snoop",
116 };
117
118 static const char * const ia_check_bus_part_type_strs[] = {
119 "Local Processor originated request",
120 "Local Processor responded to request",
121 "Local Processor observed",
122 "Generic",
123 };
124
125 static const char * const ia_check_bus_addr_space_strs[] = {
126 "Memory Access",
127 "Reserved",
128 "I/O",
129 "Other Transaction",
130 };
131
132 static const char * const ia_check_ms_error_type_strs[] = {
133 "No Error",
134 "Unclassified",
135 "Microcode ROM Parity Error",
136 "External Error",
137 "FRC Error",
138 "Internal Unclassified",
139 };
140
141 static const char * const ia_reg_ctx_strs[] = {
142 "Unclassified Data",
143 "MSR Registers (Machine Check and other MSRs)",
144 "32-bit Mode Execution Context",
145 "64-bit Mode Execution Context",
146 "FXSAVE Context",
147 "32-bit Mode Debug Registers (DR0-DR7)",
148 "64-bit Mode Debug Registers (DR0-DR7)",
149 "Memory Mapped Registers",
150 };
151
print_bool(char * str,const char * pfx,u64 check,u64 bit)152 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
153 {
154 printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
155 }
156
print_err_info_ms(const char * pfx,u16 validation_bits,u64 check)157 static void print_err_info_ms(const char *pfx, u16 validation_bits, u64 check)
158 {
159 if (validation_bits & CHECK_VALID_MS_ERR_TYPE) {
160 u8 err_type = CHECK_MS_ERR_TYPE(check);
161
162 printk("%sError Type: %u, %s\n", pfx, err_type,
163 err_type < ARRAY_SIZE(ia_check_ms_error_type_strs) ?
164 ia_check_ms_error_type_strs[err_type] : "unknown");
165 }
166
167 if (validation_bits & CHECK_VALID_MS_PCC)
168 print_bool("Processor Context Corrupt", pfx, check, CHECK_MS_PCC);
169
170 if (validation_bits & CHECK_VALID_MS_UNCORRECTED)
171 print_bool("Uncorrected", pfx, check, CHECK_MS_UNCORRECTED);
172
173 if (validation_bits & CHECK_VALID_MS_PRECISE_IP)
174 print_bool("Precise IP", pfx, check, CHECK_MS_PRECISE_IP);
175
176 if (validation_bits & CHECK_VALID_MS_RESTARTABLE_IP)
177 print_bool("Restartable IP", pfx, check, CHECK_MS_RESTARTABLE_IP);
178
179 if (validation_bits & CHECK_VALID_MS_OVERFLOW)
180 print_bool("Overflow", pfx, check, CHECK_MS_OVERFLOW);
181 }
182
print_err_info(const char * pfx,u8 err_type,u64 check)183 static void print_err_info(const char *pfx, u8 err_type, u64 check)
184 {
185 u16 validation_bits = CHECK_VALID_BITS(check);
186
187 /*
188 * The MS Check structure varies a lot from the others, so use a
189 * separate function for decoding.
190 */
191 if (err_type == ERR_TYPE_MS)
192 return print_err_info_ms(pfx, validation_bits, check);
193
194 if (validation_bits & CHECK_VALID_TRANS_TYPE) {
195 u8 trans_type = CHECK_TRANS_TYPE(check);
196
197 printk("%sTransaction Type: %u, %s\n", pfx, trans_type,
198 trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ?
199 ia_check_trans_type_strs[trans_type] : "unknown");
200 }
201
202 if (validation_bits & CHECK_VALID_OPERATION) {
203 u8 op = CHECK_OPERATION(check);
204
205 /*
206 * CACHE has more operation types than TLB or BUS, though the
207 * name and the order are the same.
208 */
209 u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7;
210
211 printk("%sOperation: %u, %s\n", pfx, op,
212 op < max_ops ? ia_check_op_strs[op] : "unknown");
213 }
214
215 if (validation_bits & CHECK_VALID_LEVEL)
216 printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check));
217
218 if (validation_bits & CHECK_VALID_PCC)
219 print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC);
220
221 if (validation_bits & CHECK_VALID_UNCORRECTED)
222 print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED);
223
224 if (validation_bits & CHECK_VALID_PRECISE_IP)
225 print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP);
226
227 if (validation_bits & CHECK_VALID_RESTARTABLE_IP)
228 print_bool("Restartable IP", pfx, check, CHECK_RESTARTABLE_IP);
229
230 if (validation_bits & CHECK_VALID_OVERFLOW)
231 print_bool("Overflow", pfx, check, CHECK_OVERFLOW);
232
233 if (err_type != ERR_TYPE_BUS)
234 return;
235
236 if (validation_bits & CHECK_VALID_BUS_PART_TYPE) {
237 u8 part_type = CHECK_BUS_PART_TYPE(check);
238
239 printk("%sParticipation Type: %u, %s\n", pfx, part_type,
240 part_type < ARRAY_SIZE(ia_check_bus_part_type_strs) ?
241 ia_check_bus_part_type_strs[part_type] : "unknown");
242 }
243
244 if (validation_bits & CHECK_VALID_BUS_TIME_OUT)
245 print_bool("Time Out", pfx, check, CHECK_BUS_TIME_OUT);
246
247 if (validation_bits & CHECK_VALID_BUS_ADDR_SPACE) {
248 u8 addr_space = CHECK_BUS_ADDR_SPACE(check);
249
250 printk("%sAddress Space: %u, %s\n", pfx, addr_space,
251 addr_space < ARRAY_SIZE(ia_check_bus_addr_space_strs) ?
252 ia_check_bus_addr_space_strs[addr_space] : "unknown");
253 }
254 }
255
cper_print_proc_ia(const char * pfx,const struct cper_sec_proc_ia * proc)256 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
257 {
258 int i;
259 struct cper_ia_err_info *err_info;
260 struct cper_ia_proc_ctx *ctx_info;
261 char newpfx[64], infopfx[64];
262 u8 err_type;
263
264 if (proc->validation_bits & VALID_LAPIC_ID)
265 printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
266
267 if (proc->validation_bits & VALID_CPUID_INFO) {
268 printk("%sCPUID Info:\n", pfx);
269 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
270 sizeof(proc->cpuid), 0);
271 }
272
273 snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
274
275 err_info = (struct cper_ia_err_info *)(proc + 1);
276 for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
277 printk("%sError Information Structure %d:\n", pfx, i);
278
279 err_type = cper_get_err_type(&err_info->err_type);
280 printk("%sError Structure Type: %s\n", newpfx,
281 err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?
282 cper_proc_error_type_strs[err_type] : "unknown");
283
284 if (err_type >= N_ERR_TYPES) {
285 printk("%sError Structure Type: %pUl\n", newpfx,
286 &err_info->err_type);
287 }
288
289 if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
290 printk("%sCheck Information: 0x%016llx\n", newpfx,
291 err_info->check_info);
292
293 if (err_type < N_ERR_TYPES) {
294 snprintf(infopfx, sizeof(infopfx), "%s ",
295 newpfx);
296
297 print_err_info(infopfx, err_type,
298 err_info->check_info);
299 }
300 }
301
302 if (err_info->validation_bits & INFO_VALID_TARGET_ID) {
303 printk("%sTarget Identifier: 0x%016llx\n",
304 newpfx, err_info->target_id);
305 }
306
307 if (err_info->validation_bits & INFO_VALID_REQUESTOR_ID) {
308 printk("%sRequestor Identifier: 0x%016llx\n",
309 newpfx, err_info->requestor_id);
310 }
311
312 if (err_info->validation_bits & INFO_VALID_RESPONDER_ID) {
313 printk("%sResponder Identifier: 0x%016llx\n",
314 newpfx, err_info->responder_id);
315 }
316
317 if (err_info->validation_bits & INFO_VALID_IP) {
318 printk("%sInstruction Pointer: 0x%016llx\n",
319 newpfx, err_info->ip);
320 }
321
322 err_info++;
323 }
324
325 ctx_info = (struct cper_ia_proc_ctx *)err_info;
326 for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {
327 int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
328 int groupsize = 4;
329
330 printk("%sContext Information Structure %d:\n", pfx, i);
331
332 printk("%sRegister Context Type: %s\n", newpfx,
333 ctx_info->reg_ctx_type < ARRAY_SIZE(ia_reg_ctx_strs) ?
334 ia_reg_ctx_strs[ctx_info->reg_ctx_type] : "unknown");
335
336 printk("%sRegister Array Size: 0x%04x\n", newpfx,
337 ctx_info->reg_arr_size);
338
339 if (ctx_info->reg_ctx_type == CTX_TYPE_MSR) {
340 groupsize = 8; /* MSRs are 8 bytes wide. */
341 printk("%sMSR Address: 0x%08x\n", newpfx,
342 ctx_info->msr_addr);
343 }
344
345 if (ctx_info->reg_ctx_type == CTX_TYPE_MMREG) {
346 printk("%sMM Register Address: 0x%016llx\n", newpfx,
347 ctx_info->mm_reg_addr);
348 }
349
350 printk("%sRegister Array:\n", newpfx);
351 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, groupsize,
352 (ctx_info + 1), ctx_info->reg_arr_size, 0);
353
354 ctx_info = (struct cper_ia_proc_ctx *)((long)ctx_info + size);
355 }
356 }
357