memory-device: complete refactoring
v5 cover memory-device: complete refactoring
This series completes refactoring of pre_plug, plug and unplug logic of memory devices. With this as a basis, we can built e.g. virtio based memory devices or internal "RAM chip" devices.
I dropped the virtio-pmem prototype for now, I will look into plugging it differently next. But this part in this series here is independent of hotplug handler changes required to make it work for virtio devices.
v4 -> v5:
- Added a bunch of RB's
- Minor spelling fixed
- Dropped "memory-device: add class function get_device_id()"
- Added "memory-device: improve "range conflicts" error message
- Dropped "memory-device: handle integer overflows properly" -- Will require more changes. But I am able to reproduce some overflows.
- "memory-device: document MemoryDeviceClass"
-- Changed documentation format as requested by Auger
- "memory-device: trace when pre_plugging/plugging/unplugging" -- Include device ID and rename tracepoints.
v3 -> v4:
- Minor comment and subject fixes
- Added "memory-device: fix alignment error message"
- Added "pc-dimm: pass PCDIMMDevice to pc_dimm_.*plug"
- Dropped "hw/acpi-build: only indicate nvdimm and pc-dimm"
- "memory-device: document MemoryDeviceClass"
-- add more details about get_plugged_size
- "memory-device: add and use memory_device_get_region_size()"
-- fixed "local_err" usage
-- due to "pc-dimm: pass PCDIMMDevice to pc_dimm_.*plug", keep PC_DIMM cast
- "memory-device: add class function get_device_id()"
-- provide default handler
- "hmp: handle virtio-pmem when printing memory device infos"
-- avoid fall-through switch case
-- add g_assert_not_reached()
- "numa: handle virtio-pmem in NUMA stats"
-- avoid fall-through switch case
-- add g_assert_not_reached()
- Added "qdev: hotplug: provide do_unplug handler"
-- unplug/unplug_request are not called for devices inside a device hierarchy
This new handler is always called when unrealizing and doesn't trigger the unrealize (in contrast to unplug/unplug_request)
- "pc: support for virtio-pmem" and "virtio-pmem: hotplug support functions" -- use do_unplug handler
- Tested "device_del vp1". It works, and I can see in the traces the address getting unassigned. QEMU crashes when shutting down, that most most likely is a result of virtio-pmem not properly unrealizing and cleaning up virtqueues. (@Pankaj if you read this )
v2 -> v3:
- Rephrased some patch subjects/descriptions
- Added "memory-device: handle integer overflows properly"
- "memory-device: forward errors in get_region_size()/get_plugged_size()" -- drop superfluous error check
- "memory-device: document MemoryDeviceClass"
-- some rewording
- replaced "memory-device: convert get_region_size() to get_memory_region()" by "memory-device: add and use memory_device_get_region_size()" and "memory-device: factor out get_memory_region() from pc-dimm" and "memory-device: drop get_region_size()"
- squashed "memory-device: add device class function set_addr()" and "pc-dimm: implement memory device class function set_addr()"
- replaced "memory-device: ids of virtio based devices are special" by "memory-device: add optional function get_device_id()"
- fixed up the virtio-pmem prototype
v1 -> v2:
- Include virtio-pmem prototype
- Add "memory-device: fix error message when hinted address is too small"
- Add "memory-device: use memory device terminology in error messages"
- Add "hw/acpi-build: only indicate nvdimm and pc-dimm"
- Add "memory-device: ids of virtio based devices are special"
- Add "memory-device: ids of virtio based devices are special"
- Minor changes/fixes for other patches
David Hildenbrand (16):
memory-device: fix alignment error message
memory-device: fix error message when hinted address is too small
memory-device: improve "range conflicts" error message
pc-dimm: pass PCDIMMDevice to pc_dimm_.*plug
memory-device: use memory device terminology in error messages
memory-device: introduce separate config option
memory-device: forward errors in get_region_size()/get_plugged_size()
memory-device: document MemoryDeviceClass
memory-device: add and use memory_device_get_region_size()
memory-device: factor out get_memory_region() from pc-dimm
memory-device: drop get_region_size()
memory-device: add device class function set_addr()
memory-device: complete factoring out pre_plug handling
memory-device: complete factoring out plug handling
memory-device: complete factoring out unplug handling
memory-device: trace when pre_plugging/plugging/unplugging
default-configs/i386-softmmu.mak | 3 +- default-configs/ppc64-softmmu.mak | 3 +- hw/Makefile.objs | 2 +- hw/i386/pc.c | 6 +- hw/mem/Makefile.objs | 4 +- hw/mem/memory-device.c | 103 ++++++++++++++++++++++++------ hw/mem/nvdimm.c | 9 ++- hw/mem/pc-dimm.c | 84 ++++++++---------------- hw/mem/trace-events | 5 +- hw/ppc/spapr.c | 29 ++++----- include/hw/mem/memory-device.h | 74 ++++++++++++++++++--- include/hw/mem/pc-dimm.h | 10 +-- qapi/misc.json | 2 +- 13 files changed, 210 insertions(+), 124 deletions(-)
Signature · 1 line
2.17.1
PATCH v5 1/16 memory-device: fix alignment error message
We're missing "x" after the leading 0.
--- hw/mem/memory-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/mem/memory-device.c +1 -1
@@ -120,7 +120,7 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,/* address_space_start indicates the maximum alignment we expect */ if (QEMU_ALIGN_UP (address_space_start, align) != address_space_start) { -error_setg (errp,"the alignment (0%" PRIx64") is not supported" , +error_setg (errp,"the alignment (0x%" PRIx64") is not supported" , align);return 0 ; }
Signature · 1 line
2.17.1
PATCH v5 2/16 memory-device: fix error message when hinted address is too small
In reply to David HildenbrandThe "at" should actually be a "before".
if (new_addr < address_space_start)
-> "can't add memory ... before... $address_space_start"
So it looks similar to the other check
} else if ((new_addr + size) > address_space_end)
-> "can't add memory ... beyond..."--- hw/mem/memory-device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
hw/mem/memory-device.c +2 -1
@@ -146,7 +146,8 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *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); +"] before 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
Signature · 1 line
2.17.1
PATCH v5 3/16 memory-device: improve "range conflicts" error message
In reply to David HildenbrandHandle id==NULL better and indicate that we are dealing with memory devices.
--- hw/mem/memory-device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
hw/mem/memory-device.c +2 -1
@@ -175,7 +175,8 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,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); +error_setg (errp,"address range conflicts with memory device" +" id='%s'" , d->id ? d->id :"(unnamed)" ); goto out; } new_addr =QEMU_ALIGN_UP (md_addr + md_size, align);
Signature · 1 line
2.17.1
Re: [Qemu-devel] [PATCH v5 03/16] memory-device: improve "range conflicts" error message
Quoted 4 lines · David Hildenbrand
Handle id==NULL better and indicate that we are dealing with memory devices.
Signed-off-by David Hildenbrand <[email protected]>
Quoted 18 lines
--- hw/mem/memory-device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)hw/mem/memory-device.c +2
-1@@ -175,7 +175,8 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,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); +error_setg (errp,"address range conflicts with memory device" +" id='%s'" , d->id ? d->id :"(unnamed)" ); goto out; } new_addr =QEMU_ALIGN_UP (md_addr + md_size, align);
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
Re: [Qemu-devel] [PATCH v5 03/16] memory-device: improve "range conflicts" error message
In reply to David HildenbrandQuoted 4 lines · David Hildenbrand
Handle id==NULL better and indicate that we are dealing with memory devices.
Signed-off-by David Hildenbrand <[email protected]>
Quoted 19 lines
--- hw/mem/memory-device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)hw/mem/memory-device.c +2
-1@@ -175,7 +175,8 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,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); +error_setg (errp,"address range conflicts with memory device" +" id='%s'" , d->id ? d->id :"(unnamed)" ); goto out; } new_addr =QEMU_ALIGN_UP (md_addr + md_size, align);
PATCH v5 4/16 pc-dimm: pass PCDIMMDevice to pc_dimm_.*plug
In reply to David HildenbrandWe're plugging/unplugging a PCDIMMDevice, so directly pass this type instead of a more generic DeviceState.
--- hw/i386/pc.c | 6 +++--- hw/mem/pc-dimm.c | 24 +++++++++++------------- hw/ppc/spapr.c | 8 ++++---- include/hw/mem/pc-dimm.h | 6 +++--- 4 files changed, 21 insertions(+), 23 deletions(-)
hw/i386/pc.c +3 -3
@@ -1699,7 +1699,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,return ; } -pc_dimm_pre_plug (dev,MACHINE (hotplug_dev), +pc_dimm_pre_plug (PC_DIMM (dev),MACHINE (hotplug_dev), pcmc->enforce_aligned_dimm ?NULL : &legacy_align, errp); }
@@ -1711,7 +1711,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,PCMachineState *pcms =PC_MACHINE (hotplug_dev);bool is_nvdimm =object_dynamic_cast (OBJECT (dev),TYPE_NVDIMM ); -pc_dimm_plug (dev,MACHINE (pcms), &local_err); +pc_dimm_plug (PC_DIMM (dev),MACHINE (pcms), &local_err);if (local_err) { goto out; }
@@ -1771,7 +1771,7 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev, goto out; } -pc_dimm_unplug (dev,MACHINE (pcms)); +pc_dimm_unplug (PC_DIMM (dev),MACHINE (pcms));object_unparent (OBJECT (dev)); out:
hw/mem/pc-dimm.c +11 -13
@@ -29,24 +29,24 @@static int pc_dimm_get_free_slot (const int *hint,int max_slots,Error **errp); -void pc_dimm_pre_plug (DeviceState *dev,MachineState *machine, +void pc_dimm_pre_plug (PCDIMMDevice *dimm,MachineState *machine,const uint64_t *legacy_align,Error **errp) { -PCDIMMDevice *dimm =PC_DIMM (dev);PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm);Error *local_err =NULL ;MemoryRegion *mr;uint64_t addr, align;int slot; - slot =object_property_get_int (OBJECT (dev),PC_DIMM_SLOT_PROP , + slot =object_property_get_int (OBJECT (dimm),PC_DIMM_SLOT_PROP , &error_abort); slot =pc_dimm_get_free_slot (slot ==PC_DIMM_UNASSIGNED_SLOT ?NULL : &slot, machine->ram_slots, &local_err);if (local_err) { goto out; } -object_property_set_int (OBJECT (dev), slot,PC_DIMM_SLOT_PROP , &error_abort); +object_property_set_int (OBJECT (dimm), slot,PC_DIMM_SLOT_PROP , + &error_abort);trace_mhp_pc_dimm_assigned_slot (slot); mr = ddc->get_memory_region (dimm, &local_err);
@@ -55,7 +55,7 @@ void pc_dimm_pre_plug(DeviceState *dev, MachineState *machine, } align = legacy_align ? *legacy_align :memory_region_get_alignment (mr); - addr =object_property_get_uint (OBJECT (dev),PC_DIMM_ADDR_PROP , + addr =object_property_get_uint (OBJECT (dimm),PC_DIMM_ADDR_PROP , &error_abort); addr =memory_device_get_free_addr (machine, !addr ?NULL : &addr, align,memory_region_size (mr), &local_err);
@@ -63,38 +63,36 @@ void pc_dimm_pre_plug(DeviceState *dev, MachineState *machine, goto out; }trace_mhp_pc_dimm_assigned_address (addr); -object_property_set_uint (OBJECT (dev), addr,PC_DIMM_ADDR_PROP , +object_property_set_uint (OBJECT (dimm), addr,PC_DIMM_ADDR_PROP , &error_abort); out:error_propagate (errp, local_err); } -void pc_dimm_plug (DeviceState *dev,MachineState *machine,Error **errp) +void pc_dimm_plug (PCDIMMDevice *dimm,MachineState *machine,Error **errp) { -PCDIMMDevice *dimm =PC_DIMM (dev);PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort);MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort);uint64_t addr; - addr =object_property_get_uint (OBJECT (dev),PC_DIMM_ADDR_PROP , + addr =object_property_get_uint (OBJECT (dimm),PC_DIMM_ADDR_PROP , &error_abort);memory_device_plug_region (machine, mr, addr); -vmstate_register_ram (vmstate_mr, dev); +vmstate_register_ram (vmstate_mr,DEVICE (dimm)); } -void pc_dimm_unplug (DeviceState *dev,MachineState *machine) +void pc_dimm_unplug (PCDIMMDevice *dimm,MachineState *machine) { -PCDIMMDevice *dimm =PC_DIMM (dev);PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort);MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort);memory_device_unplug_region (machine, mr); -vmstate_unregister_ram (vmstate_mr, dev); +vmstate_unregister_ram (vmstate_mr,DEVICE (dimm)); }static int pc_dimm_slot2bitmap (Object *obj,void *opaque)
hw/ppc/spapr.c +4 -4
@@ -3135,7 +3135,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, size =memory_region_size (mr); -pc_dimm_plug (dev,MACHINE (ms), &local_err); +pc_dimm_plug (dimm,MACHINE (ms), &local_err);if (local_err) { goto out; }
@@ -3158,7 +3158,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,return ; out_unplug: -pc_dimm_unplug (dev,MACHINE (ms)); +pc_dimm_unplug (dimm,MACHINE (ms)); out:error_propagate (errp, local_err); }
@@ -3202,7 +3202,7 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,return ; } -pc_dimm_pre_plug (dev,MACHINE (hotplug_dev),NULL , errp); +pc_dimm_pre_plug (dimm,MACHINE (hotplug_dev),NULL , errp); }struct sPAPRDIMMState {
@@ -3314,7 +3314,7 @@ static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)sPAPRMachineState *spapr =SPAPR_MACHINE (hotplug_dev);sPAPRDIMMState *ds =spapr_pending_dimm_unplugs_find (spapr,PC_DIMM (dev)); -pc_dimm_unplug (dev,MACHINE (hotplug_dev)); +pc_dimm_unplug (PC_DIMM (dev),MACHINE (hotplug_dev));object_unparent (OBJECT (dev));spapr_pending_dimm_unplugs_remove (spapr, ds); }
include/hw/mem/pc-dimm.h +3 -3
@@ -79,8 +79,8 @@ typedef struct PCDIMMDeviceClass { Error **errp); } PCDIMMDeviceClass; -void pc_dimm_pre_plug (DeviceState *dev,MachineState *machine, +void pc_dimm_pre_plug (PCDIMMDevice *dimm,MachineState *machine,const uint64_t *legacy_align,Error **errp); -void pc_dimm_plug (DeviceState *dev,MachineState *machine,Error **errp); -void pc_dimm_unplug (DeviceState *dev,MachineState *machine); +void pc_dimm_plug (PCDIMMDevice *dimm,MachineState *machine,Error **errp); +void pc_dimm_unplug (PCDIMMDevice *dimm,MachineState *machine);#endif
Signature · 1 line
2.17.1
PATCH v5 5/16 memory-device: use memory device terminology in error messages
In reply to David HildenbrandWhile we rephrased most error messages, we missed these.
--- hw/mem/memory-device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
hw/mem/memory-device.c +3 -3
@@ -87,7 +87,7 @@ static void memory_device_check_addable(MachineState *ms, uint64_t size,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 , +" in use of total space for memory devices 0x" RAM_ADDR_FMT , used_region_size, ms->maxram_size - ms->ram_size);return ; }
@@ -145,12 +145,12 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,if (hint) { new_addr = *hint;if (new_addr < address_space_start) { -error_setg (errp,"can't add memory [0x%" PRIx64":0x%" PRIx64 +error_setg (errp,"can't add memory device [0x%" PRIx64":0x%" PRIx64"] before 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 +error_setg (errp,"can't add memory device [0x%" PRIx64":0x%" PRIx64"] beyond 0x%" PRIx64, new_addr, size, address_space_end);return 0 ;
Signature · 1 line
2.17.1
PATCH v5 6/16 memory-device: introduce separate config option
In reply to David HildenbrandSome architectures might support memory devices, while they don't support DIMM/NVDIMM. So let's
- Rename CONFIG_MEM_HOTPLUG to CONFIG_MEM_DEVICE
- Introduce CONFIG_DIMM and use it similarly to CONFIG NVDIMM
CONFIG_DIMM and CONFIG_NVDIMM require CONFIG_MEM_DEVICE.
--- default-configs/i386-softmmu.mak | 3 ++- default-configs/ppc64-softmmu.mak | 3 ++- hw/Makefile.objs | 2 +- hw/mem/Makefile.objs | 4 ++-- qapi/misc.json | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-)
default-configs/i386-softmmu.mak +2 -1
@@ -50,7 +50,8 @@ CONFIG_PCI_Q35=y CONFIG_APIC=y CONFIG_IOAPIC=y CONFIG_PVPANIC=y -CONFIG_MEM_HOTPLUG=y +CONFIG_MEM_DEVICE=y +CONFIG_DIMM=y CONFIG_NVDIMM=y CONFIG_ACPI_NVDIMM=y CONFIG_PCIE_PORT=y
default-configs/ppc64-softmmu.mak +2 -1
@@ -16,4 +16,5 @@ CONFIG_VIRTIO_VGA=y CONFIG_XICS=$(CONFIG_PSERIES) CONFIG_XICS_SPAPR=$(CONFIG_PSERIES) CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM)) -CONFIG_MEM_HOTPLUG=y +CONFIG_MEM_DEVICE=y +CONFIG_DIMM=y
hw/Makefile.objs +1 -1
@@ -33,7 +33,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += vfio/ devices-dirs-$(CONFIG_SOFTMMU) += virtio/ devices-dirs-$(CONFIG_SOFTMMU) += watchdog/ devices-dirs-$(CONFIG_SOFTMMU) += xen/ -devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/ +devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ devices-dirs-$(CONFIG_SOFTMMU) += smbios/ devices-dirs-y += core/ common-obj-y += $(devices-dirs-y)
hw/mem/Makefile.objs +2 -2
@@ -1,3 +1,3 @@ -common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o -common-obj-$(CONFIG_MEM_HOTPLUG) += memory-device.o +common-obj-$(CONFIG_DIMM) += pc-dimm.o +common-obj-$(CONFIG_MEM_DEVICE) += memory-device.o common-obj-$(CONFIG_NVDIMM) += nvdimm.o
qapi/misc.json +1 -1
@@ -2066,7 +2066,7 @@ # # @plugged-memory: size of memory that can be hot-unplugged. This field # is omitted if target doesn't support memory hotplug -# (i.e. CONFIG_MEM_HOTPLUG not defined on build time). +# (i.e. CONFIG_MEM_DEVICE not defined at build time). # # Since: 2.11.0 ##
Signature · 1 line
2.17.1
PATCH v5 7/16 memory-device: forward errors in get_region_size()/get_plugged_size()
In reply to David HildenbrandLet's properly forward the errors, so errors from get_region_size() / get_plugged_size() can be handled.
Users right now call both functions after the device has been realized, which is will never fail, so it is fine to continue using error_abort.
While at it, remove a leftover error check (suggested by Igor).
--- hw/mem/memory-device.c | 9 +++------ hw/mem/pc-dimm.c | 5 +++-- include/hw/mem/memory-device.h | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-)
hw/mem/memory-device.c +3 -6
@@ -60,7 +60,7 @@ static int memory_device_used_region_size(Object *obj, void *opaque)const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (obj);if (dev->realized) { - *size += mdc->get_region_size (md); + *size += mdc->get_region_size (md, &error_abort); } }
@@ -167,10 +167,7 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,uint64_t md_size, md_addr; md_addr = mdc->get_addr (md); - md_size = mdc->get_region_size (md); -if (*errp) { - goto out; - } + md_size = mdc->get_region_size (md, &error_abort);if (ranges_overlap (md_addr, md_size, new_addr, size)) {if (hint) {
@@ -234,7 +231,7 @@ static int memory_device_plugged_size(Object *obj, void *opaque)const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (obj);if (dev->realized) { - *size += mdc->get_plugged_size (md); + *size += mdc->get_plugged_size (md, &error_abort); } }
hw/mem/pc-dimm.c +3 -2
@@ -234,14 +234,15 @@ static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)return dimm->addr; } -static uint64_t pc_dimm_md_get_region_size (const MemoryDeviceState *md) +static uint64_t pc_dimm_md_get_region_size (const MemoryDeviceState *md, +Error **errp) {/* dropping const here is fine as we don't touch the memory region */ PCDIMMDevice *dimm =PC_DIMM (md);const PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (md);MemoryRegion *mr; - mr = ddc->get_memory_region (dimm, &error_abort); + mr = ddc->get_memory_region (dimm, errp);if (!mr) {return 0 ; }
include/hw/mem/memory-device.h +2 -2
@@ -33,8 +33,8 @@ typedef struct MemoryDeviceClass {InterfaceClass parent_class;uint64_t (*get_addr)(const MemoryDeviceState *md); -uint64_t (*get_plugged_size)(const MemoryDeviceState *md); -uint64_t (*get_region_size)(const MemoryDeviceState *md); +uint64_t (*get_plugged_size)(const MemoryDeviceState *md,Error **errp); +uint64_t (*get_region_size)(const MemoryDeviceState *md,Error **errp);void (*fill_device_info)(const MemoryDeviceState *md,MemoryDeviceInfo *info); } MemoryDeviceClass;
Signature · 1 line
2.17.1
PATCH v5 8/16 memory-device: document MemoryDeviceClass
In reply to David HildenbrandDocument the functions. Don't document get_region_size(), as we will be dropping/replacing that one soon.
Use same documentation style as in include/exec/memory.h, but don't document the parameters, as they are self-explanatory.
--- include/hw/mem/memory-device.h | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
include/hw/mem/memory-device.h +36 -0
@@ -29,12 +29,48 @@ typedef struct MemoryDeviceState {Object parent_obj; } MemoryDeviceState; +/** +* MemoryDeviceClass: +* +* All memory devices need to implement TYPE_MEMORY_DEVICE as an interface. +* +* A memory device is a device that owns a memory region which is +* mapped into guest physical address space at a certain address. The +* address in guest physical memory can either be specified explicitly +* or get assigned automatically. +*/ typedef struct MemoryDeviceClass { +/* private */ InterfaceClass parent_class; +/* +* Return the address of the memory device in guest physical memory. +* +* Called when (un)plugging a memory device or when iterating over +* all memory devices mapped into guest physical address space. +* +* If "0" is returned, no address has been specified by the user and +* no address has been assigned to this memory device yet. +*/ uint64_t (*get_addr)(const MemoryDeviceState *md); + +/* +* Return the amount of memory provided by the memory device currently +* usable ("plugged") by the VM. +* +* Called when calculating the total amount of ram available to the +* VM (e.g. to report memory stats to the user). +* +* This is helpful for devices that dynamically manage the amount of +* memory accessible by the guest via the reserved memory region. For +* most devices, this corresponds to the size of the memory region. +*/ uint64_t (*get_plugged_size)(const MemoryDeviceState *md,Error **errp);uint64_t (*get_region_size)(const MemoryDeviceState *md,Error **errp); + +/* +* Translate the memory device into #MemoryDeviceInfo. +*/ void (*fill_device_info)(const MemoryDeviceState *md,MemoryDeviceInfo *info); }MemoryDeviceClass ;
Signature · 1 line
2.17.1
PATCH v5 9/16 memory-device: add and use memory_device_get_region_size()
In reply to David HildenbrandWe will factor out get_memory_region() from pc-dimm to memory device code soon. Once that is done, get_region_size() can be implemented generically and essentially be replaced by memory_device_get_region_size (and work only on get_memory_region()).
We have some users of get_memory_region() (spapr and pc-dimm code) that are only interested in the size. So let's rework them to use memory_device_get_region_size() first, then we can factor out get_memory_region() and eventually remove get_region_size() without touching the same code multiple times.
--- hw/mem/memory-device.c | 13 ++++++++++--- hw/mem/pc-dimm.c | 10 ++++------ hw/ppc/spapr.c | 21 +++++++-------------- include/hw/mem/memory-device.h | 2 ++ 4 files changed, 23 insertions(+), 23 deletions(-)
hw/mem/memory-device.c +10 -3
@@ -57,10 +57,9 @@ static int memory_device_used_region_size(Object *obj, void *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, &error_abort); + *size +=memory_device_get_region_size (md, &error_abort); } }
@@ -167,7 +166,7 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,uint64_t md_size, md_addr; md_addr = mdc->get_addr (md); - md_size = mdc->get_region_size (md, &error_abort); + md_size =memory_device_get_region_size (md, &error_abort);if (ranges_overlap (md_addr, md_size, new_addr, size)) {if (hint) {
@@ -266,6 +265,14 @@ void memory_device_unplug_region(MachineState *ms, MemoryRegion *mr)memory_region_del_subregion (&ms->device_memory->mr, mr); } +uint64_t memory_device_get_region_size (const MemoryDeviceState *md, +Error **errp) +{ +MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); + +return mdc->get_region_size (md, errp); +} +static const TypeInfo memory_device_info = { .name =TYPE_MEMORY_DEVICE , .parent =TYPE_INTERFACE ,
hw/mem/pc-dimm.c +4 -6
@@ -161,16 +161,14 @@ static Property pc_dimm_properties[] = {static void pc_dimm_get_size (Object *obj,Visitor *v,const char *name,void *opaque,Error **errp) { +Error *local_err =NULL ;uint64_t value; -MemoryRegion *mr; -PCDIMMDevice *dimm =PC_DIMM (obj); -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (obj); - mr = ddc->get_memory_region (dimm, errp); -if (!mr) { + value =memory_device_get_region_size (MEMORY_DEVICE (obj), &local_err); +if (local_err) { +error_propagate (errp, local_err);return ; } - value =memory_region_size (mr);visit_type_uint64 (v, name, &value, errp); }
hw/ppc/spapr.c +7 -14
@@ -3128,12 +3128,10 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,Error *local_err =NULL ;sPAPRMachineState *ms =SPAPR_MACHINE (hotplug_dev);PCDIMMDevice *dimm =PC_DIMM (dev); -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); -MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort);uint64_t size, addr;uint32_t node; - size =memory_region_size (mr); + size =memory_device_get_region_size (MEMORY_DEVICE (dev), &error_abort);pc_dimm_plug (dimm,MACHINE (ms), &local_err);if (local_err) {
@@ -3169,9 +3167,7 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,const sPAPRMachineClass *smc =SPAPR_MACHINE_GET_CLASS (hotplug_dev);sPAPRMachineState *spapr =SPAPR_MACHINE (hotplug_dev);PCDIMMDevice *dimm =PC_DIMM (dev); -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm);Error *local_err =NULL ; -MemoryRegion *mr;uint64_t size;Object *memdev;hwaddr pagesize;
@@ -3181,11 +3177,11 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,return ; } - mr = ddc->get_memory_region (dimm, errp); -if (!mr) { + size =memory_device_get_region_size (MEMORY_DEVICE (dimm), &local_err); +if (local_err) { +error_propagate (errp, local_err);return ; } - size =memory_region_size (mr);if (size %SPAPR_MEMORY_BLOCK_SIZE ) { error_setg(errp, "Hotplugged memory size must be a multiple of "
@@ -3257,9 +3253,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, PCDIMMDevice *dimm) {sPAPRDRConnector *drc; -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); -MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort); -uint64_t size =memory_region_size (mr); +uint64_t size =memory_device_get_region_size (MEMORY_DEVICE (dimm), + &error_abort);uint32_t nr_lmbs = size /SPAPR_MEMORY_BLOCK_SIZE ;uint32_t avail_lmbs =0 ;uint64_t addr_start, addr;
@@ -3325,14 +3320,12 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,sPAPRMachineState *spapr =SPAPR_MACHINE (hotplug_dev);Error *local_err =NULL ;PCDIMMDevice *dimm =PC_DIMM (dev); -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); -MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort);uint32_t nr_lmbs;uint64_t size, addr_start, addr;int i;sPAPRDRConnector *drc; - size =memory_region_size (mr); + size =memory_device_get_region_size (MEMORY_DEVICE (dimm), &error_abort); nr_lmbs = size /SPAPR_MEMORY_BLOCK_SIZE ; addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
include/hw/mem/memory-device.h +2 -0
@@ -83,5 +83,7 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,void memory_device_plug_region (MachineState *ms,MemoryRegion *mr,uint64_t addr);void memory_device_unplug_region (MachineState *ms,MemoryRegion *mr); +uint64_t memory_device_get_region_size (const MemoryDeviceState *md, +Error **errp);#endif
Signature · 1 line
2.17.1
PATCH v5 10/16 memory-device: factor out get_memory_region() from pc-dimm
In reply to David HildenbrandThe memory region is necessary for plugging/unplugging a memory device. The region size (via get_region_size()) is no longer sufficient, as besides the alignment, also the region itself is required in order to add it to the device memory region of the machine via
- memory_region_add_subregion
- memory_region_del_subregion
So, to factor out plugging/unplugging of memory devices from pc-dimm code, we have to factor out access to the memory region first.
--- hw/mem/nvdimm.c | 9 ++++++--- hw/mem/pc-dimm.c | 27 ++++++++++++++++++--------- include/hw/mem/memory-device.h | 15 +++++++++++++++ include/hw/mem/pc-dimm.h | 4 ---- 4 files changed, 39 insertions(+), 16 deletions(-)
hw/mem/nvdimm.c +6 -3
@@ -27,6 +27,7 @@#include "qapi/error.h" #include "qapi/visitor.h" #include "hw/mem/nvdimm.h" +#include "hw/mem/memory-device.h" static void nvdimm_get_label_size (Object *obj,Visitor *v,const char *name,void *opaque,Error **errp)
@@ -118,9 +119,10 @@ static void nvdimm_prepare_memory_region(NVDIMMDevice *nvdimm, Error **errp) nvdimm->nvdimm_mr->align = align; } -static MemoryRegion *nvdimm_get_memory_region (PCDIMMDevice *dimm,Error **errp) +static MemoryRegion *nvdimm_md_get_memory_region (MemoryDeviceState *md, +Error **errp) { -NVDIMMDevice *nvdimm =NVDIMM (dimm); +NVDIMMDevice *nvdimm =NVDIMM (md);Error *local_err =NULL ;if (!nvdimm->nvdimm_mr) {
@@ -190,11 +192,12 @@ static Property nvdimm_properties[] = {static void nvdimm_class_init (ObjectClass *oc,void *data) {PCDIMMDeviceClass *ddc =PC_DIMM_CLASS (oc); +MemoryDeviceClass *mdc =MEMORY_DEVICE_CLASS (oc);NVDIMMClass *nvc =NVDIMM_CLASS (oc);DeviceClass *dc =DEVICE_CLASS (oc); ddc->realize = nvdimm_realize; - ddc->get_memory_region = nvdimm_get_memory_region; + mdc->get_memory_region = nvdimm_md_get_memory_region; dc->props = nvdimm_properties; nvc->read_label_data = nvdimm_read_label_data;
hw/mem/pc-dimm.c +18 -9
@@ -32,7 +32,7 @@ static int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);void pc_dimm_pre_plug (PCDIMMDevice *dimm,MachineState *machine,const uint64_t *legacy_align,Error **errp) { -PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); +MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);Error *local_err =NULL ;MemoryRegion *mr;uint64_t addr, align;
@@ -49,7 +49,7 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, &error_abort);trace_mhp_pc_dimm_assigned_slot (slot); - mr = ddc->get_memory_region (dimm, &local_err); + mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), &local_err);if (local_err) { goto out; }
@@ -72,9 +72,11 @@ out:void pc_dimm_plug (PCDIMMDevice *dimm,MachineState *machine,Error **errp) {PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); +MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort); -MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort); +MemoryRegion *mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), + &error_abort);uint64_t addr; addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
@@ -87,9 +89,11 @@ void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine, Error **errp)void pc_dimm_unplug (PCDIMMDevice *dimm,MachineState *machine) {PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); +MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort); -MemoryRegion *mr = ddc->get_memory_region (dimm, &error_abort); +MemoryRegion *mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), + &error_abort);memory_device_unplug_region (machine, mr);vmstate_unregister_ram (vmstate_mr,DEVICE (dimm));
@@ -235,12 +239,11 @@ static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)static uint64_t pc_dimm_md_get_region_size (const MemoryDeviceState *md,Error **errp) { -/* dropping const here is fine as we don't touch the memory region */ -PCDIMMDevice *dimm =PC_DIMM (md); -const PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (md); +MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md);MemoryRegion *mr; - mr = ddc->get_memory_region (dimm, errp); +/* dropping const here is fine as we don't touch the memory region */ + mr = mdc->get_memory_region ((MemoryDeviceState *)md, errp);if (!mr) {return 0 ; }
@@ -248,6 +251,12 @@ static uint64_t pc_dimm_md_get_region_size(const MemoryDeviceState *md,return memory_region_size (mr); } +static MemoryRegion *pc_dimm_md_get_memory_region (MemoryDeviceState *md, +Error **errp) +{ +return pc_dimm_get_memory_region (PC_DIMM (md), errp); +} +static void pc_dimm_md_fill_device_info (const MemoryDeviceState *md,MemoryDeviceInfo *info) {
@@ -289,13 +298,13 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data) dc->props = pc_dimm_properties; dc->desc ="DIMM memory module" ; - ddc->get_memory_region = pc_dimm_get_memory_region; ddc->get_vmstate_memory_region = pc_dimm_get_memory_region; mdc->get_addr = pc_dimm_md_get_addr;/* for a dimm plugged_size == region_size */ mdc->get_plugged_size = pc_dimm_md_get_region_size; mdc->get_region_size = pc_dimm_md_get_region_size; + mdc->get_memory_region = pc_dimm_md_get_memory_region; mdc->fill_device_info = pc_dimm_md_fill_device_info; }
include/hw/mem/memory-device.h +15 -0
@@ -38,6 +38,11 @@ typedef struct MemoryDeviceState {* mapped into guest physical address space at a certain address. The * address in guest physical memory can either be specified explicitly * or get assigned automatically. +* +* Conceptually, memory devices only span one memory region. If multiple +* successive memory regions are used, a covering memory region has to +* be provided. Scattered memory regions are not supported for single +* devices. */ typedef struct MemoryDeviceClass { /* private */
@@ -68,6 +73,16 @@ typedef struct MemoryDeviceClass {uint64_t (*get_plugged_size)(const MemoryDeviceState *md,Error **errp);uint64_t (*get_region_size)(const MemoryDeviceState *md,Error **errp); +/* +* Return the memory region of the memory device. +* +* Called when (un)plugging the memory device, to (un)map the +* memory region in guest physical memory, but also to detect the +* required alignment during address assignment or when the size of the +* memory region is required. +*/ + MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp); +/* * Translate the memory device into #MemoryDeviceInfo. */
include/hw/mem/pc-dimm.h +0 -4
@@ -61,9 +61,6 @@ typedef struct PCDIMMDevice {* PCDIMMDeviceClass: * @realize: called after common dimm is realized so that the dimm based * devices get the chance to do specified operations. -* @get_memory_region: returns #MemoryRegion associated with @dimm which -* is directly mapped into the physical address space of guest. Will not -* fail after the device was realized. * @get_vmstate_memory_region: returns #MemoryRegion which indicates the * memory of @dimm should be kept during live migration. Will not fail * after the device was realized.
@@ -74,7 +71,6 @@ typedef struct PCDIMMDeviceClass {/* public */ void (*realize)(PCDIMMDevice *dimm,Error **errp); - MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm, Error **errp); MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm, Error **errp); } PCDIMMDeviceClass;
Signature · 1 line
2.17.1
PATCH v5 11/16 memory-device: drop get_region_size()
In reply to David HildenbrandThere are no remaining users of get_region_size() except memory_device_get_region_size() itself. We can make memory_device_get_region_size() work directly on get_memory_region() instead and drop get_region_size().
In addition, we can now use memory_device_get_region_size() in pc-dimm code to implement get_plugged_size()"
--- hw/mem/memory-device.c | 11 +++++++++-- hw/mem/pc-dimm.c | 18 +----------------- include/hw/mem/memory-device.h | 1 - 3 files changed, 10 insertions(+), 20 deletions(-)
hw/mem/memory-device.c +9 -2
@@ -268,9 +268,16 @@ void memory_device_unplug_region(MachineState *ms, MemoryRegion *mr)uint64_t memory_device_get_region_size (const MemoryDeviceState *md,Error **errp) { -MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); +const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); +MemoryRegion *mr; -return mdc->get_region_size (md, errp); +/* dropping const here is fine as we don't touch the memory region */ + mr = mdc->get_memory_region ((MemoryDeviceState *)md, errp); +if (!mr) { +return 0 ; + } + +return memory_region_size (mr); }static const TypeInfo memory_device_info = {
hw/mem/pc-dimm.c +1 -17
@@ -236,21 +236,6 @@ static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)return dimm->addr; } -static uint64_t pc_dimm_md_get_region_size (const MemoryDeviceState *md, -Error **errp) -{ -MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); -MemoryRegion *mr; - -/* dropping const here is fine as we don't touch the memory region */ - mr = mdc->get_memory_region ((MemoryDeviceState *)md, errp); -if (!mr) { -return 0 ; - } - -return memory_region_size (mr); -} -static MemoryRegion *pc_dimm_md_get_memory_region (MemoryDeviceState *md,Error **errp) {
@@ -302,8 +287,7 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data) mdc->get_addr = pc_dimm_md_get_addr;/* for a dimm plugged_size == region_size */ - mdc->get_plugged_size = pc_dimm_md_get_region_size; - mdc->get_region_size = pc_dimm_md_get_region_size; + mdc->get_plugged_size = memory_device_get_region_size; mdc->get_memory_region = pc_dimm_md_get_memory_region; mdc->fill_device_info = pc_dimm_md_fill_device_info; }
include/hw/mem/memory-device.h +0 -1
@@ -71,7 +71,6 @@ typedef struct MemoryDeviceClass {* most devices, this corresponds to the size of the memory region. */ uint64_t (*get_plugged_size)(const MemoryDeviceState *md,Error **errp); -uint64_t (*get_region_size)(const MemoryDeviceState *md,Error **errp);/* * Return the memory region of the memory device.
Signature · 1 line
2.17.1
PATCH v5 12/16 memory-device: add device class function set_addr()
In reply to David HildenbrandTo be able to factor out address assignment of memory devices, we will have to read (get_addr()) and write (set_addr()) the address.
We can't use properties for this purpose, as properties are device specific. E.g. while the address property for a DIMM is called "addr", it might be called differently (e.g. "memaddr") for other devices.
Especially virtio based memory devices cannot use "addr" as that is already reserved and used for the address on the bus (for the proxy device).
Also, it might be possible to have memory devices without address properties (e.g. internal DIMM-like thingies).
In contrast to get_addr(), we expect that set_addr() can fail.
Keep it simple for now for pc-dimm and simply set the static property, that will fail once realized.
--- hw/mem/pc-dimm.c | 7 +++++++ include/hw/mem/memory-device.h | 8 ++++++++ 2 files changed, 15 insertions(+)
hw/mem/pc-dimm.c +7 -0
@@ -236,6 +236,12 @@ static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)return dimm->addr; } +static void pc_dimm_md_set_addr (MemoryDeviceState *md,uint64_t addr, +Error **errp) +{ +object_property_set_uint (OBJECT (md), addr,PC_DIMM_ADDR_PROP , errp); +} +static MemoryRegion *pc_dimm_md_get_memory_region (MemoryDeviceState *md,Error **errp) {
@@ -286,6 +292,7 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data) ddc->get_vmstate_memory_region = pc_dimm_get_memory_region; mdc->get_addr = pc_dimm_md_get_addr; + mdc->set_addr = pc_dimm_md_set_addr;/* for a dimm plugged_size == region_size */ mdc->get_plugged_size = memory_device_get_region_size; mdc->get_memory_region = pc_dimm_md_get_memory_region;
include/hw/mem/memory-device.h +8 -0
@@ -59,6 +59,14 @@ typedef struct MemoryDeviceClass {*/ uint64_t (*get_addr)(const MemoryDeviceState *md); +/* +* Set the address of the memory device in guest physical memory. +* +* Called when plugging the memory device to configure the determined +* address in guest physical memory. +*/ +void (*set_addr)(MemoryDeviceState *md,uint64_t addr,Error **errp); +/* * Return the amount of memory provided by the memory device currently * usable ("plugged") by the VM.
Signature · 1 line
2.17.1
PATCH v5 13/16 memory-device: complete factoring out pre_plug handling
In reply to David HildenbrandWith all required memory device class functions in place, we can factor out pre_plug handling of memory devices. Take proper care of errors. We still have to carry along legacy_align required for pc compatibility handling.
We will factor out tracing of the address separately in a follow-up patch.
--- hw/mem/memory-device.c | 32 +++++++++++++++++++++++++++++--- hw/mem/pc-dimm.c | 15 +++------------ include/hw/mem/memory-device.h | 5 ++--- 3 files changed, 34 insertions(+), 18 deletions(-)
hw/mem/memory-device.c +29 -3
@@ -93,9 +93,10 @@ static void memory_device_check_addable(MachineState *ms, uint64_t size, } -uint64_t memory_device_get_free_addr (MachineState *ms,const uint64_t *hint, -uint64_t align,uint64_t size, -Error **errp) +static 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;
@@ -247,6 +248,31 @@ uint64_t get_plugged_memory_size(void)return size; } +void memory_device_pre_plug (MemoryDeviceState *md,MachineState *ms, +const uint64_t *legacy_align,Error **errp) +{ +const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); +Error *local_err =NULL ; +uint64_t addr, align; +MemoryRegion *mr; + + mr = mdc->get_memory_region (md, &local_err); +if (local_err) { + goto out; + } + + align = legacy_align ? *legacy_align :memory_region_get_alignment (mr); + addr = mdc->get_addr (md); + addr =memory_device_get_free_addr (ms, !addr ?NULL : &addr, align, +memory_region_size (mr), &local_err); +if (local_err) { + goto out; + } + mdc->set_addr (md, addr, &local_err); +out: +error_propagate (errp, local_err); +} +void memory_device_plug_region (MachineState *ms,MemoryRegion *mr,uint64_t addr) {
hw/mem/pc-dimm.c +3 -12
@@ -32,10 +32,8 @@ static int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);void pc_dimm_pre_plug (PCDIMMDevice *dimm,MachineState *machine,const uint64_t *legacy_align,Error **errp) { -MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);Error *local_err =NULL ; -MemoryRegion *mr; -uint64_t addr, align; +uint64_t addr;int slot; slot = object_property_get_int(OBJECT(dimm), PC_DIMM_SLOT_PROP,
@@ -49,22 +47,15 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, &error_abort);trace_mhp_pc_dimm_assigned_slot (slot); - mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), &local_err); +memory_device_pre_plug (MEMORY_DEVICE (dimm), machine, legacy_align, + &local_err);if (local_err) { goto out; } - align = legacy_align ? *legacy_align :memory_region_get_alignment (mr); addr =object_property_get_uint (OBJECT (dimm),PC_DIMM_ADDR_PROP , &error_abort); - addr =memory_device_get_free_addr (machine, !addr ?NULL : &addr, align, -memory_region_size (mr), &local_err); -if (local_err) { - goto out; - }trace_mhp_pc_dimm_assigned_address (addr); -object_property_set_uint (OBJECT (dimm), addr,PC_DIMM_ADDR_PROP , - &error_abort); out:error_propagate (errp, local_err); }
include/hw/mem/memory-device.h +2 -3
@@ -99,9 +99,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); +void memory_device_pre_plug (MemoryDeviceState *md,MachineState *ms, +const uint64_t *legacy_align,Error **errp);void memory_device_plug_region (MachineState *ms,MemoryRegion *mr,uint64_t addr);void memory_device_unplug_region (MachineState *ms,MemoryRegion *mr);
Signature · 1 line
2.17.1
PATCH v5 14/16 memory-device: complete factoring out plug handling
In reply to David HildenbrandWith the new memory device functions in place, we can factor out plugging of memory devices completely.
--- hw/mem/memory-device.c | 13 ++++++++++--- hw/mem/pc-dimm.c | 9 +-------- include/hw/mem/memory-device.h | 3 +-- 3 files changed, 12 insertions(+), 13 deletions(-)
hw/mem/memory-device.c +10 -3
@@ -273,10 +273,17 @@ out:error_propagate (errp, local_err); } -void memory_device_plug_region (MachineState *ms,MemoryRegion *mr, -uint64_t addr) +void memory_device_plug (MemoryDeviceState *md,MachineState *ms) { -/* we expect a previous call to memory_device_get_free_addr() */ +const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); +const uint64_t addr = mdc->get_addr (md); +MemoryRegion *mr; + +/* +* We expect that a previous call to memory_device_pre_plug() succeeded, so +* it can't fail at this point. +*/ + mr = mdc->get_memory_region (md, &error_abort);g_assert (ms->device_memory); memory_region_add_subregion(&ms->device_memory->mr,
hw/mem/pc-dimm.c +1 -8
@@ -63,17 +63,10 @@ out:void pc_dimm_plug (PCDIMMDevice *dimm,MachineState *machine,Error **errp) {PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); -MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort); -MemoryRegion *mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), - &error_abort); -uint64_t addr; - - addr =object_property_get_uint (OBJECT (dimm),PC_DIMM_ADDR_PROP , - &error_abort); -memory_device_plug_region (machine, mr, addr); +memory_device_plug (MEMORY_DEVICE (dimm), machine);vmstate_register_ram (vmstate_mr,DEVICE (dimm)); }
include/hw/mem/memory-device.h +1 -2
@@ -101,8 +101,7 @@ MemoryDeviceInfoList *qmp_memory_device_list(void);uint64_t get_plugged_memory_size (void );void memory_device_pre_plug (MemoryDeviceState *md,MachineState *ms,const uint64_t *legacy_align,Error **errp); -void memory_device_plug_region (MachineState *ms,MemoryRegion *mr, -uint64_t addr); +void memory_device_plug (MemoryDeviceState *md,MachineState *ms);void memory_device_unplug_region (MachineState *ms,MemoryRegion *mr);uint64_t memory_device_get_region_size (const MemoryDeviceState *md,Error **errp);
Signature · 1 line
2.17.1
PATCH v5 15/16 memory-device: complete factoring out unplug handling
In reply to David HildenbrandWith the new memory device functions in place, we can factor out unplugging of memory devices completely.
--- hw/mem/memory-device.c | 11 +++++++++-- hw/mem/pc-dimm.c | 5 +---- include/hw/mem/memory-device.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-)
hw/mem/memory-device.c +9 -2
@@ -290,9 +290,16 @@ void memory_device_plug(MemoryDeviceState *md, MachineState *ms) addr - ms->device_memory->base, mr); } -void memory_device_unplug_region (MachineState *ms,MemoryRegion *mr) +void memory_device_unplug (MemoryDeviceState *md,MachineState *ms) { -/* we expect a previous call to memory_device_get_free_addr() */ +const MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (md); +MemoryRegion *mr; + +/* +* We expect that a previous call to memory_device_pre_plug() succeeded, so +* it can't fail at this point. +*/ + mr = mdc->get_memory_region (md, &error_abort);g_assert (ms->device_memory);memory_region_del_subregion (&ms->device_memory->mr, mr);
hw/mem/pc-dimm.c +1 -4
@@ -73,13 +73,10 @@ void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine, Error **errp)void pc_dimm_unplug (PCDIMMDevice *dimm,MachineState *machine) {PCDIMMDeviceClass *ddc =PC_DIMM_GET_CLASS (dimm); -MemoryDeviceClass *mdc =MEMORY_DEVICE_GET_CLASS (dimm);MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region (dimm, &error_abort); -MemoryRegion *mr = mdc->get_memory_region (MEMORY_DEVICE (dimm), - &error_abort); -memory_device_unplug_region (machine, mr); +memory_device_unplug (MEMORY_DEVICE (dimm), machine);vmstate_unregister_ram (vmstate_mr,DEVICE (dimm)); }
include/hw/mem/memory-device.h +1 -1
@@ -102,7 +102,7 @@ uint64_t get_plugged_memory_size(void);void memory_device_pre_plug (MemoryDeviceState *md,MachineState *ms,const uint64_t *legacy_align,Error **errp);void memory_device_plug (MemoryDeviceState *md,MachineState *ms); -void memory_device_unplug_region (MachineState *ms,MemoryRegion *mr); +void memory_device_unplug (MemoryDeviceState *md,MachineState *ms);uint64_t memory_device_get_region_size (const MemoryDeviceState *md,Error **errp);
Signature · 1 line
2.17.1
PATCH v5 16/16 memory-device: trace when pre_plugging/plugging/unplugging
In reply to David HildenbrandLet's trace the address and the id of a memory device when pre_plugging/plugging/unplugging succeeded.
Trace it when pre_plugging as well as when plugging, so we really know when a specific address is actually used.
--- hw/mem/memory-device.c | 8 ++++++++ hw/mem/pc-dimm.c | 8 -------- hw/mem/trace-events | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-)
hw/mem/memory-device.c +8 -0
@@ -17,6 +17,7 @@#include "qemu/range.h" #include "hw/virtio/vhost.h" #include "sysemu/kvm.h" +#include "trace.h" static gint memory_device_addr_sort (gconstpointer a,gconstpointer b) {
@@ -269,6 +270,10 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms, goto out; } mdc->set_addr (md, addr, &local_err); +if (!local_err) { +trace_memory_device_pre_plug (DEVICE (md)->id ?DEVICE (md)->id :"" , + addr); + } out:error_propagate (errp, local_err); }
@@ -288,6 +293,7 @@ void memory_device_plug(MemoryDeviceState *md, MachineState *ms)memory_region_add_subregion (&ms->device_memory->mr, addr - ms->device_memory->base, mr); +trace_memory_device_plug (DEVICE (md)->id ?DEVICE (md)->id :"" , addr); }void memory_device_unplug (MemoryDeviceState *md,MachineState *ms)
@@ -303,6 +309,8 @@ void memory_device_unplug(MemoryDeviceState *md, MachineState *ms)g_assert (ms->device_memory);memory_region_del_subregion (&ms->device_memory->mr, mr); +trace_memory_device_unplug (DEVICE (md)->id ?DEVICE (md)->id :"" , + mdc->get_addr (md)); } uint64_t memory_device_get_region_size(const MemoryDeviceState *md,
hw/mem/pc-dimm.c +0 -8
@@ -33,7 +33,6 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, const uint64_t *legacy_align, Error **errp) { Error *local_err = NULL; -uint64_t addr;int slot; slot = object_property_get_int(OBJECT(dimm), PC_DIMM_SLOT_PROP,
@@ -49,13 +48,6 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine,memory_device_pre_plug (MEMORY_DEVICE (dimm), machine, legacy_align, &local_err); -if (local_err) { - goto out; - } - - addr =object_property_get_uint (OBJECT (dimm),PC_DIMM_ADDR_PROP , - &error_abort); -trace_mhp_pc_dimm_assigned_address (addr); out:error_propagate (errp, local_err); }
hw/mem/trace-events +4 -1
@@ -2,4 +2,7 @@ # hw/mem/pc-dimm.c mhp_pc_dimm_assigned_slot(int slot) "%d" -mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64 +# hw/mem/memory-device.c +memory_device_pre_plug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64 +memory_device_plug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64 +memory_device_unplug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64
Signature · 1 line
2.17.1
Quoted 8 lines · David Hildenbrand
This series completes refactoring of
pre_plug, plug and unplug logic of memory devices. With this as a basis, we can built e.g. virtio based memory devices or internal "RAM chip" devices.I dropped the virtio-pmem prototype for now, I will look into plugging it differently next. But this part in this series here is independent of hotplug handler changes required to make it work for virtio devices.
Quoted 11 lines
v4 -> v5:
- Added a bunch of RB's
- Minor spelling fixed
- Dropped "memory-device: add class functionget_device_id()"
- Added "memory-device: improve "range conflicts" error message
- Dropped "memory-device: handle integer overflows properly" -- Will require more changes. But I am able to reproduce some overflows.
- "memory-device: document MemoryDeviceClass"
-- Changed documentation format as requested by Auger
- "memory-device: trace when pre_plugging/plugging/unplugging" -- Include device ID and rename tracepoints.
@Paolo, @Eduardo this seems to be ready to get picked up. Thanks!
Signature · 3 lines
Thanks, David / dhildenb
Eduardo Habkost
AppliedQuoted 21 lines · David Hildenbrand
Quoted 8 lines · David Hildenbrand
This series completes refactoring of
pre_plug, plug and unplug logic of memory devices. With this as a basis, we can built e.g. virtio based memory devices or internal "RAM chip" devices.I dropped the virtio-pmem prototype for now, I will look into plugging it differently next. But this part in this series here is independent of hotplug handler changes required to make it work for virtio devices.
Quoted 11 lines
v4 -> v5:
- Added a bunch of RB's
- Minor spelling fixed
- Dropped "memory-device: add class functionget_device_id()"
- Added "memory-device: improve "range conflicts" error message
- Dropped "memory-device: handle integer overflows properly" -- Will require more changes. But I am able to reproduce some overflows.
- "memory-device: document MemoryDeviceClass"
-- Changed documentation format as requested by Auger
- "memory-device: trace when pre_plugging/plugging/unplugging" -- Include device ID and rename tracepoints.
Quoted 1 line
@Paolo, @Eduardo this seems to be ready to get picked up. Thanks!
Queued on machine-next, thanks!
Signature · 1 line
Eduardo