@@ -2144,7 +2144,8 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
- MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err);
+ MemoryDeviceInfoList *info_list =
+ qmp_query_memory_devices(true, MEMORY_DEVICE_TYPE_DIMM, &err);
MemoryDeviceInfoList *info;
MemoryDeviceInfo *value;
PCDIMMDeviceInfo *di;
@@ -178,3 +178,41 @@ static void nvdimm_register_types(void)
}
type_init(nvdimm_register_types)
+
+static int qmp_nvdimm_device_info(Object *obj, NVDIMMDeviceInfo *di)
+{
+ if (!object_dynamic_cast(obj, TYPE_NVDIMM)) {
+ return 1;
+ }
+
+ if (qmp_pc_dimm_device_info(obj, (PCDIMMDeviceInfo *)di)) {
+ return 1;
+ }
+
+ di->label_size = object_property_get_int(obj, "label-size", NULL);
+
+ return 0;
+}
+
+int qmp_nvdimm_device_list(Object *obj, void *opaque)
+{
+ MemoryDeviceInfoList ***prev = opaque;
+ NVDIMMDeviceInfo *di = g_new0(NVDIMMDeviceInfo, 1);
+
+ if (qmp_nvdimm_device_info(obj, di)) {
+ g_free(di);
+ } else {
+ MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1);
+ MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
+
+ info->type = MEMORY_DEVICE_TYPE_NVDIMM;
+ info->u.nvdimm.data = di;
+ elem->value = info;
+ elem->next = NULL;
+ **prev = elem;
+ *prev = &elem->next;
+ }
+
+ object_child_foreach(obj, qmp_nvdimm_device_list, opaque);
+ return 0;
+}
@@ -161,39 +161,52 @@ uint64_t pc_existing_dimms_capacity(Error **errp)
return cap.size;
}
+int qmp_pc_dimm_device_info(Object *obj, PCDIMMDeviceInfo *di)
+{
+ DeviceState *dev;
+ DeviceClass *dc;
+ PCDIMMDevice *dimm;
+
+ if (!object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+ return 1;
+ }
+
+ dev = DEVICE(obj);
+ dc = DEVICE_GET_CLASS(obj);
+ 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));
+
+ return 0;
+}
+
int qmp_pc_dimm_device_list(Object *obj, void *opaque)
{
MemoryDeviceInfoList ***prev = opaque;
+ PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);
- 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->u.dimm.data = di;
- elem->value = info;
- elem->next = NULL;
- **prev = elem;
- *prev = &elem->next;
- }
+ if (qmp_pc_dimm_device_info(obj, di)) {
+ g_free(di);
+ } else {
+ MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1);
+ MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
+
+ info->type = MEMORY_DEVICE_TYPE_DIMM;
+ info->u.dimm.data = di;
+ elem->value = info;
+ elem->next = NULL;
+ **prev = elem;
+ *prev = &elem->next;
}
object_child_foreach(obj, qmp_pc_dimm_device_list, opaque);
@@ -132,4 +132,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
uint32_t ram_slots);
void nvdimm_plug(AcpiNVDIMMState *state);
void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev);
+
+int qmp_nvdimm_device_list(Object *obj, void *opaque);
#endif
@@ -93,6 +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);
+int qmp_pc_dimm_device_info(Object *obj, PCDIMMDeviceInfo *di);
int qmp_pc_dimm_device_list(Object *obj, void *opaque);
uint64_t pc_existing_dimms_capacity(Error **errp);
void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
@@ -5811,24 +5811,62 @@
}
##
+# @NVDIMMDeviceInfo:
+#
+# NVDIMMDevice state information
+#
+# @label-size: size the label storage area
+#
+# Since 2.9
+##
+{ 'struct': 'NVDIMMDeviceInfo',
+ 'base': 'PCDIMMDeviceInfo',
+ 'data': { 'label-size': 'int' }
+}
+
+##
# @MemoryDeviceInfo:
#
# Union containing information about a memory device
#
+# - @dimm: since 2.1
+# - @nvdimm: since 2.9
+#
# Since: 2.1
##
-{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} }
+{ 'union': 'MemoryDeviceInfo',
+ 'data': {'dimm': 'PCDIMMDeviceInfo', 'nvdimm': 'NVDIMMDeviceInfo'}
+}
+
+##
+# @MemoryDeviceType:
+#
+# Type of memory devices.
+#
+# @dimm: pc-dimm memory device
+#
+# @nvdimm: nvdimm memory device
+#
+# Since 2.9
+##
+{ 'enum': 'MemoryDeviceType', 'data': [ 'dimm', 'nvdimm' ] }
##
# @query-memory-devices:
#
-# Lists available memory devices and their state
+# Lists available memory devices and their state. If the optional argument
+# @devtype is present, only memory devices of the specified type are included.
+#
+# @devtype: specify the type of memory devices to be listed. If 'dimm' is
+# specified, all pc-dimm devices (including nvdimm devices which is
+# a subtype of pc-dimm) will be listed. If 'nvdimm' is specified,
+# only nvdimm devices will be listed. (Since 2.9)
#
# Since: 2.1
#
# Example:
#
-# -> { "execute": "query-memory-devices" }
+# -> { "execute": "query-memory-devices", "arguments": { "devtype": "dimm" } }
# <- { "return": [ { "data":
# { "addr": 5368709120,
# "hotpluggable": true,
@@ -5842,7 +5880,9 @@
# } ] }
#
##
-{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] }
+{ 'command': 'query-memory-devices',
+ 'data': { '*devtype': 'MemoryDeviceType' },
+ 'returns': ['MemoryDeviceInfo'] }
##
# @ACPISlotType:
@@ -36,6 +36,7 @@
#include "hw/boards.h"
#include "qom/object_interfaces.h"
#include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
#include "hw/acpi/acpi_dev_interface.h"
NameInfo *qmp_query_name(Error **errp)
@@ -689,12 +690,20 @@ void qmp_object_del(const char *id, Error **errp)
user_creatable_del(id, errp);
}
-MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
+MemoryDeviceInfoList *qmp_query_memory_devices(bool has_devtype,
+ MemoryDeviceType devtype,
+ Error **errp)
{
MemoryDeviceInfoList *head = NULL;
MemoryDeviceInfoList **prev = &head;
- qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+ if (!has_devtype || devtype == MEMORY_DEVICE_TYPE_DIMM) {
+ qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+ } else if (devtype == MEMORY_DEVICE_TYPE_NVDIMM) {
+ qmp_nvdimm_device_list(qdev_get_machine(), &prev);
+ } else {
+ error_setg(errp, "unrecognized memory device type %d", devtype);
+ }
return head;
}
Add an optional argument 'devtype' to 'query-memory-devices', which is either 'dimm' or 'nvdimm'. If 'devtype' is missed or 'dimm', all memory devices will be listed. If 'devtype' is 'nvdimm', only nvdimm devices will be listed. Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com> --- Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com> Cc: Xiao Guangrong <guangrong.xiao@linux.intel.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Eric Blake <eblake@redhat.com> Cc: Markus Armbruster <armbru@redhat.com> --- hmp.c | 3 +- hw/mem/nvdimm.c | 38 ++++++++++++++++++++++++++ hw/mem/pc-dimm.c | 71 ++++++++++++++++++++++++++++-------------------- include/hw/mem/nvdimm.h | 2 ++ include/hw/mem/pc-dimm.h | 1 + qapi-schema.json | 48 +++++++++++++++++++++++++++++--- qmp.c | 13 +++++++-- 7 files changed, 140 insertions(+), 36 deletions(-)