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
