diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index 8c2656821a..ad176b700b 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -23,6 +23,45 @@ #include "qapi/visitor.h" #include "qemu/range.h" +int qmp_pc_dimm_device_list(Object *obj, void *opaque) +{ + MemoryDeviceInfoList ***prev = opaque; + + if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { + DeviceState *dev = DEVICE(obj); + + if (dev->realized) { + MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1); + MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1); + PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1); + DeviceClass *dc = DEVICE_GET_CLASS(obj); + PCDIMMDevice *dimm = PC_DIMM(obj); + + if (dev->id) { + di->has_id = true; + di->id = g_strdup(dev->id); + } + di->hotplugged = dev->hotplugged; + di->hotpluggable = dc->hotpluggable; + di->addr = dimm->addr; + di->slot = dimm->slot; + di->node = dimm->node; + di->size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP, + NULL); + di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem)); + + info->dimm = di; + elem->value = info; + elem->next = NULL; + **prev = elem; + *prev = &elem->next; + } + } + + object_child_foreach(obj, qmp_pc_dimm_device_list, opaque); + return 0; +} + static int pc_dimm_slot2bitmap(Object *obj, void *opaque) { unsigned long *bitmap = opaque; diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index 0f4a6ba1e4..761eeef801 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -76,4 +76,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, Error **errp); int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); + +int qmp_pc_dimm_device_list(Object *obj, void *opaque); #endif diff --git a/qapi-schema.json b/qapi-schema.json index 082bc3ab4e..d51a208c05 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3194,3 +3194,54 @@ # Since: 2.1 ## { 'command': 'query-memdev', 'returns': ['Memdev'] } +# @PCDIMMDeviceInfo: +# +# PCDIMMDevice state information +# +# @id: #optional device's ID +# +# @addr: physical address, where device is mapped +# +# @size: size of memory that the device provides +# +# @slot: slot number at which device is plugged in +# +# @node: NUMA node number where device is plugged in +# +# @memdev: memory backend linked with device +# +# @hotplugged: true if device was hotplugged +# +# @hotpluggable: true if device if could be added/removed while machine is running +# +# Since: 2.1 +## +{ 'type': 'PCDIMMDeviceInfo', + 'data': { '*id': 'str', + 'addr': 'int', + 'size': 'int', + 'slot': 'int', + 'node': 'int', + 'memdev': 'str', + 'hotplugged': 'bool', + 'hotpluggable': 'bool' + } +} + +## +# @MemoryDeviceInfo: +# +# Union containing information about a memory device +# +# Since: 2.1 +## +{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} } + +## +# @query-memory-devices +# +# Lists available memory devices and their state +# +# Since: 2.1 +## +{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] } diff --git a/qmp-commands.hx b/qmp-commands.hx index e47c3ea900..81054d0b1b 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3611,4 +3611,31 @@ Example (1): ] } +EQMP + + { + .name = "query-memory-devices", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_memory_devices, + }, + +SQMP +@query-memory-devices +-------------------- + +Return a list of memory devices. + +Example: +-> { "execute": "query-memory-devices" } +<- { "return": [ { "data": + { "addr": 5368709120, + "hotpluggable": true, + "hotplugged": true, + "id": "d1", + "memdev": "/objects/memX", + "node": 0, + "size": 1073741824, + "slot": 0}, + "type": "dimm" + } ] } EQMP diff --git a/qmp.c b/qmp.c index c3c0229cdf..835fd78851 100644 --- a/qmp.c +++ b/qmp.c @@ -28,6 +28,7 @@ #include "qapi/qmp-input-visitor.h" #include "hw/boards.h" #include "qom/object_interfaces.h" +#include "hw/mem/pc-dimm.h" NameInfo *qmp_query_name(Error **errp) { @@ -628,3 +629,13 @@ void qmp_object_del(const char *id, Error **errp) } object_unparent(obj); } + +MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) +{ + MemoryDeviceInfoList *head = NULL; + MemoryDeviceInfoList **prev = &head; + + qmp_pc_dimm_device_list(qdev_get_machine(), &prev); + + return head; +} diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 5a0b9174e0..997d68d5b9 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -37,3 +37,4 @@ stub-obj-y += vmstate.o stub-obj-$(CONFIG_WIN32) += fd-register.o stub-obj-y += cpus.o stub-obj-y += kvm.o +stub-obj-y += qmp_pc_dimm_device_list.o diff --git a/stubs/qmp_pc_dimm_device_list.c b/stubs/qmp_pc_dimm_device_list.c new file mode 100644 index 0000000000..5cb220c66c --- /dev/null +++ b/stubs/qmp_pc_dimm_device_list.c @@ -0,0 +1,7 @@ +#include "qom/object.h" +#include "hw/mem/pc-dimm.h" + +int qmp_pc_dimm_device_list(Object *obj, void *opaque) +{ + return 0; +}