xref: /openbmc/qemu/monitor/qmp-cmds.c (revision 85b597413d4370cb168f711192eaef2eb70535ac)
1f1b3ccfaSKevin Wolf /*
2f1b3ccfaSKevin Wolf  * QEMU Management Protocol commands
3f1b3ccfaSKevin Wolf  *
4f1b3ccfaSKevin Wolf  * Copyright IBM, Corp. 2011
5f1b3ccfaSKevin Wolf  *
6f1b3ccfaSKevin Wolf  * Authors:
7f1b3ccfaSKevin Wolf  *  Anthony Liguori   <aliguori@us.ibm.com>
8f1b3ccfaSKevin Wolf  *
9f1b3ccfaSKevin Wolf  * This work is licensed under the terms of the GNU GPL, version 2.  See
10f1b3ccfaSKevin Wolf  * the COPYING file in the top-level directory.
11f1b3ccfaSKevin Wolf  *
12f1b3ccfaSKevin Wolf  * Contributions after 2012-01-13 are licensed under the terms of the
13f1b3ccfaSKevin Wolf  * GNU GPL, version 2 or (at your option) any later version.
14f1b3ccfaSKevin Wolf  */
15f1b3ccfaSKevin Wolf 
16f1b3ccfaSKevin Wolf #include "qemu/osdep.h"
17*bf5de8c5SMarc-André Lureau #include "qemu/sockets.h"
18e6e108d1SMarkus Armbruster #include "monitor-internal.h"
19e6e108d1SMarkus Armbruster #include "monitor/qdev.h"
203125af29SMarkus Armbruster #include "monitor/qmp-helpers.h"
21f1b3ccfaSKevin Wolf #include "sysemu/sysemu.h"
22f1b3ccfaSKevin Wolf #include "sysemu/kvm.h"
2354d31236SMarkus Armbruster #include "sysemu/runstate.h"
24e6dba048SAlejandro Jimenez #include "sysemu/runstate-action.h"
25f1b3ccfaSKevin Wolf #include "sysemu/block-backend.h"
26f1b3ccfaSKevin Wolf #include "qapi/error.h"
27e6e108d1SMarkus Armbruster #include "qapi/qapi-init-commands.h"
28fa4dcf57SKevin Wolf #include "qapi/qapi-commands-control.h"
29f1b3ccfaSKevin Wolf #include "qapi/qapi-commands-misc.h"
30e6e108d1SMarkus Armbruster #include "qapi/qmp/qerror.h"
3137087fdeSDaniel P. Berrangé #include "qapi/type-helpers.h"
32f1b3ccfaSKevin Wolf #include "hw/mem/memory-device.h"
3391f2fa70SDaniel P. Berrangé #include "hw/intc/intc.h"
34f1b3ccfaSKevin Wolf 
qmp_query_name(Error ** errp)35f1b3ccfaSKevin Wolf NameInfo *qmp_query_name(Error **errp)
36f1b3ccfaSKevin Wolf {
37f1b3ccfaSKevin Wolf     NameInfo *info = g_malloc0(sizeof(*info));
38f1b3ccfaSKevin Wolf 
39f1b3ccfaSKevin Wolf     info->name = g_strdup(qemu_name);
40f1b3ccfaSKevin Wolf     return info;
41f1b3ccfaSKevin Wolf }
42f1b3ccfaSKevin Wolf 
qmp_quit(Error ** errp)43f1b3ccfaSKevin Wolf void qmp_quit(Error **errp)
44f1b3ccfaSKevin Wolf {
45e6dba048SAlejandro Jimenez     shutdown_action = SHUTDOWN_ACTION_POWEROFF;
46f1b3ccfaSKevin Wolf     qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
47f1b3ccfaSKevin Wolf }
48f1b3ccfaSKevin Wolf 
qmp_stop(Error ** errp)49f1b3ccfaSKevin Wolf void qmp_stop(Error **errp)
50f1b3ccfaSKevin Wolf {
51f1b3ccfaSKevin Wolf     /* if there is a dump in background, we should wait until the dump
52f1b3ccfaSKevin Wolf      * finished */
53544803c7SMarc-André Lureau     if (qemu_system_dump_in_progress()) {
54f1b3ccfaSKevin Wolf         error_setg(errp, "There is a dump in process, please wait.");
55f1b3ccfaSKevin Wolf         return;
56f1b3ccfaSKevin Wolf     }
57f1b3ccfaSKevin Wolf 
58f1b3ccfaSKevin Wolf     if (runstate_check(RUN_STATE_INMIGRATE)) {
59f1b3ccfaSKevin Wolf         autostart = 0;
60f1b3ccfaSKevin Wolf     } else {
61f1b3ccfaSKevin Wolf         vm_stop(RUN_STATE_PAUSED);
62f1b3ccfaSKevin Wolf     }
63f1b3ccfaSKevin Wolf }
64f1b3ccfaSKevin Wolf 
qmp_cont(Error ** errp)65f1b3ccfaSKevin Wolf void qmp_cont(Error **errp)
66f1b3ccfaSKevin Wolf {
67f1b3ccfaSKevin Wolf     BlockBackend *blk;
6868d00e42SVladimir Sementsov-Ogievskiy     BlockJob *job;
69f1b3ccfaSKevin Wolf     Error *local_err = NULL;
70f1b3ccfaSKevin Wolf 
71f1b3ccfaSKevin Wolf     /* if there is a dump in background, we should wait until the dump
72f1b3ccfaSKevin Wolf      * finished */
73544803c7SMarc-André Lureau     if (qemu_system_dump_in_progress()) {
74f1b3ccfaSKevin Wolf         error_setg(errp, "There is a dump in process, please wait.");
75f1b3ccfaSKevin Wolf         return;
76f1b3ccfaSKevin Wolf     }
77f1b3ccfaSKevin Wolf 
78f1b3ccfaSKevin Wolf     if (runstate_needs_reset()) {
79f1b3ccfaSKevin Wolf         error_setg(errp, "Resetting the Virtual Machine is required");
80f1b3ccfaSKevin Wolf         return;
81f1b3ccfaSKevin Wolf     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
82f1b3ccfaSKevin Wolf         return;
83f1b3ccfaSKevin Wolf     } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
84f1b3ccfaSKevin Wolf         error_setg(errp, "Migration is not finalized yet");
85f1b3ccfaSKevin Wolf         return;
86f1b3ccfaSKevin Wolf     }
87f1b3ccfaSKevin Wolf 
88f1b3ccfaSKevin Wolf     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
89f1b3ccfaSKevin Wolf         blk_iostatus_reset(blk);
90f1b3ccfaSKevin Wolf     }
91f1b3ccfaSKevin Wolf 
92880eeec6SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
93880eeec6SEmanuele Giuseppe Esposito         for (job = block_job_next_locked(NULL); job;
94880eeec6SEmanuele Giuseppe Esposito              job = block_job_next_locked(job)) {
95880eeec6SEmanuele Giuseppe Esposito             block_job_iostatus_reset_locked(job);
96880eeec6SEmanuele Giuseppe Esposito         }
9768d00e42SVladimir Sementsov-Ogievskiy     }
9868d00e42SVladimir Sementsov-Ogievskiy 
99f1b3ccfaSKevin Wolf     /* Continuing after completed migration. Images have been inactivated to
100f1b3ccfaSKevin Wolf      * allow the destination to take control. Need to get control back now.
101f1b3ccfaSKevin Wolf      *
102f1b3ccfaSKevin Wolf      * If there are no inactive block nodes (e.g. because the VM was just
103f1b3ccfaSKevin Wolf      * paused rather than completing a migration), bdrv_inactivate_all() simply
104f1b3ccfaSKevin Wolf      * doesn't do anything. */
1053b717194SEmanuele Giuseppe Esposito     bdrv_activate_all(&local_err);
106f1b3ccfaSKevin Wolf     if (local_err) {
107f1b3ccfaSKevin Wolf         error_propagate(errp, local_err);
108f1b3ccfaSKevin Wolf         return;
109f1b3ccfaSKevin Wolf     }
110f1b3ccfaSKevin Wolf 
111f1b3ccfaSKevin Wolf     if (runstate_check(RUN_STATE_INMIGRATE)) {
112f1b3ccfaSKevin Wolf         autostart = 1;
113f1b3ccfaSKevin Wolf     } else {
114f1b3ccfaSKevin Wolf         vm_start();
115f1b3ccfaSKevin Wolf     }
116f1b3ccfaSKevin Wolf }
117f1b3ccfaSKevin Wolf 
qmp_add_client(const char * protocol,const char * fdname,bool has_skipauth,bool skipauth,bool has_tls,bool tls,Error ** errp)118f1b3ccfaSKevin Wolf void qmp_add_client(const char *protocol, const char *fdname,
119f1b3ccfaSKevin Wolf                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
120f1b3ccfaSKevin Wolf                     Error **errp)
121f1b3ccfaSKevin Wolf {
122f916a175SMarkus Armbruster     static const struct {
1233125af29SMarkus Armbruster         const char *name;
1243125af29SMarkus Armbruster         bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
1253125af29SMarkus Armbruster                            bool has_tls, bool tls, Error **errp);
1263125af29SMarkus Armbruster     } protocol_table[] = {
1273125af29SMarkus Armbruster         { "spice", qmp_add_client_spice },
1283125af29SMarkus Armbruster #ifdef CONFIG_VNC
1293125af29SMarkus Armbruster         { "vnc", qmp_add_client_vnc },
1303125af29SMarkus Armbruster #endif
1313125af29SMarkus Armbruster #ifdef CONFIG_DBUS_DISPLAY
1323125af29SMarkus Armbruster         { "@dbus-display", qmp_add_client_dbus_display },
1333125af29SMarkus Armbruster #endif
1343125af29SMarkus Armbruster     };
1353125af29SMarkus Armbruster     int fd, i;
136f1b3ccfaSKevin Wolf 
137947e4744SKevin Wolf     fd = monitor_get_fd(monitor_cur(), fdname, errp);
138f1b3ccfaSKevin Wolf     if (fd < 0) {
139f1b3ccfaSKevin Wolf         return;
140f1b3ccfaSKevin Wolf     }
141f1b3ccfaSKevin Wolf 
142*bf5de8c5SMarc-André Lureau     if (!fd_is_socket(fd)) {
143*bf5de8c5SMarc-André Lureau         error_setg(errp, "parameter @fdname must name a socket");
144*bf5de8c5SMarc-André Lureau         close(fd);
145*bf5de8c5SMarc-André Lureau         return;
146*bf5de8c5SMarc-André Lureau     }
147*bf5de8c5SMarc-André Lureau 
1483125af29SMarkus Armbruster     for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
1493125af29SMarkus Armbruster         if (!strcmp(protocol, protocol_table[i].name)) {
1503125af29SMarkus Armbruster             if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
1513125af29SMarkus Armbruster                                               has_tls, tls, errp)) {
152f1b3ccfaSKevin Wolf                 close(fd);
1533125af29SMarkus Armbruster             }
154f1b3ccfaSKevin Wolf             return;
155f1b3ccfaSKevin Wolf         }
156f1b3ccfaSKevin Wolf     }
1573125af29SMarkus Armbruster 
158c3054a6eSMarkus Armbruster     if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
159c3054a6eSMarkus Armbruster                              protocol, errp)) {
16061d7f2a9SMarkus Armbruster         close(fd);
161f1b3ccfaSKevin Wolf     }
162f1b3ccfaSKevin Wolf }
163e6e108d1SMarkus Armbruster 
qmp_human_monitor_command(const char * command_line,bool has_cpu_index,int64_t cpu_index,Error ** errp)164e6e108d1SMarkus Armbruster char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
165e6e108d1SMarkus Armbruster                                 int64_t cpu_index, Error **errp)
166e6e108d1SMarkus Armbruster {
167e6e108d1SMarkus Armbruster     char *output = NULL;
168e6e108d1SMarkus Armbruster     MonitorHMP hmp = {};
169e6e108d1SMarkus Armbruster 
170e6e108d1SMarkus Armbruster     monitor_data_init(&hmp.common, false, true, false);
171e6e108d1SMarkus Armbruster 
172e6e108d1SMarkus Armbruster     if (has_cpu_index) {
173e6e108d1SMarkus Armbruster         int ret = monitor_set_cpu(&hmp.common, cpu_index);
174e6e108d1SMarkus Armbruster         if (ret < 0) {
175e6e108d1SMarkus Armbruster             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
176e6e108d1SMarkus Armbruster                        "a CPU number");
177e6e108d1SMarkus Armbruster             goto out;
178e6e108d1SMarkus Armbruster         }
179e6e108d1SMarkus Armbruster     }
180e6e108d1SMarkus Armbruster 
181e6e108d1SMarkus Armbruster     handle_hmp_command(&hmp, command_line);
182e6e108d1SMarkus Armbruster 
183e6e108d1SMarkus Armbruster     WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
184e6e108d1SMarkus Armbruster         output = g_strdup(hmp.common.outbuf->str);
185e6e108d1SMarkus Armbruster     }
186e6e108d1SMarkus Armbruster 
187e6e108d1SMarkus Armbruster out:
188e6e108d1SMarkus Armbruster     monitor_data_destroy(&hmp.common);
189e6e108d1SMarkus Armbruster     return output;
190e6e108d1SMarkus Armbruster }
191e6e108d1SMarkus Armbruster 
monitor_init_qmp_commands(void)192e6e108d1SMarkus Armbruster static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
193e6e108d1SMarkus Armbruster {
194e6e108d1SMarkus Armbruster     /*
195e6e108d1SMarkus Armbruster      * Two command lists:
196e6e108d1SMarkus Armbruster      * - qmp_commands contains all QMP commands
197e6e108d1SMarkus Armbruster      * - qmp_cap_negotiation_commands contains just
198e6e108d1SMarkus Armbruster      *   "qmp_capabilities", to enforce capability negotiation
199e6e108d1SMarkus Armbruster      */
200e6e108d1SMarkus Armbruster 
201e6e108d1SMarkus Armbruster     qmp_init_marshal(&qmp_commands);
202e6e108d1SMarkus Armbruster 
203e6e108d1SMarkus Armbruster     qmp_register_command(&qmp_commands, "device_add",
204e6e108d1SMarkus Armbruster                          qmp_device_add, 0, 0);
205e6e108d1SMarkus Armbruster 
206e6e108d1SMarkus Armbruster     QTAILQ_INIT(&qmp_cap_negotiation_commands);
207e6e108d1SMarkus Armbruster     qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
208e6e108d1SMarkus Armbruster                          qmp_marshal_qmp_capabilities,
209e6e108d1SMarkus Armbruster                          QCO_ALLOW_PRECONFIG, 0);
210e6e108d1SMarkus Armbruster }
211