FAILED: patch "[PATCH] cxl/mce: Make the MCE notifier per-region" 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 775d0f4558f4cec0ee0c8966595d1add1791f36e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090359-scale-swell-330d@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 775d0f4558f4cec0ee0c8966595d1add1791f36e Mon Sep 17 00:00:00 2001
From: Dave Jiang <[email protected]>
Date: Tue, 16 Jun 2026 15:49:11 -0700
Subject: [PATCH] cxl/mce: Make the MCE notifier per-region
Flavien Solt reported lifetime issues with the CXL MCE notifier, which can lead to NULL dereferences and use-after-free in the MCE handler. The notifier was registered per memory device and stored in 'struct cxl_memdev_state', even though it only needs the region state (the region's SPA range and its extended linear cache size).
Instead of keeping the memory device and endpoint alive, the correct fix is to move the notifier into 'struct cxl_region' and register it from cxl_region_probe() as it should be a per-region notifier. Setup the registration to only happen for regions that have an extended linear cache as that is the only current usage.
Remove cxl_port_get_spa_cache_alias() as it is now dead code.
[ dj: Update dev_warn() when notifier fails due to kconfig. (Ben) ]
drivers/cxl/core/mbox.c +0 -8
@@ -11,7 +11,6 @@#include "core.h" #include "trace.h" -#include "mce.h" static bool cxl_raw_allow_all;
@@ -1522,7 +1521,6 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial, u16 dvsec) {struct cxl_memdev_state *mds; -int rc; mds = devm_cxl_dev_state_create(dev, CXL_DEVTYPE_CLASSMEM, serial, dvsec, struct cxl_memdev_state, cxlds,
@@ -1534,12 +1532,6 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,mutex_init (&mds->event.log_lock); - rc =devm_cxl_register_mce_notifier (dev, &mds->mce_notifier); -if (rc == -EOPNOTSUPP ) -dev_warn (dev,"CXL MCE unsupported\n" ); -else if (rc) -return ERR_PTR (rc); -return mds; }EXPORT_SYMBOL_NS_GPL (cxl_memdev_state_create,"CXL" );
drivers/cxl/core/mce.c +13 -14
@@ -4,16 +4,16 @@#include <linux/notifier.h> #include <linux/set_memory.h> #include <asm/mce.h> -#include <cxlmem.h> +#include <cxl.h> +#include "core.h" #include "mce.h" static int cxl_handle_mce (struct notifier_block *nb,unsigned long val,void *data) { - struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state, - mce_notifier); -struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; -struct cxl_port *endpoint = cxlmd->endpoint; + struct cxl_region *cxlr = container_of(nb, struct cxl_region, + mce_notifier); +struct cxl_region_params *p = &cxlr->params;struct mce *mce = data;u64 spa, spa_alias;unsigned long pfn;
@@ -21,26 +21,25 @@ static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,if (!mce || !mce_usable_address (mce))return NOTIFY_DONE ; -if (!endpoint) -return NOTIFY_DONE ; - spa = mce->addr &MCI_ADDR_PHYSADDR ; - pfn = spa >>PAGE_SHIFT ; -if (!pfn_valid (pfn)) +if (!cxl_resource_contains_addr (p->res, spa))return NOTIFY_DONE ; - spa_alias =cxl_port_get_spa_cache_alias (endpoint, spa); -if (spa_alias == ~0ULL ) -return NOTIFY_DONE ; +if (spa >= p->res->start + p->cache_size) + spa_alias = spa - p->cache_size; +else + spa_alias = spa + p->cache_size; pfn = spa_alias >>PAGE_SHIFT ; +if (!pfn_valid (pfn)) +return NOTIFY_DONE ;/* * Take down the aliased memory page. The original memory page flagged * by the MCE will be taken cared of by the standard MCE handler. */ -dev_emerg (mds->cxlds.dev,"Offlining aliased SPA address0: %#llx\n" , +dev_emerg (&cxlr->dev,"Offlining aliased SPA address0: %#llx\n" , spa_alias);if (!memory_failure (pfn,0 ))set_mce_nospec (pfn);
drivers/cxl/core/region.c +15 -28
61 lines not on this page · raw message
drivers/cxl/cxl.h +2 -6
@@ -478,6 +478,7 @@ struct cxl_region_params {* @coord: QoS access coordinates for the region * @node_notifier: notifier for setting the access coordinates to node * @adist_notifier: notifier for calculating the abstract distance of node +* @mce_notifier: notifier for MCE */ struct cxl_region {struct device dev;
@@ -493,6 +494,7 @@ struct cxl_region {struct access_coordinate coord[ACCESS_COORDINATE_MAX ];struct notifier_block node_notifier;struct notifier_block adist_notifier; +struct notifier_block mce_notifier; };struct cxl_nvdimm_bridge {
@@ -870,7 +872,6 @@ bool is_cxl_pmem_region(struct device *dev);struct cxl_pmem_region *to_cxl_pmem_region (struct device *dev);int cxl_add_to_region (struct cxl_endpoint_decoder *cxled);struct cxl_dax_region *to_cxl_dax_region (struct device *dev); -u64 cxl_port_get_spa_cache_alias (struct cxl_port *endpoint,u64 spa);bool cxl_region_contains_resource (const struct resource *res);#else static inline bool is_cxl_pmem_region (struct device *dev)
@@ -889,11 +890,6 @@ static inline struct cxl_dax_region *to_cxl_dax_region(struct device *dev) {return NULL ; } -static inline u64 cxl_port_get_spa_cache_alias (struct cxl_port *endpoint, -u64 spa) -{ -return 0 ; -}static inline bool cxl_region_contains_resource (const struct resource *res) {return false;
drivers/cxl/cxlmem.h +0 -2
@@ -431,7 +431,6 @@ static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox)* @poison: poison driver state info * @security: security driver state info * @fw: firmware upload / activation state -* @mce_notifier: MCE notifier * * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters.
@@ -451,7 +450,6 @@ struct cxl_memdev_state {struct cxl_poison_state poison;struct cxl_security_state security;struct cxl_fw_state fw; -struct notifier_block mce_notifier; }; static inline struct cxl_memdev_state *
Sasha Levin
maintainerPATCH 1/3 dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding
From: Dan Williams <[email protected]>
[ Upstream commit 39aa1d4be12bf9f685adaa06aa2d997c1c611b16 ]
Move hmem/ earlier in the dax Makefile so that hmem_init() runs before dax_cxl.
In addition, defer registration of the dax_cxl driver to a workqueue instead of using module_cxl_driver(). This ensures that dax_hmem has an opportunity to initialize and register its deferred callback and make ownership decisions before dax_cxl begins probing and claiming Soft Reserved ranges.
Mark the dax_cxl driver as PROBE_PREFER_ASYNCHRONOUS so its probe runs out of line from other synchronous probing avoiding ordering dependencies while coordinating ownership decisions with dax_hmem.
Stable-dep-of: 775d0f4558f4 ("cxl/mce: Make the MCE notifier per-region")
--- drivers/dax/Makefile | 3 +-- drivers/dax/cxl.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-)
drivers/dax/Makefile +1 -2
@@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-y += hmem/ obj-$(CONFIG_DAX) += dax.o obj-$(CONFIG_DEV_DAX) += device_dax.o obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
@@ -10,5 +11,3 @@ dax-y += bus.o device_dax-y := device.o dax_pmem-y := pmem.o dax_cxl-y := cxl.o - -obj-y += hmem/
drivers/dax/cxl.c +26 -1
@@ -38,10 +38,35 @@ static struct cxl_driver cxl_dax_region_driver = { .id = CXL_DEVICE_DAX_REGION, .drv = { .suppress_bind_attrs = true, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; -module_cxl_driver (cxl_dax_region_driver); +static void cxl_dax_region_driver_register (struct work_struct *work) +{ +cxl_driver_register (&cxl_dax_region_driver); +} + +static DECLARE_WORK(cxl_dax_region_driver_work, cxl_dax_region_driver_register); + +static int __init cxl_dax_region_init (void ) +{ +/* +* Need to resolve a race with dax_hmem wanting to drive regions +* instead of CXL +*/ +queue_work (system_long_wq, &cxl_dax_region_driver_work); +return 0 ; +} +module_init (cxl_dax_region_init); + +static void __exit cxl_dax_region_exit(void) +{ +flush_work (&cxl_dax_region_driver_work); +cxl_driver_unregister (&cxl_dax_region_driver); +} +module_exit (cxl_dax_region_exit); +MODULE_ALIAS_CXL (CXL_DEVICE_DAX_REGION );MODULE_DESCRIPTION ("CXL DAX: direct access to CXL regions" );MODULE_LICENSE ("GPL" );
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 cxl/region: Add helper to check Soft Reserved containment by CXL regions
From: Smita Koralahalli <[email protected]>
[ Upstream commit 8e65f99b525b3f49b87db0db0d0e0fc1a0c53e40 ]
Add a helper to determine whether a given Soft Reserved memory range is fully contained within the committed CXL region.
This helper provides a primitive for policy decisions in subsequent patches such as co-ordination with dax_hmem to determine whether CXL has fully claimed ownership of Soft Reserved memory ranges.
[ sashal: Reduced backport -- upstream 8e65f99b525b3 touches 2 file(s), this
backport carries 2. Not backported here:
include/cxl/cxl.h
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 775d0f4558f4 ("cxl/mce: Make the MCE notifier per-region")
--- drivers/cxl/core/region.c | 83 +++++++++++++++++++++++++++------------ drivers/cxl/cxl.h | 5 +++ 2 files changed, 63 insertions(+), 25 deletions(-)
drivers/cxl/core/region.c +58 -25
@@ -3751,6 +3751,61 @@ static int cxl_region_debugfs_poison_clear(void *data, u64 offset)DEFINE_DEBUGFS_ATTRIBUTE (cxl_poison_clear_fops,NULL , cxl_region_debugfs_poison_clear,"%llx\n" ); +static int cxl_region_setup_poison (struct cxl_region *cxlr) +{ +struct device *dev = &cxlr->dev; +struct cxl_region_params *p = &cxlr->params; +struct dentry *dentry; + +/* Create poison attributes if all memdevs support the capabilities */ +for (int i =0 ; i < p->nr_targets; i++) { +struct cxl_endpoint_decoder *cxled = p->targets[i]; +struct cxl_memdev *cxlmd =cxled_to_memdev (cxled); + +if (!cxl_memdev_has_poison_cmd (cxlmd,CXL_POISON_ENABLED_INJECT ) || + !cxl_memdev_has_poison_cmd (cxlmd,CXL_POISON_ENABLED_CLEAR )) +return 0 ; + } + + dentry =cxl_debugfs_create_dir (dev_name (dev)); +debugfs_create_file ("inject_poison" ,0200 , dentry, cxlr, + &cxl_poison_inject_fops); +debugfs_create_file ("clear_poison" ,0200 , dentry, cxlr, + &cxl_poison_clear_fops); + +return devm_add_action_or_reset (dev, remove_debugfs, dentry); +} + +static int region_contains_resource (struct device *dev,const void *data) +{ +const struct resource *res = data; +struct cxl_region *cxlr; +struct cxl_region_params *p; + +if (!is_cxl_region (dev)) +return 0 ; + + cxlr =to_cxl_region (dev); + p = &cxlr->params; + +if (p->state !=CXL_CONFIG_COMMIT ) +return 0 ; + +if (!p->res) +return 0 ; + +return resource_contains (p->res, res) ?1 :0 ; +} + +bool cxl_region_contains_resource (const struct resource *res) +{ +guard (rwsem_read)(&cxl_rwsem.region); + struct device *dev __free(put_device) = bus_find_device( + &cxl_bus_type,NULL , res, region_contains_resource); +return !!dev; +} +EXPORT_SYMBOL_FOR_MODULES (cxl_region_contains_resource,"dax_hmem" ); +static int cxl_region_can_probe (struct cxl_region *cxlr) {struct cxl_region_params *p = &cxlr->params;
@@ -3780,7 +3835,6 @@ static int cxl_region_probe(struct device *dev) {struct cxl_region *cxlr =to_cxl_region (dev);struct cxl_region_params *p = &cxlr->params; -bool poison_supported = true;int rc; rc =cxl_region_can_probe (cxlr);
@@ -3804,30 +3858,9 @@ static int cxl_region_probe(struct device *dev)if (rc)return rc; -/* Create poison attributes if all memdevs support the capabilities */ -for (int i =0 ; i < p->nr_targets; i++) { -struct cxl_endpoint_decoder *cxled = p->targets[i]; -struct cxl_memdev *cxlmd =cxled_to_memdev (cxled); - -if (!cxl_memdev_has_poison_cmd (cxlmd,CXL_POISON_ENABLED_INJECT ) || - !cxl_memdev_has_poison_cmd (cxlmd,CXL_POISON_ENABLED_CLEAR )) { - poison_supported = false; -break ; - } - } - -if (poison_supported) { -struct dentry *dentry; - - dentry =cxl_debugfs_create_dir (dev_name (dev)); -debugfs_create_file ("inject_poison" ,0200 , dentry, cxlr, - &cxl_poison_inject_fops); -debugfs_create_file ("clear_poison" ,0200 , dentry, cxlr, - &cxl_poison_clear_fops); - rc =devm_add_action_or_reset (dev, remove_debugfs, dentry); -if (rc) -return rc; - } + rc =cxl_region_setup_poison (cxlr); +if (rc) +return rc;switch (cxlr->mode) {case CXL_PARTMODE_PMEM :
drivers/cxl/cxl.h +5 -0
@@ -887,6 +887,7 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);int cxl_add_to_region (struct cxl_endpoint_decoder *cxled);struct cxl_dax_region *to_cxl_dax_region (struct device *dev);u64 cxl_port_get_spa_cache_alias (struct cxl_port *endpoint,u64 spa); +bool cxl_region_contains_resource (const struct resource *res);#else static inline bool is_cxl_pmem_region (struct device *dev) {
@@ -909,6 +910,10 @@ static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, {return 0 ; } +static inline bool cxl_region_contains_resource (const struct resource *res) +{ +return false; +}#endif void cxl_endpoint_parse_cdat (struct cxl_port *port);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 cxl/mce: Make the MCE notifier per-region
In reply to Sasha LevinFrom: Dave Jiang <[email protected]>
[ Upstream commit 775d0f4558f4cec0ee0c8966595d1add1791f36e ]
Flavien Solt reported lifetime issues with the CXL MCE notifier, which can lead to NULL dereferences and use-after-free in the MCE handler. The notifier was registered per memory device and stored in 'struct cxl_memdev_state', even though it only needs the region state (the region's SPA range and its extended linear cache size).
Instead of keeping the memory device and endpoint alive, the correct fix is to move the notifier into 'struct cxl_region' and register it from cxl_region_probe() as it should be a per-region notifier. Setup the registration to only happen for regions that have an extended linear cache as that is the only current usage.
Remove cxl_port_get_spa_cache_alias() as it is now dead code.
[ dj: Update dev_warn() when notifier fails due to kconfig. (Ben) ]
--- drivers/cxl/core/mbox.c | 8 -------- drivers/cxl/core/mce.c | 27 ++++++++++++------------ drivers/cxl/core/region.c | 43 ++++++++++++++------------------------- drivers/cxl/cxl.h | 8 ++------ drivers/cxl/cxlmem.h | 2 -- 5 files changed, 30 insertions(+), 58 deletions(-)
drivers/cxl/core/mbox.c +0 -8
@@ -11,7 +11,6 @@#include "core.h" #include "trace.h" -#include "mce.h" static bool cxl_raw_allow_all;
@@ -1524,7 +1523,6 @@ EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");struct cxl_memdev_state *cxl_memdev_state_create (struct device *dev) {struct cxl_memdev_state *mds; -int rc; mds =devm_kzalloc (dev,sizeof (*mds),GFP_KERNEL );if (!mds) {
@@ -1539,12 +1537,6 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) mds->cxlds.reg_map.resource =CXL_RESOURCE_NONE ; mds->cxlds.type =CXL_DEVTYPE_CLASSMEM ; - rc =devm_cxl_register_mce_notifier (dev, &mds->mce_notifier); -if (rc == -EOPNOTSUPP ) -dev_warn (dev,"CXL MCE unsupported\n" ); -else if (rc) -return ERR_PTR (rc); -return mds; }EXPORT_SYMBOL_NS_GPL (cxl_memdev_state_create,"CXL" );
drivers/cxl/core/mce.c +13 -14
@@ -4,16 +4,16 @@#include <linux/notifier.h> #include <linux/set_memory.h> #include <asm/mce.h> -#include <cxlmem.h> +#include <cxl.h> +#include "core.h" #include "mce.h" static int cxl_handle_mce (struct notifier_block *nb,unsigned long val,void *data) { - struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state, - mce_notifier); -struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; -struct cxl_port *endpoint = cxlmd->endpoint; + struct cxl_region *cxlr = container_of(nb, struct cxl_region, + mce_notifier); +struct cxl_region_params *p = &cxlr->params;struct mce *mce = data;u64 spa, spa_alias;unsigned long pfn;
@@ -21,26 +21,25 @@ static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,if (!mce || !mce_usable_address (mce))return NOTIFY_DONE ; -if (!endpoint) -return NOTIFY_DONE ; - spa = mce->addr &MCI_ADDR_PHYSADDR ; - pfn = spa >>PAGE_SHIFT ; -if (!pfn_valid (pfn)) +if (!cxl_resource_contains_addr (p->res, spa))return NOTIFY_DONE ; - spa_alias =cxl_port_get_spa_cache_alias (endpoint, spa); -if (spa_alias == ~0ULL ) -return NOTIFY_DONE ; +if (spa >= p->res->start + p->cache_size) + spa_alias = spa - p->cache_size; +else + spa_alias = spa + p->cache_size; pfn = spa_alias >>PAGE_SHIFT ; +if (!pfn_valid (pfn)) +return NOTIFY_DONE ;/* * Take down the aliased memory page. The original memory page flagged * by the MCE will be taken cared of by the standard MCE handler. */ -dev_emerg (mds->cxlds.dev,"Offlining aliased SPA address0: %#llx\n" , +dev_emerg (&cxlr->dev,"Offlining aliased SPA address0: %#llx\n" , spa_alias);if (!memory_failure (pfn,0 ))set_mce_nospec (pfn);
drivers/cxl/core/region.c +15 -28
61 lines not on this page · raw message
drivers/cxl/cxl.h +2 -6
@@ -540,6 +540,7 @@ enum cxl_partition_mode {* @coord: QoS access coordinates for the region * @node_notifier: notifier for setting the access coordinates to node * @adist_notifier: notifier for calculating the abstract distance of node +* @mce_notifier: notifier for MCE */ struct cxl_region {struct device dev;
@@ -553,6 +554,7 @@ struct cxl_region {struct access_coordinate coord[ACCESS_COORDINATE_MAX ];struct notifier_block node_notifier;struct notifier_block adist_notifier; +struct notifier_block mce_notifier; };struct cxl_nvdimm_bridge {
@@ -886,7 +888,6 @@ bool is_cxl_pmem_region(struct device *dev);struct cxl_pmem_region *to_cxl_pmem_region (struct device *dev);int cxl_add_to_region (struct cxl_endpoint_decoder *cxled);struct cxl_dax_region *to_cxl_dax_region (struct device *dev); -u64 cxl_port_get_spa_cache_alias (struct cxl_port *endpoint,u64 spa);bool cxl_region_contains_resource (const struct resource *res);#else static inline bool is_cxl_pmem_region (struct device *dev)
@@ -905,11 +906,6 @@ static inline struct cxl_dax_region *to_cxl_dax_region(struct device *dev) {return NULL ; } -static inline u64 cxl_port_get_spa_cache_alias (struct cxl_port *endpoint, -u64 spa) -{ -return 0 ; -}static inline bool cxl_region_contains_resource (const struct resource *res) {return false;
drivers/cxl/cxlmem.h +0 -2
@@ -484,7 +484,6 @@ static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox)* @poison: poison driver state info * @security: security driver state info * @fw: firmware upload / activation state -* @mce_notifier: MCE notifier * * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters.
@@ -504,7 +503,6 @@ struct cxl_memdev_state {struct cxl_poison_state poison;struct cxl_security_state security;struct cxl_fw_state fw; -struct notifier_block mce_notifier; }; static inline struct cxl_memdev_state *
Signature · 1 line
2.53.0