[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5)
From: |
Igor Mammedov |
Subject: |
Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5) |
Date: |
Wed, 27 Jan 2021 22:03:12 +0100 |
On Tue, 5 Jan 2021 08:53:15 -0800
Ben Widawsky <ben.widawsky@intel.com> wrote:
> A CXL memory device (AKA Type 3) is a CXL component that contains some
> combination of volatile and persistent memory. It also implements the
> previously defined mailbox interface as well as the memory device
> firmware interface.
>
> The following example will create a 256M device in a 512M window:
>
> -object "memory-backend-file,id=cxl-mem1,share,mem-path=cxl-type3,size=512M"
> -device "cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0,size=256M"
I'd expect whole backend used by frontend, so one would not need "size" property
on frontend (like we do with memory devices).
So question is why it partially uses memdev?
> Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
> ---
> hw/core/numa.c | 3 +
> hw/cxl/cxl-mailbox-utils.c | 41 ++++++
> hw/i386/pc.c | 1 +
> hw/mem/Kconfig | 5 +
> hw/mem/cxl_type3.c | 262 +++++++++++++++++++++++++++++++++++++
> hw/mem/meson.build | 1 +
> hw/pci/pcie.c | 30 +++++
> include/hw/cxl/cxl.h | 2 +
> include/hw/cxl/cxl_pci.h | 22 ++++
> include/hw/pci/pci_ids.h | 1 +
> monitor/hmp-cmds.c | 15 +++
> qapi/machine.json | 1 +
> 12 files changed, 384 insertions(+)
> create mode 100644 hw/mem/cxl_type3.c
>
> diff --git a/hw/core/numa.c b/hw/core/numa.c
> index 68cee65f61..cd7df371e6 100644
> --- a/hw/core/numa.c
> +++ b/hw/core/numa.c
> @@ -770,6 +770,9 @@ static void numa_stat_memory_devices(NumaNodeMem
> node_mem[])
> node_mem[pcdimm_info->node].node_plugged_mem +=
> pcdimm_info->size;
> break;
> + case MEMORY_DEVICE_INFO_KIND_CXL:
> + /* FINISHME */
> + break;
> case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:
> vpi = value->u.virtio_pmem.data;
> /* TODO: once we support numa, assign to right node */
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index f68ec5b5b9..eeb10b8943 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> @@ -49,6 +49,8 @@ enum {
> LOGS = 0x04,
> #define GET_SUPPORTED 0x0
> #define GET_LOG 0x1
> + IDENTIFY = 0x40,
> + #define MEMORY_DEVICE 0x0
> };
>
> /* 8.2.8.4.5.1 Command Return Codes */
> @@ -127,6 +129,7 @@ declare_mailbox_handler(TIMESTAMP_GET);
> declare_mailbox_handler(TIMESTAMP_SET);
> declare_mailbox_handler(LOGS_GET_SUPPORTED);
> declare_mailbox_handler(LOGS_GET_LOG);
> +declare_mailbox_handler(IDENTIFY_MEMORY_DEVICE);
>
> #define IMMEDIATE_CONFIG_CHANGE (1 << 1)
> #define IMMEDIATE_POLICY_CHANGE (1 << 3)
> @@ -144,6 +147,7 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
> CXL_CMD(TIMESTAMP, SET, 8, IMMEDIATE_POLICY_CHANGE),
> CXL_CMD(LOGS, GET_SUPPORTED, 0, 0),
> CXL_CMD(LOGS, GET_LOG, 0x18, 0),
> + CXL_CMD(IDENTIFY, MEMORY_DEVICE, 0, 0),
> };
>
> #undef CXL_CMD
> @@ -262,6 +266,43 @@ define_mailbox_handler(LOGS_GET_LOG)
> return CXL_MBOX_SUCCESS;
> }
>
> +/* 8.2.9.5.1.1 */
> +define_mailbox_handler(IDENTIFY_MEMORY_DEVICE)
> +{
> + struct {
> + char fw_revision[0x10];
> + uint64_t total_capacity;
> + uint64_t volatile_capacity;
> + uint64_t persistent_capacity;
> + uint64_t partition_align;
> + uint16_t info_event_log_size;
> + uint16_t warning_event_log_size;
> + uint16_t failure_event_log_size;
> + uint16_t fatal_event_log_size;
> + uint32_t lsa_size;
> + uint8_t poison_list_max_mer[3];
> + uint16_t inject_poison_limit;
> + uint8_t poison_caps;
> + uint8_t qos_telemetry_caps;
> + } __attribute__((packed)) *id;
> + _Static_assert(sizeof(*id) == 0x43, "Bad identify size");
> +
> + if (memory_region_size(cxl_dstate->pmem) < (256 << 20)) {
> + return CXL_MBOX_INTERNAL_ERROR;
> + }
> +
> + id = (void *)cmd->payload;
> + memset(id, 0, sizeof(*id));
> +
> + /* PMEM only */
> + snprintf(id->fw_revision, 0x10, "BWFW VERSION %02d", 0);
> + id->total_capacity = memory_region_size(cxl_dstate->pmem);
> + id->persistent_capacity = memory_region_size(cxl_dstate->pmem);
> +
> + *len = sizeof(*id);
> + return CXL_MBOX_SUCCESS;
> +}
> +
> void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
> {
> uint16_t ret = CXL_MBOX_SUCCESS;
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 5458f61d10..5d41809b37 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -79,6 +79,7 @@
> #include "acpi-build.h"
> #include "hw/mem/pc-dimm.h"
> #include "hw/mem/nvdimm.h"
> +#include "hw/cxl/cxl.h"
> #include "qapi/error.h"
> #include "qapi/qapi-visit-common.h"
> #include "qapi/visitor.h"
> diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig
> index a0ef2cf648..7d9d1ced3e 100644
> --- a/hw/mem/Kconfig
> +++ b/hw/mem/Kconfig
> @@ -10,3 +10,8 @@ config NVDIMM
> default y
> depends on (PC || PSERIES || ARM_VIRT)
> select MEM_DEVICE
> +
> +config CXL_MEM_DEVICE
> + bool
> + default y if CXL
> + select MEM_DEVICE
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> new file mode 100644
> index 0000000000..3985bb8d0b
> --- /dev/null
> +++ b/hw/mem/cxl_type3.c
> @@ -0,0 +1,262 @@
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/error-report.h"
> +#include "hw/mem/memory-device.h"
> +#include "hw/mem/pc-dimm.h"
> +#include "hw/pci/pci.h"
> +#include "hw/qdev-properties.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "qemu/module.h"
> +#include "qemu/range.h"
> +#include "qemu/rcu.h"
> +#include "sysemu/hostmem.h"
> +#include "hw/cxl/cxl.h"
> +
> +typedef struct cxl_type3_dev {
> + /* Private */
> + PCIDevice parent_obj;
> +
> + /* Properties */
> + uint64_t size;
> + HostMemoryBackend *hostmem;
> +
> + /* State */
> + CXLComponentState cxl_cstate;
> + CXLDeviceState cxl_dstate;
> +} CXLType3Dev;
> +
> +#define CT3(obj) OBJECT_CHECK(CXLType3Dev, (obj), TYPE_CXL_TYPE3_DEV)
> +
> +static void build_dvsecs(CXLType3Dev *ct3d)
> +{
> + CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
> + uint8_t *dvsec;
> +
> + dvsec = (uint8_t *)&(struct dvsec_device){
> + .cap = 0x1e,
> + .ctrl = 0x6,
> + .status2 = 0x2,
> + .range1_size_hi = 0,
> + .range1_size_lo = (2 << 5) | (2 << 2) | 0x3 | ct3d->size,
> + .range1_base_hi = 0,
> + .range1_base_lo = 0,
> + };
> + cxl_component_create_dvsec(cxl_cstate, PCIE_CXL_DEVICE_DVSEC_LENGTH,
> + PCIE_CXL_DEVICE_DVSEC,
> + PCIE_CXL2_DEVICE_DVSEC_REVID, dvsec);
> +
> + dvsec = (uint8_t *)&(struct dvsec_register_locator){
> + .rsvd = 0,
> + .reg0_base_lo = RBI_COMPONENT_REG | COMPONENT_REG_BAR_IDX,
> + .reg0_base_hi = 0,
> + .reg1_base_lo = RBI_CXL_DEVICE_REG | DEVICE_REG_BAR_IDX,
> + .reg1_base_hi = 0,
> + };
> + cxl_component_create_dvsec(cxl_cstate, REG_LOC_DVSEC_LENGTH,
> REG_LOC_DVSEC,
> + REG_LOC_DVSEC_REVID, dvsec);
> +}
> +
> +static void ct3_instance_init(Object *obj)
> +{
> + /* MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(obj); */
> +}
> +
> +static void ct3_finalize(Object *obj)
> +{
> + CXLType3Dev *ct3d = CT3(obj);
> +
> + g_free(ct3d->cxl_dstate.pmem);
> +}
> +
> +static void cxl_setup_memory(CXLType3Dev *ct3d, Error **errp)
> +{
> + MemoryRegionSection mrs;
> + MemoryRegion *mr;
> + uint64_t offset = 0;
> + size_t remaining_size;
> +
> + if (!ct3d->hostmem) {
> + error_setg(errp, "memdev property must be set");
> + return;
> + }
> +
> + /* FIXME: need to check mr is the host bridge's MR */
> + mr = host_memory_backend_get_memory(ct3d->hostmem);
> +
> + /* Create our new subregion */
> + ct3d->cxl_dstate.pmem = g_new(MemoryRegion, 1);
> +
> + /* Find the first free space in the window */
> + WITH_RCU_READ_LOCK_GUARD()
> + {
> + mrs = memory_region_find(mr, offset, 1);
> + while (mrs.mr && mrs.mr != mr) {
> + offset += memory_region_size(mrs.mr);
> + mrs = memory_region_find(mr, offset, 1);
> + }
> + }
> +
> + remaining_size = memory_region_size(mr) - offset;
> + if (remaining_size < ct3d->size) {
> + g_free(ct3d->cxl_dstate.pmem);
> + error_setg(errp,
> + "Not enough free space (%zd) required for device (%"
> PRId64 ")",
> + remaining_size, ct3d->size);
> + }
> +
> + /* Register our subregion as non-volatile */
> + memory_region_init_ram(ct3d->cxl_dstate.pmem, OBJECT(ct3d),
> + "cxl_type3-memory", ct3d->size, errp);
this allocates ct3d->size of anon RAM, was this an intention?
If yes, can you clarify why extra RAM is used instead of using what
backend provides?
> + memory_region_set_nonvolatile(ct3d->cxl_dstate.pmem, true);
> +#ifdef SET_PMEM_PADDR
> + memory_region_add_subregion(mr, offset, ct3d->cxl_dstate.pmem);
> +#endif
What this hunk is supposed to do, why it's ifdef-ed?
> +}
> +
> +static MemoryRegion *cxl_md_get_memory_region(MemoryDeviceState *md,
> + Error **errp)
> +{
> + CXLType3Dev *ct3d = CT3(md);
> +
> + if (!ct3d->cxl_dstate.pmem) {
> + cxl_setup_memory(ct3d, errp);
> + }
> +
> + return ct3d->cxl_dstate.pmem;
> +}
> +
> +static void ct3_realize(PCIDevice *pci_dev, Error **errp)
> +{
> + CXLType3Dev *ct3d = CT3(pci_dev);
> + CXLComponentState *cxl_cstate = &ct3d->cxl_cstate;
> + ComponentRegisters *regs = &cxl_cstate->crb;
> + MemoryRegion *mr = ®s->component_registers;
> + uint8_t *pci_conf = pci_dev->config;
> +
> + if (!ct3d->cxl_dstate.pmem) {
> + cxl_setup_memory(ct3d, errp);
> + }
> +
> + pci_config_set_prog_interface(pci_conf, 0x10);
> + pci_config_set_class(pci_conf, PCI_CLASS_MEMORY_CXL);
> +
> + pcie_endpoint_cap_init(pci_dev, 0x80);
> + cxl_cstate->dvsec_offset = 0x100;
> +
> + ct3d->cxl_cstate.pdev = pci_dev;
> + build_dvsecs(ct3d);
> +
> + cxl_component_register_block_init(OBJECT(pci_dev), cxl_cstate,
> + TYPE_CXL_TYPE3_DEV);
> +
> + pci_register_bar(
> + pci_dev, COMPONENT_REG_BAR_IDX,
> + PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, mr);
> +
> + cxl_device_register_block_init(OBJECT(pci_dev), &ct3d->cxl_dstate);
> + pci_register_bar(pci_dev, DEVICE_REG_BAR_IDX,
> + PCI_BASE_ADDRESS_SPACE_MEMORY |
> + PCI_BASE_ADDRESS_MEM_TYPE_64,
> + &ct3d->cxl_dstate.device_registers);
> +}
> +
> +static uint64_t cxl_md_get_addr(const MemoryDeviceState *md)
> +{
> + CXLType3Dev *ct3d = CT3(md);
> +
> + return memory_region_get_ram_addr(ct3d->cxl_dstate.pmem);
> +}
> +
> +static void cxl_md_set_addr(MemoryDeviceState *md, uint64_t addr, Error
> **errp)
> +{
> + object_property_set_uint(OBJECT(md), "paddr", addr, errp);
> +}
> +
> +static void ct3d_reset(DeviceState *dev)
> +{
> + CXLType3Dev *ct3d = CT3(dev);
> + uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
> +
> + cxl_component_register_init_common(reg_state, CXL2_TYPE3_DEVICE);
> + cxl_device_register_init_common(&ct3d->cxl_dstate);
> +}
> +
> +static Property ct3_props[] = {
> + DEFINE_PROP_SIZE("size", CXLType3Dev, size, -1),
> + DEFINE_PROP_LINK("memdev", CXLType3Dev, hostmem, TYPE_MEMORY_BACKEND,
> + HostMemoryBackend *),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,
> + MemoryDeviceInfo *info)
> +{
> + PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);
> + const DeviceClass *dc = DEVICE_GET_CLASS(md);
> + const DeviceState *dev = DEVICE(md);
> + CXLType3Dev *ct3d = CT3(md);
> +
> + if (dev->id) {
> + di->has_id = true;
> + di->id = g_strdup(dev->id);
> + }
> + di->hotplugged = dev->hotplugged;
> + di->hotpluggable = dc->hotpluggable;
> + di->addr = cxl_md_get_addr(md);
> + di->slot = 0;
> + di->node = 0;
> + di->size = memory_device_get_region_size(md, NULL);
> + di->memdev = object_get_canonical_path(OBJECT(ct3d->hostmem));
> +
> +
> + info->u.cxl.data = di;
> + info->type = MEMORY_DEVICE_INFO_KIND_CXL;
> +}
> +
> +static void ct3_class_init(ObjectClass *oc, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
> + MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
> +
> + pc->realize = ct3_realize;
> + pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
> + pc->vendor_id = PCI_VENDOR_ID_INTEL;
> + pc->device_id = 0xd93; /* LVF for now */
> + pc->revision = 1;
> +
> + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> + dc->desc = "CXL PMEM Device (Type 3)";
> + dc->reset = ct3d_reset;
> + device_class_set_props(dc, ct3_props);
> +
> + mdc->get_memory_region = cxl_md_get_memory_region;
> + mdc->get_addr = cxl_md_get_addr;
> + mdc->fill_device_info = pc_dimm_md_fill_device_info;
> + mdc->get_plugged_size = memory_device_get_region_size;
> + mdc->set_addr = cxl_md_set_addr;
> +}
> +
> +static const TypeInfo ct3d_info = {
> + .name = TYPE_CXL_TYPE3_DEV,
> + .parent = TYPE_PCI_DEVICE,
> + .class_init = ct3_class_init,
> + .instance_size = sizeof(CXLType3Dev),
> + .instance_init = ct3_instance_init,
> + .instance_finalize = ct3_finalize,
> + .interfaces = (InterfaceInfo[]) {
> + { TYPE_MEMORY_DEVICE },
> + { INTERFACE_CXL_DEVICE },
> + { INTERFACE_PCIE_DEVICE },
> + {}
> + },
> +};
> +
> +static void ct3d_registers(void)
> +{
> + type_register_static(&ct3d_info);
> +}
> +
> +type_init(ct3d_registers);
> diff --git a/hw/mem/meson.build b/hw/mem/meson.build
> index 0d22f2b572..d13c3ed117 100644
> --- a/hw/mem/meson.build
> +++ b/hw/mem/meson.build
> @@ -3,5 +3,6 @@ mem_ss.add(files('memory-device.c'))
> 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'))
>
> softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
> diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
> index d4010cf8f3..1ecf6f6a55 100644
> --- a/hw/pci/pcie.c
> +++ b/hw/pci/pcie.c
> @@ -20,6 +20,7 @@
>
> #include "qemu/osdep.h"
> #include "qapi/error.h"
> +#include "hw/mem/memory-device.h"
> #include "hw/pci/pci_bridge.h"
> #include "hw/pci/pcie.h"
> #include "hw/pci/msix.h"
> @@ -27,6 +28,8 @@
> #include "hw/pci/pci_bus.h"
> #include "hw/pci/pcie_regs.h"
> #include "hw/pci/pcie_port.h"
> +#include "hw/cxl/cxl.h"
> +#include "hw/boards.h"
> #include "qemu/range.h"
>
> //#define DEBUG_PCIE
> @@ -419,6 +422,28 @@ void pcie_cap_slot_pre_plug_cb(HotplugHandler
> *hotplug_dev, DeviceState *dev,
> }
>
> pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp);
> +
> +#ifdef CXL_MEM_DEVICE
> + /*
> + * FIXME:
> + * if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_TYPE3_DEV)) {
> + * HotplugHandler *hotplug_ctrl;
> + * Error *local_err = NULL;
> + * hotplug_ctrl = qdev_get_hotplug_handler(dev);
> + * if (hotplug_ctrl) {
> + * hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);
> + * if (local_err) {
> + * error_propagate(errp, local_err);
> + * return;
> + * }
> + * }
> + */
> + if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_TYPE3_DEV)) {
> + memory_device_pre_plug(MEMORY_DEVICE(dev),
> MACHINE(qdev_get_machine()),
> + NULL, errp);
> + }
why use MEMORY_DEVICE interface instead of exposing memory as PCI BAR?
> +#endif
> }
>
> void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
> @@ -455,6 +480,11 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev,
> DeviceState *dev,
> pcie_cap_slot_event(hotplug_pdev,
> PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
> }
> +
> +#ifdef CXL_MEM_DEVICE
> + if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_TYPE3_DEV))
> + memory_device_plug(MEMORY_DEVICE(dev), MACHINE(qdev_get_machine()));
> +#endif
> }
>
> void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
> diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
> index b1e5f4a8fa..809ed7de60 100644
> --- a/include/hw/cxl/cxl.h
> +++ b/include/hw/cxl/cxl.h
> @@ -17,6 +17,8 @@
> #define COMPONENT_REG_BAR_IDX 0
> #define DEVICE_REG_BAR_IDX 2
>
> +#define TYPE_CXL_TYPE3_DEV "cxl-type3"
> +
> #define CXL_HOST_BASE 0xD0000000
> #define CXL_WINDOW_MAX 10
>
> diff --git a/include/hw/cxl/cxl_pci.h b/include/hw/cxl/cxl_pci.h
> index a53c2e5ae7..9ec28c9feb 100644
> --- a/include/hw/cxl/cxl_pci.h
> +++ b/include/hw/cxl/cxl_pci.h
> @@ -64,6 +64,28 @@ _Static_assert(sizeof(struct dvsec_header) == 10,
> * CXL 2.0 Downstream Port: 3, 4, 7, 8
> */
>
> +/* CXL 2.0 - 8.1.3 (ID 0001) */
> +struct dvsec_device {
> + struct dvsec_header hdr;
> + uint16_t cap;
> + uint16_t ctrl;
> + uint16_t status;
> + uint16_t ctrl2;
> + uint16_t status2;
> + uint16_t lock;
> + uint16_t cap2;
> + uint32_t range1_size_hi;
> + uint32_t range1_size_lo;
> + uint32_t range1_base_hi;
> + uint32_t range1_base_lo;
> + uint32_t range2_size_hi;
> + uint32_t range2_size_lo;
> + uint32_t range2_base_hi;
> + uint32_t range2_base_lo;
> +};
> +_Static_assert(sizeof(struct dvsec_device) == 0x38,
> + "dvsec device size incorrect");
> +
> /* CXL 2.0 - 8.1.5 (ID 0003) */
> struct extensions_dvsec_port {
> struct dvsec_header hdr;
> diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
> index 11f8ab7149..76bf3ed590 100644
> --- a/include/hw/pci/pci_ids.h
> +++ b/include/hw/pci/pci_ids.h
> @@ -53,6 +53,7 @@
> #define PCI_BASE_CLASS_MEMORY 0x05
> #define PCI_CLASS_MEMORY_RAM 0x0500
> #define PCI_CLASS_MEMORY_FLASH 0x0501
> +#define PCI_CLASS_MEMORY_CXL 0x0502
> #define PCI_CLASS_MEMORY_OTHER 0x0580
>
> #define PCI_BASE_CLASS_BRIDGE 0x06
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index 0dd594f92b..0f67bc61ce 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -1887,6 +1887,21 @@ void hmp_info_memory_devices(Monitor *mon, const QDict
> *qdict)
> monitor_printf(mon, " hotpluggable: %s\n",
> di->hotpluggable ? "true" : "false");
> break;
> + case MEMORY_DEVICE_INFO_KIND_CXL:
> + di = value->u.cxl.data;
> + monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
> + MemoryDeviceInfoKind_str(value->type),
> + di->id ? di->id : "");
> + monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr);
> + monitor_printf(mon, " slot: %" PRId64 "\n", di->slot);
> + monitor_printf(mon, " node: %" PRId64 "\n", di->node);
> + monitor_printf(mon, " size: %" PRIu64 "\n", di->size);
> + monitor_printf(mon, " memdev: %s\n", di->memdev);
> + monitor_printf(mon, " hotplugged: %s\n",
> + di->hotplugged ? "true" : "false");
> + monitor_printf(mon, " hotpluggable: %s\n",
> + di->hotpluggable ? "true" : "false");
> + break;
> case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:
> vpi = value->u.virtio_pmem.data;
> monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
> diff --git a/qapi/machine.json b/qapi/machine.json
> index 330189efe3..aa96d662bd 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -1394,6 +1394,7 @@
> { 'union': 'MemoryDeviceInfo',
> 'data': { 'dimm': 'PCDIMMDeviceInfo',
> 'nvdimm': 'PCDIMMDeviceInfo',
> + 'cxl': 'PCDIMMDeviceInfo',
> 'virtio-pmem': 'VirtioPMEMDeviceInfo',
> 'virtio-mem': 'VirtioMEMDeviceInfo'
> }
- [RFC PATCH v2 31/32] WIP: i386/cxl: Initialize a host bridge, (continued)
- [RFC PATCH v2 31/32] WIP: i386/cxl: Initialize a host bridge, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 16/32] qtest: allow DSDT acpi table changes, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 18/32] tests/acpi: remove stale allowed tables, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 17/32] acpi/pci: Consolidate host bridge setup, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 19/32] hw/pci: Plumb _UID through host bridges, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 20/32] hw/cxl/component: Implement host bridge MMIO (8.2.5, table 142), Ben Widawsky, 2021/01/05
- [RFC PATCH v2 21/32] acpi/pxb/cxl: Reserve host bridge MMIO, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 22/32] hw/pxb/cxl: Add "windows" for host bridges, Ben Widawsky, 2021/01/05
- [RFC PATCH v2 25/32] hw/cxl/device: Implement MMIO HDM decoding (8.2.5.12), Ben Widawsky, 2021/01/05
- [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/05
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5),
Igor Mammedov <=
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/27
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Jonathan Cameron, 2021/01/28
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/28
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/28
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/28
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Ben Widawsky, 2021/01/28
- Re: [RFC PATCH v2 24/32] hw/cxl/device: Add a memory device (8.2.8.5), Jonathan Cameron, 2021/01/28