Skip to content

Commit 0595451

Browse files
JasonTian518ardbiesheuvel
authored andcommitted
RAS: Report all ARM processor CPER information to userspace
The ARM processor CPER record was added in UEFI v2.6 and remained unchanged up to v2.10. Yet, the original arm_event trace code added by e9279e8 ("trace, ras: add ARM processor error trace event") is incomplete, as it only traces some fields of UAPI 2.6 table N.16, not exporting any information from tables N.17 to N.29 of the record. This is not enough for the user to be able to figure out what has exactly happened or to take appropriate action. According to the UEFI v2.9 specification chapter N2.4.4, the ARM processor error section includes: - several (ERR_INFO_NUM) ARM processor error information structures (Tables N.17 to N.20); - several (CONTEXT_INFO_NUM) ARM processor context information structures (Tables N.21 to N.29); - several vendor specific error information structures. The size is given by Section Length minus the size of the other fields. In addition, it also exports two fields that are parsed by the GHES driver when firmware reports it, e.g.: - error severity - CPU logical index Report all of these information to userspace via a the ARM tracepoint so that userspace can properly record the error and take decisions related to CPU core isolation according to error severity and other info. The updated ARM trace event now contains the following fields: ====================================== ============================= UEFI field on table N.16 ARM Processor trace fields ====================================== ============================= Validation handled when filling data for affinity MPIDR and running state. ERR_INFO_NUM pei_len CONTEXT_INFO_NUM ctx_len Section Length indirectly reported by pei_len, ctx_len and oem_len Error affinity level affinity MPIDR_EL1 mpidr MIDR_EL1 midr Running State running_state PSCI State psci_state Processor Error Information Structure pei_err - count at pei_len Processor Context ctx_err- count at ctx_len Vendor Specific Error Info oem - count at oem_len ====================================== ============================= It should be noted that decoding of tables N.17 to N.29, if needed, will be handled in userspace. That gives more flexibility, as there won't be any need to flood the kernel with micro-architecture specific error decoding. Also, decoding the other fields require a complex logic, and should be done for each of the several values inside the record field. So, let userspace daemons like rasdaemon decode them, parsing such tables and having vendor-specific micro-architecture-specific decoders. [mchehab: modified description, solved merge conflicts and fixed coding style] Signed-off-by: Jason Tian <jason@os.amperecomputing.com> Co-developed-by: Shengwei Luo <luoshengwei@huawei.com> Signed-off-by: Shengwei Luo <luoshengwei@huawei.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Daniel Ferguson <danielf@os.amperecomputing.com> # rebased Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Shiju Jose <shiju.jose@huawei.com> Acked-by: Borislav Petkov (AMD) <bp@alien8.de> Fixes: e9279e8 ("trace, ras: add ARM processor error trace event") Link: https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#arm-processor-error-section Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
1 parent e41ef37 commit 0595451

4 files changed

Lines changed: 99 additions & 17 deletions

File tree

drivers/acpi/apei/ghes.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -552,17 +552,16 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
552552
}
553553

554554
static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
555-
int sev, bool sync)
555+
int sev, bool sync)
556556
{
557557
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
558558
int flags = sync ? MF_ACTION_REQUIRED : 0;
559559
bool queued = false;
560560
int sec_sev, i;
561561
char *p;
562562

563-
log_arm_hw_error(err);
564-
565563
sec_sev = ghes_severity(gdata->error_severity);
564+
log_arm_hw_error(err, sec_sev);
566565
if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE)
567566
return false;
568567

@@ -895,11 +894,9 @@ static void ghes_do_proc(struct ghes *ghes,
895894

896895
arch_apei_report_mem_error(sev, mem_err);
897896
queued = ghes_handle_memory_failure(gdata, sev, sync);
898-
}
899-
else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
897+
} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
900898
ghes_handle_aer(gdata);
901-
}
902-
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
899+
} else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
903900
queued = ghes_handle_arm_hw_error(gdata, sev, sync);
904901
} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
905902
struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);

drivers/ras/ras.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,45 @@ void log_non_standard_event(const guid_t *sec_type, const guid_t *fru_id,
5353
}
5454
EXPORT_SYMBOL_GPL(log_non_standard_event);
5555

56-
void log_arm_hw_error(struct cper_sec_proc_arm *err)
56+
void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev)
5757
{
58-
trace_arm_event(err);
58+
struct cper_arm_err_info *err_info;
59+
struct cper_arm_ctx_info *ctx_info;
60+
u8 *ven_err_data;
61+
u32 ctx_len = 0;
62+
int n, sz, cpu;
63+
s32 vsei_len;
64+
u32 pei_len;
65+
u8 *pei_err, *ctx_err;
66+
67+
pei_len = sizeof(struct cper_arm_err_info) * err->err_info_num;
68+
pei_err = (u8 *)(err + 1);
69+
70+
err_info = (struct cper_arm_err_info *)(err + 1);
71+
ctx_info = (struct cper_arm_ctx_info *)(err_info + err->err_info_num);
72+
ctx_err = (u8 *)ctx_info;
73+
74+
for (n = 0; n < err->context_info_num; n++) {
75+
sz = sizeof(struct cper_arm_ctx_info) + ctx_info->size;
76+
ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + sz);
77+
ctx_len += sz;
78+
}
79+
80+
vsei_len = err->section_length - (sizeof(struct cper_sec_proc_arm) + pei_len + ctx_len);
81+
if (vsei_len < 0) {
82+
pr_warn(FW_BUG "section length: %d\n", err->section_length);
83+
pr_warn(FW_BUG "section length is too small\n");
84+
pr_warn(FW_BUG "firmware-generated error record is incorrect\n");
85+
vsei_len = 0;
86+
}
87+
ven_err_data = (u8 *)ctx_info;
88+
89+
cpu = GET_LOGICAL_INDEX(err->mpidr);
90+
if (cpu < 0)
91+
cpu = -1;
92+
93+
trace_arm_event(err, pei_err, pei_len, ctx_err, ctx_len,
94+
ven_err_data, (u32)vsei_len, sev, cpu);
5995
}
6096

