From: Manish Honap <[email protected]>

The direct mapping code takes the memory backends, component registers
and mapping slots from CXLType3Dev. Collect them in a CXLMemDevice
filled by cxl_mem_device(), and add
cxl_fmws_direct_passthrough_remove_all() to drop every mapping of a
device. The CXL Type-2 device added later in this series uses both.

No functional change for cxl-type3.

AI-used-for: code (prototype)
Signed-off-by: Manish Honap <[email protected]>
---
 hw/cxl/cxl-host.c    | 110 +++++++++++++++++++++++++++++++------------
 include/hw/cxl/cxl.h |   1 +
 2 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index 754f708cce..d9c7599679 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -209,6 +209,37 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, 
hwaddr addr,
     return found;
 }
 
+/* A CXL device with memory that a fixed memory window can map directly */
+typedef struct CXLMemDevice {
+    PCIDevice *pdev;
+    CXLComponentState *cstate;
+    HostMemoryBackend *hostvmem;
+    HostMemoryBackend *hostpmem;
+    MemoryRegion *direct_mr;
+    CXLFixedWindow **direct_mr_fw;
+} CXLMemDevice;
+
+static bool cxl_mem_device(Object *obj, CXLMemDevice *md)
+{
+    CXLType3Dev *ct3d;
+
+    if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
+        return false;
+    }
+    ct3d = CXL_TYPE3(obj);
+    if (md) {
+        *md = (CXLMemDevice) {
+            .pdev = PCI_DEVICE(ct3d),
+            .cstate = &ct3d->cxl_cstate,
+            .hostvmem = ct3d->hostvmem,
+            .hostpmem = ct3d->hostpmem,
+            .direct_mr = ct3d->direct_mr,
+            .direct_mr_fw = ct3d->direct_mr_fw,
+        };
+    }
+    return true;
+}
+
 static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr,
                                         bool allow_interleave)
 {
@@ -265,7 +296,7 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, 
hwaddr addr,
         return NULL;
     }
 
-    if (object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
+    if (cxl_mem_device(OBJECT(d), NULL)) {
         return d;
     }
 
@@ -304,7 +335,7 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, 
hwaddr addr,
         return NULL;
     }
 
