@samitouri / QOSamiQemu / commits / 6ba309a37a

hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted

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. Reviewed-by: Li Zhijian <lizhijian@fujitsu.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Gregory Price <gourry@gourry.net> Tested-by: Gregory Price <gourry@gourry.net> Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260318171918.146-3-alireza.sanaee@huawei.com>

Alireza Sanaee committed Mar 18, 2026 at 17:19 UTC 6ba309a37abd741dc8c8616d378fe27422b1e82f
1 file changed +26 -7
hw/cxl/cxl-host.c
+26 -7
@@ -104,7 +104,7 @@ void cxl_fmws_link_targets(Error **errp)
104 }
105
106 static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
107 - uint8_t *target)
107 + uint8_t *target, bool *interleaved)
108 {
109 int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
110 unsigned int hdm_count;
@@ -138,6 +138,11 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
138 found = true;
139 ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
140 iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
141 +
142 + if (interleaved) {
143 + *interleaved = iw_enc != 0;
144 + }
145 +
146 target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
147
148 if (target_idx < 4) {
@@ -157,7 +162,8 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
162 return found;
163 }
164
160 -static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
165 +static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr,
166 + bool allow_interleave)
167 {
168 CXLComponentState *hb_cstate, *usp_cstate;
169 PCIHostState *hb;
@@ -165,9 +171,13 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
171 int rb_index;
172 uint32_t *cache_mem;
173 uint8_t target;
168 - bool target_found;
174 + bool target_found, interleaved;
175 PCIDevice *rp, *d;
176
177 + if ((fw->num_targets > 1) && !allow_interleave) {
178 + return NULL;
179 + }
180 +
181 rb_index = (addr / cxl_decode_ig(fw->enc_int_gran)) % fw->num_targets;
182 hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl_host_bridge);
183 if (!hb || !hb->bus || !pci_bus_is_cxl(hb->bus)) {
@@ -187,11 +197,16 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
197
198 cache_mem = hb_cstate->crb.cache_mem_registers;
199
190 - target_found = cxl_hdm_find_target(cache_mem, addr, &target);
200 + target_found = cxl_hdm_find_target(cache_mem, addr, &target,
201 + &interleaved);
202 if (!target_found) {
203 return NULL;
204 }
205
206 + if (interleaved && !allow_interleave) {
207 + return NULL;
208 + }
209 +
210 rp = pcie_find_port_by_pn(hb->bus, target);
211 if (!rp) {
212 return NULL;
@@ -223,11 +238,15 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
238
239 cache_mem = usp_cstate->crb.cache_mem_registers;
240
226 - target_found = cxl_hdm_find_target(cache_mem, addr, &target);
241 + target_found = cxl_hdm_find_target(cache_mem, addr, &target, &interleaved);
242 if (!target_found) {
243 return NULL;
244 }
245
246 + if (interleaved && !allow_interleave) {
247 + return NULL;
248 + }
249 +
250 d = pcie_find_port_by_pn(&PCI_BRIDGE(d)->sec_bus, target);
251 if (!d) {
252 return NULL;
@@ -251,7 +270,7 @@ static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,
270 CXLFixedWindow *fw = opaque;
271 PCIDevice *d;
272
254 - d = cxl_cfmws_find_device(fw, addr + fw->base);
273 + d = cxl_cfmws_find_device(fw, addr + fw->base, true);
274 if (d == NULL) {
275 *data = 0;
276 /* Reads to invalid address return poison */
@@ -268,7 +287,7 @@ static MemTxResult cxl_write_cfmws(void *opaque, hwaddr addr,
287 CXLFixedWindow *fw = opaque;
288 PCIDevice *d;
289
271 - d = cxl_cfmws_find_device(fw, addr + fw->base);
290 + d = cxl_cfmws_find_device(fw, addr + fw->base, true);
291 if (d == NULL) {
292 /* Writes to invalid address are silent */
293 return MEMTX_OK;