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;