6197
static int __init ras_init(void)

include/linux/ras.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@ int __init parse_cec_param(char *str);
2424
void log_non_standard_event(const guid_t *sec_type,
2525
const guid_t *fru_id, const char *fru_text,
2626
const u8 sev, const u8 *err, const u32 len);
27-
void log_arm_hw_error(struct cper_sec_proc_arm *err);
28-
27+
void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev);
2928
#else
3029
static inline void
3130
log_non_standard_event(const guid_t *sec_type,
3231
const guid_t *fru_id, const char *fru_text,
3332
const u8 sev, const u8 *err, const u32 len)
3433
{ return; }
3534
static inline void
36-
log_arm_hw_error(struct cper_sec_proc_arm *err) { return; }
35+
log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev) { return; }
3736
#endif
3837

3938
struct atl_err {
@@ -53,4 +52,15 @@ static inline unsigned long
5352
amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; }
5453
#endif /* CONFIG_AMD_ATL */
5554

55+
#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
56+
#include <asm/smp_plat.h>
57+
/*
58+
* Include ARM-specific SMP header which provides a function mapping mpidr to
59+
* CPU logical index.
60+
*/
61+
#define GET_LOGICAL_INDEX(mpidr) get_logical_index(mpidr & MPIDR_HWID_BITMASK)
62+
#else
63+
#define GET_LOGICAL_INDEX(mpidr) -EINVAL
64+
#endif /* CONFIG_ARM || CONFIG_ARM64 */
65+
5666
#endif /* __RAS_H__ */

include/ras/ras_event.h

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,40 @@ TRACE_EVENT(mc_event,
168168
* This event is generated when hardware detects an ARM processor error
169169
* has occurred. UEFI 2.6 spec section N.2.4.4.
170170
*/
171+
#define APEIL "ARM Processor Err Info data len"
172+
#define APEID "ARM Processor Err Info raw data"
173+
#define APECIL "ARM Processor Err Context Info data len"
174+
#define APECID "ARM Processor Err Context Info raw data"
175+
#define VSEIL "Vendor Specific Err Info data len"
176+
#define VSEID "Vendor Specific Err Info raw data"
171177
TRACE_EVENT(arm_event,
172178

173-
TP_PROTO(const struct cper_sec_proc_arm *proc),
179+
TP_PROTO(const struct cper_sec_proc_arm *proc,
180+
const u8 *pei_err,
181+
const u32 pei_len,
182+
const u8 *ctx_err,
183+
const u32 ctx_len,
184+
const u8 *oem,
185+
const u32 oem_len,
186+
u8 sev,
187+
int cpu),
174188

175-
TP_ARGS(proc),
189+
TP_ARGS(proc, pei_err, pei_len, ctx_err, ctx_len, oem, oem_len, sev, cpu),
176190

177191
TP_STRUCT__entry(
178192
__field(u64, mpidr)
179193
__field(u64, midr)
180194
__field(u32, running_state)
181195
__field(u32, psci_state)
182196
__field(u8, affinity)
197+
__field(u32, pei_len)
198+
__dynamic_array(u8, pei_buf, pei_len)
199+
__field(u32, ctx_len)
200+
__dynamic_array(u8, ctx_buf, ctx_len)
201+
__field(u32, oem_len)
202+
__dynamic_array(u8, oem_buf, oem_len)
203+
__field(u8, sev)
204+
__field(int, cpu)
183205
),
184206

185207
TP_fast_assign(
@@ -199,12 +221,29 @@ TRACE_EVENT(arm_event,
199221
__entry->running_state = ~0;
200222
__entry->psci_state = ~0;
201223
}
224+
__entry->pei_len = pei_len;
225+
memcpy(__get_dynamic_array(pei_buf), pei_err, pei_len);
226+
__entry->ctx_len = ctx_len;
227+
memcpy(__get_dynamic_array(ctx_buf), ctx_err, ctx_len);
228+
__entry->oem_len = oem_len;
229+
memcpy(__get_dynamic_array(oem_buf), oem, oem_len);
230+
__entry->sev = sev;
231+
__entry->cpu = cpu;
202232
),
203233

204-
TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
205-
"running state: %d; PSCI state: %d",
234+
TP_printk("cpu: %d; error: %d; affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
235+
"running state: %d; PSCI state: %d; "
236+
"%s: %d; %s: %s; %s: %d; %s: %s; %s: %d; %s: %s",
237+
__entry->cpu,
238+
__entry->sev,
206239
__entry->affinity, __entry->mpidr, __entry->midr,
207-
__entry->running_state, __entry->psci_state)
240+
__entry->running_state, __entry->psci_state,
241+
APEIL, __entry->pei_len, APEID,
242+
__print_hex(__get_dynamic_array(pei_buf), __entry->pei_len),
243+
APECIL, __entry->ctx_len, APECID,
244+
__print_hex(__get_dynamic_array(ctx_buf), __entry->ctx_len),
245+
VSEIL, __entry->oem_len, VSEID,
246+
__print_hex(__get_dynamic_array(oem_buf), __entry->oem_len))
208247
);
209248

210249
/*

0 commit comments

Comments
 (0)