Skip to contentSkip to conversation

pc-dimm: factor out MemoryDevice

PATCH In review David Hildenbrand 7 participants 21 messages Apr 23, 2018 – May 14, 2018

lore
Share & tools
lore
#0 lore raw

v4 cover pc-dimm: factor out MemoryDevice

Right now we can only map PCDIMM/NVDIMM into guest address space. In the future, we might want to do the same for virtio devices - e.g. virtio-pmem or virtio-mem. Especially, they should be able to live side by side to each other.

E.g. the virto based memory devices regions will not be exposed via ACPI and friends. They will be detected just like other virtio devices and indicate the applicable memory region. This makes it possible to also use them on architectures without memory device detection support (e.g. s390x).

Let's factor out the memory device code into a MemoryDevice interface.

Please note that the "slots" assignment code is not relevant for memory devices that will not be exposed via ACPI or similar. That's why that part won't be exposed. KVM/vhost "slots" for memory regions are still necessary but don't have to be manually specified (e.g. the slot number doesn't mather).

So we are basically converting the hotplug memory region to a memory device region. I have patches that also set up such a region for s390x.

v3 -> v4:
- "pc-dimm: factor out MemoryDevice interface"
-- dropped the "errp" parameter from the interface functions
-- made as many pointers const as I could :)
-- s/built/build/
- machine: make MemoryHotplugState accessible via the machine
-- State now kept via a pointer, not queried.
-- Added patches that rename the type and cleanup the terminology for
spapr and pc
- Split up the big "pc-dimm: factor out address space logic into MemoryDevice code" into sub patches
-- We now pass the machine to the pc-dimm and MemoryDevice plug/unplug
functions, so we can avoid qdev_get_machine()
-- Moved some checks around as requested by Igor
- Added a patch to make maxmem not depend on slots

v2 -> v3:
- "pc-dimm: factor out MemoryDevice interface" --> Lookup both classes when comparing (David Gibson)

v1 -> v2:
- Fix compile issues on ppc (still untested )

David Hildenbrand (11):
pc-dimm: factor out MemoryDevice interface
machine: make MemoryHotplugState accessible via the machine
pc-dimm: no need to pass the memory region
pc-dimm: pass in the machine and to the MemoryHotplugState
pc-dimm: factor out address search into MemoryDevice code
pc-dimm: factor out capacity and slot checks into MemoryDevice
pc-dimm: move actual plug/unplug of a memory region to MemoryDevice
machine: rename MemoryHotplugState to DeviceMemoryState
pc: rename "hotplug memory" terminology to "device memory"
spapr: rename "hotplug memory" terminology to "device memory"
vl: allow 'maxmem' without 'slot'

 hw/i386/acpi-build.c                         |   7 +-
 hw/i386/pc.c                                 |  65 +++---
 hw/mem/Makefile.objs                         |   1 +
 hw/mem/memory-device.c                       | 275 ++++++++++++++++++++++++
 hw/mem/pc-dimm.c                             | 304 +++++++--------------------
 hw/ppc/spapr.c                               |  65 +++---
 hw/ppc/spapr_hcall.c                         |   7 +-
 hw/ppc/spapr_rtas_ddw.c                      |   5 +-
 include/hw/boards.h                          |  12 ++
 include/hw/i386/pc.h                         |   3 +-
 include/hw/mem/memory-device.h               |  51 +++++
 include/hw/mem/pc-dimm.h                     |  27 +--
 include/hw/ppc/spapr.h                       |   5 +-
 numa.c                                       |   3 +-
 qmp.c                                        |   4 +-
 stubs/Makefile.objs                          |   2 +-
 stubs/{qmp_pc_dimm.c => qmp_memory_device.c} |   4 +-
 vl.c                                         |  19 +-
 18 files changed, 506 insertions(+), 353 deletions(-)
 create mode 100644 hw/mem/memory-device.c
 create mode 100644 include/hw/mem/memory-device.h
 rename stubs/{qmp_pc_dimm.c => qmp_memory_device.c} (61%)
Signature · 1 line
2.14.3
#1 lore raw

PATCH v4 1/11 pc-dimm: factor out MemoryDevice interface

On the qmp level, we already have the concept of memory devices:
"query-memory-devices"
Right now, we only support NVDIMM and PCDIMM.

We want to map other devices later into the address space of the guest. Such device could e.g. be virtio devices. These devices will have a guest memory range assigned but won't be exposed via e.g. ACPI. We want to make them look like memory device, but not glued to pc-dimm.

Especially, it will not always be possible to have TYPE_PC_DIMM as a parent class (e.g. virtio devices). Let's use an interface instead. As a first part, convert handling of
- qmp_pc_dimm_device_list
- get_plugged_memory_size
to our new model. plug/unplug stuff etc. will follow later.

A memory device will have to provide the following functions:
- get_addr(): Necessary, as the property "addr" can e.g. not be used for virtio devices (already defined).
- get_plugged_size(): The amount this device offers to the guest as of now.
- get_region_size(): Because this can later on be bigger than the plugged size.
- fill_device_info(): Fill MemoryDeviceInfo, e.g. for qmp.

---
 hw/i386/acpi-build.c                         |   3 +-
 hw/mem/Makefile.objs                         |   1 +
 hw/mem/memory-device.c                       | 120 +++++++++++++++++++++++++++
 hw/mem/pc-dimm.c                             | 120 ++++++++++++++-------------
 hw/ppc/spapr.c                               |   3 +-
 hw/ppc/spapr_hcall.c                         |   1 +
 include/hw/mem/memory-device.h               |  45 ++++++++++
 include/hw/mem/pc-dimm.h                     |   2 -
 numa.c                                       |   3 +-
 qmp.c                                        |   4 +-
 stubs/Makefile.objs                          |   2 +-
 stubs/{qmp_pc_dimm.c => qmp_memory_device.c} |   4 +-
 12 files changed, 242 insertions(+), 66 deletions(-)
 create mode 100644 hw/mem/memory-device.c
 create mode 100644 include/hw/mem/memory-device.h
 rename stubs/{qmp_pc_dimm.c => qmp_memory_device.c} (61%)
hw/i386/acpi-build.c +2 -1
index 3cf2a1679c..ca3645d57b 100644
@@ -46,6 +46,7 @@
 #include "hw/acpi/vmgenid.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/timer/mc146818rtc_regs.h"
+#include "hw/mem/memory-device.h"
 #include "sysemu/numa.h"
 
 /* Supported chipsets: */
@@ -2253,7 +2254,7 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
 static void build_srat_hotpluggable_memory(GArray *table_data, uint64_t base,
                                            uint64_t len, int default_node)
 {
-    MemoryDeviceInfoList *info_list = qmp_pc_dimm_device_list();
+    MemoryDeviceInfoList *info_list = qmp_memory_device_list();
     MemoryDeviceInfoList *info;
     MemoryDeviceInfo *mi;
     PCDIMMDeviceInfo *di;
hw/mem/Makefile.objs +1 -0
index f12f8b97a2..10be4df2a2 100644
@@ -1,2 +1,3 @@
 common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_MEM_HOTPLUG) += memory-device.o
 common-obj-$(CONFIG_NVDIMM) += nvdimm.o
hw/mem/memory-device.c new file +120 -0

120 lines not on this page · raw message

hw/mem/pc-dimm.c +64 -56

160 lines not on this page · raw message

hw/ppc/spapr.c +2 -1
index a81570e7c8..a7428f7da7 100644
@@ -74,6 +74,7 @@
 #include "hw/compat.h"
 #include "qemu/cutils.h"
 #include "hw/ppc/spapr_cpu_core.h"
+#include "hw/mem/memory-device.h"
 
 #include <libfdt.h>
 
@@ -722,7 +723,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     }
 
     if (hotplug_lmb_start) {
-        dimms = qmp_pc_dimm_device_list();
+        dimms = qmp_memory_device_list();
     }
 
     /* ibm,dynamic-memory */
hw/ppc/spapr_hcall.c +1 -0
index 16bccdd5c0..4cdae3ca3a 100644
@@ -14,6 +14,7 @@
 #include "kvm_ppc.h"
 #include "hw/ppc/spapr_ovec.h"
 #include "mmu-book3s-v3.h"
+#include "hw/mem/memory-device.h"
 
 struct SPRSyncState {
     int spr;
include/hw/mem/memory-device.h new file +45 -0

45 lines not on this page · raw message

include/hw/mem/pc-dimm.h +0 -2
index 1fc479281c..e88073321f 100644
@@ -93,9 +93,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
-MemoryDeviceInfoList *qmp_pc_dimm_device_list(void);
 uint64_t pc_existing_dimms_capacity(Error **errp);
-uint64_t get_plugged_memory_size(void);
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, Error **errp);
 void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
numa.c +2 -1
index 1116c90af9..6a0eaebc01 100644
@@ -36,6 +36,7 @@
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
 #include "hw/mem/pc-dimm.h"
