1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018, Advanced Micro Devices, Inc.
4 #include <linux/cper.h>
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.
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)
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)
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)
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)
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)
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)
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)
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)
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)
75 #define CTX_TYPE_MSR 1
76 #define CTX_TYPE_MMREG 7
86 static enum err_types
cper_get_err_type(const guid_t
*err_type
)
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
))
92 else if (guid_equal(err_type
, &INFO_ERR_STRUCT_TYPE_BUS
))
94 else if (guid_equal(err_type
, &INFO_ERR_STRUCT_TYPE_MS
))
100 static const char * const ia_check_trans_type_strs
[] = {
106 static const char * const ia_check_op_strs
[] = {
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",
125 static const char * const ia_check_bus_addr_space_strs
[] = {
132 static const char * const ia_check_ms_error_type_strs
[] = {
135 "Microcode ROM Parity Error",
138 "Internal Unclassified",
141 static const char * const ia_reg_ctx_strs
[] = {
143 "MSR Registers (Machine Check and other MSRs)",
144 "32-bit Mode Execution Context",
145 "64-bit Mode Execution Context",
147 "32-bit Mode Debug Registers (DR0-DR7)",
148 "64-bit Mode Debug Registers (DR0-DR7)",
149 "Memory Mapped Registers",
152 static inline void print_bool(char *str
, const char *pfx
, u64 check
, u64 bit
)
154 printk("%s%s: %s\n", pfx
, str
, (check
& bit
) ? "true" : "false");
157 static void print_err_info_ms(const char *pfx
, u16 validation_bits
, u64 check
)
159 if (validation_bits
& CHECK_VALID_MS_ERR_TYPE
) {
160 u8 err_type
= CHECK_MS_ERR_TYPE(check
);
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");
167 if (validation_bits
& CHECK_VALID_MS_PCC
)
168 print_bool("Processor Context Corrupt", pfx
, check
, CHECK_MS_PCC
);
170 if (validation_bits
& CHECK_VALID_MS_UNCORRECTED
)
171 print_bool("Uncorrected", pfx
, check
, CHECK_MS_UNCORRECTED
);
173 if (validation_bits
& CHECK_VALID_MS_PRECISE_IP
)
174 print_bool("Precise IP", pfx
, check
, CHECK_MS_PRECISE_IP
);
176 if (validation_bits
& CHECK_VALID_MS_RESTARTABLE_IP
)
177 print_bool("Restartable IP", pfx
, check
, CHECK_MS_RESTARTABLE_IP
);
179 if (validation_bits
& CHECK_VALID_MS_OVERFLOW
)
180 print_bool("Overflow", pfx
, check
, CHECK_MS_OVERFLOW
);
183 static void print_err_info(const char *pfx
, u8 err_type
, u64 check
)
185 u16 validation_bits
= CHECK_VALID_BITS(check
);
188 * The MS Check structure varies a lot from the others, so use a
189 * separate function for decoding.
191 if (err_type
== ERR_TYPE_MS
)
192 return print_err_info_ms(pfx
, validation_bits
, check
);
194 if (validation_bits
& CHECK_VALID_TRANS_TYPE
) {
195 u8 trans_type
= CHECK_TRANS_TYPE(check
);
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");
202 if (validation_bits
& CHECK_VALID_OPERATION
) {
203 u8 op
= CHECK_OPERATION(check
);
206 * CACHE has more operation types than TLB or BUS, though the
207 * name and the order are the same.
209 u8 max_ops
= (err_type
== ERR_TYPE_CACHE
) ? 9 : 7;
211 printk("%sOperation: %u, %s\n", pfx
, op
,
212 op
< max_ops
? ia_check_op_strs
[op
] : "unknown");
215 if (validation_bits
& CHECK_VALID_LEVEL
)
216 printk("%sLevel: %llu\n", pfx
, CHECK_LEVEL(check
));
218 if (validation_bits
& CHECK_VALID_PCC
)
219 print_bool("Processor Context Corrupt", pfx
, check
, CHECK_PCC
);
221 if (validation_bits
& CHECK_VALID_UNCORRECTED
)
222 print_bool("Uncorrected", pfx
, check
, CHECK_UNCORRECTED
);
224 if (validation_bits
& CHECK_VALID_PRECISE_IP
)
225 print_bool("Precise IP", pfx
, check
, CHECK_PRECISE_IP
);
227 if (validation_bits
& CHECK_VALID_RESTARTABLE_IP
)
228 print_bool("Restartable IP", pfx
, check
, CHECK_RESTARTABLE_IP
);
230 if (validation_bits
& CHECK_VALID_OVERFLOW
)
231 print_bool("Overflow", pfx
, check
, CHECK_OVERFLOW
);
233 if (err_type
!= ERR_TYPE_BUS
)
236 if (validation_bits
& CHECK_VALID_BUS_PART_TYPE
) {
237 u8 part_type
= CHECK_BUS_PART_TYPE(check
);
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");
244 if (validation_bits
& CHECK_VALID_BUS_TIME_OUT
)
245 print_bool("Time Out", pfx
, check
, CHECK_BUS_TIME_OUT
);
247 if (validation_bits
& CHECK_VALID_BUS_ADDR_SPACE
) {
248 u8 addr_space
= CHECK_BUS_ADDR_SPACE(check
);
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");
256 void cper_print_proc_ia(const char *pfx
, const struct cper_sec_proc_ia
*proc
)
259 struct cper_ia_err_info
*err_info
;
260 struct cper_ia_proc_ctx
*ctx_info
;
261 char newpfx
[64], infopfx
[64];
264 if (proc
->validation_bits
& VALID_LAPIC_ID
)
265 printk("%sLocal APIC_ID: 0x%llx\n", pfx
, proc
->lapic_id
);
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);
273 snprintf(newpfx
, sizeof(newpfx
), "%s ", pfx
);
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
);
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");
284 if (err_type
>= N_ERR_TYPES
) {
285 printk("%sError Structure Type: %pUl\n", newpfx
,
286 &err_info
->err_type
);
289 if (err_info
->validation_bits
& INFO_VALID_CHECK_INFO
) {
290 printk("%sCheck Information: 0x%016llx\n", newpfx
,
291 err_info
->check_info
);
293 if (err_type
< N_ERR_TYPES
) {
294 snprintf(infopfx
, sizeof(infopfx
), "%s ",
297 print_err_info(infopfx
, err_type
,
298 err_info
->check_info
);
302 if (err_info
->validation_bits
& INFO_VALID_TARGET_ID
) {
303 printk("%sTarget Identifier: 0x%016llx\n",
304 newpfx
, err_info
->target_id
);
307 if (err_info
->validation_bits
& INFO_VALID_REQUESTOR_ID
) {
308 printk("%sRequestor Identifier: 0x%016llx\n",
309 newpfx
, err_info
->requestor_id
);
312 if (err_info
->validation_bits
& INFO_VALID_RESPONDER_ID
) {
313 printk("%sResponder Identifier: 0x%016llx\n",
314 newpfx
, err_info
->responder_id
);
317 if (err_info
->validation_bits
& INFO_VALID_IP
) {
318 printk("%sInstruction Pointer: 0x%016llx\n",
319 newpfx
, err_info
->ip
);
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
;
330 printk("%sContext Information Structure %d:\n", pfx
, i
);
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");
336 printk("%sRegister Array Size: 0x%04x\n", newpfx
,
337 ctx_info
->reg_arr_size
);
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
,
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
);
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);
354 ctx_info
= (struct cper_ia_proc_ctx
*)((long)ctx_info
+ size
);