From: Zhi Wang <[email protected]>

Add cxl-type2, a minimal CXL Type-2 device for testing the Linux CXL
core Type-2 support and CXL Type-2 passthrough. It does not reuse
cxl-type3, as most Type-3 features do not apply to a Type-2 device.

This patch adds the device and its volatile memory backend. The next
two add the component registers and guest access to the memory through
the fixed memory windows.

Co-developed-by: Ira Weiny <[email protected]>
Signed-off-by: Ira Weiny <[email protected]>
Signed-off-by: Zhi Wang <[email protected]>
[ clg: - use PCI_CLASS_MEMORY_CXL instead of PCI_CLASS_CXL_QEMU_ACCEL
         to match cxl_pci driver expectations
       - rebased on upstream ]
Signed-off-by: Cédric Le Goater <[email protected]>
[ mhonap: - split the original patch in three patches
          - rename cxl-accel to cxl-type2
          - use the Red Hat ID 1b36:0017 and the processing accelerator
            class 0x1200, so that cxl_pci does not bind to the device
          - require volatile-memdev
          - release the memory backend on exit
          - refuse migration, the device state is not migrated yet
          - drop MSI-X, nothing uses it yet
          - license GPL-2.0-or-later
          - reword the commit message ]
AI-used-for: code (prototype)
Signed-off-by: Manish Honap <[email protected]>
---
 MAINTAINERS                 |   1 +
 hw/mem/Kconfig              |   5 ++
 hw/mem/cxl_type2.c          | 111 ++++++++++++++++++++++++++++++++++++
 hw/mem/meson.build          |   1 +
 include/hw/cxl/cxl_device.h |  14 +++++
 5 files changed, 132 insertions(+)
 create mode 100644 hw/mem/cxl_type2.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 55463103ff..57a78bc6a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3399,6 +3399,7 @@ R: Anisa Su <[email protected]>
 L: [email protected]
 S: Supported
 F: hw/cxl/
+F: hw/mem/cxl_type2.c
 F: hw/mem/cxl_type3.c
 F: include/hw/cxl/
 F: qapi/cxl.json
diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig
index 39ddb36710..6a5cd2be61 100644
--- a/hw/mem/Kconfig
+++ b/hw/mem/Kconfig
@@ -17,6 +17,11 @@ config CXL_MEM_DEVICE
     default y if CXL
     select MEM_DEVICE
 
+config CXL_TYPE2_DEVICE
+    bool
+    default y if CXL
+    select MEM_DEVICE
+
 config SP_MEM
     bool
     select MEM_DEVICE