+#include "hw/mem/memory-device.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qemu/cutils.h"
@@ -520,7 +521,7 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
 
 static void numa_stat_memory_devices(NumaNodeMem node_mem[])
 {
-    MemoryDeviceInfoList *info_list = qmp_pc_dimm_device_list();
+    MemoryDeviceInfoList *info_list = qmp_memory_device_list();
     MemoryDeviceInfoList *info;
     PCDIMMDeviceInfo     *pcdimm_info;
 
qmp.c +2 -2
index f72261667f..3de029946a 100644
@@ -39,7 +39,7 @@
 #include "qapi/qobject-input-visitor.h"
 #include "hw/boards.h"
 #include "qom/object_interfaces.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/memory-device.h"
 #include "hw/acpi/acpi_dev_interface.h"
 
 NameInfo *qmp_query_name(Error **errp)
@@ -731,7 +731,7 @@ void qmp_object_del(const char *id, Error **errp)
 
 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
 {
-    return qmp_pc_dimm_device_list();
+    return qmp_memory_device_list();
 }
 
 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
stubs/Makefile.objs +1 -1
index 2d59d84091..53d3f32cb2 100644
@@ -34,7 +34,7 @@ stub-obj-y += uuid.o
 stub-obj-y += vm-stop.o
 stub-obj-y += vmstate.o
 stub-obj-$(CONFIG_WIN32) += fd-register.o
-stub-obj-y += qmp_pc_dimm.o
+stub-obj-y += qmp_memory_device.o
 stub-obj-y += target-monitor-defs.o
 stub-obj-y += target-get-monitor-def.o
 stub-obj-y += pc_madt_cpu_entry.o
stubs/qmp_memory_device.c renamed from stubs/qmp_pc_dimm.c +2 -2
similarity index 61%
rename from stubs/qmp_pc_dimm.c
rename to stubs/qmp_memory_device.c
index b6b2cca89e..85ff8f2d7e 100644
@@ -1,8 +1,8 @@
 #include "qemu/osdep.h"
 #include "qom/object.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/memory-device.h"
 
-MemoryDeviceInfoList *qmp_pc_dimm_device_list(void)
+MemoryDeviceInfoList *qmp_memory_device_list(void)
 {
    return NULL;
 }
Signature · 1 line
2.14.3
#2 lore raw

PATCH v4 2/11 machine: make MemoryHotplugState accessible via the machine

In reply to David Hildenbrand

Let's allow to query the MemoryHotplugState directly from the machine. If the pointer is NULL, the machine does not support memory devices. If the pointer is !NULL, the machine supports memory devices and the data structure contains information about the applicable physical guest address space region.

This allows us to generically detect if a certain machine has support for memory devices, and to generically manage it (find free address range, plug/unplug a memory region).

We will rename "MemoryHotplugState" to something more meaningful ("DeviceMemory") after we completed factoring out the pc-dimm code into MemoryDevice code.

---
 hw/i386/acpi-build.c     |  2 +-
 hw/i386/pc.c             | 35 ++++++++++++++++++++---------------
 hw/ppc/spapr.c           | 35 +++++++++++++++++++----------------
 hw/ppc/spapr_hcall.c     |  2 +-
 hw/ppc/spapr_rtas_ddw.c  |  2 +-
 include/hw/boards.h      | 12 ++++++++++++
 include/hw/i386/pc.h     |  1 -
 include/hw/mem/pc-dimm.h | 12 +-----------
 include/hw/ppc/spapr.h   |  1 -
 9 files changed, 55 insertions(+), 47 deletions(-)
hw/i386/acpi-build.c +1 -1
index ca3645d57b..70b37e6df4 100644
@@ -2411,7 +2411,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
      * providing _PXM method if necessary.
      */
     if (hotplugabble_address_space_size) {
-        build_srat_hotpluggable_memory(table_data, pcms->hotplug_memory.base,
+        build_srat_hotpluggable_memory(table_data, machine->device_memory->base,
                                        hotplugabble_address_space_size,
                                        pcms->numa_nodes - 1);
     }
hw/i386/pc.c +20 -15
index d36bac8c89..19af0733fd 100644
@@ -1371,6 +1371,9 @@ void pc_memory_init(PCMachineState *pcms,
         exit(EXIT_FAILURE);
     }
 
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+
     /* initialize hotplug memory address space */
     if (pcmc->has_reserved_memory &&
         (machine->ram_size < machine->maxram_size)) {
@@ -1390,7 +1393,7 @@ void pc_memory_init(PCMachineState *pcms,
             exit(EXIT_FAILURE);
         }
 
-        pcms->hotplug_memory.base =
+        machine->device_memory->base =
             ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30);
 
         if (pcmc->enforce_aligned_dimm) {
@@ -1398,17 +1401,17 @@ void pc_memory_init(PCMachineState *pcms,
             hotplug_mem_size += (1ULL << 30) * machine->ram_slots;
         }
 
-        if ((pcms->hotplug_memory.base + hotplug_mem_size) <
+        if ((machine->device_memory->base + hotplug_mem_size) <
             hotplug_mem_size) {
             error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
                          machine->maxram_size);
             exit(EXIT_FAILURE);
         }
 
-        memory_region_init(&pcms->hotplug_memory.mr, OBJECT(pcms),
+        memory_region_init(&machine->device_memory->mr, OBJECT(pcms),
                            "hotplug-memory", hotplug_mem_size);
-        memory_region_add_subregion(system_memory, pcms->hotplug_memory.base,
-                                    &pcms->hotplug_memory.mr);
+        memory_region_add_subregion(system_memory, machine->device_memory->base,
+                                    &machine->device_memory->mr);
     }
 
     /* Initialize PC system firmware */
@@ -1429,13 +1432,13 @@ void pc_memory_init(PCMachineState *pcms,
 
     rom_set_fw(fw_cfg);
 
-    if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
+    if (pcmc->has_reserved_memory && machine->device_memory->base) {
         uint64_t *val = g_malloc(sizeof(*val));
         PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
-        uint64_t res_mem_end = pcms->hotplug_memory.base;
+        uint64_t res_mem_end = machine->device_memory->base;
 
         if (!pcmc->broken_reserved_end) {
-            res_mem_end += memory_region_size(&pcms->hotplug_memory.mr);
+            res_mem_end += memory_region_size(&machine->device_memory->mr);
         }
         *val = cpu_to_le64(ROUND_UP(res_mem_end, 0x1ULL << 30));
         fw_cfg_add_file(fw_cfg, "etc/reserved-memory-end", val, sizeof(*val));
@@ -1462,12 +1465,13 @@ uint64_t pc_pci_hole64_start(void)
 {
     PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    MachineState *ms = MACHINE(pcms);
     uint64_t hole64_start = 0;
 
-    if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
-        hole64_start = pcms->hotplug_memory.base;
+    if (pcmc->has_reserved_memory && ms->device_memory->base) {
+        hole64_start = ms->device_memory->base;
         if (!pcmc->broken_reserved_end) {
-            hole64_start += memory_region_size(&pcms->hotplug_memory.mr);
+            hole64_start += memory_region_size(&ms->device_memory->mr);
         }
     } else {
         hole64_start = 0x100000000ULL + pcms->above_4g_mem_size;
@@ -1711,7 +1715,8 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align, &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(pcms)->device_memory, mr, align,
+                        &local_err);
     if (local_err) {
         goto out;
     }
@@ -1779,7 +1784,7 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(pcms)->device_memory, mr);
     object_unparent(OBJECT(dev));
 
  out:
@@ -2072,8 +2077,8 @@ pc_machine_get_hotplug_memory_region_size(Object *obj, Visitor *v,
                                           const char *name, void *opaque,
                                           Error **errp)
 {
-    PCMachineState *pcms = PC_MACHINE(obj);
-    int64_t value = memory_region_size(&pcms->hotplug_memory.mr);
+    MachineState *ms = MACHINE(obj);
+    int64_t value = memory_region_size(&ms->device_memory->mr);
 
     visit_type_int(v, name, &value, errp);
 }
hw/ppc/spapr.c +19 -16
index a7428f7da7..56d5e8201b 100644
@@ -681,9 +681,9 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     int ret, i, offset;
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
     uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
-    uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
-    uint32_t nr_lmbs = (spapr->hotplug_memory.base +
-                       memory_region_size(&spapr->hotplug_memory.mr)) /
+    uint32_t hotplug_lmb_start = machine->device_memory->base / lmb_size;
+    uint32_t nr_lmbs = (machine->device_memory->base +
+                       memory_region_size(&machine->device_memory->mr)) /
                        lmb_size;
     uint32_t *int_buf, *cur_index, buf_len;
     int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
@@ -903,8 +903,8 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
     GString *hypertas = g_string_sized_new(256);
     GString *qemu_hypertas = g_string_sized_new(256);
     uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
-    uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
-        memory_region_size(&spapr->hotplug_memory.mr);
+    uint64_t max_hotplug_addr = MACHINE(spapr)->device_memory->base +
+        memory_region_size(&MACHINE(spapr)->device_memory->mr);
     uint32_t lrdr_capacity[] = {
         cpu_to_be32(max_hotplug_addr >> 32),
         cpu_to_be32(max_hotplug_addr & 0xffffffff),
@@ -2174,7 +2174,7 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
     for (i = 0; i < nr_lmbs; i++) {
         uint64_t addr;
 
-        addr = i * lmb_size + spapr->hotplug_memory.base;
+        addr = i * lmb_size + machine->device_memory->base;
         spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB,
                                addr / lmb_size);
     }
@@ -2526,7 +2526,10 @@ static void spapr_machine_init(MachineState *machine)
         memory_region_add_subregion(sysmem, 0, rma_region);
     }
 
-    /* initialize hotplug memory address space */
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+
+    /* initialize device memory address space */
     if (machine->ram_size < machine->maxram_size) {
         ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
         /*
@@ -2547,12 +2550,12 @@ static void spapr_machine_init(MachineState *machine)
             exit(1);
         }
 
-        spapr->hotplug_memory.base = ROUND_UP(machine->ram_size,
+        machine->device_memory->base = ROUND_UP(machine->ram_size,
                                               SPAPR_HOTPLUG_MEM_ALIGN);
-        memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr),
+        memory_region_init(&machine->device_memory->mr, OBJECT(spapr),
                            "hotplug-memory", hotplug_mem_size);
-        memory_region_add_subregion(sysmem, spapr->hotplug_memory.base,
-                                    &spapr->hotplug_memory.mr);
+        memory_region_add_subregion(sysmem, machine->device_memory->base,
+                                    &machine->device_memory->mr);
     }
 
     if (smc->dr_lmb_enabled) {
@@ -3041,7 +3044,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     align = memory_region_get_alignment(mr);
     size = memory_region_size(mr);
 
-    pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(ms)->device_memory, mr, align, &local_err);
     if (local_err) {
         goto out;
     }
@@ -3062,7 +3065,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     return;
 
 out_unplug:
-    pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(ms)->device_memory, mr);
 out:
     error_propagate(errp, local_err);
 }
@@ -3202,7 +3205,7 @@ void spapr_lmb_release(DeviceState *dev)
      * Now that all the LMBs have been removed by the guest, call the
      * pc-dimm unplug handler to cleanup up the pc-dimm device.
      */
-    pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(spapr)->device_memory, mr);
     object_unparent(OBJECT(dev));
     spapr_pending_dimm_unplugs_remove(spapr, ds);
 }
@@ -4159,8 +4162,8 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
         /* Can't just use maxram_size, because there may be an
          * alignment gap between normal and hotpluggable memory
          * regions */
-        ram_top = spapr->hotplug_memory.base +
-            memory_region_size(&spapr->hotplug_memory.mr);
+        ram_top = MACHINE(spapr)->device_memory->base +
+            memory_region_size(&MACHINE(spapr)->device_memory->mr);
     }
 
     phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);
hw/ppc/spapr_hcall.c +1 -1
index 4cdae3ca3a..e99686389d 100644
@@ -64,7 +64,7 @@ static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
 static bool is_ram_address(sPAPRMachineState *spapr, hwaddr addr)
 {
     MachineState *machine = MACHINE(spapr);
-    MemoryHotplugState *hpms = &spapr->hotplug_memory;
+    MemoryHotplugState *hpms = machine->device_memory;
 
     if (addr < machine->ram_size) {
         return true;
hw/ppc/spapr_rtas_ddw.c +1 -1
index 177dcffc9b..d3666c1921 100644
@@ -122,7 +122,7 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
     if (machine->ram_size == machine->maxram_size) {
         max_window_size = machine->ram_size;
     } else {
-        MemoryHotplugState *hpms = &spapr->hotplug_memory;
+        MemoryHotplugState *hpms = machine->device_memory;
 
         max_window_size = hpms->base + memory_region_size(&hpms->mr);
     }
include/hw/boards.h +12 -0
index a609239112..ffc1ee782f 100644
@@ -214,6 +214,17 @@ struct MachineClass {
     int64_t (*get_default_cpu_node_id)(const MachineState *ms, int idx);
 };
 
+/**
+ * MemoryHotplugState:
+ * @base: address in guest physical address space where the memory
+ * address space for memory devices starts
+ * @mr: address space container for memory devices
+ */
+typedef struct MemoryHotplugState {
+    hwaddr base;
+    MemoryRegion mr;
+} MemoryHotplugState;
+
 /**
  * MachineState:
  */
@@ -244,6 +255,7 @@ struct MachineState {
     bool enforce_config_section;
     bool enable_graphics;
     char *memory_encryption;
+    MemoryHotplugState *device_memory;
 
     ram_addr_t ram_size;
     ram_addr_t maxram_size;
include/hw/i386/pc.h +0 -1
index ffee8413f0..07b596ee76 100644
@@ -32,7 +32,6 @@ struct PCMachineState {
     /* <public> */
 
     /* State for other subsystems/APIs: */
-    MemoryHotplugState hotplug_memory;
     Notifier machine_done;
 
     /* Pointers to devices and objects: */
include/hw/mem/pc-dimm.h +1 -11
index e88073321f..8bda37adab 100644
@@ -19,6 +19,7 @@
 #include "exec/memory.h"
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
+#include "hw/boards.h"
 
 #define TYPE_PC_DIMM "pc-dimm"
 #define PC_DIMM(obj) \
@@ -75,17 +76,6 @@ typedef struct PCDIMMDeviceClass {
     MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm);
 } PCDIMMDeviceClass;
 
-/**
- * MemoryHotplugState:
- * @base: address in guest physical address space where hotplug memory
- * address space begins.
- * @mr: hotplug memory address space container
- */
-typedef struct MemoryHotplugState {
-    hwaddr base;
-    MemoryRegion mr;
-} MemoryHotplugState;
-
 uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
                                uint64_t address_space_size,
                                uint64_t *hint, uint64_t align, uint64_t size,
include/hw/ppc/spapr.h +0 -1
index d60b7c6d7a..56ff02d32a 100644
@@ -162,7 +162,6 @@ struct sPAPRMachineState {
 
     /*< public >*/
     char *kvm_type;
-    MemoryHotplugState hotplug_memory;
 
     const char *icp_type;
 
Signature · 1 line
2.14.3
#3 lore raw

Re: [Qemu-devel] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

On Mon, Apr 23, 2018 at 06:51:17PM +0200, David Hildenbrand wrote:
[...]

Quoted 2 lines
(quoted diff) +2 -0
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

[...]

Review

Quoted 3 lines
(quoted diff) +2 -1
-    /* initialize hotplug memory address space */
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

This makes QEMU crash because machine->device_memory->base is initialized with garbage:

#1  0x00007fffef30a8f8 in abort () at /lib64/libc.so.6
#2  0x00007fffef302026 in __assert_fail_base () at /lib64/libc.so.6
#3  0x00007fffef3020d2 in  () at /lib64/libc.so.6
#4  0x0000555555833483 in int128_get64 (a=<optimized out>) at .../qemu-build/include/qemu/int128.h:22
#5  0x0000555555837c2e in memory_region_size (a=<optimized out>) at .../qemu-build/memory.c:1735
#6  0x0000555555837c2e in memory_region_size (mr=<optimized out>) at .../qemu-build/memory.c:1739
#7  0x00005555558a2b14 in pc_memory_init (pcms=pcms@entry=0x555556850050, system_memory=system_memory@entry=0x555556851e00, rom_memory=rom_memory@entry=0x5555568b8120, ram_memory=ram_memory@entry=0x7fffffffd630)
    at .../qemu-build/hw/i386/pc.c:1440

#8 0x00005555558a5a73 in pc_init1 (machine=0x555556850050, pci_type=0x555555cb6fd0 "i440FX", host_type=0x555555c43e41 "i440FX-pcihost") at .../qemu-build/hw/i386/pc_piix.c:179 #9 0x00005555559abbda in machine_run_board_init (machine=0x555556850050) at .../qemu-build/hw/core/machine.c:829
#10 0x00005555557dc515 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at .../qemu-build/vl.c:4563

I will squash the following fixup:

Quoted 1 line

From 6216fdb28476ed21c4ced4672003c9c7cb0e04d2 Mon Sep 17 00:00:00 2001

From: David Hildenbrand <[email protected]>
Date: Fri, 4 May 2018 15:54:46 +0200
Subject: [PATCH] memory-device: fix device_memory creation on pc and spapr

We have to inititalize the struct to 0. Otherwise, without "maxmem", the content is undefined, which might result in random asserts striking when e.g. reading out the size of the contained memory region.

---
 hw/i386/pc.c   | 2 +-
 hw/ppc/spapr.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
hw/i386/pc.c +1 -1
index ffcd7b85d9..868893d0a1 100644
@@ -1372,7 +1372,7 @@ void pc_memory_init(PCMachineState *pcms,
     }
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
     /* initialize device memory address space */
     if (pcmc->has_reserved_memory &&
hw/ppc/spapr.c +1 -1
index ef05075232..a1abcba6ad 100644
@@ -2637,7 +2637,7 @@ static void spapr_machine_init(MachineState *machine)
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
     /* initialize hotplug memory address space */
     if (machine->ram_size < machine->maxram_size) {
Signature · 5 lines
2.14.3


-- 
Eduardo
Reviewed-by
#4 lore raw

Re: [Qemu-devel] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

Quoted 59 lines · Eduardo Habkost

On Mon, Apr 23, 2018 at 06:51:17PM +0200, David Hildenbrand wrote:
[...]

Quoted 2 lines
(quoted diff) +2 -0
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

[...]

Review

Quoted 3 lines
(quoted diff) +2 -1
-    /* initialize hotplug memory address space */
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

This makes QEMU crash because machine->device_memory->base is initialized with garbage:

#1  0x00007fffef30a8f8 in abort () at /lib64/libc.so.6
#2  0x00007fffef302026 in __assert_fail_base () at /lib64/libc.so.6
#3  0x00007fffef3020d2 in  () at /lib64/libc.so.6
#4  0x0000555555833483 in int128_get64 (a=<optimized out>) at .../qemu-build/include/qemu/int128.h:22
#5  0x0000555555837c2e in memory_region_size (a=<optimized out>) at .../qemu-build/memory.c:1735
#6  0x0000555555837c2e in memory_region_size (mr=<optimized out>) at .../qemu-build/memory.c:1739
#7  0x00005555558a2b14 in pc_memory_init (pcms=pcms@entry=0x555556850050, system_memory=system_memory@entry=0x555556851e00, rom_memory=rom_memory@entry=0x5555568b8120, ram_memory=ram_memory@entry=0x7fffffffd630)
     at .../qemu-build/hw/i386/pc.c:1440

#8 0x00005555558a5a73 in pc_init1 (machine=0x555556850050, pci_type=0x555555cb6fd0 "i440FX", host_type=0x555555c43e41 "i440FX-pcihost") at .../qemu-build/hw/i386/pc_piix.c:179 #9 0x00005555559abbda in machine_run_board_init (machine=0x555556850050) at .../qemu-build/hw/core/machine.c:829
#10 0x00005555557dc515 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at .../qemu-build/vl.c:4563

I will squash the following fixup:

From 6216fdb28476ed21c4ced4672003c9c7cb0e04d2 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <[email protected]>
Date: Fri, 4 May 2018 15:54:46 +0200
Subject: [PATCH] memory-device: fix device_memory creation on pc and spapr

We have to inititalize the struct to 0. Otherwise, without "maxmem", the content is undefined, which might result in random asserts striking when e.g. reading out the size of the contained memory region.

---
  hw/i386/pc.c   | 2 +-
  hw/ppc/spapr.c | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)
hw/i386/pc.c +1 -1
index ffcd7b85d9..868893d0a1 100644
@@ -1372,7 +1372,7 @@ void pc_memory_init(PCMachineState *pcms,
      }
 
      /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
      /* initialize device memory address space */
      if (pcmc->has_reserved_memory &&
hw/ppc/spapr.c +0 -0
index ef05075232..a1abcba6ad 100644

hw/ppc/spapr.c static void spapr_machine_init(MachineState *machine) · line 2643

Quoted 8 lines
hw/ppc/spapr.c +1 -1
@@ -2637,7 +2637,7 @@ static void spapr_machine_init(MachineState *machine)
      memory_region_add_subregion(sysmem, 0, ram);
 
      /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
      /* initialize hotplug memory address space */
      if (machine->ram_size < machine->maxram_size) {

Thanks,
Marcel

#5 lore raw

Re: [Qemu-devel] [qemu-s390x] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

In reply to Eduardo Habkost
Quoted 61 lines · Eduardo Habkost

On Mon, Apr 23, 2018 at 06:51:17PM +0200, David Hildenbrand wrote:
[...]

Quoted 2 lines
(quoted diff) +2 -0
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

[...]

Review

Quoted 3 lines
(quoted diff) +2 -1
-    /* initialize hotplug memory address space */
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

This makes QEMU crash because machine->device_memory->base is initialized with garbage:

#1  0x00007fffef30a8f8 in abort () at /lib64/libc.so.6
#2  0x00007fffef302026 in __assert_fail_base () at /lib64/libc.so.6
#3  0x00007fffef3020d2 in  () at /lib64/libc.so.6
#4  0x0000555555833483 in int128_get64 (a=<optimized out>) at .../qemu-build/include/qemu/int128.h:22
#5  0x0000555555837c2e in memory_region_size (a=<optimized out>) at .../qemu-build/memory.c:1735
#6  0x0000555555837c2e in memory_region_size (mr=<optimized out>) at .../qemu-build/memory.c:1739
#7  0x00005555558a2b14 in pc_memory_init (pcms=pcms@entry=0x555556850050, system_memory=system_memory@entry=0x555556851e00, rom_memory=rom_memory@entry=0x5555568b8120, ram_memory=ram_memory@entry=0x7fffffffd630)
    at .../qemu-build/hw/i386/pc.c:1440

#8 0x00005555558a5a73 in pc_init1 (machine=0x555556850050, pci_type=0x555555cb6fd0 "i440FX", host_type=0x555555c43e41 "i440FX-pcihost") at .../qemu-build/hw/i386/pc_piix.c:179 #9 0x00005555559abbda in machine_run_board_init (machine=0x555556850050) at .../qemu-build/hw/core/machine.c:829
#10 0x00005555557dc515 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at .../qemu-build/vl.c:4563

I will squash the following fixup:

From 6216fdb28476ed21c4ced4672003c9c7cb0e04d2 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <[email protected]>
Date: Fri, 4 May 2018 15:54:46 +0200
Subject: [PATCH] memory-device: fix device_memory creation on pc and spapr

We have to inititalize the struct to 0. Otherwise, without "maxmem", the content is undefined, which might result in random asserts striking when e.g. reading out the size of the contained memory region.

---
 hw/i386/pc.c   | 2 +-
 hw/ppc/spapr.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
hw/i386/pc.c +1 -1
index ffcd7b85d9..868893d0a1 100644
@@ -1372,7 +1372,7 @@ void pc_memory_init(PCMachineState *pcms,
     }
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
     /* initialize device memory address space */
     if (pcmc->has_reserved_memory &&
hw/ppc/spapr.c +0 -0
index ef05075232..a1abcba6ad 100644

hw/ppc/spapr.c static void spapr_machine_init(MachineState *machine) · line 2643

Quoted 8 lines
hw/ppc/spapr.c +1 -1
@@ -2637,7 +2637,7 @@ static void spapr_machine_init(MachineState *machine)
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
     /* initialize hotplug memory address space */
     if (machine->ram_size < machine->maxram_size) {

Perfect, thanks Eduardo!

Signature · 3 lines
Thanks,

David / dhildenb
#6 lore raw

Re: [Qemu-devel] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

In reply to Eduardo Habkost
Quoted 60 lines · Eduardo Habkost

On Mon, Apr 23, 2018 at 06:51:17PM +0200, David Hildenbrand wrote:
[...]

Quoted 2 lines
(quoted diff) +2 -0
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

[...]

Review

Quoted 3 lines
(quoted diff) +2 -1
-    /* initialize hotplug memory address space */
+    /* always allocate the device memory information */
+    machine->device_memory = g_malloc(sizeof(*machine->device_memory));

This makes QEMU crash because machine->device_memory->base is initialized with garbage:

#1  0x00007fffef30a8f8 in abort () at /lib64/libc.so.6
#2  0x00007fffef302026 in __assert_fail_base () at /lib64/libc.so.6
#3  0x00007fffef3020d2 in  () at /lib64/libc.so.6
#4  0x0000555555833483 in int128_get64 (a=<optimized out>) at .../qemu-build/include/qemu/int128.h:22
#5  0x0000555555837c2e in memory_region_size (a=<optimized out>) at .../qemu-build/memory.c:1735
#6  0x0000555555837c2e in memory_region_size (mr=<optimized out>) at .../qemu-build/memory.c:1739
#7  0x00005555558a2b14 in pc_memory_init (pcms=pcms@entry=0x555556850050, system_memory=system_memory@entry=0x555556851e00, rom_memory=rom_memory@entry=0x5555568b8120, ram_memory=ram_memory@entry=0x7fffffffd630)
    at .../qemu-build/hw/i386/pc.c:1440

#8 0x00005555558a5a73 in pc_init1 (machine=0x555556850050, pci_type=0x555555cb6fd0 "i440FX", host_type=0x555555c43e41 "i440FX-pcihost") at .../qemu-build/hw/i386/pc_piix.c:179 #9 0x00005555559abbda in machine_run_board_init (machine=0x555556850050) at .../qemu-build/hw/core/machine.c:829
#10 0x00005555557dc515 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at .../qemu-build/vl.c:4563

I will squash the following fixup:

From 6216fdb28476ed21c4ced4672003c9c7cb0e04d2 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <[email protected]>
Date: Fri, 4 May 2018 15:54:46 +0200
Subject: [PATCH] memory-device: fix device_memory creation on pc and spapr

We have to inititalize the struct to 0. Otherwise, without "maxmem", the content is undefined, which might result in random asserts striking when e.g. reading out the size of the contained memory region.

---
 hw/i386/pc.c   | 2 +-
 hw/ppc/spapr.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
hw/i386/pc.c +1 -1
index ffcd7b85d9..868893d0a1 100644
@@ -1372,7 +1372,7 @@ void pc_memory_init(PCMachineState *pcms,
     }
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));
 
     /* initialize device memory address space */
     if (pcmc->has_reserved_memory &&
hw/ppc/spapr.c +0 -0
index ef05075232..a1abcba6ad 100644

hw/ppc/spapr.c static void spapr_machine_init(MachineState *machine) · line 2640

Quoted 5 lines
hw/ppc/spapr.c +1 -1
@@ -2637,7 +2637,7 @@ static void spapr_machine_init(MachineState *machine)
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* always allocate the device memory information */
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));

g_new0 since you are at it? :)

Paolo

Quoted 4 lines
hw/ppc/spapr.c +0 -0
     /* initialize hotplug memory address space */
     if (machine->ram_size < machine->maxram_size) {
 
#7 lore raw

Re: [Qemu-devel] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

On Thu, May 10, 2018 at 06:57:32PM +0200, Paolo Bonzini wrote:
[...]

Quoted 4 lines

Review

Quoted 2 lines
(quoted diff) +1 -1
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));

g_new0 since you are at it? :)

Nice suggestion, but this was already merged.

I think we have a Coccinelle script that should detect this?

Signature · 1 line
Eduardo
#8 lore raw

Re: [Qemu-devel] [PATCH v4 02/11] machine: make MemoryHotplugState accessible via the machine

Quoted 10 lines · Eduardo Habkost

On Thu, May 10, 2018 at 06:57:32PM +0200, Paolo Bonzini wrote:
[...]

Quoted 4 lines

Review

Quoted 2 lines
(quoted diff) +1 -1
-    machine->device_memory = g_malloc(sizeof(*machine->device_memory));
+    machine->device_memory = g_malloc0(sizeof(*machine->device_memory));

g_new0 since you are at it? :)

Nice suggestion, but this was already merged.

I think we have a Coccinelle script that should detect this?

Closest match is commit message b45c03f585e, referred to last in commit bdd81addf40 (both predate scripts/coccinelle/). However, that script only rewrites patterns involving sizeof(T), such as

    g_malloc(sizeof(T) * n) -> g_new(T, n)

because those are obvious improvements. It doesn't rewrite patterns like

    T *v = g_malloc(sizeof(*v)) -> T *v = g_new(T, 1)

because whether those are improvements is debatable.

Feel free to apply them wherever you think they are enough of an improvement to be worth the churn. But I wouldn't apply them tree-write without rough consensus "this is what we want going forward".

#9 lore raw

PATCH v4 3/11 pc-dimm: no need to pass the memory region

In reply to David Hildenbrand

We can just query it ourselves. When unplugging, we should always be able to the region (as it was previously plugged). E.g. PPC already assumed that and used &error_abort.

---
 hw/i386/pc.c             | 13 ++-----------
 hw/mem/pc-dimm.c         | 12 +++++++++---
 hw/ppc/spapr.c           |  9 +++------
 include/hw/mem/pc-dimm.h |  5 ++---
 4 files changed, 16 insertions(+), 23 deletions(-)
hw/i386/pc.c +2 -11
index 19af0733fd..c14dec492b 100644
@@ -1715,8 +1715,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, MACHINE(pcms)->device_memory, mr, align,
-                        &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(pcms)->device_memory, align, &local_err);
     if (local_err) {
         goto out;
     }
@@ -1766,17 +1765,9 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
                            DeviceState *dev, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
-    MemoryRegion *mr;
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
 
-    mr = ddc->get_memory_region(dimm, &local_err);
-    if (local_err) {
-        goto out;
-    }
-
     hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
     hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
 
@@ -1784,7 +1775,7 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_unplug(dev, MACHINE(pcms)->device_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(pcms)->device_memory);
     object_unparent(OBJECT(dev));
 
  out:
hw/mem/pc-dimm.c +9 -3
index ef330628c1..aeff369f6f 100644
@@ -37,7 +37,7 @@ typedef struct pc_dimms_capacity {
 } pc_dimms_capacity;
 
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
-                         MemoryRegion *mr, uint64_t align, Error **errp)
+                         uint64_t align, Error **errp)
 {
     int slot;
     MachineState *machine = MACHINE(qdev_get_machine());
@@ -46,8 +46,14 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
     Error *local_err = NULL;
     uint64_t existing_dimms_capacity = 0;
+    MemoryRegion *mr;
     uint64_t addr;
 
+    mr = ddc->get_memory_region(dimm, &local_err);
+    if (local_err) {
+        goto out;
+    }
+
     addr = object_property_get_uint(OBJECT(dimm),
                                     PC_DIMM_ADDR_PROP, &local_err);
     if (local_err) {
@@ -116,12 +122,12 @@ out:
     error_propagate(errp, local_err);
 }
 
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
-                           MemoryRegion *mr)
+void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms)
 {
     PCDIMMDevice *dimm = PC_DIMM(dev);
     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
+    MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
 
     memory_region_del_subregion(&hpms->mr, mr);
     vmstate_unregister_ram(vmstate_mr, dev);
hw/ppc/spapr.c +3 -6
index 56d5e8201b..8c13d165b4 100644
@@ -3044,7 +3044,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     align = memory_region_get_alignment(mr);
     size = memory_region_size(mr);
 
-    pc_dimm_memory_plug(dev, MACHINE(ms)->device_memory, mr, align, &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(ms)->device_memory, align, &local_err);
     if (local_err) {
         goto out;
     }
@@ -3065,7 +3065,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     return;
 
 out_unplug:
-    pc_dimm_memory_unplug(dev, MACHINE(ms)->device_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(ms)->device_memory);
 out:
     error_propagate(errp, local_err);
 }
