* [PATCH 0/6] CPER: Add Memory Error Section 2 support
@ 2026-10-19 14:56 Pierre Gondois
2026-10-19 14:56 ` [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue Pierre Gondois
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Dan Williams, Terry Bowman,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
The support is mostly duplicated from Memory Error Section handling.
Other than differences coming from the content of Memory Error
Section 1 and 2, differences in the support are:
- v2 do not rely on a compact "struct cper_mem_err_compact" struct.
This structure was used to support older versions of the Memory
Error Section (1). This is not needed for the new structure.
- The compact version is also used by the tracing framework.
To avoid relying and propagating a non-standard record format,
through trace event (cf. extlog_mem event) the new trace event
prints each field individually.
The last patch of the serie was only build-tested due to the
absence of relevant hardware. apei_mce_report_mem_error() and
arch_apei_report_mem_error() implementations were also removed since
last version.
It will also require a proper handling from the rasdaemon. Applying
this last patch without rasdaemon support will silent the reports of
Memory Error Section 2 error, cf. ras_userspace_consumers() check.
RFC: https://lore.kernel.org/all/20260929074659.2587216-1-pierre.gondois@arm.com/#t
Pierre Gondois (6):
ACPI: extlog: fix extlog_mem_event build issue
cper: add Memory Error Section 2 structures
cper: use BIT_ULL() for processor and memory validation bits
cper: add helpers to handle Memory Error Section 2
ACPI: APEI: add separate Memory Error Section 2 handlers
ACPI: extlog: add Memory Error Section 2 trace event
drivers/acpi/acpi_extlog.c | 30 +++++++-
drivers/acpi/apei/ghes.c | 49 +++++++++++-
drivers/edac/ghes_edac.c | 150 ++++++++++++++++++++++++++++++++++++
drivers/firmware/efi/cper.c | 108 ++++++++++++++++++++++++++
drivers/ras/ras.c | 1 +
include/acpi/ghes.h | 2 +
include/linux/cper.h | 129 ++++++++++++++++++++++---------
include/ras/ras_event.h | 102 ++++++++++++++++++++++++
8 files changed, 532 insertions(+), 39 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 16:36 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
` (4 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Terry Bowman, Dan Williams,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
With CONFIG_ACPI_EXTLOG=n and with the following command:
make -j4 drivers/acpi/acpi_extlog.o drivers/acpi/
trace_extlog_mem_event() is not defined. Add a extlog_mem_err_event()
wrapper to fix the build issue.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/acpi/acpi_extlog.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 7ad3b36013cc..e764d61f71ca 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -180,6 +180,15 @@ extlog_cxl_cper_handle_prot_err(struct cxl_cper_sec_prot_err *prot_err,
#endif
}
+static void
+extlog_mem_err_event(struct cper_sec_mem_err *mem, u32 err_seq,
+ const guid_t *fru_id, const char *fru_text, u8 sev)
+{
+#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
+ trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, sev);
+#endif
+}
+
static int extlog_print(struct notifier_block *nb, unsigned long val,
void *data)
{
@@ -229,8 +238,9 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
struct cper_sec_mem_err *mem = acpi_hest_get_payload(gdata);
if (gdata->error_data_length >= sizeof(*mem))
- trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
- (u8)gdata->error_severity);
+ extlog_mem_err_event(mem, err_seq, fru_id,
+ fru_text,
+ (u8)gdata->error_severity);
} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
struct cxl_cper_sec_prot_err *prot_err =
acpi_hest_get_payload(gdata);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/6] cper: add Memory Error Section 2 structures
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 14:56 ` [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 18:16 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Dan Williams, Terry Bowman,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
Add CPER Memory Error Section 2 definitions to the CPER headers.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
include/linux/cper.h | 54 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 440b35e459e5..76e82a8d29a2 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -198,6 +198,10 @@ enum {
#define CPER_SEC_PLATFORM_MEM \
GUID_INIT(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
0xED, 0x7C, 0x83, 0xB1)
+/* Platform Memory 2 */
+#define CPER_SEC_PLATFORM_MEM2 \
+ GUID_INIT(0x61EC04FC, 0x48E6, 0xD813, 0x25, 0xC9, 0x8D, 0xAA, \
+ 0x44, 0x75, 0x0B, 0x12)
#define CPER_SEC_PCIE \
GUID_INIT(0xD995E954, 0xBBC1, 0x430F, 0xAD, 0x91, 0xB4, 0x4D, \
0xCB, 0x3C, 0x6F, 0x35)
@@ -262,6 +266,30 @@ enum {
#define CPER_MEM_VALID_BANK_ADDRESS 0x100000
#define CPER_MEM_VALID_CHIP_ID 0x200000
+/* Memory Error Section 2 validation bits, UEFI v2.11 sec N.2.6. */
+#define CPER_MEM2_VALID_ERROR_STATUS BIT_ULL(0)
+#define CPER_MEM2_VALID_PA BIT_ULL(1)
+#define CPER_MEM2_VALID_PA_MASK BIT_ULL(2)
+#define CPER_MEM2_VALID_NODE BIT_ULL(3)
+#define CPER_MEM2_VALID_CARD BIT_ULL(4)
+#define CPER_MEM2_VALID_MODULE BIT_ULL(5)
+#define CPER_MEM2_VALID_BANK BIT_ULL(6)
+#define CPER_MEM2_VALID_DEVICE BIT_ULL(7)
+#define CPER_MEM2_VALID_ROW BIT_ULL(8)
+#define CPER_MEM2_VALID_COLUMN BIT_ULL(9)
+#define CPER_MEM2_VALID_RANK_NUMBER BIT_ULL(10)
+#define CPER_MEM2_VALID_BIT_POSITION BIT_ULL(11)
+#define CPER_MEM2_VALID_CHIP_ID BIT_ULL(12)
+#define CPER_MEM2_VALID_ERROR_TYPE BIT_ULL(13)
+#define CPER_MEM2_VALID_STATUS BIT_ULL(14)
+#define CPER_MEM2_VALID_REQUESTOR_ID BIT_ULL(15)
+#define CPER_MEM2_VALID_RESPONDER_ID BIT_ULL(16)
+#define CPER_MEM2_VALID_TARGET_ID BIT_ULL(17)
+#define CPER_MEM2_VALID_CARD_HANDLE BIT_ULL(18)
+#define CPER_MEM2_VALID_MODULE_HANDLE BIT_ULL(19)
+#define CPER_MEM2_VALID_BANK_GROUP BIT_ULL(20)
+#define CPER_MEM2_VALID_BANK_ADDRESS BIT_ULL(21)
+
#define CPER_MEM_EXT_ROW_MASK 0x3
#define CPER_MEM_EXT_ROW_SHIFT 16
@@ -506,6 +534,32 @@ struct cper_sec_mem_err {
u16 mem_dev_handle; /* "module handle" in UEFI 2.4 */
};
+/* Memory Error Section 2, UEFI v2.11 sec N.2.6 */
+struct cper_sec_mem_err2 {
+ u64 validation_bits;
+ u64 error_status;
+ u64 physical_addr;
+ u64 physical_addr_mask;
+ u16 node;
+ u16 card;
+ u16 module;
+ u16 bank;
+ u32 device;
+ u32 row;
+ u32 column;
+ u32 rank;
+ u32 bit_pos;
+ u8 chip_id;
+ u8 error_type;
+ u8 status;
+ u8 reserved;
+ u64 requestor_id;
+ u64 responder_id;
+ u64 target_id;
+ u32 mem_array_handle; /* "card handle" */
+ u32 mem_dev_handle; /* "module handle" */
+};
+
struct cper_mem_err_compact {
u64 validation_bits;
u16 node;
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 14:56 ` [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue Pierre Gondois
2026-10-19 14:56 ` [PATCH 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 18:21 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 4/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
` (2 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Dan Williams, Terry Bowman,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
Use the BIT_ULL() macro to describe flag bits instead of
hexadecimal values which are harder to read.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
include/linux/cper.h | 72 ++++++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 36 deletions(-)
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 76e82a8d29a2..ed355b240685 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -229,42 +229,42 @@ enum {
GUID_INIT(0x036F84E1, 0x7F37, 0x428c, 0xA7, 0x9E, 0x57, 0x5F, \
0xDF, 0xAA, 0x84, 0xEC)
-#define CPER_PROC_VALID_TYPE 0x0001
-#define CPER_PROC_VALID_ISA 0x0002
-#define CPER_PROC_VALID_ERROR_TYPE 0x0004
-#define CPER_PROC_VALID_OPERATION 0x0008
-#define CPER_PROC_VALID_FLAGS 0x0010
-#define CPER_PROC_VALID_LEVEL 0x0020
-#define CPER_PROC_VALID_VERSION 0x0040
-#define CPER_PROC_VALID_BRAND_INFO 0x0080
-#define CPER_PROC_VALID_ID 0x0100
-#define CPER_PROC_VALID_TARGET_ADDRESS 0x0200
-#define CPER_PROC_VALID_REQUESTOR_ID 0x0400
-#define CPER_PROC_VALID_RESPONDER_ID 0x0800
-#define CPER_PROC_VALID_IP 0x1000
-
-#define CPER_MEM_VALID_ERROR_STATUS 0x0001
-#define CPER_MEM_VALID_PA 0x0002
-#define CPER_MEM_VALID_PA_MASK 0x0004
-#define CPER_MEM_VALID_NODE 0x0008
-#define CPER_MEM_VALID_CARD 0x0010
-#define CPER_MEM_VALID_MODULE 0x0020
-#define CPER_MEM_VALID_BANK 0x0040
-#define CPER_MEM_VALID_DEVICE 0x0080
-#define CPER_MEM_VALID_ROW 0x0100
-#define CPER_MEM_VALID_COLUMN 0x0200
-#define CPER_MEM_VALID_BIT_POSITION 0x0400
-#define CPER_MEM_VALID_REQUESTOR_ID 0x0800
-#define CPER_MEM_VALID_RESPONDER_ID 0x1000
-#define CPER_MEM_VALID_TARGET_ID 0x2000
-#define CPER_MEM_VALID_ERROR_TYPE 0x4000
-#define CPER_MEM_VALID_RANK_NUMBER 0x8000
-#define CPER_MEM_VALID_CARD_HANDLE 0x10000
-#define CPER_MEM_VALID_MODULE_HANDLE 0x20000
-#define CPER_MEM_VALID_ROW_EXT 0x40000
-#define CPER_MEM_VALID_BANK_GROUP 0x80000
-#define CPER_MEM_VALID_BANK_ADDRESS 0x100000
-#define CPER_MEM_VALID_CHIP_ID 0x200000
+#define CPER_PROC_VALID_TYPE BIT_ULL(0)
+#define CPER_PROC_VALID_ISA BIT_ULL(1)
+#define CPER_PROC_VALID_ERROR_TYPE BIT_ULL(2)
+#define CPER_PROC_VALID_OPERATION BIT_ULL(3)
+#define CPER_PROC_VALID_FLAGS BIT_ULL(4)
+#define CPER_PROC_VALID_LEVEL BIT_ULL(5)
+#define CPER_PROC_VALID_VERSION BIT_ULL(6)
+#define CPER_PROC_VALID_BRAND_INFO BIT_ULL(7)
+#define CPER_PROC_VALID_ID BIT_ULL(8)
+#define CPER_PROC_VALID_TARGET_ADDRESS BIT_ULL(9)
+#define CPER_PROC_VALID_REQUESTOR_ID BIT_ULL(10)
+#define CPER_PROC_VALID_RESPONDER_ID BIT_ULL(11)
+#define CPER_PROC_VALID_IP BIT_ULL(12)
+
+#define CPER_MEM_VALID_ERROR_STATUS BIT_ULL(0)
+#define CPER_MEM_VALID_PA BIT_ULL(1)
+#define CPER_MEM_VALID_PA_MASK BIT_ULL(2)
+#define CPER_MEM_VALID_NODE BIT_ULL(3)
+#define CPER_MEM_VALID_CARD BIT_ULL(4)
+#define CPER_MEM_VALID_MODULE BIT_ULL(5)
+#define CPER_MEM_VALID_BANK BIT_ULL(6)
+#define CPER_MEM_VALID_DEVICE BIT_ULL(7)
+#define CPER_MEM_VALID_ROW BIT_ULL(8)
+#define CPER_MEM_VALID_COLUMN BIT_ULL(9)
+#define CPER_MEM_VALID_BIT_POSITION BIT_ULL(10)
+#define CPER_MEM_VALID_REQUESTOR_ID BIT_ULL(11)
+#define CPER_MEM_VALID_RESPONDER_ID BIT_ULL(12)
+#define CPER_MEM_VALID_TARGET_ID BIT_ULL(13)
+#define CPER_MEM_VALID_ERROR_TYPE BIT_ULL(14)
+#define CPER_MEM_VALID_RANK_NUMBER BIT_ULL(15)
+#define CPER_MEM_VALID_CARD_HANDLE BIT_ULL(16)
+#define CPER_MEM_VALID_MODULE_HANDLE BIT_ULL(17)
+#define CPER_MEM_VALID_ROW_EXT BIT_ULL(18)
+#define CPER_MEM_VALID_BANK_GROUP BIT_ULL(19)
+#define CPER_MEM_VALID_BANK_ADDRESS BIT_ULL(20)
+#define CPER_MEM_VALID_CHIP_ID BIT_ULL(21)
/* Memory Error Section 2 validation bits, UEFI v2.11 sec N.2.6. */
#define CPER_MEM2_VALID_ERROR_STATUS BIT_ULL(0)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/6] cper: add helpers to handle Memory Error Section 2
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (2 preceding siblings ...)
2026-10-19 14:56 ` [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 19:13 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
2026-10-19 14:56 ` [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Dan Williams, Terry Bowman,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
Add separate location and printing helpers for Memory Error
Section 2:
- cper_mem_err2_location()
- cper_dimm_err2_location()
- cper_print_mem2()
Similar functions/logic exists for Memory Error Section (1),
but require a compact version of the record. To avoid relying
and propagating a non-standard record format, the new functions
diretly rely on struct cper_sec_mem_err2.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/firmware/efi/cper.c | 108 ++++++++++++++++++++++++++++++++++++
include/linux/cper.h | 3 +
2 files changed, 111 insertions(+)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 06b4fdb59917..5c9b832b67a1 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -445,6 +445,106 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
printk("%s%s\n", pfx, rcd_decode_str);
}
+int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg)
+{
+ u32 len, n;
+
+ if (!msg)
+ return 0;
+
+ n = 0;
+ len = CPER_REC_LEN;
+ if (mem->validation_bits & CPER_MEM2_VALID_NODE)
+ n += scnprintf(msg + n, len - n, "node:%d ", mem->node);
+ if (mem->validation_bits & CPER_MEM2_VALID_CARD)
+ n += scnprintf(msg + n, len - n, "card:%d ", mem->card);
+ if (mem->validation_bits & CPER_MEM2_VALID_MODULE)
+ n += scnprintf(msg + n, len - n, "module:%d ", mem->module);
+ if (mem->validation_bits & CPER_MEM2_VALID_RANK_NUMBER)
+ n += scnprintf(msg + n, len - n, "rank:%u ", mem->rank);
+ if (mem->validation_bits & CPER_MEM2_VALID_BANK)
+ n += scnprintf(msg + n, len - n, "bank:%d ", mem->bank);
+ if (mem->validation_bits & CPER_MEM2_VALID_BANK_GROUP)
+ n += scnprintf(msg + n, len - n, "bank_group:%d ",
+ mem->bank >> CPER_MEM_BANK_GROUP_SHIFT);
+ if (mem->validation_bits & CPER_MEM2_VALID_BANK_ADDRESS)
+ n += scnprintf(msg + n, len - n, "bank_address:%d ",
+ mem->bank & CPER_MEM_BANK_ADDRESS_MASK);
+ if (mem->validation_bits & CPER_MEM2_VALID_DEVICE)
+ n += scnprintf(msg + n, len - n, "device:%u ", mem->device);
+ if (mem->validation_bits & CPER_MEM2_VALID_ROW)
+ n += scnprintf(msg + n, len - n, "row:%u ", mem->row);
+ if (mem->validation_bits & CPER_MEM2_VALID_COLUMN)
+ n += scnprintf(msg + n, len - n, "column:%u ", mem->column);
+ if (mem->validation_bits & CPER_MEM2_VALID_BIT_POSITION)
+ n += scnprintf(msg + n, len - n, "bit_position:%u ",
+ mem->bit_pos);
+ if (mem->validation_bits & CPER_MEM2_VALID_REQUESTOR_ID)
+ n += scnprintf(msg + n, len - n, "requestor_id:0x%016llx ",
+ mem->requestor_id);
+ if (mem->validation_bits & CPER_MEM2_VALID_RESPONDER_ID)
+ n += scnprintf(msg + n, len - n, "responder_id:0x%016llx ",
+ mem->responder_id);
+ if (mem->validation_bits & CPER_MEM2_VALID_TARGET_ID)
+ n += scnprintf(msg + n, len - n, "target_id:0x%016llx ",
+ mem->target_id);
+ if (mem->validation_bits & CPER_MEM2_VALID_CHIP_ID)
+ n += scnprintf(msg + n, len - n, "chip_id:%d ",
+ mem->chip_id);
+
+ return n;
+}
+EXPORT_SYMBOL_GPL(cper_mem_err2_location);
+
+int cper_dimm_err2_location(const struct cper_sec_mem_err2 *mem, char *msg)
+{
+ u32 len, n;
+ const char *bank = NULL, *device = NULL;
+
+ if (!msg || !(mem->validation_bits & CPER_MEM2_VALID_MODULE_HANDLE))
+ return 0;
+
+ len = CPER_REC_LEN;
+ /* SMBIOS handles are 16 bits; never truncate a Section 2 handle. */
+ if (mem->mem_dev_handle <= U16_MAX)
+ dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
+ else
+ pr_warn(FW_WARN "Memory Error Section 2 module handle 0x%x exceeds SMBIOS range\n",
+ mem->mem_dev_handle);
+ if (bank && device)
+ n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
+ else
+ n = snprintf(msg, len,
+ "DIMM location: not present. DMI handle: 0x%.8x ",
+ mem->mem_dev_handle);
+
+ return n;
+}
+EXPORT_SYMBOL_GPL(cper_dimm_err2_location);
+
+static void cper_print_mem2(const char *pfx, const struct cper_sec_mem_err2 *mem)
+{
+ char rcd_decode_str[CPER_REC_LEN];
+
+ if (mem->validation_bits & CPER_MEM2_VALID_ERROR_STATUS)
+ printk("%serror_status: %s (0x%016llx)\n", pfx,
+ cper_mem_err_status_str(mem->error_status), mem->error_status);
+ if (mem->validation_bits & CPER_MEM2_VALID_PA)
+ printk("%sphysical_address: 0x%016llx\n", pfx, mem->physical_addr);
+ if (mem->validation_bits & CPER_MEM2_VALID_PA_MASK)
+ printk("%sphysical_address_mask: 0x%016llx\n", pfx,
+ mem->physical_addr_mask);
+ if (cper_mem_err2_location(mem, rcd_decode_str))
+ printk("%s%s\n", pfx, rcd_decode_str);
+ if (mem->validation_bits & CPER_MEM2_VALID_ERROR_TYPE)
+ printk("%serror_type: %u, %s\n", pfx, mem->error_type,
+ cper_mem_err_type_str(mem->error_type));
+ if (mem->validation_bits & CPER_MEM2_VALID_STATUS)
+ printk("%sstatus: 0x%02x\n", pfx, mem->status);
+ if (cper_dimm_err2_location(mem, rcd_decode_str))
+ printk("%s%s\n", pfx, rcd_decode_str);
+}
+
static const char * const pcie_port_type_strs[] = {
"PCIe end point",
"legacy PCI end point",
@@ -650,6 +750,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
gdata->error_data_length);
else
goto err_section_too_small;
+ } else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM2)) {
+ struct cper_sec_mem_err2 *mem_err = acpi_hest_get_payload(gdata);
+
+ printk("%ssection_type: memory error 2\n", newpfx);
+ if (gdata->error_data_length >= sizeof(*mem_err))
+ cper_print_mem2(newpfx, mem_err);
+ else
+ goto err_section_too_small;
} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie = acpi_hest_get_payload(gdata);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index ed355b240685..a466cba4fd61 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -656,6 +656,9 @@ void cper_print_proc_ia(const char *pfx,
int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg);
int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg);
+int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg);
+int cper_dimm_err2_location(const struct cper_sec_mem_err2 *mem, char *msg);
+
struct acpi_hest_generic_status;
void cper_estatus_print(const char *pfx,
const struct acpi_hest_generic_status *estatus);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (3 preceding siblings ...)
2026-10-19 14:56 ` [PATCH 4/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 19:24 ` Jonathan Cameron
2026-10-19 14:56 ` [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Terry Bowman, Dan Williams,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
Add dedicated GHES and EDAC callbacks for Memory Error Section 2
records. Use a separate GHES notifier chain so existing consumers
continue to receive legacy memory error sections.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/acpi/apei/ghes.c | 49 ++++++++++++-
drivers/edac/ghes_edac.c | 150 +++++++++++++++++++++++++++++++++++++++
include/acpi/ghes.h | 2 +
3 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index fe10ab0e02f6..c7fb15543b56 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -101,6 +101,7 @@
#endif
static ATOMIC_NOTIFIER_HEAD(ghes_report_chain);
+static ATOMIC_NOTIFIER_HEAD(ghes_report_mem2_chain);
static inline bool is_hest_type_generic_v2(struct ghes *ghes)
{
@@ -551,6 +552,29 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
return false;
}
+static bool ghes_handle_memory_failure2(struct acpi_hest_generic_data *gdata,
+ int sev, bool sync)
+{
+ int flags = -1;
+ int sec_sev = ghes_severity(gdata->error_severity);
+ struct cper_sec_mem_err2 *mem_err = acpi_hest_get_payload(gdata);
+
+ if (!(mem_err->validation_bits & CPER_MEM2_VALID_PA))
+ return false;
+
+ /* iff following two events can be handled properly by now */
+ if (sec_sev == GHES_SEV_CORRECTED &&
+ (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED))
+ flags = MF_SOFT_OFFLINE;
+ if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE)
+ flags = sync ? MF_ACTION_REQUIRED : 0;
+
+ if (flags != -1)
+ return ghes_do_memory_failure(mem_err->physical_addr, flags);
+
+ return false;
+}
+
static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
int sev, bool sync)
{
@@ -915,7 +939,8 @@ static void ghes_log_hwerr(int sev, guid_t *sec_type)
return;
}
- if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
+ if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM) ||
+ guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM2)) {
hwerr_log_error_type(HWERR_RECOV_MEMORY);
return;
}
@@ -952,6 +977,16 @@ static void ghes_do_proc(struct ghes *ghes,
arch_apei_report_mem_error(sev, mem_err);
queued = ghes_handle_memory_failure(gdata, sev, sync);
+ } else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM2)) {
+ struct cper_sec_mem_err2 *mem_err = acpi_hest_get_payload(gdata);
+
+ if (gdata->error_data_length < sizeof(*mem_err)) {
+ pr_warn(FW_WARN "Memory Error Section 2 length is too small\n");
+ continue;
+ }
+
+ atomic_notifier_call_chain(&ghes_report_mem2_chain, sev, mem_err);
+ queued = ghes_handle_memory_failure2(gdata, sev, sync);
} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
ghes_handle_aer(gdata);
} else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
@@ -1973,3 +2008,15 @@ void ghes_unregister_report_chain(struct notifier_block *nb)
atomic_notifier_chain_unregister(&ghes_report_chain, nb);
}
EXPORT_SYMBOL_GPL(ghes_unregister_report_chain);
+
+void ghes_register_report_mem2_chain(struct notifier_block *nb)
+{
+ atomic_notifier_chain_register(&ghes_report_mem2_chain, nb);
+}
+EXPORT_SYMBOL_GPL(ghes_register_report_mem2_chain);
+
+void ghes_unregister_report_mem2_chain(struct notifier_block *nb)
+{
+ atomic_notifier_chain_unregister(&ghes_report_mem2_chain, nb);
+}
+EXPORT_SYMBOL_GPL(ghes_unregister_report_mem2_chain);
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index d80c88818691..b18460ba8f40 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -386,6 +386,154 @@ static struct notifier_block ghes_edac_mem_err_nb = {
.priority = 0,
};
+static int print_mem_error2_other_detail(const struct cper_sec_mem_err2 *mem, char *msg,
+ const char *location, unsigned int len)
+{
+ u32 n;
+
+ if (!msg)
+ return 0;
+
+ n = 0;
+ len -= 1;
+
+ n += scnprintf(msg + n, len - n, "APEI location: %s ", location);
+
+ if (mem->validation_bits & CPER_MEM2_VALID_ERROR_STATUS) {
+ n += scnprintf(msg + n, len - n, "status(0x%016llx): ", mem->error_status);
+ n += scnprintf(msg + n, len - n, "%s ",
+ cper_mem_err_status_str(mem->error_status));
+ }
+ if (mem->validation_bits & CPER_MEM2_VALID_STATUS)
+ n += scnprintf(msg + n, len - n, "section_status:0x%02x ",
+ mem->status);
+
+ msg[n] = '\0';
+
+ return n;
+}
+
+static int ghes_edac_report_mem_error2(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cper_sec_mem_err2 *mem_err = data;
+ struct edac_raw_error_desc *e;
+ struct mem_ctl_info *mci;
+ unsigned long sev = val;
+ struct ghes_pvt *pvt;
+ unsigned long flags;
+ char *p;
+
+ /*
+ * We can do the locking below because GHES defers error processing
+ * from NMI to IRQ context. Whenever that changes, we'd at least
+ * know.
+ */
+ if (WARN_ON_ONCE(in_nmi()))
+ return NOTIFY_OK;
+
+ spin_lock_irqsave(&ghes_lock, flags);
+
+ pvt = ghes_pvt;
+ if (!pvt)
+ goto unlock;
+
+ mci = pvt->mci;
+ e = &mci->error_desc;
+
+ /* Cleans the error report buffer */
+ memset(e, 0, sizeof(*e));
+ e->error_count = 1;
+ e->grain = 1;
+ e->msg = pvt->msg;
+ e->other_detail = pvt->other_detail;
+ e->top_layer = -1;
+ e->mid_layer = -1;
+ e->low_layer = -1;
+ *pvt->other_detail = '\0';
+ *pvt->msg = '\0';
+
+ switch (sev) {
+ case GHES_SEV_CORRECTED:
+ e->type = HW_EVENT_ERR_CORRECTED;
+ break;
+ case GHES_SEV_RECOVERABLE:
+ e->type = HW_EVENT_ERR_UNCORRECTED;
+ break;
+ case GHES_SEV_PANIC:
+ e->type = HW_EVENT_ERR_FATAL;
+ break;
+ default:
+ case GHES_SEV_NO:
+ e->type = HW_EVENT_ERR_INFO;
+ }
+
+ edac_dbg(1, "error validation_bits: 0x%08llx\n",
+ (long long)mem_err->validation_bits);
+
+ /* Error type, mapped on e->msg */
+ if (mem_err->validation_bits & CPER_MEM2_VALID_ERROR_TYPE) {
+ u8 etype = mem_err->error_type;
+
+ p = pvt->msg;
+ p += snprintf(p, sizeof(pvt->msg), "%s", cper_mem_err_type_str(etype));
+ } else {
+ strscpy(pvt->msg, "unknown error");
+ }
+
+ /* Error address */
+ if (mem_err->validation_bits & CPER_MEM2_VALID_PA) {
+ e->page_frame_number = PHYS_PFN(mem_err->physical_addr);
+ e->offset_in_page = offset_in_page(mem_err->physical_addr);
+ }
+
+ /* Error grain */
+ if (mem_err->validation_bits & CPER_MEM2_VALID_PA_MASK)
+ e->grain = ~mem_err->physical_addr_mask + 1;
+
+ /* Memory error location, mapped on e->location */
+ p = e->location;
+ p += cper_mem_err2_location(mem_err, p);
+
+ if (mem_err->validation_bits & CPER_MEM2_VALID_MODULE_HANDLE) {
+ struct dimm_info *dimm = NULL;
+
+ p += cper_dimm_err2_location(mem_err, p);
+ if (mem_err->mem_dev_handle <= U16_MAX)
+ dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);
+ else
+ pr_warn(FW_WARN "Memory Error Section 2 module handle 0x%x exceeds SMBIOS range\n",
+ mem_err->mem_dev_handle);
+ if (dimm) {
+ e->top_layer = dimm->idx;
+ strscpy(e->label, dimm->label);
+ }
+ }
+ if (p > e->location)
+ *(p - 1) = '\0';
+
+ if (!*e->label)
+ strscpy(e->label, "unknown memory");
+
+ /* All other fields are mapped on e->other_detail */
+ p = pvt->other_detail;
+ p += print_mem_error2_other_detail(mem_err, p, e->location, OTHER_DETAIL_LEN);
+ if (p > pvt->other_detail)
+ *(p - 1) = '\0';
+
+ edac_raw_mc_handle_error(e);
+
+unlock:
+ spin_unlock_irqrestore(&ghes_lock, flags);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block ghes_edac_mem_err2_nb = {
+ .notifier_call = ghes_edac_report_mem_error2,
+ .priority = 0,
+};
+
static int ghes_edac_register(struct device *dev)
{
bool fake = false;
@@ -490,6 +638,7 @@ static int ghes_edac_register(struct device *dev)
spin_unlock_irqrestore(&ghes_lock, flags);
ghes_register_report_chain(&ghes_edac_mem_err_nb);
+ ghes_register_report_mem2_chain(&ghes_edac_mem_err2_nb);
/* only set on success */
refcount_set(&ghes_refcount, 1);
@@ -533,6 +682,7 @@ static void ghes_edac_unregister(struct ghes *ghes)
if (mci)
edac_mc_free(mci);
+ ghes_unregister_report_mem2_chain(&ghes_edac_mem_err2_nb);
ghes_unregister_report_chain(&ghes_edac_mem_err_nb);
unlock:
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 8d7e5caef3f1..73d099a4ea7d 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -143,4 +143,6 @@ static inline int ghes_notify_sea(void) { return -ENOENT; }
struct notifier_block;
extern void ghes_register_report_chain(struct notifier_block *nb);
extern void ghes_unregister_report_chain(struct notifier_block *nb);
+extern void ghes_register_report_mem2_chain(struct notifier_block *nb);
+extern void ghes_unregister_report_mem2_chain(struct notifier_block *nb);
#endif /* GHES_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (4 preceding siblings ...)
2026-10-19 14:56 ` [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
@ 2026-10-19 14:56 ` Pierre Gondois
2026-10-19 19:28 ` Jonathan Cameron
5 siblings, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 14:56 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Jonathan Cameron, Dave Jiang,
Fabio M. De Francesco, Breno Leitao, Dan Williams, Terry Bowman,
Ard Biesheuvel, Morduan Zang, linux-acpi, linux-edac,
acpica-devel
Add a separte handling for Memory Error Section 2 trace events with:
- extlog_mem2_event()
- extlog_mem2 trace event
The fields of the record are individually printed so userspace
can discover the layout more dynamically if a new field is added.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/acpi/acpi_extlog.c | 16 ++++++
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 102 +++++++++++++++++++++++++++++++++++++
3 files changed, 119 insertions(+)
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index e764d61f71ca..9c0b932e22bc 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -189,6 +189,15 @@ extlog_mem_err_event(struct cper_sec_mem_err *mem, u32 err_seq,
#endif
}
+static void
+extlog_mem_err2_event(struct cper_sec_mem_err2 *mem, u32 err_seq,
+ const guid_t *fru_id, const char *fru_text, u8 sev)
+{
+#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
+ trace_extlog_mem2_event(mem, err_seq, fru_id, fru_text, sev);
+#endif
+}
+
static int extlog_print(struct notifier_block *nb, unsigned long val,
void *data)
{
@@ -241,6 +250,13 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
extlog_mem_err_event(mem, err_seq, fru_id,
fru_text,
(u8)gdata->error_severity);
+ } else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM2)) {
+ struct cper_sec_mem_err2 *mem = acpi_hest_get_payload(gdata);
+
+ if (gdata->error_data_length >= sizeof(*mem))
+ extlog_mem_err2_event(mem, err_seq, fru_id,
+ fru_text,
+ (u8)gdata->error_severity);
} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
struct cxl_cper_sec_prot_err *prot_err =
acpi_hest_get_payload(gdata);
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index 03df3db62334..c6b14202a5e9 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -111,6 +111,7 @@ subsys_initcall(ras_init);
#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
+EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem2_event);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(non_standard_event);
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index fdb785fa4613..0c0dbe068dc8 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -74,6 +74,108 @@ TRACE_EVENT(extlog_mem_event,
&__entry->fru_id,
__get_str(fru_text))
);
+
+/*
+ * Memory Error Section 2 exposes each field separately so userspace can
+ * discover its layout. Validation bits use the UEFI Section 2 assignments.
+ */
+TRACE_EVENT(extlog_mem2_event,
+ TP_PROTO(const struct cper_sec_mem_err2 *mem,
+ u32 err_seq,
+ const guid_t *fru_id,
+ const char *fru_text,
+ u8 sev),
+
+ TP_ARGS(mem, err_seq, fru_id, fru_text, sev),
+
+ TP_STRUCT__entry(
+ __field(u32, err_seq)
+ __field(u8, sev)
+ __field_struct(guid_t, fru_id)
+ __string(fru_text, fru_text)
+ __field(u64, validation_bits)
+ __field(u64, error_status)
+ __field(u64, physical_addr)
+ __field(u64, physical_addr_mask)
+ __field(u16, node)
+ __field(u16, card)
+ __field(u16, module)
+ __field(u16, bank)
+ __field(u32, device)
+ __field(u32, row)
+ __field(u32, column)
+ __field(u32, rank)
+ __field(u32, bit_pos)
+ __field(u8, chip_id)
+ __field(u8, error_type)
+ __field(u8, status)
+ __field(u64, requestor_id)
+ __field(u64, responder_id)
+ __field(u64, target_id)
+ __field(u32, mem_array_handle)
+ __field(u32, mem_dev_handle)
+ ),
+
+ TP_fast_assign(
+ __entry->err_seq = err_seq;
+ __entry->sev = sev;
+ __entry->fru_id = *fru_id;
+ __assign_str(fru_text);
+ __entry->validation_bits = mem->validation_bits;
+ __entry->error_status = mem->error_status;
+ __entry->physical_addr = mem->physical_addr;
+ __entry->physical_addr_mask = mem->physical_addr_mask;
+ __entry->node = mem->node;
+ __entry->card = mem->card;
+ __entry->module = mem->module;
+ __entry->bank = mem->bank;
+ __entry->device = mem->device;
+ __entry->row = mem->row;
+ __entry->column = mem->column;
+ __entry->rank = mem->rank;
+ __entry->bit_pos = mem->bit_pos;
+ __entry->chip_id = mem->chip_id;
+ __entry->error_type = mem->error_type;
+ __entry->status = mem->status;
+ __entry->requestor_id = mem->requestor_id;
+ __entry->responder_id = mem->responder_id;
+ __entry->target_id = mem->target_id;
+ __entry->mem_array_handle = mem->mem_array_handle;
+ __entry->mem_dev_handle = mem->mem_dev_handle;
+ ),
+
+ TP_printk("{%u} %s error: validation_bits: 0x%llx "
+ "error_status: 0x%llx physical_addr: 0x%llx "
+ "physical_addr_mask: 0x%llx node: %u card: %u "
+ "module: %u bank: %u device: %u row: %u column: %u "
+ "rank: %u bit_pos: %u chip_id: %u error_type: %u "
+ "status: 0x%x requestor_id: 0x%llx responder_id: 0x%llx "
+ "target_id: 0x%llx mem_array_handle: 0x%x "
+ "mem_dev_handle: 0x%x FRU: %pUl %.20s",
+ __entry->err_seq, cper_severity_str(__entry->sev),
+ __entry->validation_bits,
+ __entry->error_status,
+ __entry->physical_addr,
+ __entry->physical_addr_mask,
+ __entry->node,
+ __entry->card,
+ __entry->module,
+ __entry->bank,
+ __entry->device,
+ __entry->row,
+ __entry->column,
+ __entry->rank,
+ __entry->bit_pos,
+ __entry->chip_id,
+ __entry->error_type,
+ __entry->status,
+ __entry->requestor_id,
+ __entry->responder_id,
+ __entry->target_id,
+ __entry->mem_array_handle,
+ __entry->mem_dev_handle,
+ &__entry->fru_id, __get_str(fru_text))
+);
#endif
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue
2026-10-19 14:56 ` [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue Pierre Gondois
@ 2026-10-19 16:36 ` Jonathan Cameron
2026-10-19 17:55 ` Pierre Gondois
0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 16:36 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Terry Bowman, Dan Williams, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:08 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> With CONFIG_ACPI_EXTLOG=n and with the following command:
> make -j4 drivers/acpi/acpi_extlog.o drivers/acpi/
>
> trace_extlog_mem_event() is not defined. Add a extlog_mem_err_event()
> wrapper to fix the build issue.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
I'm lost. This file is normally only built if
CONFIG_ACPI_EXTLOG is not = "n" so how do you get to this code.
Ah you are forcing build of a file...
If you do need to do this sort of ifdefery it belongs in a header with
the function cleanly stubbed rather than in here.
Anyhow, far as I can tell this doesn't make any sense for
upstream.
J
> ---
> drivers/acpi/acpi_extlog.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
> index 7ad3b36013cc..e764d61f71ca 100644
> --- a/drivers/acpi/acpi_extlog.c
> +++ b/drivers/acpi/acpi_extlog.c
> @@ -180,6 +180,15 @@ extlog_cxl_cper_handle_prot_err(struct cxl_cper_sec_prot_err *prot_err,
> #endif
> }
>
> +static void
> +extlog_mem_err_event(struct cper_sec_mem_err *mem, u32 err_seq,
> + const guid_t *fru_id, const char *fru_text, u8 sev)
> +{
> +#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
> + trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, sev);
> +#endif
> +}
> +
> static int extlog_print(struct notifier_block *nb, unsigned long val,
> void *data)
> {
> @@ -229,8 +238,9 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
> struct cper_sec_mem_err *mem = acpi_hest_get_payload(gdata);
>
> if (gdata->error_data_length >= sizeof(*mem))
> - trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
> - (u8)gdata->error_severity);
> + extlog_mem_err_event(mem, err_seq, fru_id,
> + fru_text,
> + (u8)gdata->error_severity);
> } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
> struct cxl_cper_sec_prot_err *prot_err =
> acpi_hest_get_payload(gdata);
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue
2026-10-19 16:36 ` Jonathan Cameron
@ 2026-10-19 17:55 ` Pierre Gondois
0 siblings, 0 replies; 14+ messages in thread
From: Pierre Gondois @ 2026-10-19 17:55 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Terry Bowman, Dan Williams, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On 10/19/26 18:36, Jonathan Cameron wrote:
> On Mon, 19 Oct 2026 16:56:08 +0200
> Pierre Gondois <pierre.gondois@arm.com> wrote:
>
>> With CONFIG_ACPI_EXTLOG=n and with the following command:
>> make -j4 drivers/acpi/acpi_extlog.o drivers/acpi/
>>
>> trace_extlog_mem_event() is not defined. Add a extlog_mem_err_event()
>> wrapper to fix the build issue.
>>
>> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> I'm lost. This file is normally only built if
> CONFIG_ACPI_EXTLOG is not = "n" so how do you get to this code.
> Ah you are forcing build of a file...
>
> If you do need to do this sort of ifdefery it belongs in a header with
> the function cleanly stubbed rather than in here.
>
> Anyhow, far as I can tell this doesn't make any sense for
> upstream.
>
> J
Ok sure this will be dropped.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/6] cper: add Memory Error Section 2 structures
2026-10-19 14:56 ` [PATCH 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
@ 2026-10-19 18:16 ` Jonathan Cameron
0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 18:16 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Dan Williams, Terry Bowman, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:09 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Add CPER Memory Error Section 2 definitions to the CPER headers.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Checked against spec and the couple of commented names
that differ make sense to me.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits
2026-10-19 14:56 ` [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
@ 2026-10-19 18:21 ` Jonathan Cameron
0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 18:21 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Dan Williams, Terry Bowman, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:10 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Use the BIT_ULL() macro to describe flag bits instead of
> hexadecimal values which are harder to read.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Nice.
I'd do this before the previous patch, but not particularly important.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/6] cper: add helpers to handle Memory Error Section 2
2026-10-19 14:56 ` [PATCH 4/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
@ 2026-10-19 19:13 ` Jonathan Cameron
0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 19:13 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Dan Williams, Terry Bowman, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:11 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Add separate location and printing helpers for Memory Error
> Section 2:
> - cper_mem_err2_location()
> - cper_dimm_err2_location()
> - cper_print_mem2()
>
> Similar functions/logic exists for Memory Error Section (1),
> but require a compact version of the record. To avoid relying
> and propagating a non-standard record format, the new functions
> diretly rely on struct cper_sec_mem_err2.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
A few comments but they are about spec confusion or trivial.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
> ---
> drivers/firmware/efi/cper.c | 108 ++++++++++++++++++++++++++++++++++++
> include/linux/cper.h | 3 +
> 2 files changed, 111 insertions(+)
>
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index 06b4fdb59917..5c9b832b67a1 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -445,6 +445,106 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
> printk("%s%s\n", pfx, rcd_decode_str);
> }
>
> +int cper_mem_err2_location(const struct cper_sec_mem_err2 *mem, char *msg)
> +{
> + u32 len, n;
> +
> + if (!msg)
> + return 0;
> +
> + n = 0;
> + len = CPER_REC_LEN;
> + if (mem->validation_bits & CPER_MEM2_VALID_NODE)
> + n += scnprintf(msg + n, len - n, "node:%d ", mem->node);
> + if (mem->validation_bits & CPER_MEM2_VALID_CARD)
> + n += scnprintf(msg + n, len - n, "card:%d ", mem->card);
> + if (mem->validation_bits & CPER_MEM2_VALID_MODULE)
> + n += scnprintf(msg + n, len - n, "module:%d ", mem->module);
> + if (mem->validation_bits & CPER_MEM2_VALID_RANK_NUMBER)
> + n += scnprintf(msg + n, len - n, "rank:%u ", mem->rank);
> + if (mem->validation_bits & CPER_MEM2_VALID_BANK)
> + n += scnprintf(msg + n, len - n, "bank:%d ", mem->bank);
> + if (mem->validation_bits & CPER_MEM2_VALID_BANK_GROUP)
> + n += scnprintf(msg + n, len - n, "bank_group:%d ",
> + mem->bank >> CPER_MEM_BANK_GROUP_SHIFT);
> + if (mem->validation_bits & CPER_MEM2_VALID_BANK_ADDRESS)
> + n += scnprintf(msg + n, len - n, "bank_address:%d ",
> + mem->bank & CPER_MEM_BANK_ADDRESS_MASK);
I guess this makes sense. I couldn't figure out from the spec if there
are rules that say whether expected that VALID_BANK is not set when
VALID_BANK_GROUP and/or VALID_BANK_ADDRESS are set.
Safer to just over print than read stuff into the spec that isn't there.
> + if (mem->validation_bits & CPER_MEM2_VALID_DEVICE)
> + n += scnprintf(msg + n, len - n, "device:%u ", mem->device);
> + if (mem->validation_bits & CPER_MEM2_VALID_ROW)
> + n += scnprintf(msg + n, len - n, "row:%u ", mem->row);
> + if (mem->validation_bits & CPER_MEM2_VALID_COLUMN)
> + n += scnprintf(msg + n, len - n, "column:%u ", mem->column);
> + if (mem->validation_bits & CPER_MEM2_VALID_BIT_POSITION)
> + n += scnprintf(msg + n, len - n, "bit_position:%u ",
> + mem->bit_pos);
> + if (mem->validation_bits & CPER_MEM2_VALID_REQUESTOR_ID)
> + n += scnprintf(msg + n, len - n, "requestor_id:0x%016llx ",
> + mem->requestor_id);
> + if (mem->validation_bits & CPER_MEM2_VALID_RESPONDER_ID)
> + n += scnprintf(msg + n, len - n, "responder_id:0x%016llx ",
> + mem->responder_id);
> + if (mem->validation_bits & CPER_MEM2_VALID_TARGET_ID)
> + n += scnprintf(msg + n, len - n, "target_id:0x%016llx ",
> + mem->target_id);
> + if (mem->validation_bits & CPER_MEM2_VALID_CHIP_ID)
> + n += scnprintf(msg + n, len - n, "chip_id:%d ",
> + mem->chip_id);
> +
> + return n;
> +}
> +EXPORT_SYMBOL_GPL(cper_mem_err2_location);
> +
> +int cper_dimm_err2_location(const struct cper_sec_mem_err2 *mem, char *msg)
> +{
> + u32 len, n;
> + const char *bank = NULL, *device = NULL;
> +
> + if (!msg || !(mem->validation_bits & CPER_MEM2_VALID_MODULE_HANDLE))
> + return 0;
> +
> + len = CPER_REC_LEN;
I'd move this to...
> + /* SMBIOS handles are 16 bits; never truncate a Section 2 handle. */
> + if (mem->mem_dev_handle <= U16_MAX)
> + dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
> + else
> + pr_warn(FW_WARN "Memory Error Section 2 module handle 0x%x exceeds SMBIOS range\n",
> + mem->mem_dev_handle);
here just because it isn't used until down here.
> + if (bank && device)
> + n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
> + else
> + n = snprintf(msg, len,
> + "DIMM location: not present. DMI handle: 0x%.8x ",
> + mem->mem_dev_handle);
> +
> + return n;
> +}
> +EXPORT_SYMBOL_GPL(cper_dimm_err2_location);
> +
> +static void cper_print_mem2(const char *pfx, const struct cper_sec_mem_err2 *mem)
> +{
> + char rcd_decode_str[CPER_REC_LEN];
> +
> + if (mem->validation_bits & CPER_MEM2_VALID_ERROR_STATUS)
> + printk("%serror_status: %s (0x%016llx)\n", pfx,
> + cper_mem_err_status_str(mem->error_status), mem->error_status);
> + if (mem->validation_bits & CPER_MEM2_VALID_PA)
> + printk("%sphysical_address: 0x%016llx\n", pfx, mem->physical_addr);
> + if (mem->validation_bits & CPER_MEM2_VALID_PA_MASK)
> + printk("%sphysical_address_mask: 0x%016llx\n", pfx,
> + mem->physical_addr_mask);
> + if (cper_mem_err2_location(mem, rcd_decode_str))
> + printk("%s%s\n", pfx, rcd_decode_str);
> + if (mem->validation_bits & CPER_MEM2_VALID_ERROR_TYPE)
> + printk("%serror_type: %u, %s\n", pfx, mem->error_type,
> + cper_mem_err_type_str(mem->error_type));
> + if (mem->validation_bits & CPER_MEM2_VALID_STATUS)
> + printk("%sstatus: 0x%02x\n", pfx, mem->status);
> + if (cper_dimm_err2_location(mem, rcd_decode_str))
> + printk("%s%s\n", pfx, rcd_decode_str);
> +}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers
2026-10-19 14:56 ` [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
@ 2026-10-19 19:24 ` Jonathan Cameron
0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 19:24 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Terry Bowman, Dan Williams, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:12 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Add dedicated GHES and EDAC callbacks for Memory Error Section 2
> records. Use a separate GHES notifier chain so existing consumers
> continue to receive legacy memory error sections.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
A few trivial things inline.
Otherwise I'm fine with this though as you noted before the duplicating
is a bit annoying.
> ---
> drivers/acpi/apei/ghes.c | 49 ++++++++++++-
> drivers/edac/ghes_edac.c | 150 +++++++++++++++++++++++++++++++++++++++
> include/acpi/ghes.h | 2 +
> 3 files changed, 200 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index fe10ab0e02f6..c7fb15543b56 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
> index d80c88818691..b18460ba8f40 100644
> --- a/drivers/edac/ghes_edac.c
> +++ b/drivers/edac/ghes_edac.c
> +
> +static int ghes_edac_report_mem_error2(struct notifier_block *nb,
> + unsigned long val, void *data)
> +{
> + struct cper_sec_mem_err2 *mem_err = data;
> + struct edac_raw_error_desc *e;
> + struct mem_ctl_info *mci;
> + unsigned long sev = val;
> + struct ghes_pvt *pvt;
> + unsigned long flags;
> + char *p;
> +
> + /*
> + * We can do the locking below because GHES defers error processing
> + * from NMI to IRQ context. Whenever that changes, we'd at least
> + * know.
> + */
> + if (WARN_ON_ONCE(in_nmi()))
> + return NOTIFY_OK;
> +
> + spin_lock_irqsave(&ghes_lock, flags);
Perhaps use a guard so you can simplify error paths a little.
> +
> + pvt = ghes_pvt;
> + if (!pvt)
> + goto unlock;
> +
> + mci = pvt->mci;
> + e = &mci->error_desc;
> +
> + /* Cleans the error report buffer */
> + memset(e, 0, sizeof(*e));
> + e->error_count = 1;
> + e->grain = 1;
> + e->msg = pvt->msg;
> + e->other_detail = pvt->other_detail;
> + e->top_layer = -1;
> + e->mid_layer = -1;
> + e->low_layer = -1;
> + *pvt->other_detail = '\0';
> + *pvt->msg = '\0';
> +
> + switch (sev) {
> + case GHES_SEV_CORRECTED:
> + e->type = HW_EVENT_ERR_CORRECTED;
> + break;
> + case GHES_SEV_RECOVERABLE:
> + e->type = HW_EVENT_ERR_UNCORRECTED;
> + break;
> + case GHES_SEV_PANIC:
> + e->type = HW_EVENT_ERR_FATAL;
> + break;
> + default:
> + case GHES_SEV_NO:
> + e->type = HW_EVENT_ERR_INFO;
> + }
> +
Almost everything down to here is not memerr2 specific maybe factor
out an initialization helper for the edac structure?
> + edac_dbg(1, "error validation_bits: 0x%08llx\n",
> + (long long)mem_err->validation_bits);
> +
> + /* Error type, mapped on e->msg */
> + if (mem_err->validation_bits & CPER_MEM2_VALID_ERROR_TYPE) {
> + u8 etype = mem_err->error_type;
> +
> + p = pvt->msg;
> + p += snprintf(p, sizeof(pvt->msg), "%s", cper_mem_err_type_str(etype));
> + } else {
> + strscpy(pvt->msg, "unknown error");
> + }
> +
> + /* Error address */
> + if (mem_err->validation_bits & CPER_MEM2_VALID_PA) {
> + e->page_frame_number = PHYS_PFN(mem_err->physical_addr);
> + e->offset_in_page = offset_in_page(mem_err->physical_addr);
> + }
> +
> + /* Error grain */
> + if (mem_err->validation_bits & CPER_MEM2_VALID_PA_MASK)
> + e->grain = ~mem_err->physical_addr_mask + 1;
> +
> + /* Memory error location, mapped on e->location */
> + p = e->location;
> + p += cper_mem_err2_location(mem_err, p);
> +
> + if (mem_err->validation_bits & CPER_MEM2_VALID_MODULE_HANDLE) {
> + struct dimm_info *dimm = NULL;
> +
> + p += cper_dimm_err2_location(mem_err, p);
> + if (mem_err->mem_dev_handle <= U16_MAX)
> + dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);
> + else
> + pr_warn(FW_WARN "Memory Error Section 2 module handle 0x%x exceeds SMBIOS range\n",
> + mem_err->mem_dev_handle);
> + if (dimm) {
> + e->top_layer = dimm->idx;
> + strscpy(e->label, dimm->label);
> + }
> + }
> + if (p > e->location)
> + *(p - 1) = '\0';
> +
> + if (!*e->label)
> + strscpy(e->label, "unknown memory");
> +
> + /* All other fields are mapped on e->other_detail */
> + p = pvt->other_detail;
> + p += print_mem_error2_other_detail(mem_err, p, e->location, OTHER_DETAIL_LEN);
> + if (p > pvt->other_detail)
> + *(p - 1) = '\0';
> +
> + edac_raw_mc_handle_error(e);
> +
> +unlock:
> + spin_unlock_irqrestore(&ghes_lock, flags);
> +
> + return NOTIFY_OK;
> +}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event
2026-10-19 14:56 ` [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
@ 2026-10-19 19:28 ` Jonathan Cameron
0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2026-10-19 19:28 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Maciej Wieczor-Retman,
Pawel Chmielewski, Dave Jiang, Fabio M. De Francesco,
Breno Leitao, Dan Williams, Terry Bowman, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On Mon, 19 Oct 2026 16:56:13 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Add a separte handling for Memory Error Section 2 trace events with:
> - extlog_mem2_event()
> - extlog_mem2 trace event
> The fields of the record are individually printed so userspace
> can discover the layout more dynamically if a new field is added.
How useful are the pair of handles?
Otherwise I'm fine with this - subject to same comment as on patch 1.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/acpi/acpi_extlog.c | 16 ++++++
> drivers/ras/ras.c | 1 +
> include/ras/ras_event.h | 102 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 119 insertions(+)
>
> diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
> index e764d61f71ca..9c0b932e22bc 100644
> --- a/drivers/acpi/acpi_extlog.c
> +++ b/drivers/acpi/acpi_extlog.c
> @@ -189,6 +189,15 @@ extlog_mem_err_event(struct cper_sec_mem_err *mem, u32 err_seq,
> #endif
> }
>
> +static void
> +extlog_mem_err2_event(struct cper_sec_mem_err2 *mem, u32 err_seq,
> + const guid_t *fru_id, const char *fru_text, u8 sev)
> +{
> +#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
Same comment as earlier patch about oddity of protecting stuff in a file
that is normally only built if they are set.
> + trace_extlog_mem2_event(mem, err_seq, fru_id, fru_text, sev);
> +#endif
> +}
> +
> static int extlog_print(struct notifier_block *nb, unsigned long val,
> void *data)
> {
> @@ -241,6 +250,13 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
> extlog_mem_err_event(mem, err_seq, fru_id,
> fru_text,
> (u8)gdata->error_severity);
> + } else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM2)) {
> + struct cper_sec_mem_err2 *mem = acpi_hest_get_payload(gdata);
> +
> + if (gdata->error_data_length >= sizeof(*mem))
> + extlog_mem_err2_event(mem, err_seq, fru_id,
> + fru_text,
> + (u8)gdata->error_severity);
> } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
> struct cxl_cper_sec_prot_err *prot_err =
> acpi_hest_get_payload(gdata);
> diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
> index 03df3db62334..c6b14202a5e9 100644
> --- a/drivers/ras/ras.c
> +++ b/drivers/ras/ras.c
> @@ -111,6 +111,7 @@ subsys_initcall(ras_init);
>
> #if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
> EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem2_event);
> #endif
> EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
> EXPORT_TRACEPOINT_SYMBOL_GPL(non_standard_event);
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index fdb785fa4613..0c0dbe068dc8 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -74,6 +74,108 @@ TRACE_EVENT(extlog_mem_event,
> &__entry->fru_id,
> __get_str(fru_text))
> );
> +
> +/*
> + * Memory Error Section 2 exposes each field separately so userspace can
> + * discover its layout. Validation bits use the UEFI Section 2 assignments.
> + */
> +TRACE_EVENT(extlog_mem2_event,
> + TP_PROTO(const struct cper_sec_mem_err2 *mem,
> + u32 err_seq,
> + const guid_t *fru_id,
> + const char *fru_text,
> + u8 sev),
> +
> + TP_ARGS(mem, err_seq, fru_id, fru_text, sev),
> +
> + TP_STRUCT__entry(
> + __field(u32, err_seq)
> + __field(u8, sev)
> + __field_struct(guid_t, fru_id)
> + __string(fru_text, fru_text)
> + __field(u64, validation_bits)
> + __field(u64, error_status)
> + __field(u64, physical_addr)
> + __field(u64, physical_addr_mask)
> + __field(u16, node)
> + __field(u16, card)
> + __field(u16, module)
> + __field(u16, bank)
> + __field(u32, device)
> + __field(u32, row)
> + __field(u32, column)
> + __field(u32, rank)
> + __field(u32, bit_pos)
> + __field(u8, chip_id)
> + __field(u8, error_type)
> + __field(u8, status)
> + __field(u64, requestor_id)
> + __field(u64, responder_id)
> + __field(u64, target_id)
> + __field(u32, mem_array_handle)
> + __field(u32, mem_dev_handle)
> + ),
> +
> + TP_fast_assign(
> + __entry->err_seq = err_seq;
> + __entry->sev = sev;
> + __entry->fru_id = *fru_id;
> + __assign_str(fru_text);
> + __entry->validation_bits = mem->validation_bits;
> + __entry->error_status = mem->error_status;
> + __entry->physical_addr = mem->physical_addr;
> + __entry->physical_addr_mask = mem->physical_addr_mask;
> + __entry->node = mem->node;
> + __entry->card = mem->card;
> + __entry->module = mem->module;
> + __entry->bank = mem->bank;
> + __entry->device = mem->device;
> + __entry->row = mem->row;
> + __entry->column = mem->column;
> + __entry->rank = mem->rank;
> + __entry->bit_pos = mem->bit_pos;
> + __entry->chip_id = mem->chip_id;
> + __entry->error_type = mem->error_type;
> + __entry->status = mem->status;
> + __entry->requestor_id = mem->requestor_id;
> + __entry->responder_id = mem->responder_id;
> + __entry->target_id = mem->target_id;
> + __entry->mem_array_handle = mem->mem_array_handle;
> + __entry->mem_dev_handle = mem->mem_dev_handle;
> + ),
> +
> + TP_printk("{%u} %s error: validation_bits: 0x%llx "
> + "error_status: 0x%llx physical_addr: 0x%llx "
> + "physical_addr_mask: 0x%llx node: %u card: %u "
> + "module: %u bank: %u device: %u row: %u column: %u "
> + "rank: %u bit_pos: %u chip_id: %u error_type: %u "
> + "status: 0x%x requestor_id: 0x%llx responder_id: 0x%llx "
> + "target_id: 0x%llx mem_array_handle: 0x%x "
> + "mem_dev_handle: 0x%x FRU: %pUl %.20s",
> + __entry->err_seq, cper_severity_str(__entry->sev),
> + __entry->validation_bits,
> + __entry->error_status,
> + __entry->physical_addr,
> + __entry->physical_addr_mask,
> + __entry->node,
> + __entry->card,
> + __entry->module,
> + __entry->bank,
> + __entry->device,
> + __entry->row,
> + __entry->column,
> + __entry->rank,
> + __entry->bit_pos,
> + __entry->chip_id,
> + __entry->error_type,
> + __entry->status,
> + __entry->requestor_id,
> + __entry->responder_id,
> + __entry->target_id,
> + __entry->mem_array_handle,
> + __entry->mem_dev_handle,
> + &__entry->fru_id, __get_str(fru_text))
> +);
> #endif
>
> /*
> --
> 2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-19 19:29 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19 14:56 [PATCH 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 14:56 ` [PATCH 1/6] ACPI: extlog: fix extlog_mem_event build issue Pierre Gondois
2026-10-19 16:36 ` Jonathan Cameron
2026-10-19 17:55 ` Pierre Gondois
2026-10-19 14:56 ` [PATCH 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
2026-10-19 18:16 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 3/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
2026-10-19 18:21 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 4/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
2026-10-19 19:13 ` Jonathan Cameron
2026-10-19 14:56 ` [PATCH 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
2026-10-19 19:24 ` Jonathan Cameron
2026-10-19 14:56 ` [RFC PATCH 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
2026-10-19 19:28 ` Jonathan Cameron
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.