[PATCH v7 2/3] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted

Alireza Sanaee via qemu development posted 3 patches 1 month, 1 week ago
Maintainers: Jonathan Cameron <jonathan.cameron@huawei.com>, Fan Ni <fan.ni@samsung.com>
There is a newer version of this series
[PATCH v7 2/3] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
Posted by Alireza Sanaee via qemu development 1 month, 1 week ago
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>
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
---
Thanks to Li for the tag.

Change log:
v6->v7: 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
Re: [PATCH v7 2/3] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
Posted by Gregory Price 1 month, 1 week ago
On Fri, Mar 06, 2026 at 12:11:50PM +0000, 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.
> 
> Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
> Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>

Reviewed-by: Gregory Price <gourry@gourry.net>
Tested-by: Gregory Price <gourry@gourry.net>

> ---
> Thanks to Li for the tag.
> 
> Change log:
> v6->v7: 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
>
Re: [PATCH v7 2/3] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
Posted by Jonathan Cameron via qemu development 1 month, 1 week ago
On Fri, 6 Mar 2026 12:11:50 +0000
Alireza Sanaee <alireza.sanaee@huawei.com> 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.
> 
> Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
> Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>