@@ -3183,9 +3183,6 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
 void spapr_lmb_release(DeviceState *dev)
 {
     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_hotplug_handler(dev));
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
-    MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
     sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
 
     /* This information will get lost if a migration occurs
@@ -3205,7 +3202,7 @@ void spapr_lmb_release(DeviceState *dev)
      * Now that all the LMBs have been removed by the guest, call the
      * pc-dimm unplug handler to cleanup up the pc-dimm device.
      */
-    pc_dimm_memory_unplug(dev, MACHINE(spapr)->device_memory, mr);
+    pc_dimm_memory_unplug(dev, MACHINE(spapr)->device_memory);
     object_unparent(OBJECT(dev));
     spapr_pending_dimm_unplugs_remove(spapr, ds);
 }
include/hw/mem/pc-dimm.h +2 -3
index 8bda37adab..1d26e13cef 100644
@@ -85,7 +85,6 @@ int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 uint64_t pc_existing_dimms_capacity(Error **errp);
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
-                         MemoryRegion *mr, uint64_t align, Error **errp);
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
-                           MemoryRegion *mr);
+                         uint64_t align, Error **errp);
+void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms);
 #endif
Signature · 1 line
2.14.3
#10 lore raw

PATCH v4 4/11 pc-dimm: pass in the machine and to the MemoryHotplugState

