[RFC PATCH v4 25/27] cxl/core: Add private node support to cxl_sysram

Gregory Price
2026-02-22T08:50:34Z

Extend the cxl_sysram region to support N_MEMORY_PRIVATE hotplug
via add_private_memory_driver_managed(). When a caller passes
private=true to devm_cxl_add_sysram(), the memory is registered
as a private node, isolating it from normal allocations and reclaim.

Signed-off-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/core.h | 2 +-
drivers/cxl/core/region_sysram.c | 50 +++++++++++++++++++++++++-------
drivers/cxl/cxl.h | 9 ++++--
3 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 973bbcae43f7..8ca3d6d41fe4 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -56,7 +56,7 @@ u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
u64 dpa);
int devm_cxl_add_dax_region(struct cxl_region *cxlr, enum dax_driver_type);
int devm_cxl_add_pmem_region(struct cxl_region *cxlr);
-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type);
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private, enum mmop online_type);

#else
static inline u64 cxl_dpa_to_hpa(struct cxl_region *cxlr,
diff --git a/drivers/cxl/core/region_sysram.c b/drivers/cxl/core/region_sysram.c
index 47a415deb352..77aaa52e7332 100644
--- a/drivers/cxl/core/region_sysram.c
+++ b/drivers/cxl/core/region_sysram.c
@@ -85,12 +85,23 @@ static int sysram_hotplug_add(struct cxl_sysram *sysram, enum mmop online_type)
/*
* Ensure that future kexec'd kernels will not treat
* this as RAM automatically.
+ *
+ * For private regions, use add_private_memory_driver_managed()
+ * to register as N_MEMORY_PRIVATE which isolates the memory from
+ * normal allocations and reclaim.
*/
- rc = __add_memory_driver_managed(sysram->mgid,
- sysram->hpa_range.start,
- range_len(&sysram->hpa_range),
- sysram_res_name, mhp_flags,
- online_type);
+ if (sysram->private)
+ rc = add_private_memory_driver_managed(sysram->mgid,
+ sysram->hpa_range.start,
+ range_len(&sysram->hpa_range),
+ sysram_res_name, mhp_flags,
+ online_type, &sysram->np);
+ else
+ rc = __add_memory_driver_managed(sysram->mgid,
+ sysram->hpa_range.start,
+ range_len(&sysram->hpa_range),
+ sysram_res_name, mhp_flags,
+ online_type);
if (rc) {
remove_resource(res);
kfree(res);
@@ -108,10 +119,23 @@ static int sysram_hotplug_remove(struct cxl_sysram *sysram)
if (!sysram->res)
return 0;

- rc = offline_and_remove_memory(sysram->hpa_range.start,
- range_len(&sysram->hpa_range));
- if (rc)
- return rc;
+ if (sysram->private) {
+ rc = offline_and_remove_private_memory(sysram->numa_node,
+ sysram->hpa_range.start,
+ range_len(&sysram->hpa_range));
+ /*
+ * -EBUSY means memory was removed but node_private_unregister()
+ * could not complete because other regions share the node.
+ * Continue to resource cleanup since the memory is gone.
+ */
+ if (rc && rc != -EBUSY)
+ return rc;
+ } else {
+ rc = offline_and_remove_memory(sysram->hpa_range.start,
+ range_len(&sysram->hpa_range));
+ if (rc)
+ return rc;
+ }

if (sysram->res) {
remove_resource(sysram->res);
@@ -257,7 +281,8 @@ static void sysram_unregister(void *_sysram)
device_unregister(&sysram->dev);
}

-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type)
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private,
+ enum mmop online_type)
{
struct cxl_sysram *sysram __free(put_cxl_sysram) = NULL;
struct memory_dev_type *mtype;
@@ -291,6 +316,11 @@ int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type)
if (online_type >= 0)
sysram->online_type = online_type;

+ /* Set up private node registration if requested */
+ sysram->private = private;
+ if (private)
+ sysram->np.owner = sysram;
+
dev = &sysram->dev;

rc = dev_set_name(dev, "sysram_region%d", cxlr->id);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 8e8342fd4fde..54e5f9ac59dc 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/node.h>
+#include <linux/node_private.h>
#include <linux/io.h>
#include <linux/range.h>
#include <linux/dax.h>
@@ -619,6 +620,8 @@ struct cxl_dax_region {
* @mgid: Memory group id
* @mtype: Memory tier type
* @numa_node: NUMA node for this memory
+ * @private: true if this region uses N_MEMORY_PRIVATE hotplug
+ * @np: private node registration state (valid when @private is true)
*
* Device that directly performs memory hotplug for CXL RAM regions.
*/
@@ -633,6 +636,8 @@ struct cxl_sysram {
int mgid;
struct memory_dev_type *mtype;
int numa_node;
+ bool private;
+ struct node_private np;
};

/**
@@ -987,7 +992,7 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
struct cxl_sysram *to_cxl_sysram(struct device *dev);
struct device *cxl_sysram_dev(struct cxl_sysram *sysram);
-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type);
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private, enum mmop online_type);
int cxl_sysram_offline_and_remove(struct cxl_sysram *sysram);
u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
#else
@@ -1011,7 +1016,7 @@ static inline struct cxl_sysram *to_cxl_sysram(struct device *dev)
{
return NULL;
}
-static inline int devm_cxl_add_sysram(struct cxl_region *cxlr,
+static inline int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private,
enum mmop online_type)
{
return -ENXIO;
--
2.53.0