1 /*
2 * Copyright (c) 2025-2026, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef CPER_H
8 #define CPER_H
9
10 #include <cdefs.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13
14 #include <tools_share/uuid.h>
15
16 /* Generic Error Status Block */
17 #define ACPI_ESB_UE_VALID (1U << 0)
18 #define ACPI_ESB_CE_VALID (1U << 1)
19 #define ACPI_ESB_MULTI_UE (1U << 2)
20 #define ACPI_ESB_MULTI_CE (1U << 3)
21 #define ACPI_ESB_ENTRYCOUNT_SHIFT U(4)
22 #define ACPI_ESB_ENTRYCOUNT_MASK (U(0x3FF) << ACPI_ESB_ENTRYCOUNT_SHIFT)
23
24 #define ACPI_SEC_FLAG_LATENT (1U << 5)
25
26 /* Error Data Entry */
27 #define ACPI_DATA_ENTRY_REV_0300 U(0x0300)
28 #define ACPI_DATA_ENTRY_SEV_RECOVERABLE U(0)
29 #define ACPI_DATA_ENTRY_SEV_FATAL U(1)
30 #define ACPI_DATA_ENTRY_SEV_CORRECTED U(2)
31 #define ACPI_DATA_ENTRY_SEV_NONE U(3)
32
33 /* Processor Error Section header flags */
34 #define EFI_ARM_PROC_ERROR_MPIDR_VALID (1U << 0)
35 #define EFI_ARM_PROC_ERROR_AFFINITY_LEVEL_VALID (1U << 1)
36 #define EFI_ARM_PROC_ERROR_RUNNING_STATE_VALID (1U << 2)
37
38 /* Processor Error Information validation bits */
39 #define EFI_ARM_PROC_ERROR_INFO_MULTIPLE_ERROR_VALID (1U << 0)
40 #define EFI_ARM_PROC_ERROR_INFO_FLAGS_VALID (1U << 1)
41 #define EFI_ARM_PROC_ERROR_INFO_ERROR_INFO_VALID (1U << 2)
42 #define EFI_ARM_PROC_ERROR_INFO_VIRT_ADDR_VALID (1U << 3)
43 #define EFI_ARM_PROC_ERROR_INFO_PHYS_ADDR_VALID (1U << 4)
44
45 /* Processor error types */
46 #define ARM_ERROR_TYPE_CACHE U(0)
47 #define ARM_ERROR_TYPE_TLB U(1)
48
49 /* Cache error encoding */
50 #define ARM_CACHE_ERR_TX_INSTR U(0)
51 #define ARM_CACHE_ERR_TX_DATA U(1)
52 #define ARM_CACHE_ERR_TX_GENERIC U(2)
53 #define ARM_CACHE_ERR_OP_GENERIC U(0)
54
55 #define ARM_CACHE_ERR_VLD_TX_TYPE (1ULL << 0)
56 #define ARM_CACHE_ERR_VLD_OPERATION (1ULL << 1)
57 #define ARM_CACHE_ERR_VLD_LEVEL (1ULL << 2)
58 #define ARM_CACHE_ERR_VLD_PCC (1ULL << 3)
59 #define ARM_CACHE_ERR_VLD_CORRECTED (1ULL << 4)
60 #define ARM_CACHE_ERR_VLD_PRECISE_PC (1ULL << 5)
61 #define ARM_CACHE_ERR_VLD_RESTART_PC (1ULL << 6)
62 #define ARM_CACHE_ERR_TX_SHIFT 16
63 #define ARM_CACHE_ERR_TX_MASK (0x3ULL << ARM_CACHE_ERR_TX_SHIFT)
64 #define ARM_CACHE_ERR_OP_SHIFT 18
65 #define ARM_CACHE_ERR_OP_MASK (0xFULL << ARM_CACHE_ERR_OP_SHIFT)
66 #define ARM_CACHE_ERR_LEVEL_SHIFT 22
67 #define ARM_CACHE_ERR_LEVEL_MASK (0x7ULL << ARM_CACHE_ERR_LEVEL_SHIFT)
68 #define ARM_CACHE_ERR_PCC_BIT 25
69 #define ARM_CACHE_ERR_CORR_BIT 26
70 #define ARM_CACHE_ERR_PRECISE_PC_BIT 27
71 #define ARM_CACHE_ERR_RESTART_PC_BIT 28
72
73 /* Context information */
74 #define EFI_ARM_CONTEXT_INFO_REG_TYPE_4 U(4)
75 #define EFI_ARM_CONTEXT_INFO_REG_TYPE_5 U(5)
76
77 /* Record sizing */
78 #define CPU_ERR_INFO_NUM U(1)
79 #define CPU_CONTEXT_INFO_NUM U(2)
80
81 /*
82 * Error Status Block (ESB)
83 * See UEFI Spec:
84 * https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/18_ACPI_Platform_Error_Interfaces/
85 * error-source-discovery.html#generic-error-status-block
86 *
87 * @BlockStatus: Bitfield indicating UE/CE presence and number of entries
88 * @RawDataOffset: Offset to data following this header+entry
89 * @RawDataLength: Length of data (0 if none)
90 * @DataLength: Length of all following CPER data (entries + payloads)
91 * @ErrorSeverity: Error severity (CE/UE/DE)
92 */
93 struct __packed ACPI_GENERIC_ERROR_STATUS_BLOCK_HEADER {
94 uint32_t BlockStatus;
95 uint32_t RawDataOffset;
96 uint32_t RawDataLength;
97 uint32_t DataLength;
98 uint32_t ErrorSeverity;
99 };
100
101 /*
102 * ACPI Error Data Entry Header
103 * See UEFI Spec:
104 * https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/18_ACPI_Platform_Error_Interfaces/
105 * error-source-discovery.html#generic-error-data-entry
106 *
107 * @SectionType: GUID (ARM PROCESSOR ERROR SECTION GUID)
108 * @ErrorSeverity: Severity for this entry (CE/UE/DE)
109 * @Revision: 0x300
110 * @ValidationBits: FRU/time presence flags (not used here)
111 * @Flags: Misc flags (e.g., overflow/latent)
112 * @ErrorDataLength:Length in bytes of the payload following this header
113 * @FruId: Optional FRU GUID
114 * @FruText: Optional FRU text
115 * @TimestampBCD: Optional timestamp (BCD)
116 */
117 struct __packed ACPI_GENERIC_ERROR_DATA_ENTRY_HEADER {
118 struct efi_guid SectionType;
119 uint32_t ErrorSeverity;
120 uint16_t Revision;
121 uint8_t ValidationBits;
122 uint8_t Flags;
123 uint32_t ErrorDataLength;
124 struct efi_guid FruId;
125 uint8_t FruText[20];
126 uint64_t TimestampBCD;
127 };
128
129 static const struct efi_guid ARM_PROC_ERR_SECTION_GUID =
130 (struct efi_guid){ 0xE19E3D16,
131 0xBC11,
132 0x11E4,
133 { 0x9C, 0xAA, 0xC2, 0x05, 0x1D, 0x5D, 0x46, 0xB0 } };
134
135 /*
136 * ARM Processor Error Section
137 * See UEFI Spec:
138 * https://uefi.org/specs/UEFI/2.11/
139 * Apx_N_Common_Platform_Error_Record.html#arm-processor-error-section-format
140 *
141 * @ValidationBit: Bitmask of valid header fields
142 * @ErrInfoNum: Number of error-info records
143 * @ContextInfoNum: Number of context records (Type-4, Type-5/6)
144 * @SectionLength: Total length of this CPU payload (header+info+contexts)
145 * @AffinityLevel: Optional affinity level
146 * @MPIDR_EL1: MPIDR of the affected PE
147 * @MIDR_EL1: MIDR of the affected PE
148 * @RunState: Firmware-defined running state (1=running)
149 * @PsciState: Optional PSCI power state
150 */
151 struct __packed EFI_ARM_PROCESSOR_ERROR_SECTION_HEADER {
152 uint32_t ValidationBit;
153 uint16_t ErrInfoNum;
154 uint16_t ContextInfoNum;
155 uint32_t SectionLength;
156 uint8_t AffinityLevel;
157 uint8_t Rsvd0[3];
158 uint64_t MPIDR_EL1;
159 uint64_t MIDR_EL1;
160 uint32_t RunState;
161 uint32_t PsciState;
162 };
163
164 /*
165 * ARM Processor Error Information
166 * See UEFI Spec:
167 * https://uefi.org/specs/UEFI/2.11/
168 * Apx_N_Common_Platform_Error_Record.html#arm-processor-error-information-structure
169 *
170 * Describes a single error instance associated with the processor.
171 * Multiple entries may appear; this struct is one element of that array.
172 * @Version: Payload version (0)
173 * @Length: Size
174 * @ValidationBit: Bitmask of valid members
175 * @Type: ARM error type (cache/TLB)
176 * @MultipleError: Optional multi-error count (e.g., CE count)
177 * @Flags: Optional flags (overflow/first-error)
178 * @ErrorInfo: Implementation-defined 64-bit error info
179 * @VirtualFaultAddress: VA implicated (if any)
180 * @PhysicalFaultAddress: PA implicated (if any)
181 */
182 struct __packed EFI_ARM_PROCESSOR_ERROR_INFORMATION {
183 uint8_t Version;
184 uint8_t Length;
185 uint16_t ValidationBit;
186 uint8_t Type;
187 uint16_t MultipleError;
188 uint8_t Flags;
189 uint64_t ErrorInfo;
190 uint64_t VirtualFaultAddress;
191 uint64_t PhysicalFaultAddress;
192 };
193
194 /*
195 * ARM Processor Error Context Information
196 * See UEFI Spec:
197 * https://uefi.org/specs/UEFI/2.11/
198 * Apx_N_Common_Platform_Error_Record.html#arm-processor-error-context-information-headerstructure
199 *
200 * Identifies which kind of register context follows and its size.
201 * @Version: Context structure version (0)
202 * @RegisterContextType: 4=GPR, 5=EL1 sysregs
203 * @RegisterArraySize: Size of the union payload for this block
204 */
205 struct __packed EFI_ARM_PROCESSOR_ERROR_CONTEXT_INFO_HEADER {
206 uint16_t Version;
207 uint16_t RegisterContextType;
208 uint32_t RegisterArraySize;
209 };
210
211 struct __packed EFI_ARM_AARCH64_CONTEXT_GPR {
212 uint64_t X[31];
213 uint64_t SP;
214 };
215
216 struct __packed EFI_ARM_AARCH64_EL1_CONTEXT_SYSTEM_REGISTERS {
217 uint64_t ELR_EL1;
218 uint64_t ESR_EL1;
219 uint64_t FAR_EL1;
220 uint64_t ISR_EL1;
221 uint64_t MAIR_EL1;
222 uint64_t MIDR_EL1;
223 uint64_t MPIDR_EL1;
224 uint64_t SCTLR_EL1;
225 uint64_t SP_EL0;
226 uint64_t SP_EL1;
227 uint64_t SPSR_EL1;
228 uint64_t TCR_EL1;
229 uint64_t TPIDR_EL0;
230 uint64_t TPIDR_EL1;
231 uint64_t TPIDRRO_EL0;
232 uint64_t TTBR0_EL1;
233 uint64_t TTBR1_EL1;
234 };
235
236 struct __packed EFI_ARM_PROCESSOR_CONTEXT_INFORMATION {
237 struct EFI_ARM_PROCESSOR_ERROR_CONTEXT_INFO_HEADER Hdr;
238 union {
239 struct EFI_ARM_AARCH64_CONTEXT_GPR Type4Gpr;
240 struct EFI_ARM_AARCH64_EL1_CONTEXT_SYSTEM_REGISTERS Type5SysRegs;
241 } RegisterArray;
242 };
243
244 struct __packed EFI_ARM_PROCESSOR_ERROR_RECORD_DATA {
245 struct EFI_ARM_PROCESSOR_ERROR_SECTION_HEADER CpuInfo;
246 struct EFI_ARM_PROCESSOR_ERROR_INFORMATION CpuErrInfo[CPU_ERR_INFO_NUM];
247 struct EFI_ARM_PROCESSOR_CONTEXT_INFORMATION
248 CpuContextInfo[CPU_CONTEXT_INFO_NUM];
249 };
250
esb_block_status(bool uc_valid,bool ce_valid,bool multi_ue,bool multi_ce,uint16_t entry_count)251 static inline uint32_t esb_block_status(bool uc_valid, bool ce_valid,
252 bool multi_ue, bool multi_ce,
253 uint16_t entry_count)
254 {
255 uint32_t v = 0;
256
257 if (uc_valid)
258 v |= ACPI_ESB_UE_VALID;
259 if (ce_valid)
260 v |= ACPI_ESB_CE_VALID;
261 if (multi_ue)
262 v |= ACPI_ESB_MULTI_UE;
263 if (multi_ce)
264 v |= ACPI_ESB_MULTI_CE;
265 v |= ((uint32_t)entry_count << ACPI_ESB_ENTRYCOUNT_SHIFT) &
266 ACPI_ESB_ENTRYCOUNT_MASK;
267 return v;
268 }
269
270 size_t cper_write_cpu_record(void *buf, size_t buf_size);
271
272 /* Dump the CPER buffer contents */
273 void print_cper(const void *buf);
274
275 #endif /* CPER_H */
276