blob: bf9faceb865b2644982e10c829ae6b403491f3e8 [file] [log] [blame]
bellard9dc39cb2004-03-14 21:38:27 +00001/*
2 * QEMU monitor
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard9dc39cb2004-03-14 21:38:27 +00004 * Copyright (c) 2003-2004 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellard9dc39cb2004-03-14 21:38:27 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
Markus Armbrustere688df62018-02-01 12:18:31 +010024
Peter Maydelld38ea872016-01-29 17:50:05 +000025#include "qemu/osdep.h"
Kevin Wolf5bce3082019-06-13 17:33:59 +020026#include "monitor-internal.h"
Paolo Bonzini33c11872016-03-15 16:58:45 +010027#include "cpu.h"
pbrook87ecb682007-11-17 17:14:51 +000028#include "hw/hw.h"
Paolo Bonzinib4a42f82013-02-04 11:37:52 +010029#include "monitor/qdev.h"
pbrook87ecb682007-11-17 17:14:51 +000030#include "hw/usb.h"
Michael S. Tsirkina2cb15b2012-12-12 14:24:50 +020031#include "hw/pci/pci.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010032#include "sysemu/watchdog.h"
Gerd Hoffmann45a50b12009-10-01 16:42:33 +020033#include "hw/loader.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010034#include "exec/gdbstub.h"
Paolo Bonzini1422e322012-10-24 08:43:34 +020035#include "net/net.h"
Mark McLoughlin68ac40d2009-11-25 18:48:54 +000036#include "net/slirp.h"
Peter Xube933ff2018-03-26 14:38:56 +080037#include "chardev/char-mux.h"
Gerd Hoffmann75721502010-10-07 12:22:54 +020038#include "ui/qemu-spice.h"
Eduardo Habkoste35704b2015-02-08 16:51:16 -020039#include "sysemu/numa.h"
Marc-André Lureau213dcb02016-12-12 20:22:24 +030040#include "qemu/config-file.h"
Markus Armbruster856dfd82019-05-23 16:35:06 +020041#include "qemu/ctype.h"
Paolo Bonzini28ecbae2012-11-28 12:06:30 +010042#include "ui/console.h"
Gerd Hoffmannc751a742013-12-04 15:02:28 +010043#include "ui/input.h"
pbrook87ecb682007-11-17 17:14:51 +000044#include "audio/audio.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020045#include "disas/disas.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010046#include "sysemu/balloon.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010047#include "qemu/timer.h"
Vincent Palatinb3946622017-01-10 11:59:55 +010048#include "sysemu/hw_accel.h"
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +000049#include "authz/list.h"
50#include "qapi/util.h"
Markus Armbruster14a48c12019-05-23 16:35:05 +020051#include "sysemu/tcg.h"
Paolo Bonzinibdee56f2013-04-02 18:28:41 +020052#include "sysemu/tpm.h"
Markus Armbruster452fcdb2018-02-01 12:18:39 +010053#include "qapi/qmp/qdict.h"
Markus Armbrustercc7a8ea2015-03-17 17:22:46 +010054#include "qapi/qmp/qerror.h"
Markus Armbrusterfc81fa12018-02-01 12:18:40 +010055#include "qapi/qmp/qstring.h"
Markus Armbrustera9c94272016-06-22 19:11:19 +020056#include "qom/object_interfaces.h"
Lluís31965ae2011-08-31 20:31:24 +020057#include "trace/control.h"
Pavel Butsykinbf957282015-09-10 18:38:59 +030058#include "monitor/hmp-target.h"
Lluís6d8a7642011-08-31 20:30:43 +020059#ifdef CONFIG_TRACE_SIMPLE
Lluís31965ae2011-08-31 20:31:24 +020060#include "trace/simple.h"
Prerna Saxena22890ab2010-06-24 17:04:53 +053061#endif
Paolo Bonzini022c62c2012-12-17 18:19:49 +010062#include "exec/memory.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010063#include "exec/exec-all.h"
Markus Armbruster922a01a2018-02-01 12:18:46 +010064#include "qemu/option.h"
Anthony Liguori48a32be2011-09-02 12:34:48 -050065#include "hmp.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010066#include "qemu/thread.h"
Hani Benhabilesb21631f2014-05-27 23:39:37 +010067#include "block/qapi.h"
Markus Armbrustereb815e22018-02-11 10:36:05 +010068#include "qapi/qapi-commands.h"
Markus Armbruster5d756482019-02-14 16:22:38 +010069#include "qapi/qapi-emit-events.h"
Markus Armbrustere688df62018-02-01 12:18:31 +010070#include "qapi/error.h"
Wenchao Xia43a14cf2014-06-18 08:43:31 +020071#include "qapi/qmp-event.h"
Markus Armbrustereb815e22018-02-11 10:36:05 +010072#include "qapi/qapi-introspect.h"
Paolo Bonzinid2528bd2017-03-03 12:01:16 +010073#include "sysemu/cpus.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020074#include "qemu/cutils.h"
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -040075#include "tcg/tcg.h"
ths6a5bd302007-12-03 17:05:38 +000076
Jason J. Hernea4538a52015-06-26 14:07:21 -040077#if defined(TARGET_S390X)
78#include "hw/s390x/storage-keys.h"
Claudio Imbrendaf860d492016-08-15 18:44:04 +020079#include "hw/s390x/storage-attributes.h"
Jason J. Hernea4538a52015-06-26 14:07:21 -040080#endif
81
Mark McLoughlinf07918f2009-07-22 09:11:40 +010082/* file descriptors passed via SCM_RIGHTS */
Anthony Liguoric227f092009-10-01 16:12:16 -050083typedef struct mon_fd_t mon_fd_t;
84struct mon_fd_t {
Mark McLoughlinf07918f2009-07-22 09:11:40 +010085 char *name;
86 int fd;
Anthony Liguoric227f092009-10-01 16:12:16 -050087 QLIST_ENTRY(mon_fd_t) next;
Mark McLoughlinf07918f2009-07-22 09:11:40 +010088};
89
Corey Bryantba1c0482012-08-14 16:43:43 -040090/* file descriptor associated with a file descriptor set */
91typedef struct MonFdsetFd MonFdsetFd;
92struct MonFdsetFd {
93 int fd;
94 bool removed;
95 char *opaque;
96 QLIST_ENTRY(MonFdsetFd) next;
97};
98
99/* file descriptor set containing fds passed via SCM_RIGHTS */
100typedef struct MonFdset MonFdset;
101struct MonFdset {
102 int64_t id;
103 QLIST_HEAD(, MonFdsetFd) fds;
Corey Bryantadb696f2012-08-14 16:43:47 -0400104 QLIST_HEAD(, MonFdsetFd) dup_fds;
Corey Bryantba1c0482012-08-14 16:43:43 -0400105 QLIST_ENTRY(MonFdset) next;
106};
107
Luiz Capitulino2dbc8db2010-05-26 16:13:09 -0300108/* QMP checker flags */
109#define QMP_ACCEPT_UNKNOWNS 1
110
Peter Xu47451462018-06-08 11:55:11 +0800111/* Protects mon_fdsets */
112static QemuMutex mon_fdsets_lock;
Paolo Bonzinib58deb32018-12-06 11:58:10 +0100113static QLIST_HEAD(, MonFdset) mon_fdsets;
Peter Xu47451462018-06-08 11:55:11 +0800114
Kevin Wolfa0cd5e12019-06-13 17:33:56 +0200115static HMPCommand hmp_info_cmds[];
bellard9dc39cb2004-03-14 21:38:27 +0000116
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200117char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
118 int64_t cpu_index, Error **errp)
Luiz Capitulino0268d972010-10-22 10:08:02 -0200119{
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200120 char *output = NULL;
Kevin Wolfb6c7c2e2019-06-13 17:33:52 +0200121 Monitor *old_mon;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200122 MonitorHMP hmp = {};
Luiz Capitulino0268d972010-10-22 10:08:02 -0200123
Kevin Wolf92082412019-06-13 17:34:03 +0200124 monitor_data_init(&hmp.common, false, true, false);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200125
126 old_mon = cur_mon;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200127 cur_mon = &hmp.common;
Luiz Capitulino0268d972010-10-22 10:08:02 -0200128
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200129 if (has_cpu_index) {
130 int ret = monitor_set_cpu(cpu_index);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200131 if (ret < 0) {
132 cur_mon = old_mon;
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100133 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
134 "a CPU number");
Luiz Capitulino0268d972010-10-22 10:08:02 -0200135 goto out;
136 }
137 }
138
Markus Armbruster7ef6cf62015-03-06 19:12:36 +0100139 handle_hmp_command(&hmp, command_line);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200140 cur_mon = old_mon;
141
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200142 qemu_mutex_lock(&hmp.common.mon_lock);
143 if (qstring_get_length(hmp.common.outbuf) > 0) {
144 output = g_strdup(qstring_get_str(hmp.common.outbuf));
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200145 } else {
146 output = g_strdup("");
Luiz Capitulino0268d972010-10-22 10:08:02 -0200147 }
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200148 qemu_mutex_unlock(&hmp.common.mon_lock);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200149
150out:
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200151 monitor_data_destroy(&hmp.common);
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200152 return output;
Luiz Capitulino0268d972010-10-22 10:08:02 -0200153}
154
Kevin Wolfed7bda52019-06-13 17:34:01 +0200155/**
156 * Is @name in the '|' separated list of names @list?
157 */
158int hmp_compare_cmd(const char *name, const char *list)
bellard9dc39cb2004-03-14 21:38:27 +0000159{
160 const char *p, *pstart;
161 int len;
162 len = strlen(name);
163 p = list;
Kevin Wolfed7bda52019-06-13 17:34:01 +0200164 for (;;) {
bellard9dc39cb2004-03-14 21:38:27 +0000165 pstart = p;
Keno Fischer5c99fa32018-06-29 12:32:10 +0200166 p = qemu_strchrnul(p, '|');
Kevin Wolfed7bda52019-06-13 17:34:01 +0200167 if ((p - pstart) == len && !memcmp(pstart, name, len)) {
bellard9dc39cb2004-03-14 21:38:27 +0000168 return 1;
Wenchao Xiaf5438c02013-08-27 20:38:21 +0800169 }
170 if (*p == '\0') {
171 break;
172 }
Kevin Wolfed7bda52019-06-13 17:34:01 +0200173 p++;
Wenchao Xiaf5438c02013-08-27 20:38:21 +0800174 }
Wenchao Xiadcc70cd2013-08-27 20:38:22 +0800175 return 0;
bellard9dc39cb2004-03-14 21:38:27 +0000176}
177
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300178static void do_help_cmd(Monitor *mon, const QDict *qdict)
Luiz Capitulino38183182009-08-28 15:27:08 -0300179{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300180 help_cmd(mon, qdict_get_try_str(qdict, "name"));
Luiz Capitulino38183182009-08-28 15:27:08 -0300181}
182
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100183static void hmp_trace_event(Monitor *mon, const QDict *qdict)
Prerna Saxena22890ab2010-06-24 17:04:53 +0530184{
185 const char *tp_name = qdict_get_str(qdict, "name");
186 bool new_state = qdict_get_bool(qdict, "option");
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200187 bool has_vcpu = qdict_haskey(qdict, "vcpu");
188 int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
Lluís Vilanova14101d02014-08-25 13:20:03 +0200189 Error *local_err = NULL;
Blue Swirlf871d682010-10-13 19:14:29 +0000190
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200191 if (vcpu < 0) {
192 monitor_printf(mon, "argument vcpu must be positive");
193 return;
194 }
195
196 qmp_trace_event_set_state(tp_name, new_state, true, true, has_vcpu, vcpu, &local_err);
Lluís Vilanova14101d02014-08-25 13:20:03 +0200197 if (local_err) {
Markus Armbruster091e38b2015-02-10 15:15:43 +0100198 error_report_err(local_err);
Blue Swirlf871d682010-10-13 19:14:29 +0000199 }
Prerna Saxena22890ab2010-06-24 17:04:53 +0530200}
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100201
Michael Rothc45a8162011-10-02 08:44:37 -0500202#ifdef CONFIG_TRACE_SIMPLE
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100203static void hmp_trace_file(Monitor *mon, const QDict *qdict)
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100204{
205 const char *op = qdict_get_try_str(qdict, "op");
206 const char *arg = qdict_get_try_str(qdict, "arg");
207
208 if (!op) {
Markus Armbrusterba4912c2019-04-17 21:17:50 +0200209 st_print_trace_file_status();
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100210 } else if (!strcmp(op, "on")) {
211 st_set_trace_file_enabled(true);
212 } else if (!strcmp(op, "off")) {
213 st_set_trace_file_enabled(false);
214 } else if (!strcmp(op, "flush")) {
215 st_flush_trace_buffer();
216 } else if (!strcmp(op, "set")) {
217 if (arg) {
218 st_set_trace_file(arg);
219 }
220 } else {
221 monitor_printf(mon, "unexpected argument \"%s\"\n", op);
222 help_cmd(mon, "trace-file");
223 }
224}
Prerna Saxena22890ab2010-06-24 17:04:53 +0530225#endif
226
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100227static void hmp_info_help(Monitor *mon, const QDict *qdict)
bellard9dc39cb2004-03-14 21:38:27 +0000228{
Luiz Capitulino13c74252009-10-07 13:41:55 -0300229 help_cmd(mon, "info");
bellard9dc39cb2004-03-14 21:38:27 +0000230}
231
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400232static void query_commands_cb(QmpCommand *cmd, void *opaque)
bellard9bc9d1c2004-10-10 15:15:51 +0000233{
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400234 CommandInfoList *info, **list = opaque;
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200235
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400236 if (!cmd->enabled) {
237 return;
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200238 }
239
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400240 info = g_malloc0(sizeof(*info));
241 info->value = g_malloc0(sizeof(*info->value));
242 info->value->name = g_strdup(cmd->name);
243 info->next = *list;
244 *list = info;
245}
246
247CommandInfoList *qmp_query_commands(Error **errp)
248{
249 CommandInfoList *list = NULL;
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200250 MonitorQMP *mon;
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400251
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200252 assert(monitor_is_qmp(cur_mon));
253 mon = container_of(cur_mon, MonitorQMP, common);
254
255 qmp_for_each_command(mon->commands, query_commands_cb, &list);
Marc-André Lureau9e812b62016-09-12 13:19:05 +0400256
257 return list;
thsa36e69d2007-12-02 05:18:19 +0000258}
259
Daniel P. Berrange48608532012-05-21 17:59:51 +0100260EventInfoList *qmp_query_events(Error **errp)
261{
Markus Armbruster9d7b7082019-02-14 16:22:50 +0100262 /*
263 * TODO This deprecated command is the only user of
264 * QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes,
265 * they should go, too.
266 */
Daniel P. Berrange48608532012-05-21 17:59:51 +0100267 EventInfoList *info, *ev_list = NULL;
Wenchao Xia75175172014-06-18 08:43:54 +0200268 QAPIEvent e;
Daniel P. Berrange48608532012-05-21 17:59:51 +0100269
Eric Blake7fb1cf12015-11-18 01:52:57 -0700270 for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
Markus Armbruster977c7362017-08-24 10:46:08 +0200271 const char *event_name = QAPIEvent_str(e);
Daniel P. Berrange48608532012-05-21 17:59:51 +0100272 assert(event_name != NULL);
273 info = g_malloc0(sizeof(*info));
274 info->value = g_malloc0(sizeof(*info->value));
275 info->value->name = g_strdup(event_name);
276
277 info->next = ev_list;
278 ev_list = info;
279 }
280
281 return ev_list;
282}
283
Markus Armbruster39a18152015-09-16 13:06:28 +0200284/*
285 * Minor hack: generated marshalling suppressed for this command
286 * ('gen': false in the schema) so we can parse the JSON string
287 * directly into QObject instead of first parsing it with
288 * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it
289 * to QObject with generated output marshallers, every time. Instead,
Daniel P. Berrangeb3db2112016-09-30 15:45:27 +0100290 * we do it in test-qobject-input-visitor.c, just to make sure
Markus Armbrusterfb0bc832018-02-26 13:48:58 -0600291 * qapi-gen.py's output actually conforms to the schema.
Markus Armbruster39a18152015-09-16 13:06:28 +0200292 */
293static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
294 Error **errp)
295{
Marc-André Lureau7d0f9822018-03-05 18:29:51 +0100296 *ret_data = qobject_from_qlit(&qmp_schema_qlit);
Markus Armbruster39a18152015-09-16 13:06:28 +0200297}
298
Peter Xu6adf08d2018-03-09 16:59:50 +0800299static void monitor_init_qmp_commands(void)
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400300{
Markus Armbruster635db182017-03-03 13:32:27 +0100301 /*
302 * Two command lists:
303 * - qmp_commands contains all QMP commands
304 * - qmp_cap_negotiation_commands contains just
305 * "qmp_capabilities", to enforce capability negotiation
306 */
307
Markus Armbruster1527bad2017-03-03 13:32:25 +0100308 qmp_init_marshal(&qmp_commands);
Markus Armbruster05875682017-03-03 13:32:24 +0100309
Markus Armbruster1527bad2017-03-03 13:32:25 +0100310 qmp_register_command(&qmp_commands, "query-qmp-schema",
Igor Mammedovd6fe3d02018-05-11 18:51:43 +0200311 qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
Markus Armbruster1527bad2017-03-03 13:32:25 +0100312 qmp_register_command(&qmp_commands, "device_add", qmp_device_add,
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400313 QCO_NO_OPTIONS);
Markus Armbruster1527bad2017-03-03 13:32:25 +0100314 qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400315 QCO_NO_OPTIONS);
Marc-André Lureau5032a162016-09-12 13:19:02 +0400316
Markus Armbruster635db182017-03-03 13:32:27 +0100317 QTAILQ_INIT(&qmp_cap_negotiation_commands);
318 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
Igor Mammedovd6fe3d02018-05-11 18:51:43 +0200319 qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
Markus Armbruster635db182017-03-03 13:32:27 +0100320}
321
Peter Xucf869d52018-03-10 20:38:05 -0600322/*
Markus Armbruster279f9e02018-07-03 10:53:56 +0200323 * Accept QMP capabilities in @list for @mon.
324 * On success, set mon->qmp.capab[], and return true.
325 * On error, set @errp, and return false.
Peter Xucf869d52018-03-10 20:38:05 -0600326 */
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200327static bool qmp_caps_accept(MonitorQMP *mon, QMPCapabilityList *list,
Markus Armbruster279f9e02018-07-03 10:53:56 +0200328 Error **errp)
Peter Xucf869d52018-03-10 20:38:05 -0600329{
Markus Armbruster279f9e02018-07-03 10:53:56 +0200330 GString *unavailable = NULL;
331 bool capab[QMP_CAPABILITY__MAX];
Peter Xucf869d52018-03-10 20:38:05 -0600332
Markus Armbruster279f9e02018-07-03 10:53:56 +0200333 memset(capab, 0, sizeof(capab));
334
Peter Xu02130312018-03-09 16:59:53 +0800335 for (; list; list = list->next) {
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200336 if (!mon->capab_offered[list->value]) {
Markus Armbruster279f9e02018-07-03 10:53:56 +0200337 if (!unavailable) {
338 unavailable = g_string_new(QMPCapability_str(list->value));
339 } else {
340 g_string_append_printf(unavailable, ", %s",
341 QMPCapability_str(list->value));
Peter Xu02130312018-03-09 16:59:53 +0800342 }
Peter Xu02130312018-03-09 16:59:53 +0800343 }
Markus Armbruster279f9e02018-07-03 10:53:56 +0200344 capab[list->value] = true;
Peter Xu02130312018-03-09 16:59:53 +0800345 }
Peter Xu02130312018-03-09 16:59:53 +0800346
Markus Armbruster279f9e02018-07-03 10:53:56 +0200347 if (unavailable) {
348 error_setg(errp, "Capability %s not available", unavailable->str);
349 g_string_free(unavailable, true);
Peter Xucf869d52018-03-10 20:38:05 -0600350 return false;
351 }
352
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200353 memcpy(mon->capab, capab, sizeof(capab));
Peter Xucf869d52018-03-10 20:38:05 -0600354 return true;
355}
356
Peter Xu02130312018-03-09 16:59:53 +0800357void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable,
358 Error **errp)
359{
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200360 MonitorQMP *mon;
361
362 assert(monitor_is_qmp(cur_mon));
363 mon = container_of(cur_mon, MonitorQMP, common);
364
365 if (mon->commands == &qmp_commands) {
Markus Armbruster635db182017-03-03 13:32:27 +0100366 error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
367 "Capabilities negotiation is already complete, command "
368 "ignored");
369 return;
370 }
371
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200372 if (!qmp_caps_accept(mon, enable, errp)) {
Markus Armbruster279f9e02018-07-03 10:53:56 +0200373 return;
Peter Xu02130312018-03-09 16:59:53 +0800374 }
375
Kevin Wolfb8e31d62019-06-13 17:33:53 +0200376 mon->commands = &qmp_commands;
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400377}
378
Peter Xud9f25282018-06-08 11:55:07 +0800379/* Set the current CPU defined by the user. Callers must hold BQL. */
Luiz Capitulinob025c8b2011-10-06 14:02:57 -0300380int monitor_set_cpu(int cpu_index)
bellard6a00d602005-11-21 23:25:50 +0000381{
Andreas Färber55e5c282012-12-17 06:18:02 +0100382 CPUState *cpu;
bellard6a00d602005-11-21 23:25:50 +0000383
Andreas Färber1c8bb3c2013-02-15 17:01:09 +0100384 cpu = qemu_get_cpu(cpu_index);
385 if (cpu == NULL) {
386 return -1;
bellard6a00d602005-11-21 23:25:50 +0000387 }
Greg Kurz751f8cf2017-10-17 10:16:22 +0200388 g_free(cur_mon->mon_cpu_path);
389 cur_mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
Andreas Färber1c8bb3c2013-02-15 17:01:09 +0100390 return 0;
bellard6a00d602005-11-21 23:25:50 +0000391}
392
Peter Xud9f25282018-06-08 11:55:07 +0800393/* Callers must hold BQL. */
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100394static CPUState *mon_get_cpu_sync(bool synchronize)
bellard6a00d602005-11-21 23:25:50 +0000395{
Greg Kurz751f8cf2017-10-17 10:16:22 +0200396 CPUState *cpu;
397
398 if (cur_mon->mon_cpu_path) {
399 cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path,
400 TYPE_CPU, NULL);
401 if (!cpu) {
402 g_free(cur_mon->mon_cpu_path);
403 cur_mon->mon_cpu_path = NULL;
404 }
405 }
406 if (!cur_mon->mon_cpu_path) {
Thomas Huth854e67f2017-01-13 13:12:35 +0100407 if (!first_cpu) {
408 return NULL;
409 }
David Gibson27a83f82016-09-21 15:29:26 +1000410 monitor_set_cpu(first_cpu->cpu_index);
Greg Kurz751f8cf2017-10-17 10:16:22 +0200411 cpu = first_cpu;
bellard6a00d602005-11-21 23:25:50 +0000412 }
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100413 if (synchronize) {
414 cpu_synchronize_state(cpu);
415 }
Greg Kurz751f8cf2017-10-17 10:16:22 +0200416 return cpu;
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -0700417}
418
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100419CPUState *mon_get_cpu(void)
420{
421 return mon_get_cpu_sync(true);
422}
423
Pavel Butsykinbf957282015-09-10 18:38:59 +0300424CPUArchState *mon_get_cpu_env(void)
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -0700425{
Thomas Huth854e67f2017-01-13 13:12:35 +0100426 CPUState *cs = mon_get_cpu();
427
428 return cs ? cs->env_ptr : NULL;
bellard6a00d602005-11-21 23:25:50 +0000429}
430
Luiz Capitulino99b77962011-10-24 10:53:44 -0200431int monitor_get_cpu_index(void)
432{
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100433 CPUState *cs = mon_get_cpu_sync(false);
Thomas Huth854e67f2017-01-13 13:12:35 +0100434
435 return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
Luiz Capitulino99b77962011-10-24 10:53:44 -0200436}
437
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100438static void hmp_info_registers(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000439{
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000440 bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false);
441 CPUState *cs;
Thomas Huth854e67f2017-01-13 13:12:35 +0100442
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000443 if (all_cpus) {
444 CPU_FOREACH(cs) {
445 monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
Markus Armbruster90c84c52019-04-17 21:18:02 +0200446 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000447 }
448 } else {
449 cs = mon_get_cpu();
450
451 if (!cs) {
452 monitor_printf(mon, "No CPU available\n");
453 return;
454 }
455
Markus Armbruster90c84c52019-04-17 21:18:02 +0200456 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
Thomas Huth854e67f2017-01-13 13:12:35 +0100457 }
bellard9307c4c2004-04-04 12:57:25 +0000458}
459
Paolo Bonzinif0d14a92012-09-17 13:42:41 +0200460#ifdef CONFIG_TCG
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100461static void hmp_info_jit(Monitor *mon, const QDict *qdict)
bellarde3db7222005-01-26 22:00:47 +0000462{
Thomas Huthb7da97e2017-04-26 06:11:47 +0200463 if (!tcg_enabled()) {
464 error_report("JIT information is only available with accel=tcg");
465 return;
466 }
467
Markus Armbruster3de2faa2019-04-17 21:17:52 +0200468 dump_exec_info();
Markus Armbruster76c86612019-04-17 21:17:53 +0200469 dump_drift_info();
bellarde3db7222005-01-26 22:00:47 +0000470}
471
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100472static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
Max Filippov246ae242014-11-02 11:04:18 +0300473{
Markus Armbrusterd4c51a02019-04-17 21:17:51 +0200474 dump_opcount_info();
Max Filippov246ae242014-11-02 11:04:18 +0300475}
Paolo Bonzinif0d14a92012-09-17 13:42:41 +0200476#endif
Max Filippov246ae242014-11-02 11:04:18 +0300477
Emilio G. Cota97bfafe2017-08-08 13:54:42 -0400478static void hmp_info_sync_profile(Monitor *mon, const QDict *qdict)
479{
480 int64_t max = qdict_get_try_int(qdict, "max", 10);
481 bool mean = qdict_get_try_bool(qdict, "mean", false);
482 bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false);
483 enum QSPSortBy sort_by;
484
485 sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME;
Markus Armbrusterac7ff4c2019-04-17 21:17:54 +0200486 qsp_report(max, sort_by, coalesce);
Emilio G. Cota97bfafe2017-08-08 13:54:42 -0400487}
488
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100489static void hmp_info_history(Monitor *mon, const QDict *qdict)
bellardaa455482004-04-04 13:07:25 +0000490{
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200491 MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
bellardaa455482004-04-04 13:07:25 +0000492 int i;
bellard7e2515e2004-08-01 21:52:19 +0000493 const char *str;
ths3b46e622007-09-17 08:09:54 +0000494
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200495 if (!hmp_mon->rs) {
aliguoricde76ee2009-03-05 23:01:51 +0000496 return;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200497 }
bellard7e2515e2004-08-01 21:52:19 +0000498 i = 0;
499 for(;;) {
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200500 str = readline_get_history(hmp_mon->rs, i);
501 if (!str) {
bellard7e2515e2004-08-01 21:52:19 +0000502 break;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200503 }
aliguori376253e2009-03-05 23:01:23 +0000504 monitor_printf(mon, "%d: '%s'\n", i, str);
bellard8e3a9fd2004-10-09 17:32:58 +0000505 i++;
bellardaa455482004-04-04 13:07:25 +0000506 }
507}
508
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100509static void hmp_info_cpustats(Monitor *mon, const QDict *qdict)
j_mayer76a66252007-03-07 08:32:30 +0000510{
Thomas Huth854e67f2017-01-13 13:12:35 +0100511 CPUState *cs = mon_get_cpu();
512
513 if (!cs) {
514 monitor_printf(mon, "No CPU available\n");
515 return;
516 }
Markus Armbruster11cb6c12019-04-17 21:18:00 +0200517 cpu_dump_statistics(cs, 0);
j_mayer76a66252007-03-07 08:32:30 +0000518}
j_mayer76a66252007-03-07 08:32:30 +0000519
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100520static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
Prerna Saxena22890ab2010-06-24 17:04:53 +0530521{
Lluís Vilanovabd712112016-07-11 12:53:51 +0200522 const char *name = qdict_get_try_str(qdict, "name");
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200523 bool has_vcpu = qdict_haskey(qdict, "vcpu");
524 int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
Lluís Vilanovabd712112016-07-11 12:53:51 +0200525 TraceEventInfoList *events;
Lluís Vilanova14101d02014-08-25 13:20:03 +0200526 TraceEventInfoList *elem;
Lluís Vilanovabd712112016-07-11 12:53:51 +0200527 Error *local_err = NULL;
528
529 if (name == NULL) {
530 name = "*";
531 }
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200532 if (vcpu < 0) {
533 monitor_printf(mon, "argument vcpu must be positive");
534 return;
535 }
Lluís Vilanovabd712112016-07-11 12:53:51 +0200536
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200537 events = qmp_trace_event_get_state(name, has_vcpu, vcpu, &local_err);
Lluís Vilanovabd712112016-07-11 12:53:51 +0200538 if (local_err) {
539 error_report_err(local_err);
540 return;
541 }
Lluís Vilanova14101d02014-08-25 13:20:03 +0200542
543 for (elem = events; elem != NULL; elem = elem->next) {
544 monitor_printf(mon, "%s : state %u\n",
545 elem->value->name,
546 elem->value->state == TRACE_EVENT_STATE_ENABLED ? 1 : 0);
547 }
548 qapi_free_TraceEventInfoList(events);
Prerna Saxena22890ab2010-06-24 17:04:53 +0530549}
Prerna Saxena22890ab2010-06-24 17:04:53 +0530550
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100551void qmp_client_migrate_info(const char *protocol, const char *hostname,
552 bool has_port, int64_t port,
553 bool has_tls_port, int64_t tls_port,
554 bool has_cert_subject, const char *cert_subject,
555 Error **errp)
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200556{
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200557 if (strcmp(protocol, "spice") == 0) {
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100558 if (!qemu_using_spice(errp)) {
559 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200560 }
561
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100562 if (!has_port && !has_tls_port) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100563 error_setg(errp, QERR_MISSING_PARAMETER, "port/tls-port");
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100564 return;
Yonit Halperin6ec5dae2012-03-18 09:42:39 +0200565 }
566
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100567 if (qemu_spice_migrate_info(hostname,
568 has_port ? port : -1,
569 has_tls_port ? tls_port : -1,
570 cert_subject)) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100571 error_setg(errp, QERR_UNDEFINED_ERROR);
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100572 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200573 }
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100574 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200575 }
576
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100577 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol", "spice");
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200578}
579
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100580static void hmp_logfile(Monitor *mon, const QDict *qdict)
pbrooke735b912007-06-30 13:53:24 +0000581{
Markus Armbrusterdaa76aa2016-06-15 19:27:16 +0200582 Error *err = NULL;
583
584 qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err);
585 if (err) {
586 error_report_err(err);
587 }
pbrooke735b912007-06-30 13:53:24 +0000588}
589
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100590static void hmp_log(Monitor *mon, const QDict *qdict)
bellardf193c792004-03-21 17:06:25 +0000591{
592 int mask;
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300593 const char *items = qdict_get_str(qdict, "items");
ths3b46e622007-09-17 08:09:54 +0000594
bellard9307c4c2004-04-04 12:57:25 +0000595 if (!strcmp(items, "none")) {
bellardf193c792004-03-21 17:06:25 +0000596 mask = 0;
597 } else {
Peter Maydell4fde1eb2013-02-11 16:41:22 +0000598 mask = qemu_str_to_log_mask(items);
bellardf193c792004-03-21 17:06:25 +0000599 if (!mask) {
aliguori376253e2009-03-05 23:01:23 +0000600 help_cmd(mon, "log");
bellardf193c792004-03-21 17:06:25 +0000601 return;
602 }
603 }
Peter Maydell24537a02013-02-11 16:41:23 +0000604 qemu_set_log(mask);
bellardf193c792004-03-21 17:06:25 +0000605}
606
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100607static void hmp_singlestep(Monitor *mon, const QDict *qdict)
aurel321b530a62009-04-05 20:08:59 +0000608{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300609 const char *option = qdict_get_try_str(qdict, "option");
aurel321b530a62009-04-05 20:08:59 +0000610 if (!option || !strcmp(option, "on")) {
611 singlestep = 1;
612 } else if (!strcmp(option, "off")) {
613 singlestep = 0;
614 } else {
615 monitor_printf(mon, "unexpected option %s\n", option);
616 }
617}
618
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100619static void hmp_gdbserver(Monitor *mon, const QDict *qdict)
bellard8a7ddc32004-03-31 19:00:16 +0000620{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300621 const char *device = qdict_get_try_str(qdict, "device");
aliguori59030a82009-04-05 18:43:41 +0000622 if (!device)
623 device = "tcp::" DEFAULT_GDBSTUB_PORT;
624 if (gdbserver_start(device) < 0) {
625 monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
626 device);
627 } else if (strcmp(device, "none") == 0) {
aliguori36556b22009-03-28 18:05:53 +0000628 monitor_printf(mon, "Disabled gdbserver\n");
bellard8a7ddc32004-03-31 19:00:16 +0000629 } else {
aliguori59030a82009-04-05 18:43:41 +0000630 monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
631 device);
bellard8a7ddc32004-03-31 19:00:16 +0000632 }
633}
634
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100635static void hmp_watchdog_action(Monitor *mon, const QDict *qdict)
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +0100636{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300637 const char *action = qdict_get_str(qdict, "action");
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +0100638 if (select_watchdog_action(action) == -1) {
639 monitor_printf(mon, "Unknown watchdog action '%s'\n", action);
640 }
641}
642
aliguori376253e2009-03-05 23:01:23 +0000643static void monitor_printc(Monitor *mon, int c)
bellard9307c4c2004-04-04 12:57:25 +0000644{
aliguori376253e2009-03-05 23:01:23 +0000645 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +0000646 switch(c) {
647 case '\'':
aliguori376253e2009-03-05 23:01:23 +0000648 monitor_printf(mon, "\\'");
bellard9307c4c2004-04-04 12:57:25 +0000649 break;
650 case '\\':
aliguori376253e2009-03-05 23:01:23 +0000651 monitor_printf(mon, "\\\\");
bellard9307c4c2004-04-04 12:57:25 +0000652 break;
653 case '\n':
aliguori376253e2009-03-05 23:01:23 +0000654 monitor_printf(mon, "\\n");
bellard9307c4c2004-04-04 12:57:25 +0000655 break;
656 case '\r':
aliguori376253e2009-03-05 23:01:23 +0000657 monitor_printf(mon, "\\r");
bellard9307c4c2004-04-04 12:57:25 +0000658 break;
659 default:
660 if (c >= 32 && c <= 126) {
aliguori376253e2009-03-05 23:01:23 +0000661 monitor_printf(mon, "%c", c);
bellard9307c4c2004-04-04 12:57:25 +0000662 } else {
aliguori376253e2009-03-05 23:01:23 +0000663 monitor_printf(mon, "\\x%02x", c);
bellard9307c4c2004-04-04 12:57:25 +0000664 }
665 break;
666 }
aliguori376253e2009-03-05 23:01:23 +0000667 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +0000668}
669
aliguori376253e2009-03-05 23:01:23 +0000670static void memory_dump(Monitor *mon, int count, int format, int wsize,
Avi Kivitya8170e52012-10-23 12:30:10 +0200671 hwaddr addr, int is_physical)
bellard9307c4c2004-04-04 12:57:25 +0000672{
Blue Swirl23842aa2010-01-12 20:27:43 +0000673 int l, line_size, i, max_digits, len;
bellard9307c4c2004-04-04 12:57:25 +0000674 uint8_t buf[16];
675 uint64_t v;
Thomas Huth854e67f2017-01-13 13:12:35 +0100676 CPUState *cs = mon_get_cpu();
677
678 if (!cs && (format == 'i' || !is_physical)) {
679 monitor_printf(mon, "Can not dump without CPU\n");
680 return;
681 }
bellard9307c4c2004-04-04 12:57:25 +0000682
683 if (format == 'i') {
Richard Henderson1d484742017-09-14 08:38:35 -0700684 monitor_disas(mon, cs, addr, count, is_physical);
bellard9307c4c2004-04-04 12:57:25 +0000685 return;
686 }
687
688 len = wsize * count;
689 if (wsize == 1)
690 line_size = 8;
691 else
692 line_size = 16;
bellard9307c4c2004-04-04 12:57:25 +0000693 max_digits = 0;
694
695 switch(format) {
696 case 'o':
Marc-André Lureau69db8df2017-06-22 13:04:16 +0200697 max_digits = DIV_ROUND_UP(wsize * 8, 3);
bellard9307c4c2004-04-04 12:57:25 +0000698 break;
699 default:
700 case 'x':
701 max_digits = (wsize * 8) / 4;
702 break;
703 case 'u':
704 case 'd':
Marc-André Lureau69db8df2017-06-22 13:04:16 +0200705 max_digits = DIV_ROUND_UP(wsize * 8 * 10, 33);
bellard9307c4c2004-04-04 12:57:25 +0000706 break;
707 case 'c':
708 wsize = 1;
709 break;
710 }
711
712 while (len > 0) {
blueswir17743e582007-09-24 18:39:04 +0000713 if (is_physical)
aliguori376253e2009-03-05 23:01:23 +0000714 monitor_printf(mon, TARGET_FMT_plx ":", addr);
blueswir17743e582007-09-24 18:39:04 +0000715 else
aliguori376253e2009-03-05 23:01:23 +0000716 monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
bellard9307c4c2004-04-04 12:57:25 +0000717 l = len;
718 if (l > line_size)
719 l = line_size;
720 if (is_physical) {
Peter Maydell6f89ae52018-12-14 13:30:49 +0000721 AddressSpace *as = cs ? cs->as : &address_space_memory;
722 MemTxResult r = address_space_read(as, addr,
723 MEMTXATTRS_UNSPECIFIED, buf, l);
724 if (r != MEMTX_OK) {
725 monitor_printf(mon, " Cannot access memory\n");
726 break;
727 }
bellard9307c4c2004-04-04 12:57:25 +0000728 } else {
Thomas Huth854e67f2017-01-13 13:12:35 +0100729 if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
aliguori376253e2009-03-05 23:01:23 +0000730 monitor_printf(mon, " Cannot access memory\n");
aliguoric8f79b62008-08-18 14:00:20 +0000731 break;
732 }
bellard9307c4c2004-04-04 12:57:25 +0000733 }
ths5fafdf22007-09-16 21:08:06 +0000734 i = 0;
bellard9307c4c2004-04-04 12:57:25 +0000735 while (i < l) {
736 switch(wsize) {
737 default:
738 case 1:
Peter Maydell24e60302015-01-20 15:19:32 +0000739 v = ldub_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000740 break;
741 case 2:
Peter Maydell24e60302015-01-20 15:19:32 +0000742 v = lduw_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000743 break;
744 case 4:
Peter Maydell24e60302015-01-20 15:19:32 +0000745 v = (uint32_t)ldl_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000746 break;
747 case 8:
Peter Maydell24e60302015-01-20 15:19:32 +0000748 v = ldq_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000749 break;
750 }
aliguori376253e2009-03-05 23:01:23 +0000751 monitor_printf(mon, " ");
bellard9307c4c2004-04-04 12:57:25 +0000752 switch(format) {
753 case 'o':
aliguori376253e2009-03-05 23:01:23 +0000754 monitor_printf(mon, "%#*" PRIo64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000755 break;
756 case 'x':
aliguori376253e2009-03-05 23:01:23 +0000757 monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000758 break;
759 case 'u':
aliguori376253e2009-03-05 23:01:23 +0000760 monitor_printf(mon, "%*" PRIu64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000761 break;
762 case 'd':
aliguori376253e2009-03-05 23:01:23 +0000763 monitor_printf(mon, "%*" PRId64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000764 break;
765 case 'c':
aliguori376253e2009-03-05 23:01:23 +0000766 monitor_printc(mon, v);
bellard9307c4c2004-04-04 12:57:25 +0000767 break;
768 }
769 i += wsize;
770 }
aliguori376253e2009-03-05 23:01:23 +0000771 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000772 addr += l;
773 len -= l;
774 }
775}
776
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100777static void hmp_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000778{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300779 int count = qdict_get_int(qdict, "count");
780 int format = qdict_get_int(qdict, "format");
781 int size = qdict_get_int(qdict, "size");
782 target_long addr = qdict_get_int(qdict, "addr");
783
aliguori376253e2009-03-05 23:01:23 +0000784 memory_dump(mon, count, format, size, addr, 0);
bellard9307c4c2004-04-04 12:57:25 +0000785}
786
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100787static void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000788{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300789 int count = qdict_get_int(qdict, "count");
790 int format = qdict_get_int(qdict, "format");
791 int size = qdict_get_int(qdict, "size");
Avi Kivitya8170e52012-10-23 12:30:10 +0200792 hwaddr addr = qdict_get_int(qdict, "addr");
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300793
aliguori376253e2009-03-05 23:01:23 +0000794 memory_dump(mon, count, format, size, addr, 1);
bellard9307c4c2004-04-04 12:57:25 +0000795}
796
Paolo Bonzinie9628442017-04-20 15:30:58 +0200797static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
798{
799 MemoryRegionSection mrs = memory_region_find(get_system_memory(),
800 addr, 1);
801
802 if (!mrs.mr) {
803 error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
804 return NULL;
805 }
806
807 if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
808 error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr);
809 memory_region_unref(mrs.mr);
810 return NULL;
811 }
812
813 *p_mr = mrs.mr;
814 return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
815}
816
817static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
818{
819 hwaddr addr = qdict_get_int(qdict, "addr");
820 Error *local_err = NULL;
821 MemoryRegion *mr = NULL;
822 void *ptr;
823
824 ptr = gpa2hva(&mr, addr, &local_err);
825 if (local_err) {
826 error_report_err(local_err);
827 return;
828 }
829
830 monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
831 " (%s) is %p\n",
832 addr, mr->name, ptr);
833
834 memory_region_unref(mr);
835}
836
Dr. David Alan Gilbert574d9692019-04-12 16:26:52 +0100837static void hmp_gva2gpa(Monitor *mon, const QDict *qdict)
838{
839 target_ulong addr = qdict_get_int(qdict, "addr");
840 MemTxAttrs attrs;
841 CPUState *cs = mon_get_cpu();
842 hwaddr gpa;
843
844 if (!cs) {
845 monitor_printf(mon, "No cpu\n");
846 return;
847 }
848
Eduardo Habkost9d3250d2019-05-10 15:56:20 -0300849 gpa = cpu_get_phys_page_attrs_debug(cs, addr & TARGET_PAGE_MASK, &attrs);
Dr. David Alan Gilbert574d9692019-04-12 16:26:52 +0100850 if (gpa == -1) {
851 monitor_printf(mon, "Unmapped\n");
852 } else {
853 monitor_printf(mon, "gpa: %#" HWADDR_PRIx "\n",
854 gpa + (addr & ~TARGET_PAGE_MASK));
855 }
856}
857
Paolo Bonzinie9628442017-04-20 15:30:58 +0200858#ifdef CONFIG_LINUX
859static uint64_t vtop(void *ptr, Error **errp)
860{
861 uint64_t pinfo;
862 uint64_t ret = -1;
863 uintptr_t addr = (uintptr_t) ptr;
864 uintptr_t pagesize = getpagesize();
865 off_t offset = addr / pagesize * sizeof(pinfo);
866 int fd;
867
868 fd = open("/proc/self/pagemap", O_RDONLY);
869 if (fd == -1) {
870 error_setg_errno(errp, errno, "Cannot open /proc/self/pagemap");
871 return -1;
872 }
873
874 /* Force copy-on-write if necessary. */
875 atomic_add((uint8_t *)ptr, 0);
876
877 if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
878 error_setg_errno(errp, errno, "Cannot read pagemap");
879 goto out;
880 }
881 if ((pinfo & (1ull << 63)) == 0) {
882 error_setg(errp, "Page not present");
883 goto out;
884 }
885 ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
886
887out:
888 close(fd);
889 return ret;
890}
891
892static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
893{
894 hwaddr addr = qdict_get_int(qdict, "addr");
895 Error *local_err = NULL;
896 MemoryRegion *mr = NULL;
897 void *ptr;
898 uint64_t physaddr;
899
900 ptr = gpa2hva(&mr, addr, &local_err);
901 if (local_err) {
902 error_report_err(local_err);
903 return;
904 }
905
906 physaddr = vtop(ptr, &local_err);
907 if (local_err) {
908 error_report_err(local_err);
909 } else {
910 monitor_printf(mon, "Host physical address for 0x%" HWADDR_PRIx
911 " (%s) is 0x%" PRIx64 "\n",
912 addr, mr->name, (uint64_t) physaddr);
913 }
914
915 memory_region_unref(mr);
916}
917#endif
918
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300919static void do_print(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000920{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300921 int format = qdict_get_int(qdict, "format");
Avi Kivitya8170e52012-10-23 12:30:10 +0200922 hwaddr val = qdict_get_int(qdict, "val");
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300923
bellard9307c4c2004-04-04 12:57:25 +0000924 switch(format) {
925 case 'o':
Avi Kivitya8170e52012-10-23 12:30:10 +0200926 monitor_printf(mon, "%#" HWADDR_PRIo, val);
bellard9307c4c2004-04-04 12:57:25 +0000927 break;
928 case 'x':
Avi Kivitya8170e52012-10-23 12:30:10 +0200929 monitor_printf(mon, "%#" HWADDR_PRIx, val);
bellard9307c4c2004-04-04 12:57:25 +0000930 break;
931 case 'u':
Avi Kivitya8170e52012-10-23 12:30:10 +0200932 monitor_printf(mon, "%" HWADDR_PRIu, val);
bellard9307c4c2004-04-04 12:57:25 +0000933 break;
934 default:
935 case 'd':
Avi Kivitya8170e52012-10-23 12:30:10 +0200936 monitor_printf(mon, "%" HWADDR_PRId, val);
bellard9307c4c2004-04-04 12:57:25 +0000937 break;
938 case 'c':
aliguori376253e2009-03-05 23:01:23 +0000939 monitor_printc(mon, val);
bellard9307c4c2004-04-04 12:57:25 +0000940 break;
941 }
aliguori376253e2009-03-05 23:01:23 +0000942 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000943}
944
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100945static void hmp_sum(Monitor *mon, const QDict *qdict)
bellarde4cf1ad2005-06-04 20:15:57 +0000946{
947 uint32_t addr;
bellarde4cf1ad2005-06-04 20:15:57 +0000948 uint16_t sum;
Luiz Capitulinof18c16d2009-08-28 15:27:14 -0300949 uint32_t start = qdict_get_int(qdict, "start");
950 uint32_t size = qdict_get_int(qdict, "size");
bellarde4cf1ad2005-06-04 20:15:57 +0000951
952 sum = 0;
953 for(addr = start; addr < (start + size); addr++) {
Peter Maydell42874d32015-04-26 16:49:24 +0100954 uint8_t val = address_space_ldub(&address_space_memory, addr,
955 MEMTXATTRS_UNSPECIFIED, NULL);
bellarde4cf1ad2005-06-04 20:15:57 +0000956 /* BSD sum algorithm ('sum' Unix command) */
957 sum = (sum >> 1) | (sum << 15);
Stefan Weil54f7b4a2011-04-10 18:23:39 +0200958 sum += val;
bellarde4cf1ad2005-06-04 20:15:57 +0000959 }
aliguori376253e2009-03-05 23:01:23 +0000960 monitor_printf(mon, "%05d\n", sum);
bellarde4cf1ad2005-06-04 20:15:57 +0000961}
962
bellard13224a82006-07-14 22:03:35 +0000963static int mouse_button_state;
964
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100965static void hmp_mouse_move(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +0000966{
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100967 int dx, dy, dz, button;
Luiz Capitulino1d4daa92009-08-28 15:27:15 -0300968 const char *dx_str = qdict_get_str(qdict, "dx_str");
969 const char *dy_str = qdict_get_str(qdict, "dy_str");
970 const char *dz_str = qdict_get_try_str(qdict, "dz_str");
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100971
bellard13224a82006-07-14 22:03:35 +0000972 dx = strtol(dx_str, NULL, 0);
973 dy = strtol(dy_str, NULL, 0);
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100974 qemu_input_queue_rel(NULL, INPUT_AXIS_X, dx);
975 qemu_input_queue_rel(NULL, INPUT_AXIS_Y, dy);
976
977 if (dz_str) {
bellard13224a82006-07-14 22:03:35 +0000978 dz = strtol(dz_str, NULL, 0);
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100979 if (dz != 0) {
Gerd Hoffmannf22d0af2016-01-12 12:14:12 +0100980 button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100981 qemu_input_queue_btn(NULL, button, true);
982 qemu_input_event_sync();
983 qemu_input_queue_btn(NULL, button, false);
984 }
985 }
986 qemu_input_event_sync();
bellard13224a82006-07-14 22:03:35 +0000987}
988
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100989static void hmp_mouse_button(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +0000990{
Eric Blake7fb1cf12015-11-18 01:52:57 -0700991 static uint32_t bmap[INPUT_BUTTON__MAX] = {
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100992 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
993 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
994 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
995 };
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300996 int button_state = qdict_get_int(qdict, "button_state");
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100997
998 if (mouse_button_state == button_state) {
999 return;
1000 }
1001 qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state);
1002 qemu_input_event_sync();
bellard13224a82006-07-14 22:03:35 +00001003 mouse_button_state = button_state;
bellard13224a82006-07-14 22:03:35 +00001004}
1005
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001006static void hmp_ioport_read(Monitor *mon, const QDict *qdict)
bellard34405572004-06-08 00:55:58 +00001007{
Luiz Capitulinoaa93e392009-08-28 15:27:18 -03001008 int size = qdict_get_int(qdict, "size");
1009 int addr = qdict_get_int(qdict, "addr");
1010 int has_index = qdict_haskey(qdict, "index");
bellard34405572004-06-08 00:55:58 +00001011 uint32_t val;
1012 int suffix;
1013
1014 if (has_index) {
Luiz Capitulinoaa93e392009-08-28 15:27:18 -03001015 int index = qdict_get_int(qdict, "index");
Blue Swirlafcea8c2009-09-20 16:05:47 +00001016 cpu_outb(addr & IOPORTS_MASK, index & 0xff);
bellard34405572004-06-08 00:55:58 +00001017 addr++;
1018 }
1019 addr &= 0xffff;
1020
1021 switch(size) {
1022 default:
1023 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001024 val = cpu_inb(addr);
bellard34405572004-06-08 00:55:58 +00001025 suffix = 'b';
1026 break;
1027 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001028 val = cpu_inw(addr);
bellard34405572004-06-08 00:55:58 +00001029 suffix = 'w';
1030 break;
1031 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001032 val = cpu_inl(addr);
bellard34405572004-06-08 00:55:58 +00001033 suffix = 'l';
1034 break;
1035 }
aliguori376253e2009-03-05 23:01:23 +00001036 monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
1037 suffix, addr, size * 2, val);
bellard34405572004-06-08 00:55:58 +00001038}
bellarda3a91a32004-06-04 11:06:21 +00001039
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001040static void hmp_ioport_write(Monitor *mon, const QDict *qdict)
Jan Kiszkaf1147842009-07-14 10:20:11 +02001041{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001042 int size = qdict_get_int(qdict, "size");
1043 int addr = qdict_get_int(qdict, "addr");
1044 int val = qdict_get_int(qdict, "val");
1045
Jan Kiszkaf1147842009-07-14 10:20:11 +02001046 addr &= IOPORTS_MASK;
1047
1048 switch (size) {
1049 default:
1050 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001051 cpu_outb(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001052 break;
1053 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001054 cpu_outw(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001055 break;
1056 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001057 cpu_outl(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001058 break;
1059 }
1060}
1061
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001062static void hmp_boot_set(Monitor *mon, const QDict *qdict)
aurel320ecdffb2008-05-04 20:11:34 +00001063{
Gongleif1839932014-12-03 18:20:58 +00001064 Error *local_err = NULL;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001065 const char *bootdevice = qdict_get_str(qdict, "bootdevice");
aurel320ecdffb2008-05-04 20:11:34 +00001066
Gongleif1839932014-12-03 18:20:58 +00001067 qemu_boot_set(bootdevice, &local_err);
1068 if (local_err) {
Markus Armbruster193227f2015-12-18 16:35:06 +01001069 error_report_err(local_err);
aurel320ecdffb2008-05-04 20:11:34 +00001070 } else {
Gongleif1839932014-12-03 18:20:58 +00001071 monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
aurel320ecdffb2008-05-04 20:11:34 +00001072 }
1073}
1074
Markus Armbruster1ce6be22015-02-06 14:18:24 +01001075static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
Blue Swirl314e2982011-09-11 20:22:05 +00001076{
Peter Xu57bb40c2017-01-16 16:40:05 +08001077 bool flatview = qdict_get_try_bool(qdict, "flatview", false);
Alexey Kardashevskiy5e8fd942017-09-21 18:51:06 +10001078 bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
Alexey Kardashevskiyfc051ae2018-06-04 13:25:11 +10001079 bool owner = qdict_get_try_bool(qdict, "owner", false);
Peter Xu57bb40c2017-01-16 16:40:05 +08001080
Markus Armbrusterb6b71cb2019-04-17 21:17:56 +02001081 mtree_info(flatview, dispatch_tree, owner);
Blue Swirl314e2982011-09-11 20:22:05 +00001082}
1083
Markus Armbruster1ce6be22015-02-06 14:18:24 +01001084static void hmp_info_numa(Monitor *mon, const QDict *qdict)
aliguori030ea372009-04-21 22:30:47 +00001085{
aliguorib28b6232009-04-22 20:20:29 +00001086 int i;
Vadim Galitsyn31959e82017-08-29 17:30:20 +02001087 NumaNodeMem *node_mem;
Igor Mammedovf75cd442017-05-30 18:23:59 +02001088 CpuInfoList *cpu_list, *cpu;
aliguori030ea372009-04-21 22:30:47 +00001089
Igor Mammedovf75cd442017-05-30 18:23:59 +02001090 cpu_list = qmp_query_cpus(&error_abort);
Vadim Galitsyn31959e82017-08-29 17:30:20 +02001091 node_mem = g_new0(NumaNodeMem, nb_numa_nodes);
1092
zhanghailiang5b009e42014-11-04 19:49:30 +08001093 query_numa_node_mem(node_mem);
aliguori030ea372009-04-21 22:30:47 +00001094 monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
1095 for (i = 0; i < nb_numa_nodes; i++) {
1096 monitor_printf(mon, "node %d cpus:", i);
Igor Mammedovf75cd442017-05-30 18:23:59 +02001097 for (cpu = cpu_list; cpu; cpu = cpu->next) {
1098 if (cpu->value->has_props && cpu->value->props->has_node_id &&
1099 cpu->value->props->node_id == i) {
1100 monitor_printf(mon, " %" PRIi64, cpu->value->CPU);
aliguori030ea372009-04-21 22:30:47 +00001101 }
1102 }
1103 monitor_printf(mon, "\n");
1104 monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
Vadim Galitsyn31959e82017-08-29 17:30:20 +02001105 node_mem[i].node_mem >> 20);
1106 monitor_printf(mon, "node %d plugged: %" PRId64 " MB\n", i,
1107 node_mem[i].node_plugged_mem >> 20);
aliguori030ea372009-04-21 22:30:47 +00001108 }
Igor Mammedovf75cd442017-05-30 18:23:59 +02001109 qapi_free_CpuInfoList(cpu_list);
zhanghailiang5b009e42014-11-04 19:49:30 +08001110 g_free(node_mem);
aliguori030ea372009-04-21 22:30:47 +00001111}
1112
bellard5f1ce942006-02-08 22:40:15 +00001113#ifdef CONFIG_PROFILER
1114
Aurelien Jarnoe9a66252009-09-30 14:09:52 +02001115int64_t dev_time;
1116
Markus Armbruster1ce6be22015-02-06 14:18:24 +01001117static void hmp_info_profile(Monitor *mon, const QDict *qdict)
bellard5f1ce942006-02-08 22:40:15 +00001118{
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -04001119 static int64_t last_cpu_exec_time;
1120 int64_t cpu_exec_time;
1121 int64_t delta;
1122
1123 cpu_exec_time = tcg_cpu_exec_time();
1124 delta = cpu_exec_time - last_cpu_exec_time;
1125
aliguori376253e2009-03-05 23:01:23 +00001126 monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
Rutuja Shah73bcb242016-03-21 21:32:30 +05301127 dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
aliguori376253e2009-03-05 23:01:23 +00001128 monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -04001129 delta, delta / (double)NANOSECONDS_PER_SECOND);
1130 last_cpu_exec_time = cpu_exec_time;
bellard5f1ce942006-02-08 22:40:15 +00001131 dev_time = 0;
bellard5f1ce942006-02-08 22:40:15 +00001132}
1133#else
Markus Armbruster1ce6be22015-02-06 14:18:24 +01001134static void hmp_info_profile(Monitor *mon, const QDict *qdict)
bellard5f1ce942006-02-08 22:40:15 +00001135{
aliguori376253e2009-03-05 23:01:23 +00001136 monitor_printf(mon, "Internal profiler not compiled\n");
bellard5f1ce942006-02-08 22:40:15 +00001137}
1138#endif
1139
bellardec36b692006-07-16 18:57:03 +00001140/* Capture support */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001141static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
bellardec36b692006-07-16 18:57:03 +00001142
Markus Armbruster1ce6be22015-02-06 14:18:24 +01001143static void hmp_info_capture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00001144{
1145 int i;
1146 CaptureState *s;
1147
1148 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
aliguori376253e2009-03-05 23:01:23 +00001149 monitor_printf(mon, "[%d]: ", i);
bellardec36b692006-07-16 18:57:03 +00001150 s->ops.info (s->opaque);
1151 }
1152}
1153
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001154static void hmp_stopcapture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00001155{
1156 int i;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001157 int n = qdict_get_int(qdict, "n");
bellardec36b692006-07-16 18:57:03 +00001158 CaptureState *s;
1159
1160 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
1161 if (i == n) {
1162 s->ops.destroy (s->opaque);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001163 QLIST_REMOVE (s, entries);
Anthony Liguori7267c092011-08-20 22:09:37 -05001164 g_free (s);
bellardec36b692006-07-16 18:57:03 +00001165 return;
1166 }
1167 }
1168}
1169
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001170static void hmp_wavcapture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00001171{
Luiz Capitulinoc1925482009-08-28 15:27:19 -03001172 const char *path = qdict_get_str(qdict, "path");
1173 int has_freq = qdict_haskey(qdict, "freq");
1174 int freq = qdict_get_try_int(qdict, "freq", -1);
1175 int has_bits = qdict_haskey(qdict, "bits");
1176 int bits = qdict_get_try_int(qdict, "bits", -1);
1177 int has_channels = qdict_haskey(qdict, "nchannels");
1178 int nchannels = qdict_get_try_int(qdict, "nchannels", -1);
bellardec36b692006-07-16 18:57:03 +00001179 CaptureState *s;
1180
Anthony Liguori7267c092011-08-20 22:09:37 -05001181 s = g_malloc0 (sizeof (*s));
bellardec36b692006-07-16 18:57:03 +00001182
1183 freq = has_freq ? freq : 44100;
1184 bits = has_bits ? bits : 16;
1185 nchannels = has_channels ? nchannels : 2;
1186
1187 if (wav_start_capture (s, path, freq, bits, nchannels)) {
Isaku Yamahatad00b2612011-01-21 19:53:55 +09001188 monitor_printf(mon, "Failed to add wave capture\n");
Anthony Liguori7267c092011-08-20 22:09:37 -05001189 g_free (s);
Isaku Yamahatad00b2612011-01-21 19:53:55 +09001190 return;
bellardec36b692006-07-16 18:57:03 +00001191 }
Blue Swirl72cf2d42009-09-12 07:36:22 +00001192 QLIST_INSERT_HEAD (&capture_head, s, entries);
bellardec36b692006-07-16 18:57:03 +00001193}
bellardec36b692006-07-16 18:57:03 +00001194
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001195static QAuthZList *find_auth(Monitor *mon, const char *name)
aliguori76655d62009-03-06 20:27:37 +00001196{
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001197 Object *obj;
1198 Object *container;
aliguori76655d62009-03-06 20:27:37 +00001199
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001200 container = object_get_objects_root();
1201 obj = object_resolve_path_component(container, name);
1202 if (!obj) {
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001203 monitor_printf(mon, "acl: unknown list '%s'\n", name);
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001204 return NULL;
aliguori76655d62009-03-06 20:27:37 +00001205 }
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001206
1207 return QAUTHZ_LIST(obj);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001208}
aliguori76655d62009-03-06 20:27:37 +00001209
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001210static bool warn_acl;
1211static void hmp_warn_acl(void)
1212{
1213 if (warn_acl) {
1214 return;
1215 }
1216 error_report("The acl_show, acl_reset, acl_policy, acl_add, acl_remove "
1217 "commands are deprecated with no replacement. Authorization "
1218 "for VNC should be performed using the pluggable QAuthZ "
1219 "objects");
1220 warn_acl = true;
1221}
1222
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001223static void hmp_acl_show(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001224{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001225 const char *aclname = qdict_get_str(qdict, "aclname");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001226 QAuthZList *auth = find_auth(mon, aclname);
1227 QAuthZListRuleList *rules;
1228 size_t i = 0;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001229
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001230 hmp_warn_acl();
1231
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001232 if (!auth) {
1233 return;
1234 }
1235
1236 monitor_printf(mon, "policy: %s\n",
1237 QAuthZListPolicy_str(auth->policy));
1238
1239 rules = auth->rules;
1240 while (rules) {
1241 QAuthZListRule *rule = rules->value;
1242 i++;
1243 monitor_printf(mon, "%zu: %s %s\n", i,
1244 QAuthZListPolicy_str(rule->policy),
1245 rule->match);
1246 rules = rules->next;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001247 }
1248}
1249
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001250static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001251{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001252 const char *aclname = qdict_get_str(qdict, "aclname");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001253 QAuthZList *auth = find_auth(mon, aclname);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001254
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001255 hmp_warn_acl();
1256
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001257 if (!auth) {
1258 return;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001259 }
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001260
1261 auth->policy = QAUTHZ_LIST_POLICY_DENY;
1262 qapi_free_QAuthZListRuleList(auth->rules);
1263 auth->rules = NULL;
1264 monitor_printf(mon, "acl: removed all rules\n");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001265}
aliguori76655d62009-03-06 20:27:37 +00001266
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001267static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001268{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001269 const char *aclname = qdict_get_str(qdict, "aclname");
1270 const char *policy = qdict_get_str(qdict, "policy");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001271 QAuthZList *auth = find_auth(mon, aclname);
1272 int val;
1273 Error *err = NULL;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001274
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001275 hmp_warn_acl();
1276
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001277 if (!auth) {
1278 return;
1279 }
1280
1281 val = qapi_enum_parse(&QAuthZListPolicy_lookup,
1282 policy,
1283 QAUTHZ_LIST_POLICY_DENY,
1284 &err);
1285 if (err) {
1286 error_free(err);
1287 monitor_printf(mon, "acl: unknown policy '%s', "
1288 "expected 'deny' or 'allow'\n", policy);
1289 } else {
1290 auth->policy = val;
1291 if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) {
aliguori28a76be2009-03-06 20:27:40 +00001292 monitor_printf(mon, "acl: policy set to 'allow'\n");
aliguori28a76be2009-03-06 20:27:40 +00001293 } else {
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001294 monitor_printf(mon, "acl: policy set to 'deny'\n");
aliguori28a76be2009-03-06 20:27:40 +00001295 }
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001296 }
1297}
aliguori76655d62009-03-06 20:27:37 +00001298
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001299static QAuthZListFormat hmp_acl_get_format(const char *match)
1300{
1301 if (strchr(match, '*')) {
1302 return QAUTHZ_LIST_FORMAT_GLOB;
1303 } else {
1304 return QAUTHZ_LIST_FORMAT_EXACT;
1305 }
1306}
1307
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001308static void hmp_acl_add(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001309{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001310 const char *aclname = qdict_get_str(qdict, "aclname");
1311 const char *match = qdict_get_str(qdict, "match");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001312 const char *policystr = qdict_get_str(qdict, "policy");
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001313 int has_index = qdict_haskey(qdict, "index");
1314 int index = qdict_get_try_int(qdict, "index", -1);
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001315 QAuthZList *auth = find_auth(mon, aclname);
1316 Error *err = NULL;
1317 QAuthZListPolicy policy;
1318 QAuthZListFormat format;
1319 size_t i = 0;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001320
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001321 hmp_warn_acl();
1322
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001323 if (!auth) {
1324 return;
1325 }
1326
1327 policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
1328 policystr,
1329 QAUTHZ_LIST_POLICY_DENY,
1330 &err);
1331 if (err) {
1332 error_free(err);
1333 monitor_printf(mon, "acl: unknown policy '%s', "
1334 "expected 'deny' or 'allow'\n", policystr);
1335 return;
1336 }
1337
1338 format = hmp_acl_get_format(match);
1339
1340 if (has_index && index == 0) {
1341 monitor_printf(mon, "acl: unable to add acl entry\n");
1342 return;
1343 }
1344
1345 if (has_index) {
1346 i = qauthz_list_insert_rule(auth, match, policy,
1347 format, index - 1, &err);
1348 } else {
1349 i = qauthz_list_append_rule(auth, match, policy,
1350 format, &err);
1351 }
1352 if (err) {
1353 monitor_printf(mon, "acl: unable to add rule: %s",
1354 error_get_pretty(err));
1355 error_free(err);
1356 } else {
1357 monitor_printf(mon, "acl: added rule at position %zu\n", i + 1);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001358 }
1359}
aliguori76655d62009-03-06 20:27:37 +00001360
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001361static void hmp_acl_remove(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001362{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001363 const char *aclname = qdict_get_str(qdict, "aclname");
1364 const char *match = qdict_get_str(qdict, "match");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001365 QAuthZList *auth = find_auth(mon, aclname);
1366 ssize_t i = 0;
aliguori76655d62009-03-06 20:27:37 +00001367
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001368 hmp_warn_acl();
1369
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001370 if (!auth) {
1371 return;
1372 }
1373
1374 i = qauthz_list_delete_rule(auth, match);
1375 if (i >= 0) {
1376 monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1);
1377 } else {
1378 monitor_printf(mon, "acl: no matching acl entry\n");
aliguori76655d62009-03-06 20:27:37 +00001379 }
1380}
1381
Corey Bryant208c9d12012-06-22 14:36:09 -04001382void qmp_getfd(const char *fdname, Error **errp)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001383{
Anthony Liguoric227f092009-10-01 16:12:16 -05001384 mon_fd_t *monfd;
Peter Xu9409fc02018-06-08 11:55:06 +08001385 int fd, tmp_fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001386
Marc-André Lureau5345fdb2016-10-22 12:52:55 +03001387 fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001388 if (fd == -1) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001389 error_setg(errp, QERR_FD_NOT_SUPPLIED);
Corey Bryant208c9d12012-06-22 14:36:09 -04001390 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001391 }
1392
1393 if (qemu_isdigit(fdname[0])) {
Stefan Hajnoczi0b9f0e22014-04-24 13:58:18 +02001394 close(fd);
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001395 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdname",
1396 "a name not starting with a digit");
Corey Bryant208c9d12012-06-22 14:36:09 -04001397 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001398 }
1399
Peter Xu9409fc02018-06-08 11:55:06 +08001400 qemu_mutex_lock(&cur_mon->mon_lock);
Corey Bryant208c9d12012-06-22 14:36:09 -04001401 QLIST_FOREACH(monfd, &cur_mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001402 if (strcmp(monfd->name, fdname) != 0) {
1403 continue;
1404 }
1405
Peter Xu9409fc02018-06-08 11:55:06 +08001406 tmp_fd = monfd->fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001407 monfd->fd = fd;
Peter Xu9409fc02018-06-08 11:55:06 +08001408 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbruster774a6b62018-07-03 10:53:57 +02001409 /* Make sure close() is outside critical section */
Peter Xu9409fc02018-06-08 11:55:06 +08001410 close(tmp_fd);
Corey Bryant208c9d12012-06-22 14:36:09 -04001411 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001412 }
1413
Anthony Liguori7267c092011-08-20 22:09:37 -05001414 monfd = g_malloc0(sizeof(mon_fd_t));
1415 monfd->name = g_strdup(fdname);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001416 monfd->fd = fd;
1417
Corey Bryant208c9d12012-06-22 14:36:09 -04001418 QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next);
Peter Xu9409fc02018-06-08 11:55:06 +08001419 qemu_mutex_unlock(&cur_mon->mon_lock);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001420}
1421
Corey Bryant208c9d12012-06-22 14:36:09 -04001422void qmp_closefd(const char *fdname, Error **errp)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001423{
Anthony Liguoric227f092009-10-01 16:12:16 -05001424 mon_fd_t *monfd;
Peter Xu9409fc02018-06-08 11:55:06 +08001425 int tmp_fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001426
Peter Xu9409fc02018-06-08 11:55:06 +08001427 qemu_mutex_lock(&cur_mon->mon_lock);
Corey Bryant208c9d12012-06-22 14:36:09 -04001428 QLIST_FOREACH(monfd, &cur_mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001429 if (strcmp(monfd->name, fdname) != 0) {
1430 continue;
1431 }
1432
Blue Swirl72cf2d42009-09-12 07:36:22 +00001433 QLIST_REMOVE(monfd, next);
Peter Xu9409fc02018-06-08 11:55:06 +08001434 tmp_fd = monfd->fd;
Anthony Liguori7267c092011-08-20 22:09:37 -05001435 g_free(monfd->name);
1436 g_free(monfd);
Peter Xu9409fc02018-06-08 11:55:06 +08001437 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbruster774a6b62018-07-03 10:53:57 +02001438 /* Make sure close() is outside critical section */
Peter Xu9409fc02018-06-08 11:55:06 +08001439 close(tmp_fd);
Corey Bryant208c9d12012-06-22 14:36:09 -04001440 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001441 }
1442
Peter Xu9409fc02018-06-08 11:55:06 +08001443 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001444 error_setg(errp, QERR_FD_NOT_FOUND, fdname);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001445}
1446
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001447int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
Mark McLoughlin7768e042009-07-22 09:11:41 +01001448{
Anthony Liguoric227f092009-10-01 16:12:16 -05001449 mon_fd_t *monfd;
Mark McLoughlin7768e042009-07-22 09:11:41 +01001450
Peter Xu9409fc02018-06-08 11:55:06 +08001451 qemu_mutex_lock(&mon->mon_lock);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001452 QLIST_FOREACH(monfd, &mon->fds, next) {
Mark McLoughlin7768e042009-07-22 09:11:41 +01001453 int fd;
1454
1455 if (strcmp(monfd->name, fdname) != 0) {
1456 continue;
1457 }
1458
1459 fd = monfd->fd;
1460
1461 /* caller takes ownership of fd */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001462 QLIST_REMOVE(monfd, next);
Anthony Liguori7267c092011-08-20 22:09:37 -05001463 g_free(monfd->name);
1464 g_free(monfd);
Peter Xu9409fc02018-06-08 11:55:06 +08001465 qemu_mutex_unlock(&mon->mon_lock);
Mark McLoughlin7768e042009-07-22 09:11:41 +01001466
1467 return fd;
1468 }
1469
Peter Xu9409fc02018-06-08 11:55:06 +08001470 qemu_mutex_unlock(&mon->mon_lock);
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001471 error_setg(errp, "File descriptor named '%s' has not been found", fdname);
Mark McLoughlin7768e042009-07-22 09:11:41 +01001472 return -1;
1473}
1474
Corey Bryantba1c0482012-08-14 16:43:43 -04001475static void monitor_fdset_cleanup(MonFdset *mon_fdset)
1476{
1477 MonFdsetFd *mon_fdset_fd;
1478 MonFdsetFd *mon_fdset_fd_next;
1479
1480 QLIST_FOREACH_SAFE(mon_fdset_fd, &mon_fdset->fds, next, mon_fdset_fd_next) {
Corey Bryantebe52b52012-10-18 15:19:33 -04001481 if ((mon_fdset_fd->removed ||
1482 (QLIST_EMPTY(&mon_fdset->dup_fds) && mon_refcount == 0)) &&
1483 runstate_is_running()) {
Corey Bryantba1c0482012-08-14 16:43:43 -04001484 close(mon_fdset_fd->fd);
1485 g_free(mon_fdset_fd->opaque);
1486 QLIST_REMOVE(mon_fdset_fd, next);
1487 g_free(mon_fdset_fd);
1488 }
1489 }
1490
Corey Bryantadb696f2012-08-14 16:43:47 -04001491 if (QLIST_EMPTY(&mon_fdset->fds) && QLIST_EMPTY(&mon_fdset->dup_fds)) {
Corey Bryantba1c0482012-08-14 16:43:43 -04001492 QLIST_REMOVE(mon_fdset, next);
1493 g_free(mon_fdset);
1494 }
1495}
1496
Kevin Wolf7e3c0de2019-06-13 17:34:00 +02001497void monitor_fdsets_cleanup(void)
Corey Bryantefb87c12012-08-14 16:43:48 -04001498{
1499 MonFdset *mon_fdset;
1500 MonFdset *mon_fdset_next;
1501
Peter Xu47451462018-06-08 11:55:11 +08001502 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantefb87c12012-08-14 16:43:48 -04001503 QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) {
1504 monitor_fdset_cleanup(mon_fdset);
1505 }
Peter Xu47451462018-06-08 11:55:11 +08001506 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantefb87c12012-08-14 16:43:48 -04001507}
1508
Corey Bryantba1c0482012-08-14 16:43:43 -04001509AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
1510 const char *opaque, Error **errp)
1511{
1512 int fd;
1513 Monitor *mon = cur_mon;
Corey Bryantba1c0482012-08-14 16:43:43 -04001514 AddfdInfo *fdinfo;
1515
Marc-André Lureau5345fdb2016-10-22 12:52:55 +03001516 fd = qemu_chr_fe_get_msgfd(&mon->chr);
Corey Bryantba1c0482012-08-14 16:43:43 -04001517 if (fd == -1) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001518 error_setg(errp, QERR_FD_NOT_SUPPLIED);
Corey Bryantba1c0482012-08-14 16:43:43 -04001519 goto error;
1520 }
1521
Corey Bryante446f702012-10-18 15:19:32 -04001522 fdinfo = monitor_fdset_add_fd(fd, has_fdset_id, fdset_id,
1523 has_opaque, opaque, errp);
1524 if (fdinfo) {
1525 return fdinfo;
Corey Bryant9ac54af2012-10-18 15:19:31 -04001526 }
1527
Corey Bryantba1c0482012-08-14 16:43:43 -04001528error:
1529 if (fd != -1) {
1530 close(fd);
1531 }
1532 return NULL;
1533}
1534
1535void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp)
1536{
1537 MonFdset *mon_fdset;
1538 MonFdsetFd *mon_fdset_fd;
1539 char fd_str[60];
1540
Peter Xu47451462018-06-08 11:55:11 +08001541 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001542 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1543 if (mon_fdset->id != fdset_id) {
1544 continue;
1545 }
1546 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1547 if (has_fd) {
1548 if (mon_fdset_fd->fd != fd) {
1549 continue;
1550 }
1551 mon_fdset_fd->removed = true;
1552 break;
1553 } else {
1554 mon_fdset_fd->removed = true;
1555 }
1556 }
1557 if (has_fd && !mon_fdset_fd) {
1558 goto error;
1559 }
1560 monitor_fdset_cleanup(mon_fdset);
Peter Xu47451462018-06-08 11:55:11 +08001561 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001562 return;
1563 }
1564
1565error:
Peter Xu47451462018-06-08 11:55:11 +08001566 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001567 if (has_fd) {
1568 snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64,
1569 fdset_id, fd);
1570 } else {
1571 snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64, fdset_id);
1572 }
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001573 error_setg(errp, QERR_FD_NOT_FOUND, fd_str);
Corey Bryantba1c0482012-08-14 16:43:43 -04001574}
1575
1576FdsetInfoList *qmp_query_fdsets(Error **errp)
1577{
1578 MonFdset *mon_fdset;
1579 MonFdsetFd *mon_fdset_fd;
1580 FdsetInfoList *fdset_list = NULL;
1581
Peter Xu47451462018-06-08 11:55:11 +08001582 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001583 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1584 FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
1585 FdsetFdInfoList *fdsetfd_list = NULL;
1586
1587 fdset_info->value = g_malloc0(sizeof(*fdset_info->value));
1588 fdset_info->value->fdset_id = mon_fdset->id;
1589
1590 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1591 FdsetFdInfoList *fdsetfd_info;
1592
1593 fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
1594 fdsetfd_info->value = g_malloc0(sizeof(*fdsetfd_info->value));
1595 fdsetfd_info->value->fd = mon_fdset_fd->fd;
1596 if (mon_fdset_fd->opaque) {
1597 fdsetfd_info->value->has_opaque = true;
1598 fdsetfd_info->value->opaque = g_strdup(mon_fdset_fd->opaque);
1599 } else {
1600 fdsetfd_info->value->has_opaque = false;
1601 }
1602
1603 fdsetfd_info->next = fdsetfd_list;
1604 fdsetfd_list = fdsetfd_info;
1605 }
1606
1607 fdset_info->value->fds = fdsetfd_list;
1608
1609 fdset_info->next = fdset_list;
1610 fdset_list = fdset_info;
1611 }
Peter Xu47451462018-06-08 11:55:11 +08001612 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001613
1614 return fdset_list;
1615}
1616
Corey Bryante446f702012-10-18 15:19:32 -04001617AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
1618 bool has_opaque, const char *opaque,
1619 Error **errp)
1620{
1621 MonFdset *mon_fdset = NULL;
1622 MonFdsetFd *mon_fdset_fd;
1623 AddfdInfo *fdinfo;
1624
Peter Xu47451462018-06-08 11:55:11 +08001625 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryante446f702012-10-18 15:19:32 -04001626 if (has_fdset_id) {
1627 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1628 /* Break if match found or match impossible due to ordering by ID */
1629 if (fdset_id <= mon_fdset->id) {
1630 if (fdset_id < mon_fdset->id) {
1631 mon_fdset = NULL;
1632 }
1633 break;
1634 }
1635 }
1636 }
1637
1638 if (mon_fdset == NULL) {
1639 int64_t fdset_id_prev = -1;
1640 MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets);
1641
1642 if (has_fdset_id) {
1643 if (fdset_id < 0) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001644 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",
1645 "a non-negative value");
Peter Xu47451462018-06-08 11:55:11 +08001646 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryante446f702012-10-18 15:19:32 -04001647 return NULL;
1648 }
1649 /* Use specified fdset ID */
1650 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1651 mon_fdset_cur = mon_fdset;
1652 if (fdset_id < mon_fdset_cur->id) {
1653 break;
1654 }
1655 }
1656 } else {
1657 /* Use first available fdset ID */
1658 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1659 mon_fdset_cur = mon_fdset;
1660 if (fdset_id_prev == mon_fdset_cur->id - 1) {
1661 fdset_id_prev = mon_fdset_cur->id;
1662 continue;
1663 }
1664 break;
1665 }
1666 }
1667
1668 mon_fdset = g_malloc0(sizeof(*mon_fdset));
1669 if (has_fdset_id) {
1670 mon_fdset->id = fdset_id;
1671 } else {
1672 mon_fdset->id = fdset_id_prev + 1;
1673 }
1674
1675 /* The fdset list is ordered by fdset ID */
1676 if (!mon_fdset_cur) {
1677 QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next);
1678 } else if (mon_fdset->id < mon_fdset_cur->id) {
1679 QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next);
1680 } else {
1681 QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next);
1682 }
1683 }
1684
1685 mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd));
1686 mon_fdset_fd->fd = fd;
1687 mon_fdset_fd->removed = false;
1688 if (has_opaque) {
1689 mon_fdset_fd->opaque = g_strdup(opaque);
1690 }
1691 QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next);
1692
1693 fdinfo = g_malloc0(sizeof(*fdinfo));
1694 fdinfo->fdset_id = mon_fdset->id;
1695 fdinfo->fd = mon_fdset_fd->fd;
1696
Peter Xu47451462018-06-08 11:55:11 +08001697 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryante446f702012-10-18 15:19:32 -04001698 return fdinfo;
1699}
1700
Corey Bryantadb696f2012-08-14 16:43:47 -04001701int monitor_fdset_get_fd(int64_t fdset_id, int flags)
1702{
Peter Xu47451462018-06-08 11:55:11 +08001703#ifdef _WIN32
1704 return -ENOENT;
1705#else
Corey Bryantadb696f2012-08-14 16:43:47 -04001706 MonFdset *mon_fdset;
1707 MonFdsetFd *mon_fdset_fd;
1708 int mon_fd_flags;
Peter Xu47451462018-06-08 11:55:11 +08001709 int ret;
Corey Bryantadb696f2012-08-14 16:43:47 -04001710
Peter Xu47451462018-06-08 11:55:11 +08001711 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001712 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1713 if (mon_fdset->id != fdset_id) {
1714 continue;
1715 }
1716 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1717 mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
1718 if (mon_fd_flags == -1) {
Peter Xu47451462018-06-08 11:55:11 +08001719 ret = -errno;
1720 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001721 }
1722
1723 if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
Peter Xu47451462018-06-08 11:55:11 +08001724 ret = mon_fdset_fd->fd;
1725 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001726 }
1727 }
Peter Xu47451462018-06-08 11:55:11 +08001728 ret = -EACCES;
1729 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001730 }
Peter Xu47451462018-06-08 11:55:11 +08001731 ret = -ENOENT;
Corey Bryantadb696f2012-08-14 16:43:47 -04001732
Peter Xu47451462018-06-08 11:55:11 +08001733out:
1734 qemu_mutex_unlock(&mon_fdsets_lock);
1735 return ret;
1736#endif
Corey Bryantadb696f2012-08-14 16:43:47 -04001737}
1738
1739int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
1740{
1741 MonFdset *mon_fdset;
1742 MonFdsetFd *mon_fdset_fd_dup;
1743
Peter Xu47451462018-06-08 11:55:11 +08001744 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001745 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1746 if (mon_fdset->id != fdset_id) {
1747 continue;
1748 }
1749 QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
1750 if (mon_fdset_fd_dup->fd == dup_fd) {
Peter Xu47451462018-06-08 11:55:11 +08001751 goto err;
Corey Bryantadb696f2012-08-14 16:43:47 -04001752 }
1753 }
1754 mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
1755 mon_fdset_fd_dup->fd = dup_fd;
1756 QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
Peter Xu47451462018-06-08 11:55:11 +08001757 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001758 return 0;
1759 }
Peter Xu47451462018-06-08 11:55:11 +08001760
1761err:
1762 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001763 return -1;
1764}
1765
Yury Kotov854f63d2019-05-23 12:44:33 +03001766static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
Corey Bryantadb696f2012-08-14 16:43:47 -04001767{
1768 MonFdset *mon_fdset;
1769 MonFdsetFd *mon_fdset_fd_dup;
1770
Peter Xu47451462018-06-08 11:55:11 +08001771 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001772 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1773 QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
1774 if (mon_fdset_fd_dup->fd == dup_fd) {
1775 if (remove) {
1776 QLIST_REMOVE(mon_fdset_fd_dup, next);
1777 if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
1778 monitor_fdset_cleanup(mon_fdset);
1779 }
Peter Xu47451462018-06-08 11:55:11 +08001780 goto err;
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001781 } else {
Peter Xu47451462018-06-08 11:55:11 +08001782 qemu_mutex_unlock(&mon_fdsets_lock);
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001783 return mon_fdset->id;
Corey Bryantadb696f2012-08-14 16:43:47 -04001784 }
Corey Bryantadb696f2012-08-14 16:43:47 -04001785 }
1786 }
1787 }
Peter Xu47451462018-06-08 11:55:11 +08001788
1789err:
1790 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001791 return -1;
1792}
1793
Yury Kotov854f63d2019-05-23 12:44:33 +03001794int64_t monitor_fdset_dup_fd_find(int dup_fd)
Corey Bryantadb696f2012-08-14 16:43:47 -04001795{
1796 return monitor_fdset_dup_fd_find_remove(dup_fd, false);
1797}
1798
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001799void monitor_fdset_dup_fd_remove(int dup_fd)
Corey Bryantadb696f2012-08-14 16:43:47 -04001800{
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001801 monitor_fdset_dup_fd_find_remove(dup_fd, true);
Corey Bryantadb696f2012-08-14 16:43:47 -04001802}
1803
Markus Armbruster1677f4c2015-02-09 14:03:19 +01001804int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp)
Laszlo Ersek59063662014-04-10 10:24:31 +02001805{
1806 int fd;
1807 Error *local_err = NULL;
1808
1809 if (!qemu_isdigit(fdname[0]) && mon) {
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001810 fd = monitor_get_fd(mon, fdname, &local_err);
Nicholas Bellingera96ed022012-08-21 20:52:07 +00001811 } else {
1812 fd = qemu_parse_fd(fdname);
Laszlo Ersek59063662014-04-10 10:24:31 +02001813 if (fd == -1) {
1814 error_setg(&local_err, "Invalid file descriptor number '%s'",
1815 fdname);
1816 }
1817 }
1818 if (local_err) {
1819 error_propagate(errp, local_err);
1820 assert(fd == -1);
1821 } else {
1822 assert(fd != -1);
Nicholas Bellingera96ed022012-08-21 20:52:07 +00001823 }
1824
1825 return fd;
1826}
1827
Luiz Capitulinoacd0a092010-09-30 16:00:22 -03001828/* Please update hmp-commands.hx when adding or changing commands */
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02001829static HMPCommand hmp_info_cmds[] = {
Pavel Butsykinda76ee72015-09-10 18:38:58 +03001830#include "hmp-commands-info.h"
1831 { NULL, NULL, },
bellard9dc39cb2004-03-14 21:38:27 +00001832};
1833
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02001834/* hmp_cmds and hmp_info_cmds would be sorted at runtime */
Kevin Wolfed7bda52019-06-13 17:34:01 +02001835HMPCommand hmp_cmds[] = {
Wenchao Xiaa13ced52013-01-14 14:06:28 +08001836#include "hmp-commands.h"
1837 { NULL, NULL, },
1838};
1839
Kevin Wolfed7bda52019-06-13 17:34:01 +02001840/*
1841 * Set @pval to the value in the register identified by @name.
1842 * return 0 if OK, -1 if not found
1843 */
1844int get_monitor_def(int64_t *pval, const char *name)
bellard9307c4c2004-04-04 12:57:25 +00001845{
Pavel Butsykinbf957282015-09-10 18:38:59 +03001846 const MonitorDef *md = target_monitor_defs();
Thomas Huth854e67f2017-01-13 13:12:35 +01001847 CPUState *cs = mon_get_cpu();
bellard92a31b12005-02-10 22:00:52 +00001848 void *ptr;
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001849 uint64_t tmp = 0;
1850 int ret;
bellard92a31b12005-02-10 22:00:52 +00001851
Thomas Huth854e67f2017-01-13 13:12:35 +01001852 if (cs == NULL || md == NULL) {
Pavel Butsykinbf957282015-09-10 18:38:59 +03001853 return -1;
1854 }
1855
1856 for(; md->name != NULL; md++) {
Kevin Wolfed7bda52019-06-13 17:34:01 +02001857 if (hmp_compare_cmd(name, md->name)) {
bellard9307c4c2004-04-04 12:57:25 +00001858 if (md->get_value) {
bellarde95c8d52004-09-30 22:22:08 +00001859 *pval = md->get_value(md, md->offset);
bellard9307c4c2004-04-04 12:57:25 +00001860 } else {
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -07001861 CPUArchState *env = mon_get_cpu_env();
bellard6a00d602005-11-21 23:25:50 +00001862 ptr = (uint8_t *)env + md->offset;
bellard92a31b12005-02-10 22:00:52 +00001863 switch(md->type) {
1864 case MD_I32:
1865 *pval = *(int32_t *)ptr;
1866 break;
1867 case MD_TLONG:
1868 *pval = *(target_long *)ptr;
1869 break;
1870 default:
1871 *pval = 0;
1872 break;
1873 }
bellard9307c4c2004-04-04 12:57:25 +00001874 }
1875 return 0;
1876 }
1877 }
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001878
Thomas Huth854e67f2017-01-13 13:12:35 +01001879 ret = target_get_monitor_def(cs, name, &tmp);
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001880 if (!ret) {
1881 *pval = (target_long) tmp;
1882 }
1883
1884 return ret;
bellard9307c4c2004-04-04 12:57:25 +00001885}
1886
Hani Benhabiles40d19392014-05-07 23:41:30 +01001887static void add_completion_option(ReadLineState *rs, const char *str,
1888 const char *option)
1889{
1890 if (!str || !option) {
1891 return;
1892 }
1893 if (!strncmp(option, str, strlen(str))) {
1894 readline_add_completion(rs, option);
1895 }
1896}
1897
Hani Benhabiles13e315d2014-05-07 23:41:29 +01001898void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
1899{
1900 size_t len;
1901 ChardevBackendInfoList *list, *start;
1902
1903 if (nb_args != 2) {
1904 return;
1905 }
1906 len = strlen(str);
1907 readline_set_completion_index(rs, len);
1908
1909 start = list = qmp_query_chardev_backends(NULL);
1910 while (list) {
1911 const char *chr_name = list->value->name;
1912
1913 if (!strncmp(chr_name, str, len)) {
1914 readline_add_completion(rs, chr_name);
1915 }
1916 list = list->next;
1917 }
1918 qapi_free_ChardevBackendInfoList(start);
1919}
1920
Hani Benhabilesb162b492014-05-07 23:41:31 +01001921void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
1922{
1923 size_t len;
1924 int i;
1925
1926 if (nb_args != 2) {
1927 return;
1928 }
1929 len = strlen(str);
1930 readline_set_completion_index(rs, len);
Markus Armbruster1c236ba2017-08-24 10:46:06 +02001931 for (i = 0; i < NET_CLIENT_DRIVER__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02001932 add_completion_option(rs, str, NetClientDriver_str(i));
Hani Benhabilesb162b492014-05-07 23:41:31 +01001933 }
1934}
1935
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001936void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001937{
1938 GSList *list, *elt;
1939 size_t len;
1940
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001941 if (nb_args != 2) {
1942 return;
1943 }
1944
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001945 len = strlen(str);
1946 readline_set_completion_index(rs, len);
1947 list = elt = object_class_get_list(TYPE_DEVICE, false);
1948 while (elt) {
1949 const char *name;
1950 DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
1951 TYPE_DEVICE);
1952 name = object_class_get_name(OBJECT_CLASS(dc));
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001953
Eduardo Habkoste90f2a82017-05-03 17:35:44 -03001954 if (dc->user_creatable
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001955 && !strncmp(name, str, len)) {
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001956 readline_add_completion(rs, name);
1957 }
1958 elt = elt->next;
1959 }
1960 g_slist_free(list);
1961}
1962
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001963void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabiles1094fd32014-02-06 23:30:13 +01001964{
1965 GSList *list, *elt;
1966 size_t len;
1967
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001968 if (nb_args != 2) {
1969 return;
1970 }
1971
Hani Benhabiles1094fd32014-02-06 23:30:13 +01001972 len = strlen(str);
1973 readline_set_completion_index(rs, len);
1974 list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
1975 while (elt) {
1976 const char *name;
1977
1978 name = object_class_get_name(OBJECT_CLASS(elt->data));
1979 if (!strncmp(name, str, len) && strcmp(name, TYPE_USER_CREATABLE)) {
1980 readline_add_completion(rs, name);
1981 }
1982 elt = elt->next;
1983 }
1984 g_slist_free(list);
1985}
1986
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001987static void peripheral_device_del_completion(ReadLineState *rs,
1988 const char *str, size_t len)
1989{
Marcel Apfelbaum4cae4d52014-11-26 13:50:01 +02001990 Object *peripheral = container_get(qdev_get_machine(), "/peripheral");
1991 GSList *list, *item;
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001992
Marcel Apfelbaum4cae4d52014-11-26 13:50:01 +02001993 list = qdev_build_hotpluggable_device_list(peripheral);
1994 if (!list) {
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001995 return;
1996 }
1997
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001998 for (item = list; item; item = g_slist_next(item)) {
1999 DeviceState *dev = item->data;
2000
2001 if (dev->id && !strncmp(str, dev->id, len)) {
2002 readline_add_completion(rs, dev->id);
2003 }
2004 }
2005
2006 g_slist_free(list);
2007}
2008
Hani Benhabiles6297d9a2014-05-07 23:41:28 +01002009void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
2010{
2011 size_t len;
2012 ChardevInfoList *list, *start;
2013
2014 if (nb_args != 2) {
2015 return;
2016 }
2017 len = strlen(str);
2018 readline_set_completion_index(rs, len);
2019
2020 start = list = qmp_query_chardev(NULL);
2021 while (list) {
2022 ChardevInfo *chr = list->value;
2023
2024 if (!strncmp(chr->label, str, len)) {
2025 readline_add_completion(rs, chr->label);
2026 }
2027 list = list->next;
2028 }
2029 qapi_free_ChardevInfoList(start);
2030}
2031
Hani Benhabiles8e597772014-05-27 23:39:30 +01002032static void ringbuf_completion(ReadLineState *rs, const char *str)
2033{
2034 size_t len;
2035 ChardevInfoList *list, *start;
2036
2037 len = strlen(str);
2038 readline_set_completion_index(rs, len);
2039
2040 start = list = qmp_query_chardev(NULL);
2041 while (list) {
2042 ChardevInfo *chr_info = list->value;
2043
2044 if (!strncmp(chr_info->label, str, len)) {
Marc-André Lureau0ec7b3e2016-12-07 16:20:22 +03002045 Chardev *chr = qemu_chr_find(chr_info->label);
Marc-André Lureau777357d2016-12-07 18:39:10 +03002046 if (chr && CHARDEV_IS_RINGBUF(chr)) {
Hani Benhabiles8e597772014-05-27 23:39:30 +01002047 readline_add_completion(rs, chr_info->label);
2048 }
2049 }
2050 list = list->next;
2051 }
2052 qapi_free_ChardevInfoList(start);
2053}
2054
Hani Benhabiles8e597772014-05-27 23:39:30 +01002055void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
2056{
2057 if (nb_args != 2) {
2058 return;
2059 }
2060 ringbuf_completion(rs, str);
2061}
2062
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01002063void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
2064{
2065 size_t len;
2066
2067 if (nb_args != 2) {
2068 return;
2069 }
2070
2071 len = strlen(str);
2072 readline_set_completion_index(rs, len);
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08002073 peripheral_device_del_completion(rs, str, len);
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01002074}
2075
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01002076void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabilesb48fa072014-02-06 23:30:12 +01002077{
2078 ObjectPropertyInfoList *list, *start;
2079 size_t len;
2080
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01002081 if (nb_args != 2) {
2082 return;
2083 }
Hani Benhabilesb48fa072014-02-06 23:30:12 +01002084 len = strlen(str);
2085 readline_set_completion_index(rs, len);
2086
2087 start = list = qmp_qom_list("/objects", NULL);
2088 while (list) {
2089 ObjectPropertyInfo *info = list->value;
2090
2091 if (!strncmp(info->type, "child<", 5)
2092 && !strncmp(info->name, str, len)) {
2093 readline_add_completion(rs, info->name);
2094 }
2095 list = list->next;
2096 }
2097 qapi_free_ObjectPropertyInfoList(start);
2098}
2099
Hani Benhabiles29136cd2014-05-07 23:41:27 +01002100void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
2101{
2102 int i;
2103 char *sep;
2104 size_t len;
2105
2106 if (nb_args != 2) {
2107 return;
2108 }
2109 sep = strrchr(str, '-');
2110 if (sep) {
2111 str = sep + 1;
2112 }
2113 len = strlen(str);
2114 readline_set_completion_index(rs, len);
Eric Blake7fb1cf12015-11-18 01:52:57 -07002115 for (i = 0; i < Q_KEY_CODE__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02002116 if (!strncmp(str, QKeyCode_str(i), len)) {
2117 readline_add_completion(rs, QKeyCode_str(i));
Hani Benhabiles29136cd2014-05-07 23:41:27 +01002118 }
2119 }
2120}
2121
Hani Benhabiles40d19392014-05-07 23:41:30 +01002122void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
2123{
2124 size_t len;
2125
2126 len = strlen(str);
2127 readline_set_completion_index(rs, len);
2128 if (nb_args == 2) {
Jason Wangeaed4832015-04-23 14:21:38 +08002129 NetClientState *ncs[MAX_QUEUE_NUM];
Hani Benhabiles40d19392014-05-07 23:41:30 +01002130 int count, i;
2131 count = qemu_find_net_clients_except(NULL, ncs,
Eric Blakef394b2e2016-07-13 21:50:23 -06002132 NET_CLIENT_DRIVER_NONE,
Jason Wangeaed4832015-04-23 14:21:38 +08002133 MAX_QUEUE_NUM);
Jason Wangbcfa4d62015-04-23 14:21:39 +08002134 for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
Hani Benhabiles40d19392014-05-07 23:41:30 +01002135 const char *name = ncs[i]->name;
2136 if (!strncmp(str, name, len)) {
2137 readline_add_completion(rs, name);
2138 }
2139 }
2140 } else if (nb_args == 3) {
2141 add_completion_option(rs, str, "on");
2142 add_completion_option(rs, str, "off");
2143 }
2144}
2145
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002146void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
2147{
2148 int len, count, i;
Jason Wangeaed4832015-04-23 14:21:38 +08002149 NetClientState *ncs[MAX_QUEUE_NUM];
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002150
2151 if (nb_args != 2) {
2152 return;
2153 }
2154
2155 len = strlen(str);
2156 readline_set_completion_index(rs, len);
Eric Blakef394b2e2016-07-13 21:50:23 -06002157 count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_DRIVER_NIC,
Jason Wangeaed4832015-04-23 14:21:38 +08002158 MAX_QUEUE_NUM);
Jason Wangbcfa4d62015-04-23 14:21:39 +08002159 for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002160 QemuOpts *opts;
2161 const char *name = ncs[i]->name;
2162 if (strncmp(str, name, len)) {
2163 continue;
2164 }
2165 opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), name);
2166 if (opts) {
2167 readline_add_completion(rs, name);
2168 }
2169 }
2170}
2171
Lluís Vilanovabd712112016-07-11 12:53:51 +02002172void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *str)
2173{
2174 size_t len;
2175
2176 len = strlen(str);
2177 readline_set_completion_index(rs, len);
2178 if (nb_args == 2) {
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002179 TraceEventIter iter;
2180 TraceEvent *ev;
2181 char *pattern = g_strdup_printf("%s*", str);
2182 trace_event_iter_init(&iter, pattern);
2183 while ((ev = trace_event_iter_next(&iter)) != NULL) {
2184 readline_add_completion(rs, trace_event_get_name(ev));
Lluís Vilanovabd712112016-07-11 12:53:51 +02002185 }
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002186 g_free(pattern);
Lluís Vilanovabd712112016-07-11 12:53:51 +02002187 }
2188}
2189
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002190void trace_event_completion(ReadLineState *rs, int nb_args, const char *str)
2191{
2192 size_t len;
2193
2194 len = strlen(str);
2195 readline_set_completion_index(rs, len);
2196 if (nb_args == 2) {
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002197 TraceEventIter iter;
2198 TraceEvent *ev;
2199 char *pattern = g_strdup_printf("%s*", str);
2200 trace_event_iter_init(&iter, pattern);
2201 while ((ev = trace_event_iter_next(&iter)) != NULL) {
2202 readline_add_completion(rs, trace_event_get_name(ev));
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002203 }
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002204 g_free(pattern);
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002205 } else if (nb_args == 3) {
2206 add_completion_option(rs, str, "on");
2207 add_completion_option(rs, str, "off");
2208 }
2209}
2210
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002211void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
2212{
Hani Benhabiles4bb08af2014-07-29 23:22:40 +01002213 int i;
2214
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002215 if (nb_args != 2) {
2216 return;
2217 }
2218 readline_set_completion_index(rs, strlen(str));
Michal Privoznik14d53b42017-09-07 10:05:24 +02002219 for (i = 0; i < WATCHDOG_ACTION__MAX; i++) {
2220 add_completion_option(rs, str, WatchdogAction_str(i));
Hani Benhabiles4bb08af2014-07-29 23:22:40 +01002221 }
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002222}
2223
Hani Benhabilesc68a0402014-05-27 23:39:32 +01002224void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
2225 const char *str)
2226{
2227 size_t len;
2228
2229 len = strlen(str);
2230 readline_set_completion_index(rs, len);
2231 if (nb_args == 2) {
2232 int i;
Eric Blake7fb1cf12015-11-18 01:52:57 -07002233 for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02002234 const char *name = MigrationCapability_str(i);
Hani Benhabilesc68a0402014-05-27 23:39:32 +01002235 if (!strncmp(str, name, len)) {
2236 readline_add_completion(rs, name);
2237 }
2238 }
2239 } else if (nb_args == 3) {
2240 add_completion_option(rs, str, "on");
2241 add_completion_option(rs, str, "off");
2242 }
2243}
2244
Liang Li50e9a622015-03-23 16:32:29 +08002245void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
2246 const char *str)
2247{
2248 size_t len;
2249
2250 len = strlen(str);
2251 readline_set_completion_index(rs, len);
2252 if (nb_args == 2) {
2253 int i;
Eric Blake7fb1cf12015-11-18 01:52:57 -07002254 for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02002255 const char *name = MigrationParameter_str(i);
Liang Li50e9a622015-03-23 16:32:29 +08002256 if (!strncmp(str, name, len)) {
2257 readline_add_completion(rs, name);
2258 }
2259 }
2260 }
2261}
2262
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002263static void vm_completion(ReadLineState *rs, const char *str)
2264{
2265 size_t len;
Kevin Wolf7c8eece2016-03-22 18:58:50 +01002266 BlockDriverState *bs;
Kevin Wolf88be7b42016-05-20 18:49:07 +02002267 BdrvNextIterator it;
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002268
2269 len = strlen(str);
2270 readline_set_completion_index(rs, len);
Kevin Wolf7c8eece2016-03-22 18:58:50 +01002271
Kevin Wolf88be7b42016-05-20 18:49:07 +02002272 for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002273 SnapshotInfoList *snapshots, *snapshot;
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002274 AioContext *ctx = bdrv_get_aio_context(bs);
2275 bool ok = false;
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002276
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002277 aio_context_acquire(ctx);
2278 if (bdrv_can_snapshot(bs)) {
2279 ok = bdrv_query_snapshot_info_list(bs, &snapshots, NULL) == 0;
2280 }
2281 aio_context_release(ctx);
2282 if (!ok) {
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002283 continue;
2284 }
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002285
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002286 snapshot = snapshots;
2287 while (snapshot) {
2288 char *completion = snapshot->value->name;
2289 if (!strncmp(str, completion, len)) {
2290 readline_add_completion(rs, completion);
2291 }
2292 completion = snapshot->value->id;
2293 if (!strncmp(str, completion, len)) {
2294 readline_add_completion(rs, completion);
2295 }
2296 snapshot = snapshot->next;
2297 }
2298 qapi_free_SnapshotInfoList(snapshots);
2299 }
2300
2301}
2302
2303void delvm_completion(ReadLineState *rs, int nb_args, const char *str)
2304{
2305 if (nb_args == 2) {
2306 vm_completion(rs, str);
2307 }
2308}
2309
2310void loadvm_completion(ReadLineState *rs, int nb_args, const char *str)
2311{
2312 if (nb_args == 2) {
2313 vm_completion(rs, str);
2314 }
2315}
2316
Wayne Xia816f8922011-10-12 11:32:41 +08002317static int
2318compare_mon_cmd(const void *a, const void *b)
2319{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02002320 return strcmp(((const HMPCommand *)a)->name,
2321 ((const HMPCommand *)b)->name);
Wayne Xia816f8922011-10-12 11:32:41 +08002322}
2323
2324static void sortcmdlist(void)
2325{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02002326 qsort(hmp_cmds, ARRAY_SIZE(hmp_cmds) - 1,
2327 sizeof(*hmp_cmds),
2328 compare_mon_cmd);
2329 qsort(hmp_info_cmds, ARRAY_SIZE(hmp_info_cmds) - 1,
2330 sizeof(*hmp_info_cmds),
2331 compare_mon_cmd);
Wayne Xia816f8922011-10-12 11:32:41 +08002332}
2333
Peter Xu6adf08d2018-03-09 16:59:50 +08002334void monitor_init_globals(void)
2335{
Kevin Wolf1d95db72019-06-13 17:34:02 +02002336 monitor_init_globals_core();
Peter Xu6adf08d2018-03-09 16:59:50 +08002337 monitor_init_qmp_commands();
Peter Xu6adf08d2018-03-09 16:59:50 +08002338 sortcmdlist();
Peter Xu47451462018-06-08 11:55:11 +08002339 qemu_mutex_init(&mon_fdsets_lock);
Peter Xu6adf08d2018-03-09 16:59:50 +08002340}
2341
Igor Mammedovd4633542016-06-10 06:29:06 +05302342HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
2343{
2344 MachineState *ms = MACHINE(qdev_get_machine());
2345 MachineClass *mc = MACHINE_GET_CLASS(ms);
2346
Igor Mammedovc5514d02017-02-10 11:20:57 +01002347 if (!mc->has_hotpluggable_cpus) {
Igor Mammedovd4633542016-06-10 06:29:06 +05302348 error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus");
2349 return NULL;
2350 }
2351
Igor Mammedovc5514d02017-02-10 11:20:57 +01002352 return machine_query_hotpluggable_cpus(ms);
Igor Mammedovd4633542016-06-10 06:29:06 +05302353}