*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "qemu/option.h"
-#include "monitor/monitor.h"
+#include "qemu/sockets.h"
+#include "monitor-internal.h"
+#include "monitor/qdev.h"
+#include "monitor/qmp-helpers.h"
#include "sysemu/sysemu.h"
-#include "qemu/config-file.h"
-#include "qemu/uuid.h"
-#include "chardev/char.h"
-#include "ui/qemu-spice.h"
-#include "ui/vnc.h"
#include "sysemu/kvm.h"
#include "sysemu/runstate.h"
#include "sysemu/runstate-action.h"
-#include "sysemu/arch_init.h"
-#include "sysemu/blockdev.h"
#include "sysemu/block-backend.h"
#include "qapi/error.h"
-#include "qapi/qapi-commands-acpi.h"
-#include "qapi/qapi-commands-block.h"
+#include "qapi/qapi-init-commands.h"
#include "qapi/qapi-commands-control.h"
-#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
-#include "qapi/qapi-commands-ui.h"
#include "qapi/qmp/qerror.h"
+#include "qapi/type-helpers.h"
#include "hw/mem/memory-device.h"
-#include "hw/acpi/acpi_dev_interface.h"
+#include "hw/intc/intc.h"
+#include "hw/rdma/rdma.h"
NameInfo *qmp_query_name(Error **errp)
{
NameInfo *info = g_malloc0(sizeof(*info));
- if (qemu_name) {
- info->has_name = true;
- info->name = g_strdup(qemu_name);
- }
-
- return info;
-}
-
-KvmInfo *qmp_query_kvm(Error **errp)
-{
- KvmInfo *info = g_malloc0(sizeof(*info));
-
- info->enabled = kvm_enabled();
- info->present = kvm_available();
-
- return info;
-}
-
-UuidInfo *qmp_query_uuid(Error **errp)
-{
- UuidInfo *info = g_malloc0(sizeof(*info));
-
- info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
+ info->name = g_strdup(qemu_name);
return info;
}
{
/* if there is a dump in background, we should wait until the dump
* finished */
- if (dump_in_progress()) {
+ if (qemu_system_dump_in_progress()) {
error_setg(errp, "There is a dump in process, please wait.");
return;
}
}
}
-void qmp_system_reset(Error **errp)
-{
- qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
-}
-
-void qmp_system_powerdown(Error **errp)
-{
- qemu_system_powerdown_request();
-}
-
void qmp_cont(Error **errp)
{
BlockBackend *blk;
/* if there is a dump in background, we should wait until the dump
* finished */
- if (dump_in_progress()) {
+ if (qemu_system_dump_in_progress()) {
error_setg(errp, "There is a dump in process, please wait.");
return;
}
blk_iostatus_reset(blk);
}
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
- block_job_iostatus_reset(job);
+ WITH_JOB_LOCK_GUARD() {
+ for (job = block_job_next_locked(NULL); job;
+ job = block_job_next_locked(job)) {
+ block_job_iostatus_reset_locked(job);
+ }
}
/* Continuing after completed migration. Images have been inactivated to
* If there are no inactive block nodes (e.g. because the VM was just
* paused rather than completing a migration), bdrv_inactivate_all() simply
* doesn't do anything. */
- bdrv_invalidate_cache_all(&local_err);
+ bdrv_activate_all(&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
-void qmp_system_wakeup(Error **errp)
-{
- if (!qemu_wakeup_suspend_enabled()) {
- error_setg(errp,
- "wake-up from suspend is not supported by this guest");
- return;
- }
-
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
-}
-
-void qmp_set_password(const char *protocol, const char *password,
- bool has_connected, const char *connected, Error **errp)
-{
- int disconnect_if_connected = 0;
- int fail_if_connected = 0;
- int rc;
-
- if (has_connected) {
- if (strcmp(connected, "fail") == 0) {
- fail_if_connected = 1;
- } else if (strcmp(connected, "disconnect") == 0) {
- disconnect_if_connected = 1;
- } else if (strcmp(connected, "keep") == 0) {
- /* nothing */
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER, "connected");
- return;
- }
- }
-
- if (strcmp(protocol, "spice") == 0) {
- if (!qemu_using_spice(errp)) {
- return;
- }
- rc = qemu_spice.set_passwd(password, fail_if_connected,
- disconnect_if_connected);
- } else if (strcmp(protocol, "vnc") == 0) {
- if (fail_if_connected || disconnect_if_connected) {
- /* vnc supports "connected=keep" only */
- error_setg(errp, QERR_INVALID_PARAMETER, "connected");
- return;
- }
- /* Note that setting an empty password will not disable login through
- * this interface. */
- rc = vnc_display_password(NULL, password);
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
- "'vnc' or 'spice'");
- return;
- }
-
- if (rc != 0) {
- error_setg(errp, "Could not set password");
- }
-}
-
-void qmp_expire_password(const char *protocol, const char *whenstr,
- Error **errp)
-{
- time_t when;
- int rc;
-
- if (strcmp(whenstr, "now") == 0) {
- when = 0;
- } else if (strcmp(whenstr, "never") == 0) {
- when = TIME_MAX;
- } else if (whenstr[0] == '+') {
- when = time(NULL) + strtoull(whenstr+1, NULL, 10);
- } else {
- when = strtoull(whenstr, NULL, 10);
- }
-
- if (strcmp(protocol, "spice") == 0) {
- if (!qemu_using_spice(errp)) {
- return;
- }
- rc = qemu_spice.set_pw_expire(when);
- } else if (strcmp(protocol, "vnc") == 0) {
- rc = vnc_display_pw_expire(NULL, when);
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
- "'vnc' or 'spice'");
- return;
- }
-
- if (rc != 0) {
- error_setg(errp, "Could not set password expire time");
- }
-}
-
-#ifdef CONFIG_VNC
-void qmp_change_vnc_password(const char *password, Error **errp)
-{
- if (vnc_display_password(NULL, password) < 0) {
- error_setg(errp, "Could not set password");
- }
-}
-#endif
-
void qmp_add_client(const char *protocol, const char *fdname,
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
Error **errp)
{
- Chardev *s;
- int fd;
+ static const struct {
+ const char *name;
+ bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
+ bool has_tls, bool tls, Error **errp);
+ } protocol_table[] = {
+ { "spice", qmp_add_client_spice },
+#ifdef CONFIG_VNC
+ { "vnc", qmp_add_client_vnc },
+#endif
+#ifdef CONFIG_DBUS_DISPLAY
+ { "@dbus-display", qmp_add_client_dbus_display },
+#endif
+ };
+ int fd, i;
fd = monitor_get_fd(monitor_cur(), fdname, errp);
if (fd < 0) {
return;
}
- if (strcmp(protocol, "spice") == 0) {
- if (!qemu_using_spice(errp)) {
- 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);
+ if (!fd_is_socket(fd)) {
+ error_setg(errp, "parameter @fdname must name a socket");
+ close(fd);
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);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
+ if (!strcmp(protocol, protocol_table[i].name)) {
+ if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
+ has_tls, tls, errp)) {
+ close(fd);
+ }
return;
}
- return;
}
- error_setg(errp, "protocol '%s' is invalid", protocol);
- close(fd);
+ if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
+ protocol, errp)) {
+ close(fd);
+ }
}
-
-MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
+char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
+ int64_t cpu_index, Error **errp)
{
- return qmp_memory_device_list();
-}
+ char *output = NULL;
+ MonitorHMP hmp = {};
-ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
-{
- bool ambig;
- ACPIOSTInfoList *head = NULL;
- ACPIOSTInfoList **prev = &head;
- Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
+ monitor_data_init(&hmp.common, false, true, false);
- if (obj) {
- AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
- AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
+ if (has_cpu_index) {
+ int ret = monitor_set_cpu(&hmp.common, cpu_index);
+ if (ret < 0) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+ "a CPU number");
+ goto out;
+ }
+ }
- adevc->ospm_status(adev, &prev);
- } else {
- error_setg(errp, "command is not supported, missing ACPI device");
+ handle_hmp_command(&hmp, command_line);
+
+ WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
+ output = g_strdup(hmp.common.outbuf->str);
}
- return head;
+out:
+ monitor_data_destroy(&hmp.common);
+ return output;
}
-MemoryInfo *qmp_query_memory_size_summary(Error **errp)
+static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
{
- MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
- MachineState *ms = MACHINE(qdev_get_machine());
+ /*
+ * Two command lists:
+ * - qmp_commands contains all QMP commands
+ * - qmp_cap_negotiation_commands contains just
+ * "qmp_capabilities", to enforce capability negotiation
+ */
- mem_info->base_memory = ms->ram_size;
+ qmp_init_marshal(&qmp_commands);
- mem_info->plugged_memory = get_plugged_memory_size();
- mem_info->has_plugged_memory =
- mem_info->plugged_memory != (uint64_t)-1;
+ qmp_register_command(&qmp_commands, "device_add",
+ qmp_device_add, 0, 0);
- return mem_info;
+ QTAILQ_INIT(&qmp_cap_negotiation_commands);
+ qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
+ qmp_marshal_qmp_capabilities,
+ QCO_ALLOW_PRECONFIG, 0);
}