-    if (!object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
+    if (!cxl_mem_device(OBJECT(d), NULL)) {
         return NULL;
     }
 
@@ -312,7 +343,7 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, 
hwaddr addr,
 }
 
 typedef struct CXLDirectPTState {
-    CXLType3Dev *ct3d;
+    CXLMemDevice md;
     hwaddr decoder_base;
     hwaddr decoder_size;
     hwaddr dpa_base;
@@ -322,15 +353,15 @@ typedef struct CXLDirectPTState {
 static void cxl_fmws_direct_passthrough_setup(CXLDirectPTState *state,
                                               CXLFixedWindow *fw)
 {
-    CXLType3Dev *ct3d = state->ct3d;
+    CXLMemDevice *md = &state->md;
     MemoryRegion *mr = NULL;
     uint64_t vmr_size = 0, pmr_size = 0, offset = 0;
     MemoryRegion *direct_mr;
     g_autofree char *direct_mr_name = NULL;
     unsigned int idx = state->hdm_decoder_idx;
 
-    if (ct3d->hostvmem) {
-        MemoryRegion *vmr = host_memory_backend_get_memory(ct3d->hostvmem);
+    if (md->hostvmem) {
+        MemoryRegion *vmr = host_memory_backend_get_memory(md->hostvmem);
 
         vmr_size = memory_region_size(vmr);
         if (state->dpa_base < vmr_size) {
@@ -338,8 +369,8 @@ static void 
cxl_fmws_direct_passthrough_setup(CXLDirectPTState *state,
             offset = state->dpa_base;
         }
     }
-    if (!mr && ct3d->hostpmem) {
-        MemoryRegion *pmr = host_memory_backend_get_memory(ct3d->hostpmem);
+    if (!mr && md->hostpmem) {
+        MemoryRegion *pmr = host_memory_backend_get_memory(md->hostpmem);
 
         pmr_size = memory_region_size(pmr);
         if (state->dpa_base - vmr_size < pmr_size) {
@@ -351,37 +382,49 @@ static void 
cxl_fmws_direct_passthrough_setup(CXLDirectPTState *state,
         return;
     }
 
-    if (ct3d->direct_mr_fw[idx]) {
+    if (md->direct_mr_fw[idx]) {
         return;
     }
 
-    direct_mr = &ct3d->direct_mr[idx];
+    direct_mr = &md->direct_mr[idx];
     direct_mr_name = g_strdup_printf("cxl-direct-mapping-alias-%u", idx);
     if (!direct_mr_name) {
         return;
     }
 
-    memory_region_init_alias(direct_mr, OBJECT(ct3d), direct_mr_name, mr,
+    memory_region_init_alias(direct_mr, OBJECT(md->pdev), direct_mr_name, mr,
                              offset, state->decoder_size);
     memory_region_transaction_begin();
     memory_region_add_subregion(&fw->mr,
                                 state->decoder_base - fw->base, direct_mr);
     memory_region_transaction_commit();
-    ct3d->direct_mr_fw[idx] = fw;
+    md->direct_mr_fw[idx] = fw;
+}
+
+static void cxl_fmws_direct_passthrough_unmap(CXLMemDevice *md,
+                                              unsigned int idx)
+{
+    CXLFixedWindow *owner_fw = md->direct_mr_fw[idx];
+    MemoryRegion *direct_mr = &md->direct_mr[idx];
+
+    memory_region_transaction_begin();
+    memory_region_del_subregion(&owner_fw->mr, direct_mr);
+    object_unparent(OBJECT(direct_mr));
+    memory_region_transaction_commit();
+    md->direct_mr_fw[idx] = NULL;
 }
 
-static void cxl_fmws_direct_passthrough_remove(CXLType3Dev *ct3d,
+static void cxl_fmws_direct_passthrough_remove(CXLMemDevice *md,
                                                uint64_t decoder_base,
                                                unsigned int idx)
 {
-    CXLFixedWindow *owner_fw = ct3d->direct_mr_fw[idx];
-    MemoryRegion *direct_mr = &ct3d->direct_mr[idx];
+    CXLFixedWindow *owner_fw = md->direct_mr_fw[idx];
 
     if (!owner_fw) {
         return;
     }
 
-    if (!memory_region_is_mapped(direct_mr)) {
+    if (!memory_region_is_mapped(&md->direct_mr[idx])) {
         return;
     }
 
@@ -389,11 +432,21 @@ static void 
cxl_fmws_direct_passthrough_remove(CXLType3Dev *ct3d,
         return;
     }
 
-    memory_region_transaction_begin();
-    memory_region_del_subregion(&owner_fw->mr, direct_mr);
-    object_unparent(OBJECT(direct_mr));
-    memory_region_transaction_commit();
-    ct3d->direct_mr_fw[idx] = NULL;
+    cxl_fmws_direct_passthrough_unmap(md, idx);
+}
+
+void cxl_fmws_direct_passthrough_remove_all(PCIDevice *dev)
+{
+    CXLMemDevice md;
+
+    if (!cxl_mem_device(OBJECT(dev), &md)) {
+        return;
+    }
+    for (unsigned int i = 0; i < CXL_HDM_DECODER_COUNT; i++) {
+        if (md.direct_mr_fw[i]) {
+            cxl_fmws_direct_passthrough_unmap(&md, i);
+        }
+    }
 }
 
 static int cxl_fmws_direct_passthrough(Object *obj, void *opaque)
@@ -421,19 +474,18 @@ static int update_non_interleaved(Object *obj, void 
*opaque)
 {
     const int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - 
R_CXL_HDM_DECODER0_BASE_LO;
     bool commit = *(bool *)opaque;
-    CXLType3Dev *ct3d;
+    CXLMemDevice md;
     uint32_t *cache_mem;
     unsigned int hdm_count, i;
     int interleave_ways_dec;
     uint32_t cap;
     uint64_t dpa_base = 0;
 
-    if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
+    if (!cxl_mem_device(obj, &md)) {
         return 0;
     }
 
-    ct3d = CXL_TYPE3(obj);
-    cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
+    cache_mem = md.cstate->crb.cache_mem_registers;
     cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
     hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
                                                  CXL_HDM_DECODER_CAPABILITY,
@@ -447,8 +499,8 @@ static int update_non_interleaved(Object *obj, void *opaque)
         committed = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED);
 
         /*
-         * Optimization: Looking for a fully committed path; if the type 3 HDM
-         * decoder is not commmitted, it cannot lie on such a path.
+         * Optimization: Looking for a fully committed path; if the endpoint
+         * HDM decoder is not committed, it cannot lie on such a path.
          */
         if (commit && !committed) {
             return 0;
@@ -473,10 +525,10 @@ static int update_non_interleaved(Object *obj, void 
*opaque)
 
         if (iw == 0) {
             if (!commit) {
-                cxl_fmws_direct_passthrough_remove(ct3d, decoder_base, i);
+                cxl_fmws_direct_passthrough_remove(&md, decoder_base, i);
             } else {
                 CXLDirectPTState state = {
-                    .ct3d = ct3d,
+                    .md = md,
                     .decoder_base = decoder_base,
                     .decoder_size = decoder_size,
                     .dpa_base = dpa_base,
diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
index 7cf3dc622c..e3a3a43236 100644
--- a/include/hw/cxl/cxl.h
+++ b/include/hw/cxl/cxl.h
@@ -84,4 +84,5 @@ typedef struct CXLDownstreamPort CXLDownstreamPort;
 DECLARE_INSTANCE_CHECKER(CXLDownstreamPort, CXL_DSP, TYPE_CXL_DSP)
 
 void cfmws_update_non_interleaved(bool commit);
+void cxl_fmws_direct_passthrough_remove_all(PCIDevice *dev);
 #endif
-- 
2.53.0


Reply via email to