[PATCH 1/3] cxl/hdm: Reject switch decoder interleave ways that overflow targets
Alison Schofield <[email protected]>
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <dad02aebdc2d82537d779ddff459c8c4b5a614da.1783974681.git.alison.schofield@intel.com> |
Switch decoder enumeration validates that the interleave ways encoding is legal, but not that the resulting number of ways fits the available targets. A decoder reporting more interleave ways than available targets can overflow the target arrays during enumeration and target population. Reject decoders during enumeration if their interleave ways exceed the hardware target list or the reported target count. Link: https://sashiko.dev/#/patchset/[email protected]?part=1 Fixes: d17d0540a0db ("cxl/core/hdm: Add CXL standard decoder enumeration to the core") Signed-off-by: Alison Schofield <[email protected]> --- drivers/cxl/core/hdm.c | 18 ++++++++++++++++++ drivers/cxl/cxl.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index 0c80b76a5f9b..d86a607d2a2c 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -1084,6 +1084,24 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, cxld->interleave_ways, cxld->interleave_granularity); if (!cxled) { + struct cxl_switch_decoder *cxlsd = + to_cxl_switch_decoder(&cxld->dev); + + if (cxld->interleave_ways > CXL_HDM_DECODER0_TL_TARGETS) { + dev_err(&port->dev, + "decoder%d.%d: interleave ways: %d exceeds target list capacity: %d\n", + port->id, cxld->id, cxld->interleave_ways, + CXL_HDM_DECODER0_TL_TARGETS); + return -ENXIO; + } + if (cxld->interleave_ways > cxlsd->nr_targets) { + dev_err(&port->dev, + "decoder%d.%d: interleave ways: %d exceeds targets: %d\n", + port->id, cxld->id, cxld->interleave_ways, + cxlsd->nr_targets); + return -ENXIO; + } + lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which)); target_list.value = (hi << 32) + lo; diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index c0e5308e4d1b..6dda96c42849 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -67,6 +67,8 @@ extern const struct nvdimm_security_ops *cxl_security_ops; #define CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12) #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24) #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28) +/* Target list is two 32-bit registers holding one target id per byte */ +#define CXL_HDM_DECODER0_TL_TARGETS 8 #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i) #define CXL_HDM_DECODER0_SKIP_HIGH(i) CXL_HDM_DECODER0_TL_HIGH(i) -- 2.37.3