Extend cxl_cfmws_find_device() with a parameter that filters on whether the
address lies in an interleaved range. For now all callers accept
interleave configurations so no functional changes.
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
---
Change log:
v5->v6: No change.
hw/cxl/cxl-host.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index a94b893e99..2dc9f77007 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -104,7 +104,7 @@ void cxl_fmws_link_targets(Error **errp)
}
static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
- uint8_t *target)
+ uint8_t *target, bool *interleaved)
{
int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
unsigned int hdm_count;
@@ -138,6 +138,11 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
found = true;
ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
+
+ if (interleaved) {
+ *interleaved = iw_enc != 0;
+ }
+
target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
if (target_idx < 4) {
@@ -157,7 +162,8 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
return found;
}
-static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
+static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr,
+ bool allow_interleave)
{
CXLComponentState *hb_cstate, *usp_cstate;
PCIHostState *hb;
@@ -165,9 +171,13 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
int rb_index;
uint32_t *cache_mem;
uint8_t target;
- bool target_found;
+ bool target_found, interleaved;
PCIDevice *rp, *d;
+ if ((fw->num_targets > 1) && !allow_interleave) {
+ return NULL;
+ }
+
rb_index = (addr / cxl_decode_ig(fw->enc_int_gran)) % fw->num_targets;
hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl_host_bridge);
if (!hb || !hb->bus || !pci_bus_is_cxl(hb->bus)) {
@@ -187,11 +197,16 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
cache_mem = hb_cstate->crb.cache_mem_registers;
- target_found = cxl_hdm_find_target(cache_mem, addr, &target);
+ target_found = cxl_hdm_find_target(cache_mem, addr, &target,
+ &interleaved);
if (!target_found) {
return NULL;
}
+ if (interleaved && !allow_interleave) {
+ return NULL;
+ }
+
rp = pcie_find_port_by_pn(hb->bus, target);
if (!rp) {
return NULL;
@@ -223,11 +238,15 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
cache_mem = usp_cstate->crb.cache_mem_registers;
- target_found = cxl_hdm_find_target(cache_mem, addr, &target);
+ target_found = cxl_hdm_find_target(cache_mem, addr, &target, &interleaved);
if (!target_found) {
return NULL;
}
+ if (interleaved && !allow_interleave) {
+ return NULL;
+ }
+
d = pcie_find_port_by_pn(&PCI_BRIDGE(d)->sec_bus, target);
if (!d) {
return NULL;
@@ -251,7 +270,7 @@ static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,
CXLFixedWindow *fw = opaque;
PCIDevice *d;
- d = cxl_cfmws_find_device(fw, addr + fw->base);
+ d = cxl_cfmws_find_device(fw, addr + fw->base, true);
if (d == NULL) {
*data = 0;
/* Reads to invalid address return poison */
@@ -268,7 +287,7 @@ static MemTxResult cxl_write_cfmws(void *opaque, hwaddr addr,
CXLFixedWindow *fw = opaque;
PCIDevice *d;
- d = cxl_cfmws_find_device(fw, addr + fw->base);
+ d = cxl_cfmws_find_device(fw, addr + fw->base, true);
if (d == NULL) {
/* Writes to invalid address are silent */
return MEMTX_OK;
--
2.43.0
On 26/02/2026 23:20, Alireza Sanaee wrote: > Extend cxl_cfmws_find_device() with a parameter that filters on whether the > address lies in an interleaved range. For now all callers accept > interleave configurations so no functional changes. > > Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com> Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
© 2016 - 2026 Red Hat, Inc.