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 */ 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 */ 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