Skip to content

Commit 96b0105

Browse files
mchehabardbiesheuvel
authored andcommitted
efi/cper: align ARM CPER type with UEFI 2.9A/2.10 specs
Up to UEFI spec 2.9, the type byte of CPER struct for ARM processor was defined simply as: Type at byte offset 4: - Cache error - TLB Error - Bus Error - Micro-architectural Error All other values are reserved Yet, there was no information about how this would be encoded. Spec 2.9A errata corrected it by defining: - Bit 1 - Cache Error - Bit 2 - TLB Error - Bit 3 - Bus Error - Bit 4 - Micro-architectural Error All other values are reserved That actually aligns with the values already defined on older versions at N.2.4.1. Generic Processor Error Section. Spec 2.10 also preserve the same encoding as 2.9A. Adjust CPER and GHES handling code for both generic and ARM processors to properly handle UEFI 2.9A and 2.10 encoding. Link: https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#arm-processor-error-information Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Acked-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
1 parent a976d79 commit 96b0105

3 files changed

Lines changed: 39 additions & 37 deletions

File tree

drivers/acpi/apei/ghes.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/moduleparam.h>
2323
#include <linux/init.h>
2424
#include <linux/acpi.h>
25+
#include <linux/bitfield.h>
2526
#include <linux/io.h>
2627
#include <linux/interrupt.h>
2728
#include <linux/timer.h>
@@ -556,6 +557,7 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
556557
{
557558
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
558559
int flags = sync ? MF_ACTION_REQUIRED : 0;
560+
char error_type[120];
559561
bool queued = false;
560562
int sec_sev, i;
561563
char *p;
@@ -568,9 +570,8 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
568570
p = (char *)(err + 1);
569571
for (i = 0; i < err->err_info_num; i++) {
570572
struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p;
571-
bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR);
573+
bool is_cache = err_info->type & CPER_ARM_CACHE_ERROR;
572574
bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR);
573-
const char *error_type = "unknown error";
574575

575576
/*
576577
* The field (err_info->error_info & BIT(26)) is fixed to set to
@@ -584,12 +585,15 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
584585
continue;
585586
}
586587

587-
if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs))
588-
error_type = cper_proc_error_type_strs[err_info->type];
588+
cper_bits_to_str(error_type, sizeof(error_type),
589+
FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
590+
cper_proc_error_type_strs,
591+
ARRAY_SIZE(cper_proc_error_type_strs));
589592

590593
pr_warn_ratelimited(FW_WARN GHES_PFX
591-
"Unhandled processor error type: %s\n",
592-
error_type);
594+
"Unhandled processor error type 0x%02x: %s%s\n",
595+
err_info->type, error_type,
596+
(err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
593597
p += err_info->length;
594598
}
595599

drivers/firmware/efi/cper-arm.c

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,11 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
9393
bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
9494
bool time_out, access_mode;
9595

96-
/* If the type is unknown, bail. */
97-
if (type > CPER_ARM_MAX_TYPE)
98-
return;
99-
10096
/*
10197
* Vendor type errors have error information values that are vendor
10298
* specific.
10399
*/
104-
if (type == CPER_ARM_VENDOR_ERROR)
100+
if (type & CPER_ARM_VENDOR_ERROR)
105101
return;
106102

107103
if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
@@ -116,43 +112,38 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
116112
if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
117113
op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
118114
& CPER_ARM_ERR_OPERATION_MASK);
119-
switch (type) {
120-
case CPER_ARM_CACHE_ERROR:
115+
if (type & CPER_ARM_CACHE_ERROR) {
121116
if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
122-
printk("%soperation type: %s\n", pfx,
117+
printk("%scache error, operation type: %s\n", pfx,
123118
arm_cache_err_op_strs[op_type]);
124119
}
125-
break;
126-
case CPER_ARM_TLB_ERROR:
120+
}
121+
if (type & CPER_ARM_TLB_ERROR) {
127122
if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
128-
printk("%soperation type: %s\n", pfx,
123+
printk("%sTLB error, operation type: %s\n", pfx,
129124
arm_tlb_err_op_strs[op_type]);
130125
}
131-
break;
132-
case CPER_ARM_BUS_ERROR:
126+
}
127+
if (type & CPER_ARM_BUS_ERROR) {
133128
if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
134-
printk("%soperation type: %s\n", pfx,
129+
printk("%sbus error, operation type: %s\n", pfx,
135130
arm_bus_err_op_strs[op_type]);
136131
}
137-
break;
138132
}
139133
}
140134

141135
if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
142136
level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
143137
& CPER_ARM_ERR_LEVEL_MASK);
144-
switch (type) {
145-
case CPER_ARM_CACHE_ERROR:
138+
if (type & CPER_ARM_CACHE_ERROR)
146139
printk("%scache level: %d\n", pfx, level);
147-
break;
148-
case CPER_ARM_TLB_ERROR:
140+
141+
if (type & CPER_ARM_TLB_ERROR)
149142
printk("%sTLB level: %d\n", pfx, level);
150-
break;
151-
case CPER_ARM_BUS_ERROR:
143+
144+
if (type & CPER_ARM_BUS_ERROR)
152145
printk("%saffinity level at which the bus error occurred: %d\n",
153146
pfx, level);
154-
break;
155-
}
156147
}
157148

158149
if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
@@ -241,6 +232,7 @@ void cper_print_proc_arm(const char *pfx,
241232
struct cper_arm_err_info *err_info;
242233
struct cper_arm_ctx_info *ctx_info;
243234
char newpfx[64], infopfx[ARRAY_SIZE(newpfx) + 1];
235+
char error_type[120];
244236

245237
printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
246238

@@ -289,9 +281,15 @@ void cper_print_proc_arm(const char *pfx,
289281
newpfx);
290282
}
291283

292-
printk("%serror_type: %d, %s\n", newpfx, err_info->type,
293-
err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
294-
cper_proc_error_type_strs[err_info->type] : "unknown");
284+
cper_bits_to_str(error_type, sizeof(error_type),
285+
FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
286+
cper_proc_error_type_strs,
287+
ARRAY_SIZE(cper_proc_error_type_strs));
288+
289+
printk("%serror_type: 0x%02x: %s%s\n", newpfx, err_info->type,
290+
error_type,
291+
(err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
292+
295293
if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
296294
printk("%serror_info: 0x%016llx\n", newpfx,
297295
err_info->error_info);

include/linux/cper.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ enum {
297297
#define CPER_ARM_INFO_FLAGS_PROPAGATED BIT(2)
298298
#define CPER_ARM_INFO_FLAGS_OVERFLOW BIT(3)
299299

300-
#define CPER_ARM_CACHE_ERROR 0
301-
#define CPER_ARM_TLB_ERROR 1
302-
#define CPER_ARM_BUS_ERROR 2
303-
#define CPER_ARM_VENDOR_ERROR 3
304-
#define CPER_ARM_MAX_TYPE CPER_ARM_VENDOR_ERROR
300+
#define CPER_ARM_ERR_TYPE_MASK GENMASK(4,1)
301+
#define CPER_ARM_CACHE_ERROR BIT(1)
302+
#define CPER_ARM_TLB_ERROR BIT(2)
303+
#define CPER_ARM_BUS_ERROR BIT(3)
304+
#define CPER_ARM_VENDOR_ERROR BIT(4)
305305

306306
#define CPER_ARM_ERR_VALID_TRANSACTION_TYPE BIT(0)
307307
#define CPER_ARM_ERR_VALID_OPERATION_TYPE BIT(1)

0 commit comments

Comments
 (0)