blob: 1ca44fbd72f423e231b4bc59eee8e7148feb227d [file] [log] [blame]
Anthony Liguori48a32be2011-09-02 12:34:48 -05001/*
Kevin Wolff1b3ccf2019-06-13 17:33:58 +02002 * QEMU Management Protocol commands
Anthony Liguori48a32be2011-09-02 12:34:48 -05003 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
Paolo Bonzini6b620ca2012-01-13 17:44:23 +010012 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
Anthony Liguori48a32be2011-09-02 12:34:48 -050014 */
15
Peter Maydelld38ea872016-01-29 17:50:05 +000016#include "qemu/osdep.h"
Marc-André Lureaubf5de8c2023-03-06 16:27:45 +040017#include "qemu/sockets.h"
Markus Armbrustere6e108d2023-01-24 13:19:44 +010018#include "monitor-internal.h"
19#include "monitor/qdev.h"
Markus Armbruster3125af22023-01-09 20:03:14 +010020#include "monitor/qmp-helpers.h"
Philippe Mathieu-Daudé32cad1f2024-12-03 15:20:13 +010021#include "system/system.h"
22#include "system/kvm.h"
23#include "system/runstate.h"
24#include "system/runstate-action.h"
25#include "system/block-backend.h"
Markus Armbrustere688df62018-02-01 12:18:31 +010026#include "qapi/error.h"
Markus Armbrustere6e108d2023-01-24 13:19:44 +010027#include "qapi/qapi-init-commands.h"
Kevin Wolffa4dcf52020-01-29 11:22:37 +010028#include "qapi/qapi-commands-control.h"
Markus Armbruster112ed242018-02-26 17:13:27 -060029#include "qapi/qapi-commands-misc.h"
Markus Armbrustere6e108d2023-01-24 13:19:44 +010030#include "qapi/qmp/qerror.h"
Daniel P. Berrangé37087fd2021-09-08 10:35:43 +010031#include "qapi/type-helpers.h"
David Hildenbrand2cc0e2e2018-04-23 18:51:16 +020032#include "hw/mem/memory-device.h"
Daniel P. Berrangé91f2fa72021-09-08 10:35:43 +010033#include "hw/intc/intc.h"
Peter Xu8597af72024-12-06 18:08:38 -050034#include "migration/misc.h"
Anthony Liguori48a32be2011-09-02 12:34:48 -050035
36NameInfo *qmp_query_name(Error **errp)
37{
38 NameInfo *info = g_malloc0(sizeof(*info));
39
Markus Armbruster94927182022-11-04 17:06:59 +010040 info->name = g_strdup(qemu_name);
Anthony Liguori48a32be2011-09-02 12:34:48 -050041 return info;
42}
Luiz Capitulinob9c15f12011-08-26 17:38:13 -030043
Markus Armbruster7daecb32014-05-02 13:26:31 +020044void qmp_quit(Error **errp)
Luiz Capitulino7a7f3252011-09-15 14:20:28 -030045{
Alejandro Jimeneze6dba042020-12-11 11:52:43 -050046 shutdown_action = SHUTDOWN_ACTION_POWEROFF;
Dominik Csapak92548932018-12-05 12:01:31 +010047 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
Luiz Capitulino7a7f3252011-09-15 14:20:28 -030048}
49
Luiz Capitulino5f158f22011-09-15 14:34:39 -030050void qmp_stop(Error **errp)
51{
Peter Xu65d64f32016-02-18 13:16:49 +080052 /* if there is a dump in background, we should wait until the dump
53 * finished */
Marc-André Lureau544803c2022-03-23 19:57:31 +040054 if (qemu_system_dump_in_progress()) {
Peter Xu65d64f32016-02-18 13:16:49 +080055 error_setg(errp, "There is a dump in process, please wait.");
56 return;
57 }
58
Paolo Bonzini1e998142012-10-23 14:54:21 +020059 if (runstate_check(RUN_STATE_INMIGRATE)) {
60 autostart = 0;
61 } else {
62 vm_stop(RUN_STATE_PAUSED);
63 }
Luiz Capitulino5f158f22011-09-15 14:34:39 -030064}
65
Luiz Capitulinoe42e8182011-11-22 17:58:31 -020066void qmp_cont(Error **errp)
67{
Max Reitz373340b2015-10-19 17:53:22 +020068 BlockBackend *blk;
Vladimir Sementsov-Ogievskiy68d00e42019-06-06 18:41:30 +030069 BlockJob *job;
Daniel P. Berrange788cf9f2017-06-23 17:24:15 +010070 Error *local_err = NULL;
Luiz Capitulinoe42e8182011-11-22 17:58:31 -020071
Peter Xu65d64f32016-02-18 13:16:49 +080072 /* if there is a dump in background, we should wait until the dump
73 * finished */
Marc-André Lureau544803c2022-03-23 19:57:31 +040074 if (qemu_system_dump_in_progress()) {
Peter Xu65d64f32016-02-18 13:16:49 +080075 error_setg(errp, "There is a dump in process, please wait.");
76 return;
77 }
78
Hu Taoede085b2013-04-26 11:24:40 +080079 if (runstate_needs_reset()) {
Cole Robinsonf231b882014-03-21 19:42:26 -040080 error_setg(errp, "Resetting the Virtual Machine is required");
Luiz Capitulinoe42e8182011-11-22 17:58:31 -020081 return;
Luiz Capitulinoad02b962012-04-27 13:33:36 -030082 } else if (runstate_check(RUN_STATE_SUSPENDED)) {
83 return;
Vladimir Sementsov-Ogievskiy9183dd12019-01-24 15:25:24 +030084 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
85 error_setg(errp, "Migration is not finalized yet");
86 return;
Luiz Capitulinoe42e8182011-11-22 17:58:31 -020087 }
88
Max Reitz373340b2015-10-19 17:53:22 +020089 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
90 blk_iostatus_reset(blk);
Markus Armbrusterab319792014-05-02 13:26:42 +020091 }
Kevin Wolf7c8eece2016-03-22 18:58:50 +010092
Emanuele Giuseppe Esposito880eeec2022-09-26 05:32:04 -040093 WITH_JOB_LOCK_GUARD() {
94 for (job = block_job_next_locked(NULL); job;
95 job = block_job_next_locked(job)) {
96 block_job_iostatus_reset_locked(job);
97 }
Vladimir Sementsov-Ogievskiy68d00e42019-06-06 18:41:30 +030098 }
99
Paolo Bonzini1e998142012-10-23 14:54:21 +0200100 if (runstate_check(RUN_STATE_INMIGRATE)) {
101 autostart = 1;
102 } else {
Peter Xue4e5e892024-12-06 18:08:34 -0500103 /*
104 * Continuing after completed migration. Images have been
105 * inactivated to allow the destination to take control. Need to
106 * get control back now.
Peter Xue4e5e892024-12-06 18:08:34 -0500107 */
Peter Xu8597af72024-12-06 18:08:38 -0500108 if (!migration_block_activate(&local_err)) {
Peter Xue4e5e892024-12-06 18:08:34 -0500109 error_propagate(errp, local_err);
110 return;
111 }
Paolo Bonzini1e998142012-10-23 14:54:21 +0200112 vm_start();
113 }
Luiz Capitulinoe42e8182011-11-22 17:58:31 -0200114}
Anthony Liguorib4b12c62011-12-12 14:29:34 -0600115
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300116void qmp_add_client(const char *protocol, const char *fdname,
117 bool has_skipauth, bool skipauth, bool has_tls, bool tls,
118 Error **errp)
119{
Markus Armbrusterf916a172023-01-09 20:03:17 +0100120 static const struct {
Markus Armbruster3125af22023-01-09 20:03:14 +0100121 const char *name;
122 bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
123 bool has_tls, bool tls, Error **errp);
124 } protocol_table[] = {
125 { "spice", qmp_add_client_spice },
126#ifdef CONFIG_VNC
127 { "vnc", qmp_add_client_vnc },
128#endif
129#ifdef CONFIG_DBUS_DISPLAY
130 { "@dbus-display", qmp_add_client_dbus_display },
131#endif
132 };
Markus Armbruster3125af22023-01-09 20:03:14 +0100133 int fd, i;
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300134
Kevin Wolf947e4742020-10-05 17:58:44 +0200135 fd = monitor_get_fd(monitor_cur(), fdname, errp);
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300136 if (fd < 0) {
137 return;
138 }
139
Marc-André Lureaubf5de8c2023-03-06 16:27:45 +0400140 if (!fd_is_socket(fd)) {
141 error_setg(errp, "parameter @fdname must name a socket");
142 close(fd);
143 return;
144 }
145
Markus Armbruster3125af22023-01-09 20:03:14 +0100146 for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
147 if (!strcmp(protocol, protocol_table[i].name)) {
148 if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
149 has_tls, tls, errp)) {
150 close(fd);
151 }
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300152 return;
153 }
Markus Armbruster3125af22023-01-09 20:03:14 +0100154 }
155
Markus Armbrusterc3054a62023-01-24 13:19:18 +0100156 if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
157 protocol, errp)) {
Markus Armbruster3125af22023-01-09 20:03:14 +0100158 close(fd);
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300159 }
Luiz Capitulinob224e5e2012-09-13 16:52:20 -0300160}
Markus Armbrustere6e108d2023-01-24 13:19:44 +0100161
162char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
163 int64_t cpu_index, Error **errp)
164{
165 char *output = NULL;
166 MonitorHMP hmp = {};
167
168 monitor_data_init(&hmp.common, false, true, false);
169
170 if (has_cpu_index) {
171 int ret = monitor_set_cpu(&hmp.common, cpu_index);
172 if (ret < 0) {
173 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
174 "a CPU number");
175 goto out;
176 }
177 }
178
179 handle_hmp_command(&hmp, command_line);
180
181 WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
182 output = g_strdup(hmp.common.outbuf->str);
183 }
184
185out:
186 monitor_data_destroy(&hmp.common);
187 return output;
188}
189
190static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
191{
192 /*
193 * Two command lists:
194 * - qmp_commands contains all QMP commands
195 * - qmp_cap_negotiation_commands contains just
196 * "qmp_capabilities", to enforce capability negotiation
197 */
198
199 qmp_init_marshal(&qmp_commands);
200
201 qmp_register_command(&qmp_commands, "device_add",
202 qmp_device_add, 0, 0);
203
204 QTAILQ_INIT(&qmp_cap_negotiation_commands);
205 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
206 qmp_marshal_qmp_capabilities,
207 QCO_ALLOW_PRECONFIG, 0);
208}