@@ -1780,6 +1780,8 @@ show qdev device model list
show roms
@item info tpm
show the TPM device
+@item info devices
+show the devices registered with migration capability
@end table
ETEXI
@@ -1714,3 +1714,26 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "\n");
}
+
+void hmp_info_devices(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ QemuDeviceList *device_list = qmp_query_devices(&err);
+
+ if (device_list) {
+ monitor_printf(mon, "devices:\n");
+ while (device_list) {
+ monitor_printf(mon, "device-name: %s, ",
+ device_list->value->device_name);
+ monitor_printf(mon, "version: %ld\n",
+ device_list->value->version);
+ device_list = device_list->next;
+ }
+ }
+
+ if (err) {
+ hmp_handle_error(mon, &err);
+ }
+
+ qapi_free_QemuDeviceList(device_list);
+}
@@ -38,6 +38,7 @@ void hmp_info_balloon(Monitor *mon, const QDict *qdict);
void hmp_info_pci(Monitor *mon, const QDict *qdict);
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
void hmp_info_tpm(Monitor *mon, const QDict *qdict);
+void hmp_info_devices(Monitor *mon, const QDict *qdict);
void hmp_quit(Monitor *mon, const QDict *qdict);
void hmp_stop(Monitor *mon, const QDict *qdict);
void hmp_system_reset(Monitor *mon, const QDict *qdict);
@@ -2918,6 +2918,13 @@ static mon_cmd_t info_cmds[] = {
.mhandler.cmd = hmp_info_memdev,
},
{
+ .name = "devices",
+ .args_type = "",
+ .params = "",
+ .help = "show registered devices",
+ .mhandler.cmd = hmp_info_devices,
+ },
+ {
.name = NULL,
},
};
@@ -3480,3 +3480,29 @@
# Since: 2.1
##
{ 'command': 'rtc-reset-reinjection' }
+
+##
+# @QemuDevice
+#
+# device that is registered with SaveVMHandlers
+#
+# @device-name: name of the device that is registered with
+# SaveVMHandlers (in vmsd structure).
+#
+# @version: version of the device.
+#
+# Since 2.2
+##
+{ 'type': 'QemuDevice',
+ 'data': { 'device-name': 'str',
+ '*version': 'int' } }
+
+##
+# @query-devices
+#
+# returns the list of QemuDevice
+#
+# Since 2.2
+##
+{ 'command': 'query-devices',
+ 'returns': [ 'QemuDevice' ] }
@@ -3755,3 +3755,46 @@ Example:
<- { "return": {} }
EQMP
+
+ {
+ .name = "query-devices",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_devices,
+ },
+
+SQMP
+query-devices
+-------------
+
+Shows registered devices along with the version
+
+Example (1):
+
+-> { "execute": "query-devices" }
+<- { "return": [
+ {
+ [ { 'device-name': 'kvm-tpr-opt', 'version': 1 },
+ { 'device-name': 'apic', 'version': 3 },
+ { 'device-name': 'kvmclock', 'version': 1 },
+ { 'device-name': 'fw_cfg', 'version': 2 },
+ { 'device-name': 'I440FX', 'version': 3 },
+ { 'device-name': 'PIIX3', 'version': 3 },
+ { 'device-name': 'i8259', 'version': 1 },
+ { 'device-name': 'i8259', 'version': 1 },
+ { 'device-name': 'ioapic', 'version': 3 },
+ { 'device-name': 'cirrus_vga', 'version': 2 },
+ { 'device-name': 'hpet', 'version': 2 },
+ { 'device-name': 'mc146818rtc', 'version': 3 },
+ { 'device-name': 'i8254', 'version': 3 },
+ { 'device-name': 'serial', 'version': 3 },
+ { 'device-name': 'pckbd', 'version': 3 },
+ { 'device-name': 'vmmouse', 'version': 0 },
+ { 'device-name': 'port92', 'version': 1 },
+ { 'device-name': 'fdc', 'version': 2 },
+ { 'device-name': 'e1000', 'version': 2 },
+ { 'device-name': 'ide', 'version': 3 },
+ { 'device-name': 'piix4_pm', 'version': 3 } ]
+ }
+ ]
+ }
+EQMP
@@ -233,6 +233,7 @@ typedef struct SaveStateEntry {
void *opaque;
CompatEntry *compat;
int is_ram;
+ DeviceState *dev;
} SaveStateEntry;
@@ -429,6 +430,7 @@ int register_savevm_live(DeviceState *dev,
se->ops = ops;
se->opaque = opaque;
se->vmsd = NULL;
+ se->dev = dev;
/* if this is a live_savem then set is_ram */
if (ops->save_live_setup != NULL) {
se->is_ram = 1;
@@ -519,6 +521,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
se->opaque = opaque;
se->vmsd = vmsd;
se->alias_id = alias_id;
+ se->dev = dev;
if (dev) {
char *id = qdev_get_dev_path(dev);
@@ -1137,6 +1140,48 @@ void do_savevm(Monitor *mon, const QDict *qdict)
}
}
+static QemuDeviceList *create_device_list(const char *name, int version,
+ QemuDeviceList *list)
+{
+ QemuDeviceList *temp_list;
+ QemuDeviceList *parent_list = list;
+ int len;
+
+ temp_list = g_malloc0(sizeof(QemuDeviceList));
+ len = strlen(name);
+ temp_list->value = g_malloc0(sizeof(QemuDevice));
+ temp_list->value->device_name = g_malloc0(sizeof(char)*(len+1));
+ strcpy(temp_list->value->device_name, name);
+ temp_list->value->version = version;
+ temp_list->next = NULL;
+
+ if (!list) {
+ return temp_list;
+ }
+
+ while (list->next) {
+ list = list->next;
+ }
+ list->next = temp_list;
+
+ return parent_list;
+}
+
+QemuDeviceList *qmp_query_devices(Error **errp)
+{
+ QemuDeviceList *device_list = NULL;
+ SaveStateEntry *se;
+
+ QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+ if (se->dev) {
+ device_list = create_device_list(se->vmsd->name, se->version_id,
+ device_list);
+ }
+ }
+
+ return device_list;
+}
+
void qmp_xen_save_devices_state(const char *filename, Error **errp)
{
QEMUFile *f;
Added both qmp and hmp interface to get the information about the devices that have been qdevified and are registered with the SaveVMHandlers. I have not used any format to print the device information for the hmp interface. It would be great if anyone can give me some pointers about this about the printing format if there is something. The qmp command to extract the information about the devices is qmp_query_devices which provides the list of device names and their respective version. The hmp command name is 'info devices' which lists the same information as provided by the qmp interface. Signed-off-by: Sanidhya Kashyap <sanidhya.iiith@gmail.com> --- hmp-commands.hx | 2 ++ hmp.c | 23 +++++++++++++++++++++++ hmp.h | 1 + monitor.c | 7 +++++++ qapi-schema.json | 26 ++++++++++++++++++++++++++ qmp-commands.hx | 43 +++++++++++++++++++++++++++++++++++++++++++ savevm.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 147 insertions(+)