1 /*
2 * Copyright (c) 2025-2026, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <string.h>
8
9 #include <arch_helpers.h>
10 #include <common/debug.h>
11 #include <lib/el3_runtime/aarch64/context.h>
12 #include <lib/el3_runtime/context_mgmt.h>
13 #include <lib/extensions/ras.h>
14
15 #include <cper.h>
16 #include <rdaspen_ras.h>
17
18 /* Convert ERXSTATUS_EL1 bits to CPER severity */
esb_severity_from_erx(uint64_t err_status)19 static inline uint32_t esb_severity_from_erx(uint64_t err_status)
20 {
21 if (err_status & ERX_STATUS_CE)
22 return ACPI_DATA_ENTRY_SEV_CORRECTED;
23 if (err_status & ERX_STATUS_DE)
24 return ACPI_DATA_ENTRY_SEV_RECOVERABLE;
25 if (err_status & ERX_STATUS_UE)
26 return ACPI_DATA_ENTRY_SEV_FATAL;
27 return ACPI_DATA_ENTRY_SEV_NONE;
28 }
29
arm_error_type_from_unit(uint64_t err_misc0)30 static inline uint8_t arm_error_type_from_unit(uint64_t err_misc0)
31 {
32 unsigned int unit = ERXMISC0_UNIT(err_misc0);
33
34 switch (unit) {
35 case ERXMISC0_UNIT_L2_TLB:
36 return ARM_ERROR_TYPE_TLB;
37 default:
38 return ARM_ERROR_TYPE_CACHE;
39 }
40 }
41
42 /*
43 * ARM CACHE ERROR STRUCTURE
44 *
45 * - Validation Bit (bits 15:0): Set valid bits for the fields encoded
46 * - Transaction Type (bits 17:16): INSTR / DATA / GENERIC (derived from UNIT)
47 * - Operation (bits 21:18): set to GENERIC
48 * - Level (bits 24:22): cache level (1 for L1, 2 for L2), derived from UNIT
49 * - Processor Context Corrupt (bit 25): value = 0 (not corrupted)
50 * - Corrected (bit 26): value from 'corrected' parameter
51 * - Precise PC (bit 27): value = 0
52 * - Restartable PC (bit 28): value = 0
53 * - Reserved (63:29): zero
54 */
arm_cache_error_structure(uint64_t err_misc0,bool corrected)55 static inline uint64_t arm_cache_error_structure(uint64_t err_misc0,
56 bool corrected)
57 {
58 uint64_t info = 0;
59 unsigned int unit = ERXMISC0_UNIT(err_misc0);
60
61 uint64_t tx_value = ARM_CACHE_ERR_TX_GENERIC;
62 uint64_t level_value = 0;
63
64 switch (unit) {
65 case ERXMISC0_UNIT_L1I:
66 /* TxType = Instruction, Level = 1 */
67 tx_value = ARM_CACHE_ERR_TX_INSTR;
68 level_value = 1u;
69 break;
70
71 case ERXMISC0_UNIT_L1D:
72 /* TxType = Data, Level = 1 */
73 tx_value = ARM_CACHE_ERR_TX_DATA;
74 level_value = 1u;
75 break;
76
77 case ERXMISC0_UNIT_L2_CACHE:
78 /* TxType = Generic, Level = 2 */
79 tx_value = ARM_CACHE_ERR_TX_GENERIC;
80 level_value = 2u;
81 break;
82
83 default:
84 break;
85 }
86
87 /* Validation bits (bit order: 0..6) */
88 info |= ARM_CACHE_ERR_VLD_TX_TYPE; /* Bit 0: Transaction Type Valid */
89 info |= ARM_CACHE_ERR_VLD_OPERATION; /* Bit 1: Operation Valid */
90 info |= ARM_CACHE_ERR_VLD_LEVEL; /* Bit 2: Level Valid */
91 info |= ARM_CACHE_ERR_VLD_PCC; /* Bit 3: PCC Valid */
92 info |= ARM_CACHE_ERR_VLD_CORRECTED; /* Bit 4: Corrected Valid */
93 info |= ARM_CACHE_ERR_VLD_PRECISE_PC; /* Bit 5: Precise PC Valid */
94 info |= ARM_CACHE_ERR_VLD_RESTART_PC; /* Bit 6: Restartable PC Valid */
95
96 /* Transaction Type (bits 17:16) */
97 info |= (tx_value << ARM_CACHE_ERR_TX_SHIFT) & ARM_CACHE_ERR_TX_MASK;
98
99 /* Level (bits 24:22) */
100 info |= (level_value << ARM_CACHE_ERR_LEVEL_SHIFT) & ARM_CACHE_ERR_LEVEL_MASK;
101
102 /* Corrected (bit 26) */
103 if (corrected)
104 info |= (1ULL << ARM_CACHE_ERR_CORR_BIT);
105
106 return info;
107 }
108
109 /*
110 * ARM PROCESSOR ERROR CONTEXT INFORMATION
111 *
112 * Context[0] Type-4: AArch64 GPRs (x0..x30 + SP_EL0)
113 * Context[1] Type-5: EL1 registers
114 */
115 static bool
fill_ns_context_blocks(struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA * sec)116 fill_ns_context_blocks(struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *sec)
117 {
118 cpu_context_t *ns = cm_get_context(NON_SECURE);
119
120 if (!ns) {
121 VERBOSE("CPER: no NON_SECURE cpu_context\n");
122 return false;
123 }
124
125 /* -------- Type 4: GPRs (x0..x30 + SP_EL0) -------- */
126 gp_regs_t *gpr = get_gpregs_ctx(ns);
127
128 if (!gpr)
129 return false;
130
131 sec->CpuContextInfo[0].Hdr.Version = 0;
132 sec->CpuContextInfo[0].Hdr.RegisterContextType =
133 EFI_ARM_CONTEXT_INFO_REG_TYPE_4;
134 sec->CpuContextInfo[0].Hdr.RegisterArraySize =
135 (uint32_t)sizeof(sec->CpuContextInfo[0].RegisterArray.Type4Gpr);
136 struct EFI_ARM_AARCH64_CONTEXT_GPR *type4GprRegValues =
137 &sec->CpuContextInfo[0].RegisterArray.Type4Gpr;
138
139 type4GprRegValues->X[0] = read_ctx_reg(gpr, CTX_GPREG_X0);
140 type4GprRegValues->X[1] = read_ctx_reg(gpr, CTX_GPREG_X1);
141 type4GprRegValues->X[2] = read_ctx_reg(gpr, CTX_GPREG_X2);
142 type4GprRegValues->X[3] = read_ctx_reg(gpr, CTX_GPREG_X3);
143 type4GprRegValues->X[4] = read_ctx_reg(gpr, CTX_GPREG_X4);
144 type4GprRegValues->X[5] = read_ctx_reg(gpr, CTX_GPREG_X5);
145 type4GprRegValues->X[6] = read_ctx_reg(gpr, CTX_GPREG_X6);
146 type4GprRegValues->X[7] = read_ctx_reg(gpr, CTX_GPREG_X7);
147 type4GprRegValues->X[8] = read_ctx_reg(gpr, CTX_GPREG_X8);
148 type4GprRegValues->X[9] = read_ctx_reg(gpr, CTX_GPREG_X9);
149 type4GprRegValues->X[10] = read_ctx_reg(gpr, CTX_GPREG_X10);
150 type4GprRegValues->X[11] = read_ctx_reg(gpr, CTX_GPREG_X11);
151 type4GprRegValues->X[12] = read_ctx_reg(gpr, CTX_GPREG_X12);
152 type4GprRegValues->X[13] = read_ctx_reg(gpr, CTX_GPREG_X13);
153 type4GprRegValues->X[14] = read_ctx_reg(gpr, CTX_GPREG_X14);
154 type4GprRegValues->X[15] = read_ctx_reg(gpr, CTX_GPREG_X15);
155 type4GprRegValues->X[16] = read_ctx_reg(gpr, CTX_GPREG_X16);
156 type4GprRegValues->X[17] = read_ctx_reg(gpr, CTX_GPREG_X17);
157 type4GprRegValues->X[18] = read_ctx_reg(gpr, CTX_GPREG_X18);
158 type4GprRegValues->X[19] = read_ctx_reg(gpr, CTX_GPREG_X19);
159 type4GprRegValues->X[20] = read_ctx_reg(gpr, CTX_GPREG_X20);
160 type4GprRegValues->X[21] = read_ctx_reg(gpr, CTX_GPREG_X21);
161 type4GprRegValues->X[22] = read_ctx_reg(gpr, CTX_GPREG_X22);
162 type4GprRegValues->X[23] = read_ctx_reg(gpr, CTX_GPREG_X23);
163 type4GprRegValues->X[24] = read_ctx_reg(gpr, CTX_GPREG_X24);
164 type4GprRegValues->X[25] = read_ctx_reg(gpr, CTX_GPREG_X25);
165 type4GprRegValues->X[26] = read_ctx_reg(gpr, CTX_GPREG_X26);
166 type4GprRegValues->X[27] = read_ctx_reg(gpr, CTX_GPREG_X27);
167 type4GprRegValues->X[28] = read_ctx_reg(gpr, CTX_GPREG_X28);
168 type4GprRegValues->X[29] = read_ctx_reg(gpr, CTX_GPREG_X29);
169 type4GprRegValues->X[30] = read_ctx_reg(gpr, CTX_GPREG_LR);
170 type4GprRegValues->SP = read_ctx_reg(gpr, CTX_GPREG_SP_EL0);
171
172 /* -------- Type 5: EL1 sysregs -------- */
173 el1_sysregs_t *el1 = get_el1_sysregs_ctx(ns);
174
175 if (!el1)
176 return false;
177
178 sec->CpuContextInfo[1].Hdr.Version = 0;
179 sec->CpuContextInfo[1].Hdr.RegisterContextType =
180 EFI_ARM_CONTEXT_INFO_REG_TYPE_5;
181 sec->CpuContextInfo[1].Hdr.RegisterArraySize = (uint32_t)sizeof(
182 sec->CpuContextInfo[1].RegisterArray.Type5SysRegs);
183 struct EFI_ARM_AARCH64_EL1_CONTEXT_SYSTEM_REGISTERS *type5SysRegValues =
184 &sec->CpuContextInfo[1].RegisterArray.Type5SysRegs;
185
186 type5SysRegValues->SPSR_EL1 = read_el1_ctx_common(el1, spsr_el1);
187 type5SysRegValues->ELR_EL1 = read_el1_ctx_common(el1, elr_el1);
188 type5SysRegValues->ESR_EL1 = read_el1_ctx_common(el1, esr_el1);
189 type5SysRegValues->FAR_EL1 = read_el1_ctx_common(el1, far_el1);
190 type5SysRegValues->ISR_EL1 = 0;
191
192 type5SysRegValues->MAIR_EL1 = read_el1_ctx_common(el1, mair_el1);
193 type5SysRegValues->MIDR_EL1 = read_midr_el1();
194 type5SysRegValues->MPIDR_EL1 = read_mpidr_el1();
195 type5SysRegValues->SCTLR_EL1 = read_ctx_sctlr_el1_reg_errata(ns);
196
197 type5SysRegValues->SP_EL0 =
198 read_ctx_reg(get_gpregs_ctx(ns), CTX_GPREG_SP_EL0);
199 type5SysRegValues->SP_EL1 = read_el1_ctx_common(el1, sp_el1);
200 type5SysRegValues->SPSR_EL1 = read_el1_ctx_common(el1, spsr_el1);
201
202 type5SysRegValues->TCR_EL1 = read_ctx_tcr_el1_reg_errata(ns);
203 type5SysRegValues->TPIDR_EL0 = read_el1_ctx_common(el1, tpidr_el0);
204 type5SysRegValues->TPIDR_EL1 = read_el1_ctx_common(el1, tpidr_el1);
205 type5SysRegValues->TPIDRRO_EL0 = read_el1_ctx_common(el1, tpidrro_el0);
206 type5SysRegValues->TTBR0_EL1 = read_el1_ctx_common(el1, ttbr0_el1);
207 type5SysRegValues->TTBR1_EL1 = read_el1_ctx_common(el1, ttbr1_el1);
208
209 return true;
210 }
211
212 /*
213 * cper_write_cpu_record - Build a single CPER ESB + ARM CPU section into a buffer
214 *
215 * This constructs a Common Platform Error Record (CPER) with:
216 * - 1 Error Status Block (ESB) header,
217 * - 1 Data Entry (ARM Processor Specific Section GUID),
218 * - 1 ARM CPU section payload containing:
219 * * Section header (EFI_ARM_PROCESSOR_ERROR_SECTION_HEADER),
220 * * One error info (EFI_ARM_PROCESSOR_ERROR_INFORMATION),
221 * * One context info (EFI_ARM_PROCESSOR_ERROR_CONTEXT_INFORMATION), containing:
222 * Type-4 (GPRs) and Type-5 (EL1) registers.
223 */
224
cper_write_cpu_record(void * buf,size_t buf_size)225 size_t cper_write_cpu_record(void *buf, size_t buf_size)
226 {
227 if (!buf)
228 return 0;
229
230 uint64_t err_status = read_erxstatus_el1();
231 uint64_t err_misc0 = read_erxmisc0_el1();
232 uint64_t err_addr = read_erxaddr_el1();
233
234 /* Compute size of CPU payload section */
235
236 uint32_t context_header_size =
237 sizeof(struct EFI_ARM_PROCESSOR_ERROR_CONTEXT_INFO_HEADER);
238 uint32_t context0_size = context_header_size +
239 sizeof(struct EFI_ARM_AARCH64_CONTEXT_GPR);
240 uint32_t context1_size =
241 context_header_size +
242 sizeof(struct EFI_ARM_AARCH64_EL1_CONTEXT_SYSTEM_REGISTERS);
243 uint32_t contexts_total_size = context0_size + context1_size;
244
245 uint32_t section_size =
246 (uint32_t)sizeof(
247 struct EFI_ARM_PROCESSOR_ERROR_SECTION_HEADER) +
248 (uint32_t)sizeof(struct EFI_ARM_PROCESSOR_ERROR_INFORMATION) *
249 CPU_ERR_INFO_NUM + contexts_total_size;
250
251 /* Total size: ESB + DataEntry + CPU payload */
252 size_t size = sizeof(struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER) +
253 sizeof(struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER) +
254 section_size;
255
256 if (buf_size < size) {
257 WARN("RAS: ESB buffer too small (need %zu, have %zu)\n", size,
258 buf_size);
259 return 0;
260 }
261
262 struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER *esb =
263 (struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER *)buf;
264 struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER *de =
265 (struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER *)(esb + 1);
266 struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *sec =
267 (struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *)(de + 1);
268
269 /* Error Status Block Header */
270 memset(esb, 0, sizeof(*esb));
271 esb->BlockStatus = esb_block_status((err_status & ERX_STATUS_UE) != 0,
272 (err_status & ERX_STATUS_CE) != 0,
273 false, false, 1);
274 esb->RawDataOffset = (uint32_t)(sizeof(*esb) + sizeof(*de));
275 esb->RawDataLength = 0;
276 esb->DataLength = (uint32_t)(sizeof(*de) + section_size);
277 esb->ErrorSeverity = esb_severity_from_erx(err_status);
278
279 /* Error Data Entry */
280 memset(de, 0, sizeof(*de));
281 de->SectionType = ARM_PROC_ERR_SECTION_GUID;
282 de->ErrorSeverity = esb->ErrorSeverity;
283 de->Revision = ACPI_DATA_ENTRY_REV_0300;
284 de->ValidationBits = 0;
285 de->Flags = (err_status & ERX_STATUS_DE) ? ACPI_SEC_FLAG_LATENT : 0;
286 de->ErrorDataLength = section_size;
287
288 /* Payload: CPU section */
289 memset(sec, 0, section_size);
290
291 /* ARM Processor Error Section */
292 sec->CpuInfo.ValidationBit = (EFI_ARM_PROC_ERROR_MPIDR_VALID |
293 EFI_ARM_PROC_ERROR_RUNNING_STATE_VALID);
294 sec->CpuInfo.ErrInfoNum = CPU_ERR_INFO_NUM;
295 sec->CpuInfo.ContextInfoNum = CPU_CONTEXT_INFO_NUM;
296 sec->CpuInfo.SectionLength = section_size;
297 sec->CpuInfo.AffinityLevel = 0;
298 sec->CpuInfo.MPIDR_EL1 = read_mpidr_el1();
299 sec->CpuInfo.MIDR_EL1 = read_midr_el1();
300 sec->CpuInfo.RunState = 1;
301 sec->CpuInfo.PsciState = 0;
302
303 /* ARM Processor Error Information */
304 struct EFI_ARM_PROCESSOR_ERROR_INFORMATION *ei = &sec->CpuErrInfo[0];
305 bool ce = (err_status & ERX_STATUS_CE) != 0;
306 bool phys_addr_valid = ERX_STATUS_ADDRV(err_status);
307
308 ei->Version = 0;
309 ei->Length = (uint8_t)sizeof(*ei);
310 ei->ValidationBit =
311 (EFI_ARM_PROC_ERROR_INFO_MULTIPLE_ERROR_VALID |
312 EFI_ARM_PROC_ERROR_INFO_FLAGS_VALID |
313 (phys_addr_valid ? EFI_ARM_PROC_ERROR_INFO_PHYS_ADDR_VALID :
314 0));
315 ei->Type = arm_error_type_from_unit(err_misc0);
316 ei->MultipleError = 0;
317 ei->Flags = 0;
318 ei->ErrorInfo = 0;
319 ei->VirtualFaultAddress = 0;
320 ei->PhysicalFaultAddress = err_addr;
321 if (ei->Type == ARM_ERROR_TYPE_CACHE) {
322 ei->ValidationBit |= EFI_ARM_PROC_ERROR_INFO_ERROR_INFO_VALID;
323 ei->ErrorInfo = arm_cache_error_structure(err_misc0, ce);
324 }
325
326 /* ARM Processor Error Context Information (Type 4 and 5 contexts) */
327 cm_el1_sysregs_context_save(NON_SECURE);
328 if (!fill_ns_context_blocks(sec))
329 WARN("CPER: Non-secure EL1 context unavailable; context blocks left zeroed\n");
330
331 return size;
332 }
333
print_guid(struct efi_guid g)334 static void print_guid(struct efi_guid g)
335 {
336 VERBOSE(" SectionType = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
337 g.time_low, g.time_mid, g.time_hi_and_version,
338 g.clock_seq_and_node[0], g.clock_seq_and_node[1],
339 g.clock_seq_and_node[2], g.clock_seq_and_node[3],
340 g.clock_seq_and_node[4], g.clock_seq_and_node[5],
341 g.clock_seq_and_node[6], g.clock_seq_and_node[7]);
342 }
343
print_cache_error_info(uint64_t info)344 static void print_cache_error_info(uint64_t info)
345 {
346 uint64_t validation = (info & 0x7FULL);
347 unsigned int tx = (unsigned int)((info & ARM_CACHE_ERR_TX_MASK) >>
348 ARM_CACHE_ERR_TX_SHIFT);
349 unsigned int op = (unsigned int)((info & ARM_CACHE_ERR_OP_MASK) >>
350 ARM_CACHE_ERR_OP_SHIFT);
351 unsigned int lvl = (unsigned int)((info & ARM_CACHE_ERR_LEVEL_MASK) >>
352 ARM_CACHE_ERR_LEVEL_SHIFT);
353 unsigned int pcc = (unsigned int)((info >> ARM_CACHE_ERR_PCC_BIT) & 1U);
354 unsigned int corr = (unsigned int)((info >> ARM_CACHE_ERR_CORR_BIT) & 1U);
355 unsigned int ppc = (unsigned int)((info >> ARM_CACHE_ERR_PRECISE_PC_BIT) & 1U);
356 unsigned int rpc = (unsigned int)((info >> ARM_CACHE_ERR_RESTART_PC_BIT) & 1U);
357 uint64_t reserved = (info >> 29);
358
359 VERBOSE(" CacheErrorInfo:\n");
360 VERBOSE(" ValidationBit = 0x%04llx\n",
361 (unsigned long long)validation);
362 VERBOSE(" TransactionType = %u\n", tx);
363 VERBOSE(" Operation = %u\n", op);
364 VERBOSE(" Level = %u\n", lvl);
365 VERBOSE(" ProcessorContextCorrupt = %u\n", pcc);
366 VERBOSE(" Corrected = %u\n", corr);
367 VERBOSE(" PrecisePC = %u\n", ppc);
368 VERBOSE(" RestartablePC = %u\n", rpc);
369 VERBOSE(" Reserved[63:29] = 0x%08llx\n",
370 (unsigned long long)reserved);
371 }
372
373 static void
print_esb_header(const struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER * esb)374 print_esb_header(const struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER *esb)
375 {
376 if (esb == NULL) {
377 WARN("CPER: null ESB header\n");
378 return;
379 }
380 VERBOSE("ESB.Header:\n");
381 VERBOSE(" BlockStatus = 0x%08x\n", esb->BlockStatus);
382 VERBOSE(" RawDataOffset = 0x%08x\n", esb->RawDataOffset);
383 VERBOSE(" RawDataLength = %u\n", esb->RawDataLength);
384 VERBOSE(" DataLength = %u\n", esb->DataLength);
385 VERBOSE(" ErrorSeverity = %u\n", esb->ErrorSeverity);
386 }
387
388 static void
print_data_entry_header(const struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER * de)389 print_data_entry_header(const struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER *de)
390 {
391 if (de == NULL) {
392 WARN("CPER: null Data Entry header\n");
393 return;
394 }
395 VERBOSE("DataEntry:\n");
396 print_guid(de->SectionType);
397 VERBOSE(" ErrorSeverity = %u\n", de->ErrorSeverity);
398 VERBOSE(" Revision = 0x%04x\n", de->Revision);
399 VERBOSE(" ValidationBits= 0x%02x\n", de->ValidationBits);
400 VERBOSE(" Flags = 0x%02x\n", de->Flags);
401 VERBOSE(" ErrorDataLen = %u\n", de->ErrorDataLength);
402 }
403
404 static void
print_cpu_section_header(const struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA * sec)405 print_cpu_section_header(const struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *sec)
406 {
407 if (sec == NULL) {
408 WARN("CPER: null CPU section\n");
409 return;
410 }
411 VERBOSE("CPU Section:\n");
412 VERBOSE(" ValidationBit = 0x%08x\n", sec->CpuInfo.ValidationBit);
413 VERBOSE(" ErrInfoNum = %u\n", sec->CpuInfo.ErrInfoNum);
414 VERBOSE(" CtxtInfoNum = %u\n", sec->CpuInfo.ContextInfoNum);
415 VERBOSE(" SectionLength = %u\n", sec->CpuInfo.SectionLength);
416 VERBOSE(" MPIDR_EL1 = 0x%016llx\n",
417 (unsigned long long)sec->CpuInfo.MPIDR_EL1);
418 VERBOSE(" MIDR_EL1 = 0x%016llx\n",
419 (unsigned long long)sec->CpuInfo.MIDR_EL1);
420 VERBOSE(" RunState = %u\n", sec->CpuInfo.RunState);
421 VERBOSE(" PsciState = %u\n", sec->CpuInfo.PsciState);
422 }
423
424 static void
print_error_info(const struct EFI_ARM_PROCESSOR_ERROR_INFORMATION * ei)425 print_error_info(const struct EFI_ARM_PROCESSOR_ERROR_INFORMATION *ei)
426 {
427 if (ei == NULL) {
428 WARN("CPER: null ErrorInfo\n");
429 return;
430 }
431 VERBOSE("ErrorInfo[0]:\n");
432 VERBOSE(" Version = %u\n", ei->Version);
433 VERBOSE(" Length = %u\n", ei->Length);
434 VERBOSE(" ValidationBit = 0x%04x\n", ei->ValidationBit);
435 VERBOSE(" Type = %u\n", ei->Type);
436 VERBOSE(" MultipleError = %u\n", ei->MultipleError);
437 VERBOSE(" Flags = 0x%02x\n", ei->Flags);
438 VERBOSE(" ErrorInfo = 0x%016llx\n",
439 (unsigned long long)ei->ErrorInfo);
440
441 if (ei->Type == ARM_ERROR_TYPE_CACHE &&
442 (ei->ValidationBit & EFI_ARM_PROC_ERROR_INFO_ERROR_INFO_VALID) &&
443 ei->ErrorInfo != 0) {
444 print_cache_error_info(ei->ErrorInfo);
445 }
446
447 VERBOSE(" VirtFaultAddr = 0x%016llx\n",
448 (unsigned long long)ei->VirtualFaultAddress);
449 VERBOSE(" PhysFaultAddr = 0x%016llx\n",
450 (unsigned long long)ei->PhysicalFaultAddress);
451 }
452
453 static void
print_context_block(const struct EFI_ARM_PROCESSOR_CONTEXT_INFORMATION * c,unsigned int idx)454 print_context_block(const struct EFI_ARM_PROCESSOR_CONTEXT_INFORMATION *c,
455 unsigned int idx)
456 {
457 if (c == NULL) {
458 WARN("CPER: null Context block\n");
459 return;
460 }
461 VERBOSE("Context[%u]: type=%u size=%u\n", idx,
462 c->Hdr.RegisterContextType, c->Hdr.RegisterArraySize);
463
464 switch (c->Hdr.RegisterContextType) {
465 case EFI_ARM_CONTEXT_INFO_REG_TYPE_4:
466 VERBOSE(" GPR x0..x3: %016llx %016llx %016llx %016llx\n",
467 (unsigned long long)c->RegisterArray.Type4Gpr.X[0],
468 (unsigned long long)c->RegisterArray.Type4Gpr.X[1],
469 (unsigned long long)c->RegisterArray.Type4Gpr.X[2],
470 (unsigned long long)c->RegisterArray.Type4Gpr.X[3]);
471 VERBOSE(" SP = 0x%016llx\n",
472 (unsigned long long)c->RegisterArray.Type4Gpr.SP);
473 break;
474
475 case EFI_ARM_CONTEXT_INFO_REG_TYPE_5:
476 VERBOSE(" EL1: SPSR=0x%016llx\n",
477 (unsigned long long)
478 c->RegisterArray.Type5SysRegs.SPSR_EL1);
479 VERBOSE(" EL1: ELR=0x%016llx\n",
480 (unsigned long long)
481 c->RegisterArray.Type5SysRegs.ELR_EL1);
482 VERBOSE(" EL1: ESR=0x%016llx\n",
483 (unsigned long long)
484 c->RegisterArray.Type5SysRegs.ESR_EL1);
485 VERBOSE(" EL1: FAR=0x%016llx\n",
486 (unsigned long long)
487 c->RegisterArray.Type5SysRegs.FAR_EL1);
488 VERBOSE(" ISR_EL1 = 0x%016llx\n",
489 (unsigned long long)
490 c->RegisterArray.Type5SysRegs.ISR_EL1);
491 VERBOSE(" MAIR_EL1 = 0x%016llx\n",
492 (unsigned long long)
493 c->RegisterArray.Type5SysRegs.MAIR_EL1);
494 VERBOSE(" MIDR_EL1 = 0x%016llx\n",
495 (unsigned long long)
496 c->RegisterArray.Type5SysRegs.MIDR_EL1);
497 VERBOSE(" MPIDR_EL1 = 0x%016llx\n",
498 (unsigned long long)
499 c->RegisterArray.Type5SysRegs.MPIDR_EL1);
500 VERBOSE(" SCTLR_EL1 = 0x%016llx\n",
501 (unsigned long long)
502 c->RegisterArray.Type5SysRegs.SCTLR_EL1);
503 VERBOSE(" SP_EL0 = 0x%016llx\n",
504 (unsigned long long)
505 c->RegisterArray.Type5SysRegs.SP_EL0);
506 VERBOSE(" SP_EL1 = 0x%016llx\n",
507 (unsigned long long)
508 c->RegisterArray.Type5SysRegs.SP_EL1);
509 VERBOSE(" TCR_EL1 = 0x%016llx\n",
510 (unsigned long long)
511 c->RegisterArray.Type5SysRegs.TCR_EL1);
512 VERBOSE(" TPIDR_EL0 = 0x%016llx\n",
513 (unsigned long long)
514 c->RegisterArray.Type5SysRegs.TPIDR_EL0);
515 VERBOSE(" TPIDR_EL1 = 0x%016llx\n",
516 (unsigned long long)
517 c->RegisterArray.Type5SysRegs.TPIDR_EL1);
518 VERBOSE(" TPIDRRO_EL0= 0x%016llx\n",
519 (unsigned long long)
520 c->RegisterArray.Type5SysRegs.TPIDRRO_EL0);
521 VERBOSE(" TTBR0_EL1 = 0x%016llx\n",
522 (unsigned long long)
523 c->RegisterArray.Type5SysRegs.TTBR0_EL1);
524 VERBOSE(" TTBR1_EL1 = 0x%016llx\n",
525 (unsigned long long)
526 c->RegisterArray.Type5SysRegs.TTBR1_EL1);
527 break;
528
529 default:
530 VERBOSE(" Unknown context type %u\n",
531 c->Hdr.RegisterContextType);
532 break;
533 }
534 }
535
536 static void
print_contexts(const struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA * sec)537 print_contexts(const struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *sec)
538 {
539 for (unsigned int i = 0; i < sec->CpuInfo.ContextInfoNum; i++)
540 print_context_block(&sec->CpuContextInfo[i], i);
541 }
542
543 /* Dump the CPER buffer contents */
print_cper(const void * buf)544 void print_cper(const void *buf)
545 {
546 if (!buf) {
547 WARN("%s : null buffer\n", __func__);
548 return;
549 }
550
551 const struct ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER *esb = buf;
552 const struct ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER *de =
553 (const void *)(esb + 1);
554 const struct EFI_ARM_PROCESSOR_ERROR_RECORD_DATA *sec =
555 (const void *)(de + 1);
556 const struct EFI_ARM_PROCESSOR_ERROR_INFORMATION *ei =
557 &sec->CpuErrInfo[0];
558
559 VERBOSE("\n========== CPER DUMP ==========\n");
560
561 print_esb_header(esb);
562 print_data_entry_header(de);
563 print_cpu_section_header(sec);
564 print_error_info(ei);
565 print_contexts(sec);
566
567 VERBOSE("========== END OF CPER DUMP ==========\n\n");
568 }
569