In reply to David Hildenbrand

We use the machine internally either way, so let's just pass it in then.

---
 hw/i386/pc.c             | 4 ++--
 hw/mem/pc-dimm.c         | 8 ++++----
 hw/ppc/spapr.c           | 6 +++---
 include/hw/mem/pc-dimm.h | 4 ++--
 4 files changed, 11 insertions(+), 11 deletions(-)
hw/i386/pc.c +2 -2
index c14dec492b..4b2ede9029 100644
@@ -1715,7 +1715,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, MACHINE(pcms)->device_memory, align, &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(pcms), align, &local_err);
     if (local_err) {
         goto out;
     }
@@ -1775,7 +1775,7 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_unplug(dev, MACHINE(pcms)->device_memory);
+    pc_dimm_memory_unplug(dev, MACHINE(pcms));
     object_unparent(OBJECT(dev));
 
  out:
hw/mem/pc-dimm.c +4 -4
index aeff369f6f..37b8be80a1 100644
@@ -36,11 +36,11 @@ typedef struct pc_dimms_capacity {
      Error    **errp;
 } pc_dimms_capacity;
 
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+void pc_dimm_memory_plug(DeviceState *dev, MachineState *machine,
                          uint64_t align, Error **errp)
 {
     int slot;
-    MachineState *machine = MACHINE(qdev_get_machine());
+    MemoryHotplugState *hpms = machine->device_memory;
     PCDIMMDevice *dimm = PC_DIMM(dev);
     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
@@ -122,14 +122,14 @@ out:
     error_propagate(errp, local_err);
 }
 
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms)
+void pc_dimm_memory_unplug(DeviceState *dev, MachineState *machine)
 {
     PCDIMMDevice *dimm = PC_DIMM(dev);
     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
 
-    memory_region_del_subregion(&hpms->mr, mr);
+    memory_region_del_subregion(&machine->device_memory->mr, mr);
     vmstate_unregister_ram(vmstate_mr, dev);
 }
 
