X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/5b4448d27d7c6ff6e18a1edc8245cb1db783e37c..b6e9f63711ea19b110574e384477bad4ea74f4a2:/qmp.c diff --git a/qmp.c b/qmp.c index 1222b6c9c4..d8a3c00b97 100644 --- a/qmp.c +++ b/qmp.c @@ -21,9 +21,8 @@ #include "kvm.h" #include "arch_init.h" #include "hw/qdev.h" -#include "qapi/qmp-input-visitor.h" -#include "qapi/qmp-output-visitor.h" #include "blockdev.h" +#include "qemu/qom-qobject.h" NameInfo *qmp_query_name(Error **errp) { @@ -86,7 +85,11 @@ void qmp_quit(Error **err) void qmp_stop(Error **errp) { - vm_stop(RUN_STATE_PAUSED); + if (runstate_check(RUN_STATE_INMIGRATE)) { + autostart = 0; + } else { + vm_stop(RUN_STATE_PAUSED); + } } void qmp_system_reset(Error **errp) @@ -145,13 +148,12 @@ void qmp_cont(Error **errp) { Error *local_err = NULL; - if (runstate_check(RUN_STATE_INMIGRATE)) { - error_set(errp, QERR_MIGRATION_EXPECTED); - return; - } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) || + if (runstate_check(RUN_STATE_INTERNAL_ERROR) || runstate_check(RUN_STATE_SHUTDOWN)) { error_set(errp, QERR_RESET_REQUIRED); return; + } else if (runstate_check(RUN_STATE_SUSPENDED)) { + return; } bdrv_iterate(iostatus_bdrv_it, NULL); @@ -161,26 +163,35 @@ void qmp_cont(Error **errp) return; } - vm_start(); + if (runstate_check(RUN_STATE_INMIGRATE)) { + autostart = 1; + } else { + vm_start(); + } } -DevicePropertyInfoList *qmp_qom_list(const char *path, Error **errp) +void qmp_system_wakeup(Error **errp) { - DeviceState *dev; + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); +} + +ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) +{ + Object *obj; bool ambiguous = false; - DevicePropertyInfoList *props = NULL; - DeviceProperty *prop; + ObjectPropertyInfoList *props = NULL; + ObjectProperty *prop; - dev = qdev_resolve_path(path, &ambiguous); - if (dev == NULL) { + obj = object_resolve_path(path, &ambiguous); + if (obj == NULL) { error_set(errp, QERR_DEVICE_NOT_FOUND, path); return NULL; } - QTAILQ_FOREACH(prop, &dev->properties, node) { - DevicePropertyInfoList *entry = g_malloc0(sizeof(*entry)); + QTAILQ_FOREACH(prop, &obj->properties, node) { + ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry)); - entry->value = g_malloc0(sizeof(DevicePropertyInfo)); + entry->value = g_malloc0(sizeof(ObjectPropertyInfo)); entry->next = props; props = entry; @@ -198,19 +209,15 @@ int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret) const char *property = qdict_get_str(qdict, "property"); QObject *value = qdict_get(qdict, "value"); Error *local_err = NULL; - QmpInputVisitor *mi; - DeviceState *dev; + Object *obj; - dev = qdev_resolve_path(path, NULL); - if (!dev) { + obj = object_resolve_path(path, NULL); + if (!obj) { error_set(&local_err, QERR_DEVICE_NOT_FOUND, path); goto out; } - mi = qmp_input_visitor_new(value); - qdev_property_set(dev, qmp_input_get_visitor(mi), property, &local_err); - - qmp_input_visitor_cleanup(mi); + object_property_set_qobject(obj, value, property, &local_err); out: if (local_err) { @@ -227,22 +234,15 @@ int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret) const char *path = qdict_get_str(qdict, "path"); const char *property = qdict_get_str(qdict, "property"); Error *local_err = NULL; - QmpOutputVisitor *mo; - DeviceState *dev; + Object *obj; - dev = qdev_resolve_path(path, NULL); - if (!dev) { + obj = object_resolve_path(path, NULL); + if (!obj) { error_set(&local_err, QERR_DEVICE_NOT_FOUND, path); goto out; } - mo = qmp_output_visitor_new(); - qdev_property_get(dev, qmp_output_get_visitor(mo), property, &local_err); - if (!local_err) { - *ret = qmp_output_get_qobject(mo); - } - - qmp_output_visitor_cleanup(mo); + *ret = object_property_get_qobject(obj, property, &local_err); out: if (local_err) { @@ -354,11 +354,9 @@ void qmp_change_vnc_password(const char *password, Error **errp) } } -static void qmp_change_vnc_listen(const char *target, Error **err) +static void qmp_change_vnc_listen(const char *target, Error **errp) { - if (vnc_display_open(NULL, target) < 0) { - error_set(err, QERR_VNC_SERVER_FAILED, target); - } + vnc_display_open(NULL, target, errp); } static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, @@ -395,3 +393,135 @@ void qmp_change(const char *device, const char *target, qmp_change_blockdev(device, target, has_arg, arg, err); } } + +static void qom_list_types_tramp(ObjectClass *klass, void *data) +{ + ObjectTypeInfoList *e, **pret = data; + ObjectTypeInfo *info; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(object_class_get_name(klass)); + + e = g_malloc0(sizeof(*e)); + e->value = info; + e->next = *pret; + *pret = e; +} + +ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, + const char *implements, + bool has_abstract, + bool abstract, + Error **errp) +{ + ObjectTypeInfoList *ret = NULL; + + object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); + + return ret; +} + +DevicePropertyInfoList *qmp_device_list_properties(const char *typename, + Error **errp) +{ + ObjectClass *klass; + Property *prop; + DevicePropertyInfoList *prop_list = NULL; + + klass = object_class_by_name(typename); + if (klass == NULL) { + error_set(errp, QERR_DEVICE_NOT_FOUND, typename); + return NULL; + } + + klass = object_class_dynamic_cast(klass, TYPE_DEVICE); + if (klass == NULL) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + "name", TYPE_DEVICE); + return NULL; + } + + do { + for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { + DevicePropertyInfoList *entry; + DevicePropertyInfo *info; + + /* + * TODO Properties without a parser are just for dirty hacks. + * qdev_prop_ptr is the only such PropertyInfo. It's marked + * for removal. This conditional should be removed along with + * it. + */ + if (!prop->info->set) { + continue; /* no way to set it, don't show */ + } + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(prop->name); + info->type = g_strdup(prop->info->legacy_name ?: prop->info->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = prop_list; + prop_list = entry; + } + klass = object_class_get_parent(klass); + } while (klass != object_class_by_name(TYPE_DEVICE)); + + return prop_list; +} + +CpuDefinitionInfoList GCC_WEAK *arch_query_cpu_definitions(Error **errp) +{ + error_set(errp, QERR_NOT_SUPPORTED); + return NULL; +} + +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + return arch_query_cpu_definitions(errp); +} + +void qmp_add_client(const char *protocol, const char *fdname, + bool has_skipauth, bool skipauth, bool has_tls, bool tls, + Error **errp) +{ + CharDriverState *s; + int fd; + + fd = monitor_get_fd(cur_mon, fdname, errp); + if (fd < 0) { + return; + } + + if (strcmp(protocol, "spice") == 0) { + if (!using_spice) { + error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice"); + close(fd); + return; + } + skipauth = has_skipauth ? skipauth : false; + tls = has_tls ? tls : false; + if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { + error_setg(errp, "spice failed to add client"); + close(fd); + } + return; +#ifdef CONFIG_VNC + } else if (strcmp(protocol, "vnc") == 0) { + skipauth = has_skipauth ? skipauth : false; + vnc_display_add_client(NULL, fd, skipauth); + return; +#endif + } else if ((s = qemu_chr_find(protocol)) != NULL) { + if (qemu_chr_add_client(s, fd) < 0) { + error_setg(errp, "failed to add client"); + close(fd); + return; + } + return; + } + + error_setg(errp, "protocol '%s' is invalid", protocol); + close(fd); +}