All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.