hw/ppc/spapr.c +3 -3
index 8c13d165b4..8ecb716f72 100644
@@ -3044,7 +3044,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     align = memory_region_get_alignment(mr);
     size = memory_region_size(mr);
 
-    pc_dimm_memory_plug(dev, MACHINE(ms)->device_memory, align, &local_err);
+    pc_dimm_memory_plug(dev, MACHINE(ms), align, &local_err);
     if (local_err) {
         goto out;
     }
@@ -3065,7 +3065,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     return;
 
 out_unplug:
-    pc_dimm_memory_unplug(dev, MACHINE(ms)->device_memory);
+    pc_dimm_memory_unplug(dev, MACHINE(ms));
 out:
     error_propagate(errp, local_err);
 }
@@ -3202,7 +3202,7 @@ void spapr_lmb_release(DeviceState *dev)
      * Now that all the LMBs have been removed by the guest, call the
      * pc-dimm unplug handler to cleanup up the pc-dimm device.
      */
-    pc_dimm_memory_unplug(dev, MACHINE(spapr)->device_memory);
+    pc_dimm_memory_unplug(dev, MACHINE(spapr));
     object_unparent(OBJECT(dev));
     spapr_pending_dimm_unplugs_remove(spapr, ds);
 }
include/hw/mem/pc-dimm.h +2 -2
index 1d26e13cef..aa5930fbb6 100644
@@ -84,7 +84,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 uint64_t pc_existing_dimms_capacity(Error **errp);
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+void pc_dimm_memory_plug(DeviceState *dev, MachineState *machine,
                          uint64_t align, Error **errp);
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms);
+void pc_dimm_memory_unplug(DeviceState *dev, MachineState *machine);
 #endif
Signature · 1 line
2.14.3
#11 lore raw

PATCH v4 5/11 pc-dimm: factor out address search into MemoryDevice code

In reply to David Hildenbrand

This mainly moves code, but does a handfull of optimizations:
- We pass the machine instead of the address space properties
- We check the hinted address directly and handle fragmented memory better
- We make the search independent of pc-dimm

---
 hw/mem/memory-device.c         |  86 ++++++++++++++++++++++++++++++++
 hw/mem/pc-dimm.c               | 109 +----------------------------------------
 include/hw/mem/memory-device.h |   3 ++
 include/hw/mem/pc-dimm.h       |   5 --
 4 files changed, 91 insertions(+), 112 deletions(-)
hw/mem/memory-device.c +86 -0
index 6cbdaf99f3..a2cb85462f 100644
@@ -48,6 +48,92 @@ static int memory_device_build_list(Object *obj, void *opaque)
     return 0;
 }
 
+uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
+                                     uint64_t align, uint64_t size,
+                                     Error **errp)
+{
+    uint64_t address_space_start, address_space_end;
+    GSList *list = NULL, *item;
+    uint64_t new_addr = 0;
+
+    if (!ms->device_memory) {
+        error_setg(errp, "memory devices (e.g. for memory hotplug) are not "
+                         "supported by the machine");
+        return 0;
+    }
+
+    if (!memory_region_size(&ms->device_memory->mr)) {
+        error_setg(errp, "memory devices (e.g. for memory hotplug) are not "
+                         "enabled, please specify the maxmem option");
+        return 0;
+    }
+    address_space_start = ms->device_memory->base;
+    address_space_end = address_space_start +
+                        memory_region_size(&ms->device_memory->mr);
+    g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
+    g_assert(address_space_end >= address_space_start);
+
+    if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
+        error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
+                   align);
+        return 0;
+    }
+
+    if (QEMU_ALIGN_UP(size, align) != size) {
+        error_setg(errp, "backend memory size must be multiple of 0x%"
+                   PRIx64, align);
+        return 0;
+    }
+
+    if (hint) {
+        new_addr = *hint;
+        if (new_addr < address_space_start) {
+            error_setg(errp, "can't add memory [0x%" PRIx64 ":0x%" PRIx64
+                       "] at 0x%" PRIx64, new_addr, size, address_space_start);
+            return 0;
+        } else if ((new_addr + size) > address_space_end) {
+            error_setg(errp, "can't add memory [0x%" PRIx64 ":0x%" PRIx64
+                       "] beyond 0x%" PRIx64, new_addr, size,
+                       address_space_end);
+            return 0;
+        }
+    } else {
+        new_addr = address_space_start;
+    }
+
+    /* find address range that will fit new memory device */
+    object_child_foreach(OBJECT(ms), memory_device_build_list, &list);
+    for (item = list; item; item = g_slist_next(item)) {
+        const MemoryDeviceState *md = item->data;
+        const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(OBJECT(md));
+        uint64_t md_size, md_addr;
+
+        md_addr = mdc->get_addr(md);
+        md_size = mdc->get_region_size(md);
+        if (*errp) {
+            goto out;
+        }
+
+        if (ranges_overlap(md_addr, md_size, new_addr, size)) {
+            if (hint) {
+                const DeviceState *d = DEVICE(md);
+                error_setg(errp, "address range conflicts with '%s'", d->id);
+                goto out;
+            }
+            new_addr = QEMU_ALIGN_UP(md_addr + md_size, align);
+        }
+    }
+
+    if (new_addr + size > address_space_end) {
+        error_setg(errp, "could not find position in guest address space for "
+                   "memory device - memory fragmented due to alignments");
+        goto out;
+    }
+out:
+    g_slist_free(list);
+    return new_addr;
+}
+
 MemoryDeviceInfoList *qmp_memory_device_list(void)
 {
     GSList *devices = NULL, *item;
hw/mem/pc-dimm.c +2 -107

128 lines not on this page · raw message

include/hw/mem/memory-device.h +3 -0
index 31f64cbab2..3427c7d424 100644
@@ -41,5 +41,8 @@ typedef struct MemoryDeviceClass {
 
 MemoryDeviceInfoList *qmp_memory_device_list(void);
 uint64_t get_plugged_memory_size(void);
+uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
+                                     uint64_t align, uint64_t size,
+                                     Error **errp);
 
 #endif
include/hw/mem/pc-dimm.h +0 -5
index aa5930fbb6..e37fb5d5db 100644
@@ -76,11 +76,6 @@ typedef struct PCDIMMDeviceClass {
     MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm);
 } PCDIMMDeviceClass;
 
-uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
-                               uint64_t address_space_size,
-                               uint64_t *hint, uint64_t align, uint64_t size,
-                               Error **errp);
-
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 uint64_t pc_existing_dimms_capacity(Error **errp);
Signature · 1 line
2.14.3
#12 lore raw

PATCH v4 6/11 pc-dimm: factor out capacity and slot checks into MemoryDevice

In reply to David Hildenbrand

Move the checks into memory_device_get_free_addr(). This will check before doing any calculations if we have KVM/vhost slots left and if the total region size would be exceeded.

Of course, while at it, make it independent of pc-dimm code.

---
 hw/mem/memory-device.c   | 51 ++++++++++++++++++++++++++++++++++++++++
 hw/mem/pc-dimm.c         | 60 ------------------------------------------------
 include/hw/mem/pc-dimm.h |  1 -
 3 files changed, 51 insertions(+), 61 deletions(-)
hw/mem/memory-device.c +51 -0
index a2cb85462f..8535ddcb14 100644
@@ -15,6 +15,8 @@
 #include "qapi/error.h"
 #include "hw/boards.h"
 #include "qemu/range.h"
+#include "hw/virtio/vhost.h"
+#include "sysemu/kvm.h"
 
 static gint memory_device_addr_sort(gconstpointer a, gconstpointer b)
 {
@@ -48,6 +50,50 @@ static int memory_device_build_list(Object *obj, void *opaque)
     return 0;
 }
 
+static int memory_device_used_region_size(Object *obj, void *opaque)
+{
+    uint64_t *size = opaque;
+
+    if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) {
+        const DeviceState *dev = DEVICE(obj);
+        const MemoryDeviceState *md = MEMORY_DEVICE(obj);
+        const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(obj);
+
+        if (dev->realized) {
+            *size += mdc->get_region_size(md);
+        }
+    }
+
+    object_child_foreach(obj, memory_device_used_region_size, opaque);
+    return 0;
+}
+
+static void memory_device_check_addable(MachineState *ms, uint64_t size,
+                                        Error **errp)
+{
+    uint64_t used_region_size = 0;
+
+    /* we will need a new memory slot for kvm and vhost */
+    if (kvm_enabled() && !kvm_has_free_slot(ms)) {
+        error_setg(errp, "hypervisor has no free memory slots left");
+        return;
+    }
+    if (!vhost_has_free_slot()) {
+        error_setg(errp, "a used vhost backend has no free memory slots left");
+        return;
+    }
+
+    /* will we exceed the total amount of memory specified */
+    memory_device_used_region_size(OBJECT(ms), &used_region_size);
+    if (used_region_size + size > ms->maxram_size - ms->ram_size) {
+        error_setg(errp, "not enough space, currently 0x%" PRIx64
+                   " in use of total hot pluggable 0x" RAM_ADDR_FMT,
+                   used_region_size, ms->maxram_size - ms->ram_size);
+        return;
+    }
+
+}
+
 uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
                                      uint64_t align, uint64_t size,
                                      Error **errp)
@@ -73,6 +119,11 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
     g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
     g_assert(address_space_end >= address_space_start);
 
+    memory_device_check_addable(ms, size, errp);
+    if (*errp) {
+        return 0;
+    }
+
     if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
         error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
                    align);
hw/mem/pc-dimm.c +0 -60

91 lines not on this page · raw message

include/hw/mem/pc-dimm.h +0 -1
index e37fb5d5db..627c8601d9 100644
@@ -78,7 +78,6 @@ typedef struct PCDIMMDeviceClass {
 
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
-uint64_t pc_existing_dimms_capacity(Error **errp);
 void pc_dimm_memory_plug(DeviceState *dev, MachineState *machine,
                          uint64_t align, Error **errp);
 void pc_dimm_memory_unplug(DeviceState *dev, MachineState *machine);
Signature · 1 line
2.14.3
#13 lore raw

PATCH v4 7/11 pc-dimm: move actual plug/unplug of a memory region to MemoryDevice

In reply to David Hildenbrand

Registering the memory region for migration has do be done by the owner. There could be cases, where we don't want to migrate the memory.

---
 hw/mem/memory-device.c         | 18 ++++++++++++++++++
 hw/mem/pc-dimm.c               |  5 ++---
 include/hw/mem/memory-device.h |  3 +++
 3 files changed, 23 insertions(+), 3 deletions(-)
hw/mem/memory-device.c +18 -0
index 8535ddcb14..3e04f3954e 100644
@@ -243,6 +243,24 @@ uint64_t get_plugged_memory_size(void)
     return size;
 }
 
+void memory_device_plug_region(MachineState *ms, MemoryRegion *mr,
+                               uint64_t addr)
+{
+    /* we expect a previous call to memory_device_get_free_addr() */
+    g_assert(ms->device_memory);
+
+    memory_region_add_subregion(&ms->device_memory->mr,
+                                addr - ms->device_memory->base, mr);
+}
+
+void memory_device_unplug_region(MachineState *ms, MemoryRegion *mr)
+{
+    /* we expect a previous call to memory_device_get_free_addr() */
+    g_assert(ms->device_memory);
+
+    memory_region_del_subregion(&ms->device_memory->mr, mr);
+}
+
 static const TypeInfo memory_device_info = {
     .name          = TYPE_MEMORY_DEVICE,
     .parent        = TYPE_INTERFACE,
hw/mem/pc-dimm.c +2 -3
index 8aa2d36ce9..0119c68e01 100644
@@ -36,7 +36,6 @@ void pc_dimm_memory_plug(DeviceState *dev, MachineState *machine,
                          uint64_t align, Error **errp)
 {
     int slot;
-    MemoryHotplugState *hpms = machine->device_memory;
     PCDIMMDevice *dimm = PC_DIMM(dev);
     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
@@ -83,7 +82,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MachineState *machine,
     }
     trace_mhp_pc_dimm_assigned_slot(slot);
 
-    memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
+    memory_device_plug_region(machine, mr, addr);
     vmstate_register_ram(vmstate_mr, dev);
 
 out:
@@ -97,7 +96,7 @@ void pc_dimm_memory_unplug(DeviceState *dev, MachineState *machine)
     MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
 
-    memory_region_del_subregion(&machine->device_memory->mr, mr);
+    memory_device_unplug_region(machine, mr);
     vmstate_unregister_ram(vmstate_mr, dev);
 }
 
include/hw/mem/memory-device.h +3 -0
index 3427c7d424..2853b084b5 100644
@@ -44,5 +44,8 @@ uint64_t get_plugged_memory_size(void);
 uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
                                      uint64_t align, uint64_t size,
                                      Error **errp);
+void memory_device_plug_region(MachineState *ms, MemoryRegion *mr,
+                               uint64_t addr);
+void memory_device_unplug_region(MachineState *ms, MemoryRegion *mr);
 
 #endif
Signature · 1 line
2.14.3
#14 lore raw

PATCH v4 8/11 machine: rename MemoryHotplugState to DeviceMemoryState

In reply to David Hildenbrand

Rename it to better match the new terminology.

---
 hw/ppc/spapr_hcall.c    | 6 +++---
 hw/ppc/spapr_rtas_ddw.c | 5 ++---
 include/hw/boards.h     | 8 ++++----
 3 files changed, 9 insertions(+), 10 deletions(-)
