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 <[email protected]> --- 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
