FAILED: patch "[PATCH] cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size" failed to apply to 6.18-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x c268f949e219f9e179558e836f457f6c5fbec416
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072028-shaky-author-b5df@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From c268f949e219f9e179558e836f457f6c5fbec416 Mon Sep 17 00:00:00 2001
From: Terry Bowman <[email protected]>
Date: Fri, 5 Jun 2026 13:06:10 -0500
Subject: [PATCH] cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size
The CXL r4.0 8.2.4.17.7 RAS Capability Structure has total length 0x58 bytes (CXL_RAS_CAPABILITY_LENGTH); the Header Log occupies the trailing 64 bytes at offset 0x18. CXL_HEADERLOG_SIZE was defined as SZ_512, eight times the actual on-device size.
header_log_copy() reads CXL_HEADERLOG_SIZE_U32 (128) dwords from the RAS capability iomap, overrunning the 88-byte mapping by 448 bytes. The cxl_aer_uncorrectable_error trace event memcpy()s CXL_HEADERLOG_SIZE
(512) bytes from its source. For the CPER caller the source is struct cxl_ras_capability_regs::header_log[16] (64 bytes) embedded in a stack-local cxl_cper_prot_err_work_data, so the memcpy reads 448 bytes of kernel stack into the trace event ring buffer where userspace can read it via tracefs.
Set CXL_HEADERLOG_SIZE to 64 and derive CXL_HEADERLOG_SIZE_U32 from it, bringing all iomap readers into agreement on 16 dwords. Userspace tools such as rasdaemon have grown a dependency on the buggy 512-byte (128 u32) header_log layout in the cxl_aer_uncorrectable_error trace event. Add CXL_HEADERLOG_TRACE_SIZE_U32 = 128 and use it for the trace event __array and its memcpy to preserve that ABI. Both callers now pass a zero-filled u32[CXL_HEADERLOG_TRACE_SIZE_U32] staging buffer with only the first CXL_HEADERLOG_SIZE_U32 (16) entries populated from hardware; the remaining 112 u32s are zero-padded, keeping the 512-byte trace ring buffer layout intact.
[ dj: Replaced 64 with SZ_64 per RichardC ]
drivers/cxl/core/ras.c +20 -7
@@ -8,6 +8,10 @@#include <cxlpci.h> #include "trace.h" +/* Check that UCE header definition is maintained to keep ABI intact */ +static_assert (CXL_HEADERLOG_TRACE_SIZE_U32 ==128 , +"rasdaemon ABI requires exactly 128 u32s" ); +static void cxl_cper_trace_corr_port_prot_err (struct pci_dev *pdev,struct cxl_ras_capability_regs ras_cap) {
@@ -19,6 +23,7 @@ static void cxl_cper_trace_corr_port_prot_err(struct pci_dev *pdev,static void cxl_cper_trace_uncorr_port_prot_err (struct pci_dev *pdev,struct cxl_ras_capability_regs ras_cap) { +u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32 ] = {};u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask;u32 fe;
@@ -28,8 +33,8 @@ static void cxl_cper_trace_uncorr_port_prot_err(struct pci_dev *pdev,else fe = status; -trace_cxl_port_aer_uncorrectable_error (&pdev->dev, status, fe, - ras_cap.header_log); +memcpy (hl, ras_cap.header_log,CXL_HEADERLOG_SIZE ); +trace_cxl_port_aer_uncorrectable_error (&pdev->dev, status, fe, hl); } static void cxl_cper_trace_corr_prot_err(struct cxl_memdev *cxlmd,
@@ -44,6 +49,7 @@ static void cxl_cper_trace_uncorr_prot_err(struct cxl_memdev *cxlmd, struct cxl_ras_capability_regs ras_cap) { + u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32] = {};u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask;u32 fe;
@@ -53,8 +59,15 @@ cxl_cper_trace_uncorr_prot_err(struct cxl_memdev *cxlmd,else fe = status; -trace_cxl_aer_uncorrectable_error (cxlmd, status, fe, - ras_cap.header_log); +/* +* ras_cap.header_log[] holds CXL_HEADERLOG_SIZE_U32 (16) hardware +* dwords. Copy them into the front of a zero-filled +* CXL_HEADERLOG_TRACE_SIZE_U32 (128) u32 staging buffer so the trace +* event memcpy sees a full 512-byte source and the userspace ABI +* (rasdaemon) is preserved. +*/ +memcpy (hl, ras_cap.header_log,CXL_HEADERLOG_SIZE ); +trace_cxl_aer_uncorrectable_error (cxlmd, status, fe, hl); }static int match_memdev_by_parent (struct device *dev,const void *uport)
@@ -204,12 +217,12 @@ static void header_log_copy(void __iomem *ras_base, u32 *log) {void __iomem *addr;u32 *log_addr; -int i, log_u32_size =CXL_HEADERLOG_SIZE /sizeof (u32); +int i; addr = ras_base +CXL_RAS_HEADER_LOG_OFFSET ; log_addr = log; -for (i =0 ; i < log_u32_size; i++) { +for (i =0 ; i <CXL_HEADERLOG_SIZE_U32 ; i++) { *log_addr =readl (addr); log_addr++; addr +=sizeof (u32);
@@ -222,7 +235,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)*/ bool cxl_handle_ras (struct device *dev,void __iomem *ras_base) { -u32 hl[CXL_HEADERLOG_SIZE_U32 ]; +u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32 ] = {};void __iomem *addr;u32 status;u32 fe;
drivers/cxl/core/trace.h +16 -8
@@ -56,7 +56,7 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error, __string(host, dev_name(dev->parent)) __field(u32, status) __field(u32, first_error) -__array (u32, header_log,CXL_HEADERLOG_SIZE_U32 ) +__array (u32, header_log,CXL_HEADERLOG_TRACE_SIZE_U32 ) ),TP_fast_assign ( __assign_str(device);
@@ -64,10 +64,14 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error, __entry->status = status; __entry->first_error = fe;/* -* Embed the 512B headerlog data for user app retrieval and -* parsing, but no need to print this in the trace buffer. +* Embed headerlog data for user app retrieval and parsing, +* but no need to print in the trace buffer. Only +* CXL_HEADERLOG_SIZE_U32 (16) dwords are hardware data; +* the remaining entries preserve the 512-byte ABI layout +* rasdaemon depends on and are zero-filled by the caller. */ -memcpy (__entry->header_log, hl,CXL_HEADERLOG_SIZE ); +memcpy (__entry->header_log, hl, +CXL_HEADERLOG_TRACE_SIZE_U32 *sizeof (u32)); ), TP_printk("device=%s host=%s status: '%s' first_error: '%s'", __get_str(device), __get_str(host),
@@ -85,7 +89,7 @@ TRACE_EVENT(cxl_aer_uncorrectable_error, __field(u64, serial) __field(u32, status) __field(u32, first_error) -__array (u32, header_log,CXL_HEADERLOG_SIZE_U32 ) +__array (u32, header_log,CXL_HEADERLOG_TRACE_SIZE_U32 ) ),TP_fast_assign ( __assign_str(memdev);
@@ -94,10 +98,14 @@ TRACE_EVENT(cxl_aer_uncorrectable_error, __entry->status = status; __entry->first_error = fe;/* -* Embed the 512B headerlog data for user app retrieval and -* parsing, but no need to print this in the trace buffer. +* Embed headerlog data for user app retrieval and parsing, +* but no need to print in the trace buffer. Only +* CXL_HEADERLOG_SIZE_U32 (16) dwords are hardware data; +* the remaining entries preserve the 512-byte ABI layout +* rasdaemon depends on and are zero-filled by the caller. */ -memcpy (__entry->header_log, hl,CXL_HEADERLOG_SIZE ); +memcpy (__entry->header_log, hl, +CXL_HEADERLOG_TRACE_SIZE_U32 *sizeof (u32)); ), TP_printk("memdev=%s host=%s serial=%lld: status: '%s' first_error: '%s'", __get_str(memdev), __get_str(host), __entry->serial,
drivers/cxl/cxl.h +12 -2
@@ -158,8 +158,18 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)#define CXL_RAS_CAP_CONTROL_FE_MASK GENMASK(5, 0)#define CXL_RAS_HEADER_LOG_OFFSET 0x18#define CXL_RAS_CAPABILITY_LENGTH 0x58 -#define CXL_HEADERLOG_SIZE SZ_512 -#define CXL_HEADERLOG_SIZE_U32 SZ_512 / sizeof(u32) +#define CXL_HEADERLOG_SIZE SZ_64 +#define CXL_HEADERLOG_SIZE_U32 (CXL_HEADERLOG_SIZE / sizeof(u32)) + +/* +* The RAS UCE trace event header array was originally sized at SZ_512/sizeof(u32) +* = 128 u32s due to a bug. Userspace tools (rasdaemon) have grown a dependency +* on that 512-byte layout. Keep the trace array at 128 u32s to preserve the +* ABI; only CXL_HEADERLOG_SIZE_U32 (16) dwords are valid hardware data, the +* remainder are zero-filled. +*/ +#define CXL_HEADERLOG_TRACE_SIZE SZ_512 +#define CXL_HEADERLOG_TRACE_SIZE_U32 (CXL_HEADERLOG_TRACE_SIZE / sizeof(u32))/* CXL 2.0 8.2.8.1 Device Capabilities Array Register */ #define CXLDEV_CAP_ARRAY_OFFSET 0x0
Sasha Levin
maintainerPATCH 1/4 cxl/pci: Remove unnecessary CXL Endpoint handling helper functions
From: Terry Bowman <[email protected]>
[ Upstream commit ca3d1a53e62093d17436abd447463da9c0f4e56b ]
The CXL driver's cxl_handle_endpoint_cor_ras()/cxl_handle_endpoint_ras() are unnecessary helper functions used only for Endpoints. Remove these functions as they are not common for all CXL devices and do not provide value for EP handling.
Rename __cxl_handle_ras to cxl_handle_ras() and __cxl_handle_cor_ras() to cxl_handle_cor_ras().
Stable-dep-of: c268f949e219 ("cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size")
--- drivers/cxl/core/pci.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-)
drivers/cxl/core/pci.c +8 -18
@@ -711,8 +711,8 @@ void read_cdat_data(struct cxl_port *port) }EXPORT_SYMBOL_NS_GPL (read_cdat_data,"CXL" ); -static void __cxl_handle_cor_ras (struct cxl_dev_state *cxlds, -void __iomem *ras_base) +static void cxl_handle_cor_ras (struct cxl_dev_state *cxlds, +void __iomem *ras_base) {void __iomem *addr;u32 status;
@@ -728,11 +728,6 @@ static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds, } } -static void cxl_handle_endpoint_cor_ras (struct cxl_dev_state *cxlds) -{ -return __cxl_handle_cor_ras (cxlds, cxlds->regs.ras); -} -/* CXL spec rev3.0 8.2.4.16.1 */ static void header_log_copy (void __iomem *ras_base,u32 *log) {
@@ -754,8 +749,8 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)* Log the state of the RAS status registers and prepare them to log the * next error status. Return 1 if reset needed. */ -static bool __cxl_handle_ras (struct cxl_dev_state *cxlds, -void __iomem *ras_base) +static bool cxl_handle_ras (struct cxl_dev_state *cxlds, +void __iomem *ras_base) {u32 hl[CXL_HEADERLOG_SIZE_U32 ];void __iomem *addr;
@@ -788,11 +783,6 @@ static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,return true; } -static bool cxl_handle_endpoint_ras (struct cxl_dev_state *cxlds) -{ -return __cxl_handle_ras (cxlds, cxlds->regs.ras); -} -#ifdef CONFIG_PCIEAER_CXL static void cxl_dport_map_rch_aer (struct cxl_dport *dport)
@@ -871,13 +861,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");static void cxl_handle_rdport_cor_ras (struct cxl_dev_state *cxlds,struct cxl_dport *dport) { -return __cxl_handle_cor_ras (cxlds, dport->regs.ras); +return cxl_handle_cor_ras (cxlds, dport->regs.ras); }static bool cxl_handle_rdport_ras (struct cxl_dev_state *cxlds,struct cxl_dport *dport) { -return __cxl_handle_ras (cxlds, dport->regs.ras); +return cxl_handle_ras (cxlds, dport->regs.ras); }/*
@@ -974,7 +964,7 @@ void cxl_cor_error_detected(struct pci_dev *pdev)if (cxlds->rcd)cxl_handle_rdport_errors (cxlds); -cxl_handle_endpoint_cor_ras (cxlds); +cxl_handle_cor_ras (cxlds, cxlds->regs.ras); } }EXPORT_SYMBOL_NS_GPL (cxl_cor_error_detected,"CXL" );
@@ -1003,7 +993,7 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,* chance the situation is recoverable dump the status of the RAS * capability registers and bounce the active state of the memdev. */ - ue =cxl_handle_endpoint_ras (cxlds); + ue =cxl_handle_ras (cxlds, cxlds->regs.ras); }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/4 cxl/pci: Remove unnecessary CXL RCH handling helper functions
From: Terry Bowman <[email protected]>
[ Upstream commit eb78ef4d6f0e51243c1ee117f801dbc503e886ab ]
cxl_handle_rdport_cor_ras() and cxl_handle_rdport_ras() are specific to Restricted CXL Host (RCH) handling. Improve readability and maintainability by replacing these and instead using the common cxl_handle_cor_ras() and cxl_handle_ras() functions.
Stable-dep-of: c268f949e219 ("cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size")
--- drivers/cxl/core/pci.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-)
drivers/cxl/core/pci.c +2 -14
@@ -858,18 +858,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host) }EXPORT_SYMBOL_NS_GPL (cxl_dport_init_ras_reporting,"CXL" ); -static void cxl_handle_rdport_cor_ras (struct cxl_dev_state *cxlds, -struct cxl_dport *dport) -{ -return cxl_handle_cor_ras (cxlds, dport->regs.ras); -} - -static bool cxl_handle_rdport_ras (struct cxl_dev_state *cxlds, -struct cxl_dport *dport) -{ -return cxl_handle_ras (cxlds, dport->regs.ras); -} -/* * Copy the AER capability registers using 32 bit read accesses. * This is necessary because RCRB AER capability is MMIO mapped. Clear the
@@ -939,9 +927,9 @@ static void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds)pci_print_aer (pdev, severity, &aer_regs);if (severity ==AER_CORRECTABLE ) -cxl_handle_rdport_cor_ras (cxlds, dport); +cxl_handle_cor_ras (cxlds, dport->regs.ras);else - cxl_handle_rdport_ras(cxlds, dport); + cxl_handle_ras(cxlds, dport->regs.ras); }#else
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/4 cxl/pci: Remove CXL VH handling in CONFIG_PCIEAER_CXL conditional blocks from core/pci.c
In reply to Sasha LevinFrom: Dave Jiang <[email protected]>
[ Upstream commit 7ff8b1d60881c5f97b5ae426e14d2822917d3b69 ]
Create new config CONFIG_CXL_RAS and put all CXL RAS items behind the config. The config will depend on CPER and PCIE AER to build. Move the related VH RAS code from core/pci.c to core/ras.c.
Restricted CXL host (RCH) RAS functions will be moved in a future patch.
Stable-dep-of: c268f949e219 ("cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size")
--- drivers/cxl/Kconfig | 4 + drivers/cxl/core/Makefile | 2 +- drivers/cxl/core/core.h | 31 +++++++ drivers/cxl/core/pci.c | 189 +------------------------------------- drivers/cxl/core/ras.c | 176 +++++++++++++++++++++++++++++++++++ drivers/cxl/cxl.h | 8 -- drivers/cxl/cxlpci.h | 16 ++++ tools/testing/cxl/Kbuild | 2 +- 8 files changed, 233 insertions(+), 195 deletions(-)
drivers/cxl/Kconfig +4 -0
@@ -234,4 +234,8 @@ config CXL_MCE def_bool y depends on X86_MCE && MEMORY_FAILURE +config CXL_RAS + def_bool y + depends on ACPI_APEI_GHES && PCIEAER && CXL_PCI + endif
drivers/cxl/core/Makefile +1 -1
@@ -14,9 +14,9 @@ cxl_core-y += pci.o cxl_core-y += hdm.o cxl_core-y += pmu.o cxl_core-y += cdat.o -cxl_core-y += ras.o cxl_core-$(CONFIG_TRACING) += trace.o cxl_core-$(CONFIG_CXL_REGION) += region.o cxl_core-$(CONFIG_CXL_MCE) += mce.o cxl_core-$(CONFIG_CXL_FEATURES) += features.o cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += edac.o +cxl_core-$(CONFIG_CXL_RAS) += ras.o
drivers/cxl/core/core.h +31 -0
@@ -144,8 +144,39 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);int cxl_port_get_switch_dport_bandwidth (struct cxl_port *port,struct access_coordinate *c); +#ifdef CONFIG_CXL_RAS int cxl_ras_init (void );void cxl_ras_exit (void ); +bool cxl_handle_ras (struct cxl_dev_state *cxlds,void __iomem *ras_base); +void cxl_handle_cor_ras (struct cxl_dev_state *cxlds,void __iomem *ras_base); +#else +static inline int cxl_ras_init (void ) +{ +return 0 ; +} + +static inline void cxl_ras_exit (void ) +{ +} + +static inline bool cxl_handle_ras (struct cxl_dev_state *cxlds,void __iomem *ras_base) +{ +return false; +} +static inline void cxl_handle_cor_ras (struct cxl_dev_state *cxlds,void __iomem *ras_base) { } +#endif /* CONFIG_CXL_RAS */ + +/* Restricted CXL Host specific RAS functions */ +#ifdef CONFIG_CXL_RAS +void cxl_dport_map_rch_aer (struct cxl_dport *dport); +void cxl_disable_rch_root_ints (struct cxl_dport *dport); +void cxl_handle_rdport_errors (struct cxl_dev_state *cxlds); +#else +static inline void cxl_dport_map_rch_aer (struct cxl_dport *dport) { } +static inline void cxl_disable_rch_root_ints (struct cxl_dport *dport) { } +static inline void cxl_handle_rdport_errors (struct cxl_dev_state *cxlds) { } +#endif /* CONFIG_CXL_RAS */ +int cxl_gpf_port_setup (struct cxl_dport *dport);struct cxl_hdm ;
drivers/cxl/core/pci.c +4 -185
221 lines not on this page · raw message
drivers/cxl/core/ras.c +176 -0
185 lines not on this page · raw message
drivers/cxl/cxl.h +0 -8
@@ -781,14 +781,6 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, resource_size_t rcrb); -#ifdef CONFIG_PCIEAER_CXL -void cxl_setup_parent_dport (struct device *host,struct cxl_dport *dport); -void cxl_dport_init_ras_reporting (struct cxl_dport *dport,struct device *host); -#else -static inline void cxl_dport_init_ras_reporting (struct cxl_dport *dport, -struct device *host) { } -#endif -struct cxl_decoder *to_cxl_decoder (struct device *dev);struct cxl_root_decoder *to_cxl_root_decoder (struct device *dev);struct cxl_switch_decoder *to_cxl_switch_decoder (struct device *dev);
drivers/cxl/cxlpci.h +16 -0
@@ -130,7 +130,23 @@ static inline bool cxl_pci_flit_256(struct pci_dev *pdev)int devm_cxl_port_enumerate_dports (struct cxl_port *port);struct cxl_dev_state ;void read_cdat_data (struct cxl_port *port); + +#ifdef CONFIG_CXL_RAS void cxl_cor_error_detected (struct pci_dev *pdev);pci_ers_result_t cxl_error_detected (struct pci_dev *pdev,pci_channel_state_t state); +void cxl_dport_init_ras_reporting (struct cxl_dport *dport,struct device *host); +#else +static inline void cxl_cor_error_detected (struct pci_dev *pdev) { } + +static inline pci_ers_result_t cxl_error_detected (struct pci_dev *pdev, +pci_channel_state_t state) +{ +return PCI_ERS_RESULT_NONE ; +} + +static inline void cxl_dport_init_ras_reporting (struct cxl_dport *dport, +struct device *host) { } +#endif +#endif /* __CXL_PCI_H__ */
tools/testing/cxl/Kbuild +1 -1
@@ -58,12 +58,12 @@ cxl_core-y += $(CXL_CORE_SRC)/pci.o cxl_core-y += $(CXL_CORE_SRC)/hdm.o cxl_core-y += $(CXL_CORE_SRC)/pmu.o cxl_core-y += $(CXL_CORE_SRC)/cdat.o -cxl_core-y += $(CXL_CORE_SRC)/ras.o cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o cxl_core-$(CONFIG_CXL_MCE) += $(CXL_CORE_SRC)/mce.o cxl_core-$(CONFIG_CXL_FEATURES) += $(CXL_CORE_SRC)/features.o cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += $(CXL_CORE_SRC)/edac.o +cxl_core-$(CONFIG_CXL_RAS) += $(CXL_CORE_SRC)/ras.o cxl_core-y += config_check.o cxl_core-y += cxl_core_test.o cxl_core-y += cxl_core_exports.o
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/4 cxl: Fix CXL_HEADERLOG_SIZE to match RAS Capability size
In reply to Sasha LevinFrom: Terry Bowman <[email protected]>
[ Upstream commit c268f949e219f9e179558e836f457f6c5fbec416 ]
The CXL r4.0 8.2.4.17.7 RAS Capability Structure has total length 0x58 bytes (CXL_RAS_CAPABILITY_LENGTH); the Header Log occupies the trailing 64 bytes at offset 0x18. CXL_HEADERLOG_SIZE was defined as SZ_512, eight times the actual on-device size.
header_log_copy() reads CXL_HEADERLOG_SIZE_U32 (128) dwords from the RAS capability iomap, overrunning the 88-byte mapping by 448 bytes. The cxl_aer_uncorrectable_error trace event memcpy()s CXL_HEADERLOG_SIZE
(512) bytes from its source. For the CPER caller the source is struct cxl_ras_capability_regs::header_log[16] (64 bytes) embedded in a stack-local cxl_cper_prot_err_work_data, so the memcpy reads 448 bytes of kernel stack into the trace event ring buffer where userspace can read it via tracefs.
Set CXL_HEADERLOG_SIZE to 64 and derive CXL_HEADERLOG_SIZE_U32 from it, bringing all iomap readers into agreement on 16 dwords. Userspace tools such as rasdaemon have grown a dependency on the buggy 512-byte (128 u32) header_log layout in the cxl_aer_uncorrectable_error trace event. Add CXL_HEADERLOG_TRACE_SIZE_U32 = 128 and use it for the trace event __array and its memcpy to preserve that ABI. Both callers now pass a zero-filled u32[CXL_HEADERLOG_TRACE_SIZE_U32] staging buffer with only the first CXL_HEADERLOG_SIZE_U32 (16) entries populated from hardware; the remaining 112 u32s are zero-padded, keeping the 512-byte trace ring buffer layout intact.
[ dj: Replaced 64 with SZ_64 per RichardC ]
--- drivers/cxl/core/ras.c | 27 ++++++++++++++++++++------- drivers/cxl/core/trace.h | 24 ++++++++++++++++-------- drivers/cxl/cxl.h | 14 ++++++++++++-- 3 files changed, 48 insertions(+), 17 deletions(-)
drivers/cxl/core/ras.c +20 -7
@@ -8,6 +8,10 @@#include <cxlpci.h> #include "trace.h" +/* Check that UCE header definition is maintained to keep ABI intact */ +static_assert (CXL_HEADERLOG_TRACE_SIZE_U32 ==128 , +"rasdaemon ABI requires exactly 128 u32s" ); +static void cxl_cper_trace_corr_port_prot_err (struct pci_dev *pdev,struct cxl_ras_capability_regs ras_cap) {
@@ -19,6 +23,7 @@ static void cxl_cper_trace_corr_port_prot_err(struct pci_dev *pdev,static void cxl_cper_trace_uncorr_port_prot_err (struct pci_dev *pdev,struct cxl_ras_capability_regs ras_cap) { +u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32 ] = {};u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask;u32 fe;
@@ -28,8 +33,8 @@ static void cxl_cper_trace_uncorr_port_prot_err(struct pci_dev *pdev,else fe = status; -trace_cxl_port_aer_uncorrectable_error (&pdev->dev, status, fe, - ras_cap.header_log); +memcpy (hl, ras_cap.header_log,CXL_HEADERLOG_SIZE ); +trace_cxl_port_aer_uncorrectable_error (&pdev->dev, status, fe, hl); } static void cxl_cper_trace_corr_prot_err(struct cxl_memdev *cxlmd,
@@ -44,6 +49,7 @@ static void cxl_cper_trace_uncorr_prot_err(struct cxl_memdev *cxlmd, struct cxl_ras_capability_regs ras_cap) { + u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32] = {};u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask;u32 fe;
@@ -53,8 +59,15 @@ cxl_cper_trace_uncorr_prot_err(struct cxl_memdev *cxlmd,else fe = status; -trace_cxl_aer_uncorrectable_error (cxlmd, status, fe, - ras_cap.header_log); +/* +* ras_cap.header_log[] holds CXL_HEADERLOG_SIZE_U32 (16) hardware +* dwords. Copy them into the front of a zero-filled +* CXL_HEADERLOG_TRACE_SIZE_U32 (128) u32 staging buffer so the trace +* event memcpy sees a full 512-byte source and the userspace ABI +* (rasdaemon) is preserved. +*/ +memcpy (hl, ras_cap.header_log,CXL_HEADERLOG_SIZE ); +trace_cxl_aer_uncorrectable_error (cxlmd, status, fe, hl); }static int match_memdev_by_parent (struct device *dev,const void *uport)
@@ -181,12 +194,12 @@ static void header_log_copy(void __iomem *ras_base, u32 *log) {void __iomem *addr;u32 *log_addr; -int i, log_u32_size =CXL_HEADERLOG_SIZE /sizeof (u32); +int i; addr = ras_base +CXL_RAS_HEADER_LOG_OFFSET ; log_addr = log; -for (i =0 ; i < log_u32_size; i++) { +for (i =0 ; i <CXL_HEADERLOG_SIZE_U32 ; i++) { *log_addr =readl (addr); log_addr++; addr +=sizeof (u32);
@@ -199,7 +212,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)*/ bool cxl_handle_ras (struct cxl_dev_state *cxlds,void __iomem *ras_base) { -u32 hl[CXL_HEADERLOG_SIZE_U32 ]; +u32 hl[CXL_HEADERLOG_TRACE_SIZE_U32 ] = {};void __iomem *addr;u32 status;u32 fe;
drivers/cxl/core/trace.h +16 -8
@@ -56,7 +56,7 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error, __string(host, dev_name(dev->parent)) __field(u32, status) __field(u32, first_error) -__array (u32, header_log,CXL_HEADERLOG_SIZE_U32 ) +__array (u32, header_log,CXL_HEADERLOG_TRACE_SIZE_U32 ) ),TP_fast_assign ( __assign_str(device);
@@ -64,10 +64,14 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error, __entry->status = status; __entry->first_error = fe;/* -* Embed the 512B headerlog data for user app retrieval and -* parsing, but no need to print this in the trace buffer. +* Embed headerlog data for user app retrieval and parsing, +* but no need to print in the trace buffer. Only +* CXL_HEADERLOG_SIZE_U32 (16) dwords are hardware data; +* the remaining entries preserve the 512-byte ABI layout +* rasdaemon depends on and are zero-filled by the caller. */ -memcpy (__entry->header_log, hl,CXL_HEADERLOG_SIZE ); +memcpy (__entry->header_log, hl, +CXL_HEADERLOG_TRACE_SIZE_U32 *sizeof (u32)); ), TP_printk("device=%s host=%s status: '%s' first_error: '%s'", __get_str(device), __get_str(host),
@@ -85,7 +89,7 @@ TRACE_EVENT(cxl_aer_uncorrectable_error, __field(u64, serial) __field(u32, status) __field(u32, first_error) -__array (u32, header_log,CXL_HEADERLOG_SIZE_U32 ) +__array (u32, header_log,CXL_HEADERLOG_TRACE_SIZE_U32 ) ),TP_fast_assign ( __assign_str(memdev);
@@ -94,10 +98,14 @@ TRACE_EVENT(cxl_aer_uncorrectable_error, __entry->status = status; __entry->first_error = fe;/* -* Embed the 512B headerlog data for user app retrieval and -* parsing, but no need to print this in the trace buffer. +* Embed headerlog data for user app retrieval and parsing, +* but no need to print in the trace buffer. Only +* CXL_HEADERLOG_SIZE_U32 (16) dwords are hardware data; +* the remaining entries preserve the 512-byte ABI layout +* rasdaemon depends on and are zero-filled by the caller. */ -memcpy (__entry->header_log, hl,CXL_HEADERLOG_SIZE ); +memcpy (__entry->header_log, hl, +CXL_HEADERLOG_TRACE_SIZE_U32 *sizeof (u32)); ), TP_printk("memdev=%s host=%s serial=%lld: status: '%s' first_error: '%s'", __get_str(memdev), __get_str(host), __entry->serial,
drivers/cxl/cxl.h +12 -2
@@ -148,8 +148,18 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)#define CXL_RAS_CAP_CONTROL_FE_MASK GENMASK(5, 0)#define CXL_RAS_HEADER_LOG_OFFSET 0x18#define CXL_RAS_CAPABILITY_LENGTH 0x58 -#define CXL_HEADERLOG_SIZE SZ_512 -#define CXL_HEADERLOG_SIZE_U32 SZ_512 / sizeof(u32) +#define CXL_HEADERLOG_SIZE SZ_64 +#define CXL_HEADERLOG_SIZE_U32 (CXL_HEADERLOG_SIZE / sizeof(u32)) + +/* +* The RAS UCE trace event header array was originally sized at SZ_512/sizeof(u32) +* = 128 u32s due to a bug. Userspace tools (rasdaemon) have grown a dependency +* on that 512-byte layout. Keep the trace array at 128 u32s to preserve the +* ABI; only CXL_HEADERLOG_SIZE_U32 (16) dwords are valid hardware data, the +* remainder are zero-filled. +*/ +#define CXL_HEADERLOG_TRACE_SIZE SZ_512 +#define CXL_HEADERLOG_TRACE_SIZE_U32 (CXL_HEADERLOG_TRACE_SIZE / sizeof(u32))/* CXL 2.0 8.2.8.1 Device Capabilities Array Register */ #define CXLDEV_CAP_ARRAY_OFFSET 0x0
Signature · 1 line
2.53.0