From 43c95d782d6cc2297b6235d9ecb1f66f08e9928a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 1 Nov 2014 13:56:09 -0200 Subject: [PATCH 1/3] qdev: Create qdev_get_device_class() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the DeviceClass lookup from qdev_device_add() to a separate function. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- qdev-monitor.c | 70 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index fac7d179fe..982f3f4c09 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -180,6 +180,44 @@ static const char *find_typename_by_alias(const char *alias) return NULL; } +static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) +{ + ObjectClass *oc; + DeviceClass *dc; + + oc = object_class_by_name(*driver); + if (!oc) { + const char *typename = find_typename_by_alias(*driver); + + if (typename) { + *driver = typename; + oc = object_class_by_name(*driver); + } + } + + if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) { + error_setg(errp, "'%s' is not a valid device model name", *driver); + return NULL; + } + + if (object_class_is_abstract(oc)) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "driver", + "non-abstract device type"); + return NULL; + } + + dc = DEVICE_CLASS(oc); + if (dc->cannot_instantiate_with_device_add_yet || + (qdev_hotplug && !dc->hotpluggable)) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "driver", + "pluggable device type"); + return NULL; + } + + return dc; +} + + int qdev_device_help(QemuOpts *opts) { Error *local_err = NULL; @@ -455,7 +493,6 @@ static BusState *qbus_find(const char *path) DeviceState *qdev_device_add(QemuOpts *opts) { - ObjectClass *oc; DeviceClass *dc; const char *driver, *path, *id; DeviceState *dev; @@ -469,33 +506,10 @@ DeviceState *qdev_device_add(QemuOpts *opts) } /* find driver */ - oc = object_class_by_name(driver); - if (!oc) { - const char *typename = find_typename_by_alias(driver); - - if (typename) { - driver = typename; - oc = object_class_by_name(driver); - } - } - - if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, - "'%s' is not a valid device model name", driver); - return NULL; - } - - if (object_class_is_abstract(oc)) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", - "non-abstract device type"); - return NULL; - } - - dc = DEVICE_CLASS(oc); - if (dc->cannot_instantiate_with_device_add_yet || - (qdev_hotplug && !dc->hotpluggable)) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", - "pluggable device type"); + dc = qdev_get_device_class(&driver, &err); + if (err) { + qerror_report_err(err); + error_free(err); return NULL; } From 5185f0e0a6bb076cd1cd0115ef785298a97a71fe Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 1 Nov 2014 13:56:10 -0200 Subject: [PATCH 2/3] qdev: Move error printing to the end of qdev_device_help() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- qdev-monitor.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index 982f3f4c09..a9702d89c2 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -245,9 +245,7 @@ int qdev_device_help(QemuOpts *opts) prop_list = qmp_device_list_properties(driver, &local_err); if (local_err) { - error_printf("%s\n", error_get_pretty(local_err)); - error_free(local_err); - return 1; + goto error; } for (prop = prop_list; prop; prop = prop->next) { @@ -263,6 +261,11 @@ int qdev_device_help(QemuOpts *opts) qapi_free_DevicePropertyInfoList(prop_list); return 1; + +error: + error_printf("%s\n", error_get_pretty(local_err)); + error_free(local_err); + return 1; } static Object *qdev_get_peripheral(void) From 31bed5509dfcbdfc293154ce81086a4dbd7a80b6 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 1 Nov 2014 13:56:11 -0200 Subject: [PATCH 3/3] qdev: Use qdev_get_device_class() for -device ,help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we try to list properties from classes that can be safely used with "-device". Fixes the following crashes: $ qemu-system-x86_64 -device x86_64-cpu,help ** ERROR:qom/object.c:336:object_initialize_with_type: assertion failed: (type->abstract == false) Aborted (core dumped) $ qemu-system-x86_64 -device host-x86_64-cpu,help qemu-system-x86_64: [...]/target-i386/cpu.c:1329: host_x86_cpu_initfn: Assertion `(kvm_allowed)' failed. Aborted (core dumped) After applying this patch: $ qemu-system-x86_64 -device x86_64-cpu,help Parameter 'driver' expects non-abstract device type $ qemu-system-x86_64 -device host-x86_64-cpu,help Parameter 'driver' expects pluggable device type Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- qdev-monitor.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index a9702d89c2..ebfa701a9d 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -235,12 +235,9 @@ int qdev_device_help(QemuOpts *opts) return 0; } - if (!object_class_by_name(driver)) { - const char *typename = find_typename_by_alias(driver); - - if (typename) { - driver = typename; - } + qdev_get_device_class(&driver, &local_err); + if (local_err) { + goto error; } prop_list = qmp_device_list_properties(driver, &local_err);