[PATCH v2 1/2] cxl/hdm: Allow zero sized HDM decoders
From: Richard Cheng
Date: Tue Jun 02 2026 - 01:41:17 EST
CXL r3.2 §8.2.4.20.12 and §14.13.10 permit committing an HDM decoder
with size 0. BIOS commits and LOCKs such decoders to burn slots,
preventing the OS from programming new regions through them, e.g. for a
Type 3 device in a Trusted Computing Base (TCB) established via the
Trusted Security Protocol (TSP).
init_hdm_decoder() rejects these with -ENXIO and aborts port
enumeration, so "cxl list" shows nothing for the affected port.
Set port->commit_end before the size check so later contiguous decoders
pass the out-of-order check, and skip devm_cxl_dpa_reserve() since
zero-size decoder wouldn't need to reserve DPA ranges.
The decoder is added to topology normally, LOCK is read from the HW
control register so "cxl list" reflects the slot's real state.
Signed-off-by: Vishal Aslot <vaslot@xxxxxxxxxx>
Signed-off-by: Richard Cheng <icheng@xxxxxxxxxx>
---
Changelog
v1->v2:
- Add zero-size committed decoders to the topology instead of
skipping them. Drop v1's -ENOSPC sentinel and the matching
"continue" in devm_cxl_enumerate_decoders(); fall through so
add_hdm_decoder() registers the decoder.
- Set port->commit_end unconditionally for any committed decoder,
not only non-zero-size ones, so subsequent decoders satisfy the
out-of-order check.
- Add an explicit early-return before devm_cxl_dpa_reserve() in the
endpoint-decoder path. __cxl_dpa reserve() rejects zero-size
decoders
- Spell out TSP and TCB and cite spec sections in commit message
- Reorder series, implementation first
---
drivers/cxl/core/hdm.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 0c80b76a5f9b..467ac45bee55 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -1031,13 +1031,12 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
return -ENXIO;
}
- if (size == 0) {
- dev_warn(&port->dev,
- "decoder%d.%d: Committed with zero size\n",
- port->id, cxld->id);
- return -ENXIO;
- }
port->commit_end = cxld->id;
+
+ if (size == 0)
+ dev_dbg(&port->dev,
+ "decoder%d.%d: Committed with zero size\n",
+ port->id, cxld->id);
} else {
if (cxled) {
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
@@ -1096,6 +1095,10 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
if (!committed)
return 0;
+ /* Committed zero-size decoder has nothing to reserve in DPA. */
+ if (size == 0)
+ return 0;
+
dpa_size = div_u64_rem(size, cxld->interleave_ways, &remainder);
if (remainder) {
dev_err(&port->dev,
--
2.43.0