hw/ppc/spapr_hcall.c +3 -3
index e99686389d..3b3d927c98 100644
@@ -64,13 +64,13 @@ static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
 static bool is_ram_address(sPAPRMachineState *spapr, hwaddr addr)
 {
     MachineState *machine = MACHINE(spapr);
-    MemoryHotplugState *hpms = machine->device_memory;
+    DeviceMemoryState *dms = machine->device_memory;
 
     if (addr < machine->ram_size) {
         return true;
     }
-    if ((addr >= hpms->base)
-        && ((addr - hpms->base) < memory_region_size(&hpms->mr))) {
+    if ((addr >= dms->base)
+        && ((addr - dms->base) < memory_region_size(&dms->mr))) {
         return true;
     }
 
hw/ppc/spapr_rtas_ddw.c +2 -3
index d3666c1921..329feb148f 100644
@@ -122,9 +122,8 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
     if (machine->ram_size == machine->maxram_size) {
         max_window_size = machine->ram_size;
     } else {
-        MemoryHotplugState *hpms = machine->device_memory;
-
-        max_window_size = hpms->base + memory_region_size(&hpms->mr);
+        max_window_size = machine->device_memory->base +
+                          memory_region_size(&machine->device_memory->mr);
     }
 
     avail = SPAPR_PCI_DMA_MAX_WINDOWS - spapr_phb_get_active_win_num(sphb);
include/hw/boards.h +4 -4
index ffc1ee782f..8748964e6f 100644
@@ -215,15 +215,15 @@ struct MachineClass {
 };
 
 /**
- * MemoryHotplugState:
+ * DeviceMemoryState:
  * @base: address in guest physical address space where the memory
  * address space for memory devices starts
  * @mr: address space container for memory devices
  */
-typedef struct MemoryHotplugState {
+typedef struct DeviceMemoryState {
     hwaddr base;
     MemoryRegion mr;
-} MemoryHotplugState;
+} DeviceMemoryState;
 
 /**
  * MachineState:
@@ -255,7 +255,7 @@ struct MachineState {
     bool enforce_config_section;
     bool enable_graphics;
     char *memory_encryption;
-    MemoryHotplugState *device_memory;
+    DeviceMemoryState *device_memory;
 
     ram_addr_t ram_size;
     ram_addr_t maxram_size;
Signature · 1 line
2.14.3
#15 lore raw

PATCH v4 9/11 pc: rename "hotplug memory" terminology to "device memory"

In reply to David Hildenbrand

Let's make it clear that we are dealing with device memory. That it can be used for memory hotplug is just a special case.

---
 hw/i386/acpi-build.c |  2 +-
 hw/i386/pc.c         | 25 ++++++++++++-------------
 include/hw/i386/pc.h |  2 +-
 3 files changed, 14 insertions(+), 15 deletions(-)
hw/i386/acpi-build.c +1 -1
index 70b37e6df4..123430fbff 100644
@@ -2313,7 +2313,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
     PCMachineState *pcms = PC_MACHINE(machine);
     ram_addr_t hotplugabble_address_space_size =
-        object_property_get_int(OBJECT(pcms), PC_MACHINE_MEMHP_REGION_SIZE,
+        object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
                                 NULL);
 
     srat_start = table_data->len;
hw/i386/pc.c +12 -13
index 4b2ede9029..afbdf48fbb 100644
@@ -1374,11 +1374,10 @@ void pc_memory_init(PCMachineState *pcms,
     /* always allocate the device memory information */
     machine->device_memory = g_malloc(sizeof(*machine->device_memory));
 
-    /* initialize hotplug memory address space */
+    /* initialize device memory address space */
     if (pcmc->has_reserved_memory &&
         (machine->ram_size < machine->maxram_size)) {
-        ram_addr_t hotplug_mem_size =
-            machine->maxram_size - machine->ram_size;
+        ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
 
         if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {
             error_report("unsupported amount of memory slots: %"PRIu64,
@@ -1397,19 +1396,19 @@ void pc_memory_init(PCMachineState *pcms,
             ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30);
 
         if (pcmc->enforce_aligned_dimm) {
-            /* size hotplug region assuming 1G page max alignment per slot */
-            hotplug_mem_size += (1ULL << 30) * machine->ram_slots;
+            /* size device region assuming 1G page max alignment per slot */
+            device_mem_size += (1ULL << 30) * machine->ram_slots;
         }
 
-        if ((machine->device_memory->base + hotplug_mem_size) <
-            hotplug_mem_size) {
+        if ((machine->device_memory->base + device_mem_size) <
+            device_mem_size) {
             error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
                          machine->maxram_size);
             exit(EXIT_FAILURE);
         }
 
         memory_region_init(&machine->device_memory->mr, OBJECT(pcms),
-                           "hotplug-memory", hotplug_mem_size);
+                           "device-memory", device_mem_size);
         memory_region_add_subregion(system_memory, machine->device_memory->base,
                                     &machine->device_memory->mr);
     }
@@ -2064,9 +2063,9 @@ static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
 }
 
 static void
-pc_machine_get_hotplug_memory_region_size(Object *obj, Visitor *v,
-                                          const char *name, void *opaque,
-                                          Error **errp)
+pc_machine_get_device_memory_region_size(Object *obj, Visitor *v,
+                                         const char *name, void *opaque,
+                                         Error **errp)
 {
     MachineState *ms = MACHINE(obj);
     int64_t value = memory_region_size(&ms->device_memory->mr);
@@ -2373,8 +2372,8 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     nc->nmi_monitor_handler = x86_nmi;
     mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
 
-    object_class_property_add(oc, PC_MACHINE_MEMHP_REGION_SIZE, "int",
-        pc_machine_get_hotplug_memory_region_size, NULL,
+    object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int",
+        pc_machine_get_device_memory_region_size, NULL,
         NULL, NULL, &error_abort);
 
     object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
include/hw/i386/pc.h +1 -1
index 07b596ee76..2e834e6ded 100644
@@ -71,7 +71,7 @@ struct PCMachineState {
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
-#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
+#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
 #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
 #define PC_MACHINE_VMPORT           "vmport"
 #define PC_MACHINE_SMM              "smm"
Signature · 1 line
2.14.3
#16 lore raw

PATCH v4 10/11 spapr: rename "hotplug memory" terminology to "device memory"

In reply to David Hildenbrand

Let's make it clear at relevant places that we are dealing with device memory. That it can be used for memory hotplug is just a special case.

---
 hw/ppc/spapr.c         | 28 ++++++++++++++--------------
 include/hw/ppc/spapr.h |  4 ++--
 2 files changed, 16 insertions(+), 16 deletions(-)
hw/ppc/spapr.c +14 -14
index 8ecb716f72..a32b88e41d 100644
@@ -681,7 +681,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     int ret, i, offset;
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
     uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
-    uint32_t hotplug_lmb_start = machine->device_memory->base / lmb_size;
+    uint32_t device_lmb_start = machine->device_memory->base / lmb_size;
     uint32_t nr_lmbs = (machine->device_memory->base +
                        memory_region_size(&machine->device_memory->mr)) /
                        lmb_size;
@@ -690,7 +690,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     MemoryDeviceInfoList *dimms = NULL;
 
     /*
-     * Don't create the node if there is no hotpluggable memory
+     * Don't create the node if there is no device memory
      */
     if (machine->ram_size == machine->maxram_size) {
         return 0;
@@ -722,7 +722,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         goto out;
     }
 
-    if (hotplug_lmb_start) {
+    if (device_lmb_start) {
         dimms = qmp_memory_device_list();
     }
 
@@ -733,7 +733,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         uint64_t addr = i * lmb_size;
         uint32_t *dynamic_memory = cur_index;
 
-        if (i >= hotplug_lmb_start) {
+        if (i >= device_lmb_start) {
             sPAPRDRConnector *drc;
 
             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
@@ -752,7 +752,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         } else {
             /*
              * LMB information for RMA, boot time RAM and gap b/n RAM and
-             * hotplug memory region -- all these are marked as reserved
+             * device memory region -- all these are marked as reserved
              * and as having no valid DRC.
              */
             dynamic_memory[0] = cpu_to_be32(addr >> 32);
@@ -903,11 +903,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
     GString *hypertas = g_string_sized_new(256);
     GString *qemu_hypertas = g_string_sized_new(256);
     uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
-    uint64_t max_hotplug_addr = MACHINE(spapr)->device_memory->base +
+    uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
         memory_region_size(&MACHINE(spapr)->device_memory->mr);
     uint32_t lrdr_capacity[] = {
-        cpu_to_be32(max_hotplug_addr >> 32),
-        cpu_to_be32(max_hotplug_addr & 0xffffffff),
+        cpu_to_be32(max_device_addr >> 32),
+        cpu_to_be32(max_device_addr & 0xffffffff),
         0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
         cpu_to_be32(max_cpus / smp_threads),
     };
@@ -2531,7 +2531,7 @@ static void spapr_machine_init(MachineState *machine)
 
     /* initialize device memory address space */
     if (machine->ram_size < machine->maxram_size) {
-        ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
+        ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
         /*
          * Limit the number of hotpluggable memory slots to half the number
          * slots that KVM supports, leaving the other half for PCI and other
@@ -2551,9 +2551,9 @@ static void spapr_machine_init(MachineState *machine)
         }
 
         machine->device_memory->base = ROUND_UP(machine->ram_size,
-                                              SPAPR_HOTPLUG_MEM_ALIGN);
+                                                SPAPR_DEVICE_MEM_ALIGN);
         memory_region_init(&machine->device_memory->mr, OBJECT(spapr),
-                           "hotplug-memory", hotplug_mem_size);
+                           "device-memory", device_mem_size);
         memory_region_add_subregion(sysmem, machine->device_memory->base,
                                     &machine->device_memory->mr);
     }
@@ -4154,11 +4154,11 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
     hwaddr phb0_base, phb_base;
     int i;
 
-    /* Do we have hotpluggable memory? */
+    /* Do we have device memory? */
     if (MACHINE(spapr)->maxram_size > ram_top) {
         /* Can't just use maxram_size, because there may be an
-         * alignment gap between normal and hotpluggable memory
-         * regions */
+         * alignment gap between normal and device memory regions
+         */
         ram_top = MACHINE(spapr)->device_memory->base +
             memory_region_size(&MACHINE(spapr)->device_memory->mr);
     }
include/hw/ppc/spapr.h +2 -2
index 56ff02d32a..3388750fc7 100644
@@ -747,8 +747,8 @@ int spapr_rng_populate_dt(void *fdt);
  */
 #define SPAPR_MAX_RAM_SLOTS     32
 
-/* 1GB alignment for hotplug memory region */
-#define SPAPR_HOTPLUG_MEM_ALIGN (1ULL << 30)
+/* 1GB alignment for device memory region */
+#define SPAPR_DEVICE_MEM_ALIGN (1ULL << 30)
 
 /*
  * Number of 32 bit words in each LMB list entry in ibm,dynamic-memory
Signature · 1 line
2.14.3
Acked-by on v4 10/11
#17 lore raw

Re: [Qemu-devel] [PATCH v4 10/11] spapr: rename "hotplug memory" terminology to "device memory"

Quoted 4 lines · David Hildenbrand

Let's make it clear at relevant places that we are dealing with device memory. That it can be used for memory hotplug is just a special case.

Quoted 120 lines
---
 hw/ppc/spapr.c         | 28 ++++++++++++++--------------
 include/hw/ppc/spapr.h |  4 ++--
 2 files changed, 16 insertions(+), 16 deletions(-)
hw/ppc/spapr.c +14 -14
index 8ecb716f72..a32b88e41d 100644
@@ -681,7 +681,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     int ret, i, offset;
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
     uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
-    uint32_t hotplug_lmb_start = machine->device_memory->base / lmb_size;
+    uint32_t device_lmb_start = machine->device_memory->base / lmb_size;
     uint32_t nr_lmbs = (machine->device_memory->base +
                        memory_region_size(&machine->device_memory->mr)) /
                        lmb_size;
@@ -690,7 +690,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     MemoryDeviceInfoList *dimms = NULL;
 
     /*
-     * Don't create the node if there is no hotpluggable memory
+     * Don't create the node if there is no device memory
      */
     if (machine->ram_size == machine->maxram_size) {
         return 0;
@@ -722,7 +722,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         goto out;
     }
 
-    if (hotplug_lmb_start) {
+    if (device_lmb_start) {
         dimms = qmp_memory_device_list();
     }
 
@@ -733,7 +733,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         uint64_t addr = i * lmb_size;
         uint32_t *dynamic_memory = cur_index;
 
-        if (i >= hotplug_lmb_start) {
+        if (i >= device_lmb_start) {
             sPAPRDRConnector *drc;
 
             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
@@ -752,7 +752,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
         } else {
             /*
              * LMB information for RMA, boot time RAM and gap b/n RAM and
-             * hotplug memory region -- all these are marked as reserved
+             * device memory region -- all these are marked as reserved
              * and as having no valid DRC.
              */
             dynamic_memory[0] = cpu_to_be32(addr >> 32);
@@ -903,11 +903,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
     GString *hypertas = g_string_sized_new(256);
     GString *qemu_hypertas = g_string_sized_new(256);
     uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
-    uint64_t max_hotplug_addr = MACHINE(spapr)->device_memory->base +
+    uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
         memory_region_size(&MACHINE(spapr)->device_memory->mr);
     uint32_t lrdr_capacity[] = {
-        cpu_to_be32(max_hotplug_addr >> 32),
-        cpu_to_be32(max_hotplug_addr & 0xffffffff),
+        cpu_to_be32(max_device_addr >> 32),
+        cpu_to_be32(max_device_addr & 0xffffffff),
         0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
         cpu_to_be32(max_cpus / smp_threads),
     };
@@ -2531,7 +2531,7 @@ static void spapr_machine_init(MachineState *machine)
 
     /* initialize device memory address space */
     if (machine->ram_size < machine->maxram_size) {
-        ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
+        ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
         /*
          * Limit the number of hotpluggable memory slots to half the number
          * slots that KVM supports, leaving the other half for PCI and other
@@ -2551,9 +2551,9 @@ static void spapr_machine_init(MachineState *machine)
         }
 
         machine->device_memory->base = ROUND_UP(machine->ram_size,
-                                              SPAPR_HOTPLUG_MEM_ALIGN);
+                                                SPAPR_DEVICE_MEM_ALIGN);
         memory_region_init(&machine->device_memory->mr, OBJECT(spapr),
-                           "hotplug-memory", hotplug_mem_size);
+                           "device-memory", device_mem_size);
         memory_region_add_subregion(sysmem, machine->device_memory->base,
                                     &machine->device_memory->mr);
     }
@@ -4154,11 +4154,11 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
     hwaddr phb0_base, phb_base;
     int i;
 
-    /* Do we have hotpluggable memory? */
+    /* Do we have device memory? */
     if (MACHINE(spapr)->maxram_size > ram_top) {
         /* Can't just use maxram_size, because there may be an
-         * alignment gap between normal and hotpluggable memory
-         * regions */
+         * alignment gap between normal and device memory regions
+         */
         ram_top = MACHINE(spapr)->device_memory->base +
             memory_region_size(&MACHINE(spapr)->device_memory->mr);
     }
include/hw/ppc/spapr.h +2 -2
index 56ff02d32a..3388750fc7 100644
@@ -747,8 +747,8 @@ int spapr_rng_populate_dt(void *fdt);
  */
 #define SPAPR_MAX_RAM_SLOTS     32
 
-/* 1GB alignment for hotplug memory region */
-#define SPAPR_HOTPLUG_MEM_ALIGN (1ULL << 30)
+/* 1GB alignment for device memory region */
+#define SPAPR_DEVICE_MEM_ALIGN (1ULL << 30)
 
 /*
  * Number of 32 bit words in each LMB list entry in ibm,dynamic-memory
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#18 lore raw

PATCH v4 11/11 vl: allow 'maxmem' without 'slot'

In reply to David Hildenbrand

We will be able to have memory devices (e.g. virtio) not requiring the slot parameter (e.g. not exposed via ACPI). We still need the maxmem parameter to setup a proper memory region for device memory. And some architectures (e.g. s390x) will have to set up the maximum possible guest address space size based on the maxmem parameter.

As far as I can see, all code (pc.c,spapr.c,ACPI code) should handle !slots just fine, even though maxmem is set.

---
 vl.c | 19 ++++---------------
 1 file changed, 4 insertions(+), 15 deletions(-)
vl.c +4 -15
index fce1fd12d8..acb815bc14 100644
@@ -2887,7 +2887,6 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
 {
     uint64_t sz;
     const char *mem_str;
-    const char *maxmem_str, *slots_str;
     const ram_addr_t default_ram_size = mc->default_ram_size;
     QemuOpts *opts = qemu_find_opts_singleton("memory");
     Location loc;
@@ -2933,9 +2932,7 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
     qemu_opt_set_number(opts, "size", ram_size, &error_abort);
     *maxram_size = ram_size;
 
-    maxmem_str = qemu_opt_get(opts, "maxmem");
-    slots_str = qemu_opt_get(opts, "slots");
-    if (maxmem_str && slots_str) {
+    if (qemu_opt_get(opts, "maxmem")) {
         uint64_t slots;
 
         sz = qemu_opt_get_size(opts, "maxmem", 0);
@@ -2946,13 +2943,7 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
                          "the initial memory size (0x" RAM_ADDR_FMT ")",
                          sz, ram_size);
             exit(EXIT_FAILURE);
-        } else if (sz > ram_size) {
-            if (!slots) {
-                error_report("invalid value of -m option: maxmem was "
-                             "specified, but no hotplug slots were specified");
-                exit(EXIT_FAILURE);
-            }
-        } else if (slots) {
+        } else if (slots && sz == ram_size) {
             error_report("invalid value of -m option maxmem: "
                          "memory slots were specified but maximum memory size "
                          "(0x%" PRIx64 ") is equal to the initial memory size "
@@ -2962,10 +2953,8 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
 
         *maxram_size = sz;
         *ram_slots = slots;
-    } else if ((!maxmem_str && slots_str) ||
-            (maxmem_str && !slots_str)) {
-        error_report("invalid -m option value: missing "
-                "'%s' option", slots_str ? "maxmem" : "slots");
+    } else if (qemu_opt_get(opts, "slots")) {
+        error_report("invalid -m option value: missing 'maxmem' option");
         exit(EXIT_FAILURE);
     }
 
Signature · 1 line
2.14.3
Reviewed-by on the v4 series
#19 lore raw
In reply to David Hildenbrand
Quoted 12 lines · David Hildenbrand

Right now we can only map PCDIMM/NVDIMM into guest address space. In the future, we might want to do the same for virtio devices - e.g. virtio-pmem or virtio-mem. Especially, they should be able to live side by side to each other.

E.g. the virto based memory devices regions will not be exposed via ACPI and friends. They will be detected just like other virtio devices and indicate the applicable memory region. This makes it possible to also use them on architectures without memory device detection support (e.g. s390x).

Let's factor out the memory device code into a MemoryDevice interface.

Quoted 8 lines

Please note that the "slots" assignment code is not relevant for memory devices that will not be exposed via ACPI or similar. That's why that part won't be exposed. KVM/vhost "slots" for memory regions are still necessary but don't have to be manually specified (e.g. the slot number doesn't mather).

So we are basically converting the hotplug memory region to a memory device region. I have patches that also set up such a region for s390x.

Who's merging this? Eduardo?

Quoted 62 lines

v3 -> v4:
- "pc-dimm: factor out MemoryDevice interface"
-- dropped the "errp" parameter from the interface functions
-- made as many pointers const as I could :)
-- s/built/build/
- machine: make MemoryHotplugState accessible via the machine
-- State now kept via a pointer, not queried.
-- Added patches that rename the type and cleanup the terminology for
spapr and pc
- Split up the big "pc-dimm: factor out address space logic into MemoryDevice code" into sub patches
-- We now pass the machine to the pc-dimm and MemoryDevice plug/unplug
functions, so we can avoid qdev_get_machine()
-- Moved some checks around as requested by Igor
- Added a patch to make maxmem not depend on slots

v2 -> v3:
- "pc-dimm: factor out MemoryDevice interface" --> Lookup both classes when comparing (David Gibson)

v1 -> v2:
- Fix compile issues on ppc (still untested )

David Hildenbrand (11):
pc-dimm: factor out MemoryDevice interface
machine: make MemoryHotplugState accessible via the machine
pc-dimm: no need to pass the memory region
pc-dimm: pass in the machine and to the MemoryHotplugState
pc-dimm: factor out address search into MemoryDevice code
pc-dimm: factor out capacity and slot checks into MemoryDevice
pc-dimm: move actual plug/unplug of a memory region to MemoryDevice
machine: rename MemoryHotplugState to DeviceMemoryState
pc: rename "hotplug memory" terminology to "device memory"
spapr: rename "hotplug memory" terminology to "device memory"
vl: allow 'maxmem' without 'slot'

 hw/i386/acpi-build.c                         |   7 +-
 hw/i386/pc.c                                 |  65 +++---
 hw/mem/Makefile.objs                         |   1 +
 hw/mem/memory-device.c                       | 275 ++++++++++++++++++++++++
 hw/mem/pc-dimm.c                             | 304 +++++++--------------------
 hw/ppc/spapr.c                               |  65 +++---
 hw/ppc/spapr_hcall.c                         |   7 +-
 hw/ppc/spapr_rtas_ddw.c                      |   5 +-
 include/hw/boards.h                          |  12 ++
 include/hw/i386/pc.h                         |   3 +-
 include/hw/mem/memory-device.h               |  51 +++++
 include/hw/mem/pc-dimm.h                     |  27 +--
 include/hw/ppc/spapr.h                       |   5 +-
 numa.c                                       |   3 +-
 qmp.c                                        |   4 +-
 stubs/Makefile.objs                          |   2 +-
 stubs/{qmp_pc_dimm.c => qmp_memory_device.c} |   4 +-
 vl.c                                         |  19 +-
 18 files changed, 506 insertions(+), 353 deletions(-)
 create mode 100644 hw/mem/memory-device.c
 create mode 100644 include/hw/mem/memory-device.h
 rename stubs/{qmp_pc_dimm.c => qmp_memory_device.c} (61%)
Signature · 1 line
2.14.3
#20 lore raw
Quoted 19 lines · Michael S. Tsirkin
Quoted 18 lines · David Hildenbrand

Right now we can only map PCDIMM/NVDIMM into guest address space. In the future, we might want to do the same for virtio devices - e.g. virtio-pmem or virtio-mem. Especially, they should be able to live side by side to each other.

E.g. the virto based memory devices regions will not be exposed via ACPI and friends. They will be detected just like other virtio devices and indicate the applicable memory region. This makes it possible to also use them on architectures without memory device detection support (e.g. s390x).

Let's factor out the memory device code into a MemoryDevice interface.

Please note that the "slots" assignment code is not relevant for memory devices that will not be exposed via ACPI or similar. That's why that part won't be exposed. KVM/vhost "slots" for memory regions are still necessary but don't have to be manually specified (e.g. the slot number doesn't mather).

Quoted 6 lines
Quoted 2 lines

So we are basically converting the hotplug memory region to a memory device region. I have patches that also set up such a region for s390x.

Who's merging this? Eduardo?

I just queued it. Thanks!

Signature · 1 line
Eduardo