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