diff --git a/hw/mem/cxl_type2.c b/hw/mem/cxl_type2.c
new file mode 100644
index 0000000000..4769793e06
--- /dev/null
+++ b/hw/mem/cxl_type2.c
@@ -0,0 +1,111 @@
+/*
+ * CXL Type-2 device
+ *
+ * Copyright(C) 2024 NVIDIA Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/cxl/cxl.h"
+#include "hw/pci/pci.h"
+#include "migration/vmstate.h"
+#include "system/hostmem.h"
+
+static void clean_memory(PCIDevice *pci_dev)
+{
+    CXLType2Dev *ct2d = CXL_TYPE2(pci_dev);
+
+    address_space_destroy(&ct2d->hostvmem_as);
+    host_memory_backend_set_mapped(ct2d->hostvmem, false);
+}
+
+static bool setup_memory(PCIDevice *pci_dev, Error **errp)
+{
+    CXLType2Dev *ct2d = CXL_TYPE2(pci_dev);
+    MemoryRegion *vmr;
+
+    if (!ct2d->hostvmem) {
+        error_setg(errp, "volatile-memdev property must be set");
+        return false;
+    }
+    vmr = host_memory_backend_get_memory(ct2d->hostvmem);
+    if (!vmr) {
+        error_setg(errp, "volatile memdev must have backing device");
+        return false;
+    }
+    if (host_memory_backend_is_mapped(ct2d->hostvmem)) {
+        error_setg(errp, "memory backend %s can't be used multiple times.",
+                   
object_get_canonical_path_component(OBJECT(ct2d->hostvmem)));
+        return false;
+    }
+    memory_region_set_nonvolatile(vmr, false);
+    memory_region_set_enabled(vmr, true);
+    host_memory_backend_set_mapped(ct2d->hostvmem, true);
+    address_space_init(&ct2d->hostvmem_as, vmr, "cxl-type2-dpa-vmem-space");
+    return true;
+}
+
+static void cxl_type2_realize(PCIDevice *pci_dev, Error **errp)
+{
+    if (!setup_memory(pci_dev, errp)) {
+        return;
+    }
+
+    pcie_endpoint_cap_init(pci_dev, 0x80);
+}
+
+static void cxl_type2_exit(PCIDevice *pci_dev)
+{
+    clean_memory(pci_dev);
+}
+
+static const Property cxl_type2_props[] = {
+    DEFINE_PROP_LINK("volatile-memdev", CXLType2Dev, hostvmem,
+                     TYPE_MEMORY_BACKEND, HostMemoryBackend *),
+};
+
+static const VMStateDescription cxl_type2_vmsd = {
+    .name = TYPE_CXL_TYPE2,
+    .unmigratable = 1,
+};
+
+static void cxl_type2_class_init(ObjectClass *oc, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
+
+    pc->realize = cxl_type2_realize;
+    pc->exit = cxl_type2_exit;
+
+    pc->class_id = PCI_CLASS_ACCELERATOR_PROCESSING;
+    pc->vendor_id = PCI_VENDOR_ID_REDHAT;
+    pc->device_id = PCI_DEVICE_ID_REDHAT_CXL_TYPE2;
+    pc->revision = 1;
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->desc = "CXL Type-2 device";
+    dc->vmsd = &cxl_type2_vmsd;
+    device_class_set_props(dc, cxl_type2_props);
+}
+
+static const TypeInfo cxl_type2_dev_info = {
+    .name = TYPE_CXL_TYPE2,
+    .parent = TYPE_PCI_DEVICE,
+    .class_init = cxl_type2_class_init,
+    .instance_size = sizeof(CXLType2Dev),
+    .interfaces = (const InterfaceInfo[]) {
+        { INTERFACE_CXL_DEVICE },
+        { INTERFACE_PCIE_DEVICE },
+        {}
+    },
+};
+
+static void cxl_type2_dev_registers(void)
+{
+    type_register_static(&cxl_type2_dev_info);
+}
+
+type_init(cxl_type2_dev_registers);
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
index f410d75475..0b2c193a78 100644
--- a/hw/mem/meson.build
+++ b/hw/mem/meson.build
@@ -4,6 +4,7 @@ mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
 mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
 mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
 mem_ss.add(when: 'CONFIG_CXL_MEM_DEVICE', if_true: files('cxl_type3.c'))
+mem_ss.add(when: 'CONFIG_CXL_TYPE2_DEVICE', if_true: files('cxl_type2.c'))
 mem_ss.add(when: 'CONFIG_SP_MEM', if_true: files('sp-mem.c'))
 stub_ss.add(files('cxl_type3_stubs.c'))
 
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 608d05165a..aeccf42855 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -830,6 +830,20 @@ struct CSWMBCCIDev {
 #define TYPE_CXL_SWITCH_MAILBOX_CCI "cxl-switch-mailbox-cci"
 OBJECT_DECLARE_TYPE(CSWMBCCIDev, CSWMBCCIClass, CXL_SWITCH_MAILBOX_CCI)
 
+struct CXLType2Dev {
+    /* Private */
+    PCIDevice parent_obj;
+
+    /* Properties */
+    HostMemoryBackend *hostvmem;
+
+    /* State */
+    AddressSpace hostvmem_as;
+};
+
+#define TYPE_CXL_TYPE2 "cxl-type2"
+OBJECT_DECLARE_SIMPLE_TYPE(CXLType2Dev, CXL_TYPE2)
+
 MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
                            unsigned size, MemTxAttrs attrs);
 MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
-- 
2.53.0


Reply via email to