[RFC PATCH 4/4] cxl/extent: Reject tagged extents that span DC partitions

From: John Groves

Date: Thu Apr 23 2026 - 19:52:50 EST


From: John Groves <John@xxxxxxxxxx>

A CXL DC partition is described by a CDAT DSMAS entry whose attribute
bits cover sharable vs. non-sharable, writable vs. read-only, and HW
vs. SW cache coherency (HDM-DB vs. HDM-H). A single tagged allocation
is a single host-visible object; it cannot meaningfully straddle two
partitions whose CDAT attributes disagree.

At today's driver granularity each DC partition maps to at most one
DSMAS entry (see update_perf_entry() in core/cdat.c and the
"Dynamic RAM perf mismatch" warning), and the only attribute plumbed
out of DSMAS into cxl_dpa_perf is ->shareable. Comparing the
containing cxl_dpa_partition of every extent in a tag group is
therefore a sufficient proxy for "same CDAT attributes": if all
extents resolve to the same partition pointer, they share every
attribute the driver currently distinguishes, and the check will
continue to hold as more DSMAS attributes get plumbed in the future
without needing to inspect them individually here.

Add cxl_check_group_partition() as step (4) of cxl_add_pending(),
between sequence-number integrity and the alignment gate. It walks
the sorted group, resolves each extent via cxl_extent_dc_partition(),
and rejects the whole group with a firmware-bug warning naming the
two offending DPAs if any extent's partition differs from the first.

The check is skipped for the null UUID: the spec does not define a
cross-chain identity for untagged extents, and the driver aggregates
them separately.

Signed-off-by: John Groves <John@xxxxxxxxxx>
Signed-off-by: John Groves <john@xxxxxxxxxx>
---
drivers/cxl/core/mbox.c | 84 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 80 insertions(+), 4 deletions(-)

diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 3ffcd90698f3c..b5300b48879f9 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1529,6 +1529,65 @@ static int cxl_check_group_seq(struct device *dev,
return 0;
}

+/*
+ * For tagged groups, reject allocations that span DC partitions.
+ *
+ * A tag is an allocation identity; the CDAT DSMAS entry that describes
+ * the containing DC partition is what tells the host which attributes
+ * (sharable, writable, HW cache coherency) apply. At current driver
+ * granularity each DC partition is described by at most one DSMAS and
+ * the only plumbed attribute is part->perf.shareable — but partition
+ * identity is a sufficient proxy for "same set of CDAT attributes."
+ * Comparing the containing cxl_dpa_partition of every extent to the
+ * first extent's therefore implicitly enforces attribute equality for
+ * all attributes the driver distinguishes today, and will keep doing so
+ * as more attributes become CDAT-plumbed.
+ *
+ * Untagged (null-UUID) groups are not meaningful here: the spec does
+ * not define a cross-chain identity for them and the driver aggregates
+ * them separately; skip the check.
+ */
+static int cxl_check_group_partition(struct cxl_memdev_state *mds,
+ const uuid_t *tag,
+ const struct list_head *group)
+{
+ struct device *dev = mds->cxlds.dev;
+ const struct cxl_dpa_partition *first_part = NULL;
+ u64 first_dpa = 0;
+ struct cxl_extent_list_node *pos;
+
+ if (uuid_is_null(tag) || list_empty(group))
+ return 0;
+
+ list_for_each_entry(pos, group, list) {
+ struct cxl_extent *extent = pos->extent;
+ struct range ext_range = (struct range) {
+ .start = le64_to_cpu(extent->start_dpa),
+ .end = le64_to_cpu(extent->start_dpa) +
+ le64_to_cpu(extent->length) - 1,
+ };
+ const struct cxl_dpa_partition *part;
+
+ part = cxl_extent_dc_partition(mds, extent, &ext_range);
+ if (!part)
+ return -ENXIO;
+
+ if (!first_part) {
+ first_part = part;
+ first_dpa = ext_range.start;
+ continue;
+ }
+
+ if (part != first_part) {
+ dev_warn(dev,
+ "Tag %pUb: extents span DC partitions (DPA:%#llx and DPA:%#llx), firmware bug\n",
+ tag, first_dpa, ext_range.start);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
/*
* Assemble the pending Add-Capacity events into dax devices and send the
* ADD_DC_RESPONSE.
@@ -1597,13 +1656,18 @@ static int cxl_check_group_seq(struct device *dev,
* group is exactly 1, 2, ..., n (sharable). Mix, gap,
* duplicate, or a non-zero set that does not start at 1 is a
* firmware bug; drop the whole group.
- * 4. Alignment gate — every extent's start_dpa and length must be
+ * 4. Partition equality — for tagged groups, every extent must
+ * resolve to the same DC partition. CDAT describes a partition
+ * with a DSMAS entry carrying sharable / writable / coherency
+ * attributes; a single allocation cannot span differing CDAT
+ * attributes. Skipped for the null UUID.
+ * 5. Alignment gate — every extent's start_dpa and length must be
* CXL_DCD_EXTENT_ALIGN-aligned, else drop the whole group with
* a warning. Partial acceptance would leave an unusable dax
* device.
- * 5. Validate + cxl_add_extent() each surviving extent into a fresh
+ * 6. Validate + cxl_add_extent() each surviving extent into a fresh
* region_extent built up in add_ctx.
- * 6. Online + notify the region_extent, splice accepted extents
+ * 7. Online + notify the region_extent, splice accepted extents
* into the response list, clear the add_ctx slot so the next
* tag's group can build its own. online_region_extent() inserts
* each realized region_extent into cxlr_dax->region_extents
@@ -1673,7 +1737,19 @@ static int cxl_add_pending(struct cxl_memdev_state *mds)
continue;
}

- /* (4) Alignment gate — abort the group if any member fails */
+ /*
+ * (4) Partition equality — tagged allocations cannot span DC
+ * partitions, because a DC partition is the unit at which CDAT
+ * attributes (sharable, writable, coherency) are described.
+ * Skipped for the null UUID.
+ */
+ if (cxl_check_group_partition(mds, &tag, &group)) {
+ list_for_each_entry_safe(pos, tmp, &group, list)
+ delete_extent_node(pos);
+ continue;
+ }
+
+ /* (5) Alignment gate — abort the group if any member fails */
list_for_each_entry(pos, &group, list) {
if (!cxl_extent_dcd_aligned(pos->extent)) {
dev_warn(dev,
--
2.53.0