* [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
@ 2026-10-19 20:38 Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 1/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 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
V1: https://lore.kernel.org/all/20261019145643.1877246-1-pierre.gondois@arm.com/
- Corrections from Jonathan's review
- New patch:
[PATCH v2 4/6] EDAC/ghes: Extract error report initialization
- Last patch not in RFC as it has been reviewed by Jonathan@
[PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event
Pierre Gondois (6):
cper: use BIT_ULL() for processor and memory validation bits
cper: add Memory Error Section 2 structures
cper: add helpers to handle Memory Error Section 2
EDAC/ghes: Extract error report initialization
ACPI: APEI: add separate Memory Error Section 2 handlers
ACPI: extlog: add Memory Error Section 2 trace event
drivers/acpi/acpi_extlog.c | 6 ++
drivers/acpi/apei/ghes.c | 49 +++++++++-
drivers/edac/ghes_edac.c | 184 ++++++++++++++++++++++++++++++------
drivers/firmware/efi/cper.c | 109 +++++++++++++++++++++
drivers/ras/ras.c | 1 +
include/acpi/ghes.h | 2 +
include/linux/cper.h | 129 ++++++++++++++++++-------
include/ras/ras_event.h | 102 ++++++++++++++++++++
8 files changed, 514 insertions(+), 68 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 1/6] cper: use BIT_ULL() for processor and memory validation bits
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
` (5 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Jonathan Cameron,
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
Use the BIT_ULL() macro to describe flag bits instead of
hexadecimal values which are harder to read.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
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 440b35e459e5..81cda9874b25 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -225,42 +225,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)
#define CPER_MEM_EXT_ROW_MASK 0x3
#define CPER_MEM_EXT_ROW_SHIFT 16
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 2/6] cper: add Memory Error Section 2 structures
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 1/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 3/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
` (4 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Jonathan Cameron,
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
Add CPER Memory Error Section 2 definitions to the CPER headers.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
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 81cda9874b25..ed355b240685 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 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)
+#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 [flat|nested] 15+ messages in thread
* [PATCH v2 3/6] cper: add helpers to handle Memory Error Section 2
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 1/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 4/6] EDAC/ghes: Extract error report initialization Pierre Gondois
` (3 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Jonathan Cameron,
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
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
directly rely on struct cper_sec_mem_err2.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/firmware/efi/cper.c | 109 ++++++++++++++++++++++++++++++++++++
include/linux/cper.h | 3 +
2 files changed, 112 insertions(+)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 06b4fdb59917..42e324d5707c 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -445,6 +445,107 @@ 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;
+
+ /* 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);
+
+ len = CPER_REC_LEN;
+ 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 +751,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 [flat|nested] 15+ messages in thread
* [PATCH v2 4/6] EDAC/ghes: Extract error report initialization
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (2 preceding siblings ...)
2026-10-19 20:38 ` [PATCH v2 3/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-20 17:09 ` Jonathan Cameron
2026-10-19 20:38 ` [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 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
Extract a ghes_edac_init_error() function to prepare for
Memory Error Section 2 support (and re-usage).
Also use a guard in the caller ghes_edac_report_mem_error()
function for code simplification.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/edac/ghes_edac.c | 66 +++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 31 deletions(-)
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index d80c88818691..b90150c67f4b 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -267,37 +267,14 @@ static int print_mem_error_other_detail(const struct cper_sec_mem_err *mem, char
return n;
}
-static int ghes_edac_report_mem_error(struct notifier_block *nb,
- unsigned long val, void *data)
+/* Caller must hold ghes_lock. */
+static struct edac_raw_error_desc *
+ghes_edac_init_error(struct ghes_pvt *pvt, unsigned long sev)
{
- struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;
- struct cper_mem_err_compact cmem;
- 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;
+ struct edac_raw_error_desc *e = &pvt->mci->error_desc;
/* Cleans the error report buffer */
- memset(e, 0, sizeof (*e));
+ memset(e, 0, sizeof(*e));
e->error_count = 1;
e->grain = 1;
e->msg = pvt->msg;
@@ -323,6 +300,36 @@ static int ghes_edac_report_mem_error(struct notifier_block *nb,
e->type = HW_EVENT_ERR_INFO;
}
+ return e;
+}
+
+static int ghes_edac_report_mem_error(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;
+ struct cper_mem_err_compact cmem;
+ struct edac_raw_error_desc *e;
+ struct mem_ctl_info *mci;
+ struct ghes_pvt *pvt;
+ 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;
+
+ guard(spinlock_irqsave)(&ghes_lock);
+
+ pvt = ghes_pvt;
+ if (!pvt)
+ return NOTIFY_OK;
+
+ mci = pvt->mci;
+ e = ghes_edac_init_error(pvt, val);
+
edac_dbg(1, "error validation_bits: 0x%08llx\n",
(long long)mem_err->validation_bits);
@@ -375,9 +382,6 @@ static int ghes_edac_report_mem_error(struct notifier_block *nb,
edac_raw_mc_handle_error(e);
-unlock:
- spin_unlock_irqrestore(&ghes_lock, flags);
-
return NOTIFY_OK;
}
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (3 preceding siblings ...)
2026-10-19 20:38 ` [PATCH v2 4/6] EDAC/ghes: Extract error report initialization Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-20 17:17 ` Jonathan Cameron
2026-10-19 20:38 ` [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
2026-10-20 17:10 ` [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Jonathan Cameron
6 siblings, 1 reply; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 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 | 118 +++++++++++++++++++++++++++++++++++++++
include/acpi/ghes.h | 2 +
3 files changed, 168 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 b90150c67f4b..01defc4e3bf1 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -390,6 +390,122 @@ 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;
+ struct ghes_pvt *pvt;
+ 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;
+
+ guard(spinlock_irqsave)(&ghes_lock);
+
+ pvt = ghes_pvt;
+ if (!pvt)
+ return NOTIFY_OK;
+
+ mci = pvt->mci;
+ e = ghes_edac_init_error(pvt, val);
+
+ 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);
+
+ 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;
@@ -494,6 +610,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);
@@ -537,6 +654,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 [flat|nested] 15+ messages in thread
* [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (4 preceding siblings ...)
2026-10-19 20:38 ` [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
@ 2026-10-19 20:38 ` Pierre Gondois
2026-10-24 0:09 ` Jonathan Cameron
2026-10-20 17:10 ` [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Jonathan Cameron
6 siblings, 1 reply; 15+ messages in thread
From: Pierre Gondois @ 2026-10-19 20:38 UTC (permalink / raw)
To: linux-kernel
Cc: James Morse, Mark Brown, Pierre Gondois, Jonathan Cameron,
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
Add a separate handling for Memory Error Section 2 trace events.
The fields of the record are individually printed so userspace
can discover the layout more dynamically if a new field is added.
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/acpi/acpi_extlog.c | 6 +++
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 102 +++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+)
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 7ad3b36013cc..9e4d16e06244 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -231,6 +231,12 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
if (gdata->error_data_length >= sizeof(*mem))
trace_extlog_mem_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))
+ trace_extlog_mem2_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] 15+ messages in thread
* Re: [PATCH v2 4/6] EDAC/ghes: Extract error report initialization
2026-10-19 20:38 ` [PATCH v2 4/6] EDAC/ghes: Extract error report initialization Pierre Gondois
@ 2026-10-20 17:09 ` Jonathan Cameron
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-20 17:09 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 22:38:43 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Extract a ghes_edac_init_error() function to prepare for
> Memory Error Section 2 support (and re-usage).
>
> Also use a guard in the caller ghes_edac_report_mem_error()
> function for code simplification.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/edac/ghes_edac.c | 66 +++++++++++++++++++++-------------------
> 1 file changed, 35 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
> index d80c88818691..b90150c67f4b 100644
> --- a/drivers/edac/ghes_edac.c
> +++ b/drivers/edac/ghes_edac.c
> @@ -267,37 +267,14 @@ static int print_mem_error_other_detail(const struct cper_sec_mem_err *mem, char
> return n;
> }
>
> -static int ghes_edac_report_mem_error(struct notifier_block *nb,
> - unsigned long val, void *data)
> +/* Caller must hold ghes_lock. */
> +static struct edac_raw_error_desc *
> +ghes_edac_init_error(struct ghes_pvt *pvt, unsigned long sev)
Slightly unusual to have an init function that doesn't directly take the thing
being initialized. I'd pass it in. The clearly of pvt->msg and pvt->other_detail
is also a bit of a surprise for a function that claims to be initializing something
else so I'd do those outside of the helper.
Or maybe rename helper to something like
ghes_edac_fill_error_from_pvt()
Not sure that really conveys the modification of pvt data hidden in here though.
Perhaps this refactor was a bad suggestion from me and better to just duplicate
the code. What do ACPI maintainers think?
> {
> - struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;
> - struct cper_mem_err_compact cmem;
> - 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;
> + struct edac_raw_error_desc *e = &pvt->mci->error_desc;
>
> /* Cleans the error report buffer */
> - memset(e, 0, sizeof (*e));
> + memset(e, 0, sizeof(*e));
> e->error_count = 1;
> e->grain = 1;
> e->msg = pvt->msg;
> @@ -323,6 +300,36 @@ static int ghes_edac_report_mem_error(struct notifier_block *nb,
> e->type = HW_EVENT_ERR_INFO;
> }
>
> + return e;
> +}
> +
> +static int ghes_edac_report_mem_error(struct notifier_block *nb,
> + unsigned long val, void *data)
> +{
> + struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;
> + struct cper_mem_err_compact cmem;
> + struct edac_raw_error_desc *e;
> + struct mem_ctl_info *mci;
> + struct ghes_pvt *pvt;
> + 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;
> +
> + guard(spinlock_irqsave)(&ghes_lock);
> +
> + pvt = ghes_pvt;
> + if (!pvt)
> + return NOTIFY_OK;
> +
> + mci = pvt->mci;
> + e = ghes_edac_init_error(pvt, val);
> +
> edac_dbg(1, "error validation_bits: 0x%08llx\n",
> (long long)mem_err->validation_bits);
>
> @@ -375,9 +382,6 @@ static int ghes_edac_report_mem_error(struct notifier_block *nb,
>
> edac_raw_mc_handle_error(e);
>
> -unlock:
> - spin_unlock_irqrestore(&ghes_lock, flags);
> -
> return NOTIFY_OK;
> }
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
` (5 preceding siblings ...)
2026-10-19 20:38 ` [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
@ 2026-10-20 17:10 ` Jonathan Cameron
2026-10-22 7:07 ` Pierre Gondois
6 siblings, 1 reply; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-20 17:10 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 22:38:39 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> 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.
Hi Pierre,
I'd slow down a bit. We are mid merge window and convention is normally
one version a week or so anyway. Better to gather up feedback from
a number of folk and spin only one revision to cover it all.
Jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers
2026-10-19 20:38 ` [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
@ 2026-10-20 17:17 ` Jonathan Cameron
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-20 17:17 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 22:38:44 +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>
I think this is is ok. I don't love the dual notifier chains but
right now I also don't have a better idea.
So a somewhat tentative
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Jonathan
> ---
> drivers/acpi/apei/ghes.c | 49 +++++++++++++++-
> drivers/edac/ghes_edac.c | 118 +++++++++++++++++++++++++++++++++++++++
> include/acpi/ghes.h | 2 +
> 3 files changed, 168 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 b90150c67f4b..01defc4e3bf1 100644
> --- a/drivers/edac/ghes_edac.c
> +++ b/drivers/edac/ghes_edac.c
> @@ -390,6 +390,122 @@ 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;
> + struct ghes_pvt *pvt;
> + 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;
> +
> + guard(spinlock_irqsave)(&ghes_lock);
> +
> + pvt = ghes_pvt;
> + if (!pvt)
> + return NOTIFY_OK;
> +
> + mci = pvt->mci;
> + e = ghes_edac_init_error(pvt, val);
> +
> + 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);
> +
> + return NOTIFY_OK;
> +}
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
2026-10-20 17:10 ` [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Jonathan Cameron
@ 2026-10-22 7:07 ` Pierre Gondois
2026-10-23 21:26 ` Jonathan Cameron
0 siblings, 1 reply; 15+ messages in thread
From: Pierre Gondois @ 2026-10-22 7:07 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, Dan Williams, Terry Bowman, Ard Biesheuvel,
Morduan Zang, linux-acpi, linux-edac, acpica-devel
On 10/20/26 19:10, Jonathan Cameron wrote:
> On Mon, 19 Oct 2026 22:38:39 +0200
> Pierre Gondois <pierre.gondois@arm.com> wrote:
>
>> 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.
> Hi Pierre,
>
> I'd slow down a bit. We are mid merge window and convention is normally
> one version a week or so anyway. Better to gather up feedback from
> a number of folk and spin only one revision to cover it all.
>
Hello Jonathan,
Ok sure, as the v1 was reviewed quickly I thought there was a chance
of having the serie accepted quickly aswell. I ll wait a bit more.
Thanks for the review,
Pierre
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
2026-10-22 7:07 ` Pierre Gondois
@ 2026-10-23 21:26 ` Jonathan Cameron
2026-10-23 22:40 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-23 21:26 UTC (permalink / raw)
To: Pierre Gondois, Tony Luck, Borislav Petkov
Cc: linux-kernel, James Morse, Mark Brown, Rafael J. Wysocki,
Len Brown, 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, Ashok Raj
On Thu, 22 Oct 2026 09:07:25 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> On 10/20/26 19:10, Jonathan Cameron wrote:
> > On Mon, 19 Oct 2026 22:38:39 +0200
> > Pierre Gondois <pierre.gondois@arm.com> wrote:
> >
> >> 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.
> > Hi Pierre,
> >
> > I'd slow down a bit. We are mid merge window and convention is normally
> > one version a week or so anyway. Better to gather up feedback from
> > a number of folk and spin only one revision to cover it all.
> >
> Hello Jonathan,
>
> Ok sure, as the v1 was reviewed quickly I thought there was a chance
> of having the serie accepted quickly aswell. I ll wait a bit more.
>
> Thanks for the review,
>
> Pierre
>
A general question that came up in a related thread with one of
our RAS architects. How does firmware decide what to send? As far as
I can tell firwmare has no way to know whether the OS understands the CPER
Memory Section 2.
So options that come to mind.
1. Firmware must send a CPER with both Memory Section and Memory Section 2.
2. For whatever other reason a platform knows it doesn't work with old kernel
so can assume support in kernel and hopefully userspace got updated too.
3. We propose some additional discoverability (quickly - code first) to ACPI
so that it can be a negotiated contract between OS and firmware.
Until the OS confirms it understands Memory Section 2, firmware has to send
the older one (or risk the record not being understood). After that
negotiation it can do what it likes - probably send the Memory Section 2 form.
Option 1 and 2 are ugly at best.
Obvious path to me for option 3 is an _OSC like the one for generic initiators
that we discovered a need for whilst implementing that years ago.
Anyhow have a better idea? The above doesn't solve the end to end problem as
maybe userspace still has no idea what this new tracepoint is, but at least gets
us past hop 1 (so through the kernel).
If we conclude _OSC plan works I'll draft a code first proposal.
Jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
2026-10-23 21:26 ` Jonathan Cameron
@ 2026-10-23 22:40 ` Mauro Carvalho Chehab
2026-10-24 0:04 ` Jonathan Cameron
0 siblings, 1 reply; 15+ messages in thread
From: Mauro Carvalho Chehab @ 2026-10-23 22:40 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Pierre Gondois, Tony Luck, Borislav Petkov, linux-kernel,
James Morse, Mark Brown, Rafael J. Wysocki, Len Brown,
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, Ashok Raj
On Fri, 23 Oct 2026 14:26:21 -0700
Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> wrote:
> On Thu, 22 Oct 2026 09:07:25 +0200
> Pierre Gondois <pierre.gondois@arm.com> wrote:
>
> > On 10/20/26 19:10, Jonathan Cameron wrote:
> > > On Mon, 19 Oct 2026 22:38:39 +0200
> > > Pierre Gondois <pierre.gondois@arm.com> wrote:
> > >
> > >> 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.
> > > Hi Pierre,
> > >
> > > I'd slow down a bit. We are mid merge window and convention is normally
> > > one version a week or so anyway. Better to gather up feedback from
> > > a number of folk and spin only one revision to cover it all.
> > >
> > Hello Jonathan,
> >
> > Ok sure, as the v1 was reviewed quickly I thought there was a chance
> > of having the serie accepted quickly aswell. I ll wait a bit more.
> >
> > Thanks for the review,
> >
> > Pierre
> >
>
> A general question that came up in a related thread with one of
> our RAS architects. How does firmware decide what to send? As far as
> I can tell firwmare has no way to know whether the OS understands the CPER
> Memory Section 2.
>
> So options that come to mind.
> 1. Firmware must send a CPER with both Memory Section and Memory Section 2.
Please don't do this: this would require either Kernespace or userspace to
discard one of the reports, only if the other one is there, which can be
tricky. Could be done more easily at userspace, but only if some database
support is enabled, but, at least on rasdaemon, this is an optional module.
> 2. For whatever other reason a platform knows it doesn't work with old kernel
> so can assume support in kernel and hopefully userspace got updated too.
>
> 3. We propose some additional discoverability (quickly - code first) to ACPI
> so that it can be a negotiated contract between OS and firmware.
> Until the OS confirms it understands Memory Section 2, firmware has to send
> the older one (or risk the record not being understood). After that
> negotiation it can do what it likes - probably send the Memory Section 2 form.
>
> Option 1 and 2 are ugly at best.
>
> Obvious path to me for option 3 is an _OSC like the one for generic initiators
> that we discovered a need for whilst implementing that years ago.
>
> Anyhow have a better idea? The above doesn't solve the end to end problem as
> maybe userspace still has no idea what this new tracepoint is, but at least gets
> us past hop 1 (so through the kernel).
>
> If we conclude _OSC plan works I'll draft a code first proposal.
>
> Jonathan
Regards,
Mauro
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/6] CPER: Add Memory Error Section 2 support
2026-10-23 22:40 ` Mauro Carvalho Chehab
@ 2026-10-24 0:04 ` Jonathan Cameron
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-24 0:04 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Pierre Gondois, Tony Luck, Borislav Petkov, linux-kernel,
James Morse, Mark Brown, Rafael J. Wysocki, Len Brown,
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, Ashok Raj
On Sat, 24 Oct 2026 00:40:33 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> On Fri, 23 Oct 2026 14:26:21 -0700
> Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> wrote:
>
> > On Thu, 22 Oct 2026 09:07:25 +0200
> > Pierre Gondois <pierre.gondois@arm.com> wrote:
> >
> > > On 10/20/26 19:10, Jonathan Cameron wrote:
> > > > On Mon, 19 Oct 2026 22:38:39 +0200
> > > > Pierre Gondois <pierre.gondois@arm.com> wrote:
> > > >
> > > >> 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.
> > > > Hi Pierre,
> > > >
> > > > I'd slow down a bit. We are mid merge window and convention is normally
> > > > one version a week or so anyway. Better to gather up feedback from
> > > > a number of folk and spin only one revision to cover it all.
> > > >
> > > Hello Jonathan,
> > >
> > > Ok sure, as the v1 was reviewed quickly I thought there was a chance
> > > of having the serie accepted quickly aswell. I ll wait a bit more.
> > >
> > > Thanks for the review,
> > >
> > > Pierre
> > >
> >
> > A general question that came up in a related thread with one of
> > our RAS architects. How does firmware decide what to send? As far as
> > I can tell firwmare has no way to know whether the OS understands the CPER
> > Memory Section 2.
> >
> > So options that come to mind.
> > 1. Firmware must send a CPER with both Memory Section and Memory Section 2.
>
> Please don't do this: this would require either Kernespace or userspace to
> discard one of the reports, only if the other one is there, which can be
> tricky. Could be done more easily at userspace, but only if some database
> support is enabled, but, at least on rasdaemon, this is an optional module.
Good. That confirms my view that is horrible.
>
> > 2. For whatever other reason a platform knows it doesn't work with old kernel
> > so can assume support in kernel and hopefully userspace got updated too.
> >
> > 3. We propose some additional discoverability (quickly - code first) to ACPI
> > so that it can be a negotiated contract between OS and firmware.
> > Until the OS confirms it understands Memory Section 2, firmware has to send
> > the older one (or risk the record not being understood). After that
> > negotiation it can do what it likes - probably send the Memory Section 2 form.
> >
> > Option 1 and 2 are ugly at best.
> >
> > Obvious path to me for option 3 is an _OSC like the one for generic initiators
> > that we discovered a need for whilst implementing that years ago.
> >
> > Anyhow have a better idea? The above doesn't solve the end to end problem as
> > maybe userspace still has no idea what this new tracepoint is, but at least gets
> > us past hop 1 (so through the kernel).
> >
> > If we conclude _OSC plan works I'll draft a code first proposal.
> >
> > Jonathan
On another note, Pierre, any plans to actually enable a path to the tracepoints
on arm64? Today they only emerge from acpi_extlog which is x86 only.
We definitely want the richer data for PFA and obviously for userspace nice
to share tracepoints with extlog.
Jonathan
>
> Regards,
> Mauro
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event
2026-10-19 20:38 ` [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
@ 2026-10-24 0:09 ` Jonathan Cameron
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Cameron @ 2026-10-24 0:09 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 22:38:45 +0200
Pierre Gondois <pierre.gondois@arm.com> wrote:
> Add a separate handling for Memory Error Section 2 trace events.
> The fields of the record are individually printed so userspace
> can discover the layout more dynamically if a new field is added.
>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/acpi/acpi_extlog.c | 6 +++
> drivers/ras/ras.c | 1 +
> include/ras/ras_event.h | 102 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 109 insertions(+)
>
> diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
> index 7ad3b36013cc..9e4d16e06244 100644
> --- a/drivers/acpi/acpi_extlog.c
> +++ b/drivers/acpi/acpi_extlog.c
> @@ -231,6 +231,12 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
> if (gdata->error_data_length >= sizeof(*mem))
> trace_extlog_mem_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))
> + trace_extlog_mem2_event(mem, err_seq, fru_id, fru_text,
> + (u8)gdata->error_severity);
Was just giving this a spin and looks like mix of tabs and spaces (with the spaces
in the middle). Git moaned when I was applying it.
J
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-10-24 0:09 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 20:38 [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 1/6] cper: use BIT_ULL() for processor and memory validation bits Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 2/6] cper: add Memory Error Section 2 structures Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 3/6] cper: add helpers to handle Memory Error Section 2 Pierre Gondois
2026-10-19 20:38 ` [PATCH v2 4/6] EDAC/ghes: Extract error report initialization Pierre Gondois
2026-10-20 17:09 ` Jonathan Cameron
2026-10-19 20:38 ` [PATCH v2 5/6] ACPI: APEI: add separate Memory Error Section 2 handlers Pierre Gondois
2026-10-20 17:17 ` Jonathan Cameron
2026-10-19 20:38 ` [PATCH v2 6/6] ACPI: extlog: add Memory Error Section 2 trace event Pierre Gondois
2026-10-24 0:09 ` Jonathan Cameron
2026-10-20 17:10 ` [PATCH v2 0/6] CPER: Add Memory Error Section 2 support Jonathan Cameron
2026-10-22 7:07 ` Pierre Gondois
2026-10-23 21:26 ` Jonathan Cameron
2026-10-23 22:40 ` Mauro Carvalho Chehab
2026-10-24 0:04 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®