blob: 89bb970b00452dd071c02d3518d3c37cfa367dc3 [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"
Paolo Bonzinib4a42f82013-02-04 11:37:52 +010028#include "monitor/qdev.h"
pbrook87ecb682007-11-17 17:14:51 +000029#include "hw/usb.h"
Michael S. Tsirkina2cb15b2012-12-12 14:24:50 +020030#include "hw/pci/pci.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010031#include "sysemu/watchdog.h"
Gerd Hoffmann45a50b12009-10-01 16:42:33 +020032#include "hw/loader.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010033#include "exec/gdbstub.h"
Paolo Bonzini1422e322012-10-24 08:43:34 +020034#include "net/net.h"
Mark McLoughlin68ac40d2009-11-25 18:48:54 +000035#include "net/slirp.h"
Peter Xube933ff2018-03-26 14:38:56 +080036#include "chardev/char-mux.h"
Gerd Hoffmann75721502010-10-07 12:22:54 +020037#include "ui/qemu-spice.h"
Marc-André Lureau213dcb02016-12-12 20:22:24 +030038#include "qemu/config-file.h"
Markus Armbruster856dfd82019-05-23 16:35:06 +020039#include "qemu/ctype.h"
Paolo Bonzini28ecbae2012-11-28 12:06:30 +010040#include "ui/console.h"
Gerd Hoffmannc751a742013-12-04 15:02:28 +010041#include "ui/input.h"
pbrook87ecb682007-11-17 17:14:51 +000042#include "audio/audio.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020043#include "disas/disas.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010044#include "sysemu/balloon.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010045#include "qemu/timer.h"
Vincent Palatinb3946622017-01-10 11:59:55 +010046#include "sysemu/hw_accel.h"
Markus Armbruster54d31232019-08-12 07:23:59 +020047#include "sysemu/runstate.h"
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +000048#include "authz/list.h"
49#include "qapi/util.h"
Markus Armbruster55225c82019-06-19 22:10:44 +020050#include "sysemu/blockdev.h"
51#include "sysemu/sysemu.h"
Markus Armbruster14a48c12019-05-23 16:35:05 +020052#include "sysemu/tcg.h"
Paolo Bonzinibdee56f2013-04-02 18:28:41 +020053#include "sysemu/tpm.h"
Markus Armbruster452fcdb2018-02-01 12:18:39 +010054#include "qapi/qmp/qdict.h"
Markus Armbrustercc7a8ea2015-03-17 17:22:46 +010055#include "qapi/qmp/qerror.h"
Markus Armbrusterfc81fa12018-02-01 12:18:40 +010056#include "qapi/qmp/qstring.h"
Markus Armbrustera9c94272016-06-22 19:11:19 +020057#include "qom/object_interfaces.h"
Lluís31965ae2011-08-31 20:31:24 +020058#include "trace/control.h"
Pavel Butsykinbf957282015-09-10 18:38:59 +030059#include "monitor/hmp-target.h"
Markus Armbruster275307a2019-06-19 22:10:36 +020060#include "monitor/hmp.h"
Lluís6d8a7642011-08-31 20:30:43 +020061#ifdef CONFIG_TRACE_SIMPLE
Lluís31965ae2011-08-31 20:31:24 +020062#include "trace/simple.h"
Prerna Saxena22890ab2010-06-24 17:04:53 +053063#endif
Paolo Bonzini022c62c2012-12-17 18:19:49 +010064#include "exec/memory.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010065#include "exec/exec-all.h"
Markus Armbruster922a01a2018-02-01 12:18:46 +010066#include "qemu/option.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010067#include "qemu/thread.h"
Hani Benhabilesb21631f2014-05-27 23:39:37 +010068#include "block/qapi.h"
Maxim Levitskya2dde2f2020-03-08 11:24:32 +020069#include "block/block-hmp-cmds.h"
Markus Armbruster00ca24f2019-11-20 19:25:48 +010070#include "qapi/qapi-commands-char.h"
Kevin Wolffa4dcf52020-01-29 11:22:37 +010071#include "qapi/qapi-commands-control.h"
Markus Armbruster00ca24f2019-11-20 19:25:48 +010072#include "qapi/qapi-commands-migration.h"
73#include "qapi/qapi-commands-misc.h"
74#include "qapi/qapi-commands-qom.h"
75#include "qapi/qapi-commands-trace.h"
Markus Armbruster00ca24f2019-11-20 19:25:48 +010076#include "qapi/qapi-init-commands.h"
Markus Armbrustere688df62018-02-01 12:18:31 +010077#include "qapi/error.h"
Wenchao Xia43a14cf2014-06-18 08:43:31 +020078#include "qapi/qmp-event.h"
Paolo Bonzinid2528bd2017-03-03 12:01:16 +010079#include "sysemu/cpus.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020080#include "qemu/cutils.h"
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -040081#include "tcg/tcg.h"
ths6a5bd302007-12-03 17:05:38 +000082
Jason J. Hernea4538a52015-06-26 14:07:21 -040083#if defined(TARGET_S390X)
84#include "hw/s390x/storage-keys.h"
Claudio Imbrendaf860d492016-08-15 18:44:04 +020085#include "hw/s390x/storage-attributes.h"
Jason J. Hernea4538a52015-06-26 14:07:21 -040086#endif
87
Mark McLoughlinf07918f2009-07-22 09:11:40 +010088/* file descriptors passed via SCM_RIGHTS */
Anthony Liguoric227f092009-10-01 16:12:16 -050089typedef struct mon_fd_t mon_fd_t;
90struct mon_fd_t {
Mark McLoughlinf07918f2009-07-22 09:11:40 +010091 char *name;
92 int fd;
Anthony Liguoric227f092009-10-01 16:12:16 -050093 QLIST_ENTRY(mon_fd_t) next;
Mark McLoughlinf07918f2009-07-22 09:11:40 +010094};
95
Corey Bryantba1c0482012-08-14 16:43:43 -040096/* file descriptor associated with a file descriptor set */
97typedef struct MonFdsetFd MonFdsetFd;
98struct MonFdsetFd {
99 int fd;
100 bool removed;
101 char *opaque;
102 QLIST_ENTRY(MonFdsetFd) next;
103};
104
105/* file descriptor set containing fds passed via SCM_RIGHTS */
106typedef struct MonFdset MonFdset;
107struct MonFdset {
108 int64_t id;
109 QLIST_HEAD(, MonFdsetFd) fds;
Corey Bryantadb696f2012-08-14 16:43:47 -0400110 QLIST_HEAD(, MonFdsetFd) dup_fds;
Corey Bryantba1c0482012-08-14 16:43:43 -0400111 QLIST_ENTRY(MonFdset) next;
112};
113
Peter Xu47451462018-06-08 11:55:11 +0800114/* Protects mon_fdsets */
115static QemuMutex mon_fdsets_lock;
Paolo Bonzinib58deb32018-12-06 11:58:10 +0100116static QLIST_HEAD(, MonFdset) mon_fdsets;
Peter Xu47451462018-06-08 11:55:11 +0800117
Kevin Wolfa0cd5e12019-06-13 17:33:56 +0200118static HMPCommand hmp_info_cmds[];
bellard9dc39cb2004-03-14 21:38:27 +0000119
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200120char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
121 int64_t cpu_index, Error **errp)
Luiz Capitulino0268d972010-10-22 10:08:02 -0200122{
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200123 char *output = NULL;
Kevin Wolfb6c7c2e2019-06-13 17:33:52 +0200124 Monitor *old_mon;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200125 MonitorHMP hmp = {};
Luiz Capitulino0268d972010-10-22 10:08:02 -0200126
Kevin Wolf92082412019-06-13 17:34:03 +0200127 monitor_data_init(&hmp.common, false, true, false);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200128
129 old_mon = cur_mon;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200130 cur_mon = &hmp.common;
Luiz Capitulino0268d972010-10-22 10:08:02 -0200131
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200132 if (has_cpu_index) {
133 int ret = monitor_set_cpu(cpu_index);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200134 if (ret < 0) {
135 cur_mon = old_mon;
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100136 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
137 "a CPU number");
Luiz Capitulino0268d972010-10-22 10:08:02 -0200138 goto out;
139 }
140 }
141
Markus Armbruster7ef6cf62015-03-06 19:12:36 +0100142 handle_hmp_command(&hmp, command_line);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200143 cur_mon = old_mon;
144
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200145 qemu_mutex_lock(&hmp.common.mon_lock);
146 if (qstring_get_length(hmp.common.outbuf) > 0) {
147 output = g_strdup(qstring_get_str(hmp.common.outbuf));
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200148 } else {
149 output = g_strdup("");
Luiz Capitulino0268d972010-10-22 10:08:02 -0200150 }
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200151 qemu_mutex_unlock(&hmp.common.mon_lock);
Luiz Capitulino0268d972010-10-22 10:08:02 -0200152
153out:
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200154 monitor_data_destroy(&hmp.common);
Luiz Capitulinod51a67b2011-11-25 17:52:45 -0200155 return output;
Luiz Capitulino0268d972010-10-22 10:08:02 -0200156}
157
Kevin Wolfed7bda52019-06-13 17:34:01 +0200158/**
159 * Is @name in the '|' separated list of names @list?
160 */
161int hmp_compare_cmd(const char *name, const char *list)
bellard9dc39cb2004-03-14 21:38:27 +0000162{
163 const char *p, *pstart;
164 int len;
165 len = strlen(name);
166 p = list;
Kevin Wolfed7bda52019-06-13 17:34:01 +0200167 for (;;) {
bellard9dc39cb2004-03-14 21:38:27 +0000168 pstart = p;
Keno Fischer5c99fa32018-06-29 12:32:10 +0200169 p = qemu_strchrnul(p, '|');
Kevin Wolfed7bda52019-06-13 17:34:01 +0200170 if ((p - pstart) == len && !memcmp(pstart, name, len)) {
bellard9dc39cb2004-03-14 21:38:27 +0000171 return 1;
Wenchao Xiaf5438c02013-08-27 20:38:21 +0800172 }
173 if (*p == '\0') {
174 break;
175 }
Kevin Wolfed7bda52019-06-13 17:34:01 +0200176 p++;
Wenchao Xiaf5438c02013-08-27 20:38:21 +0800177 }
Wenchao Xiadcc70cd2013-08-27 20:38:22 +0800178 return 0;
bellard9dc39cb2004-03-14 21:38:27 +0000179}
180
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300181static void do_help_cmd(Monitor *mon, const QDict *qdict)
Luiz Capitulino38183182009-08-28 15:27:08 -0300182{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300183 help_cmd(mon, qdict_get_try_str(qdict, "name"));
Luiz Capitulino38183182009-08-28 15:27:08 -0300184}
185
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100186static void hmp_trace_event(Monitor *mon, const QDict *qdict)
Prerna Saxena22890ab2010-06-24 17:04:53 +0530187{
188 const char *tp_name = qdict_get_str(qdict, "name");
189 bool new_state = qdict_get_bool(qdict, "option");
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200190 bool has_vcpu = qdict_haskey(qdict, "vcpu");
191 int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
Lluís Vilanova14101d02014-08-25 13:20:03 +0200192 Error *local_err = NULL;
Blue Swirlf871d682010-10-13 19:14:29 +0000193
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200194 if (vcpu < 0) {
195 monitor_printf(mon, "argument vcpu must be positive");
196 return;
197 }
198
199 qmp_trace_event_set_state(tp_name, new_state, true, true, has_vcpu, vcpu, &local_err);
Lluís Vilanova14101d02014-08-25 13:20:03 +0200200 if (local_err) {
Markus Armbruster091e38b2015-02-10 15:15:43 +0100201 error_report_err(local_err);
Blue Swirlf871d682010-10-13 19:14:29 +0000202 }
Prerna Saxena22890ab2010-06-24 17:04:53 +0530203}
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100204
Michael Rothc45a8162011-10-02 08:44:37 -0500205#ifdef CONFIG_TRACE_SIMPLE
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100206static void hmp_trace_file(Monitor *mon, const QDict *qdict)
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100207{
208 const char *op = qdict_get_try_str(qdict, "op");
209 const char *arg = qdict_get_try_str(qdict, "arg");
210
211 if (!op) {
Markus Armbrusterba4912c2019-04-17 21:17:50 +0200212 st_print_trace_file_status();
Stefan Hajnoczic5ceb522010-07-13 09:26:33 +0100213 } else if (!strcmp(op, "on")) {
214 st_set_trace_file_enabled(true);
215 } else if (!strcmp(op, "off")) {
216 st_set_trace_file_enabled(false);
217 } else if (!strcmp(op, "flush")) {
218 st_flush_trace_buffer();
219 } else if (!strcmp(op, "set")) {
220 if (arg) {
221 st_set_trace_file(arg);
222 }
223 } else {
224 monitor_printf(mon, "unexpected argument \"%s\"\n", op);
225 help_cmd(mon, "trace-file");
226 }
227}
Prerna Saxena22890ab2010-06-24 17:04:53 +0530228#endif
229
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100230static void hmp_info_help(Monitor *mon, const QDict *qdict)
bellard9dc39cb2004-03-14 21:38:27 +0000231{
Luiz Capitulino13c74252009-10-07 13:41:55 -0300232 help_cmd(mon, "info");
bellard9dc39cb2004-03-14 21:38:27 +0000233}
234
Peter Xu6adf08d2018-03-09 16:59:50 +0800235static void monitor_init_qmp_commands(void)
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400236{
Markus Armbruster635db182017-03-03 13:32:27 +0100237 /*
238 * Two command lists:
239 * - qmp_commands contains all QMP commands
240 * - qmp_cap_negotiation_commands contains just
241 * "qmp_capabilities", to enforce capability negotiation
242 */
243
Markus Armbruster1527bad2017-03-03 13:32:25 +0100244 qmp_init_marshal(&qmp_commands);
Markus Armbruster05875682017-03-03 13:32:24 +0100245
Markus Armbruster1527bad2017-03-03 13:32:25 +0100246 qmp_register_command(&qmp_commands, "query-qmp-schema",
Igor Mammedovd6fe3d02018-05-11 18:51:43 +0200247 qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
Markus Armbruster1527bad2017-03-03 13:32:25 +0100248 qmp_register_command(&qmp_commands, "device_add", qmp_device_add,
Marc-André Lureauedcfaef2016-09-12 13:19:00 +0400249 QCO_NO_OPTIONS);
Kevin Wolf5f07c4d2020-02-24 15:29:55 +0100250 qmp_register_command(&qmp_commands, "object-add", qmp_object_add,
251 QCO_NO_OPTIONS);
Marc-André Lureau5032a162016-09-12 13:19:02 +0400252
Markus Armbruster635db182017-03-03 13:32:27 +0100253 QTAILQ_INIT(&qmp_cap_negotiation_commands);
254 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
Igor Mammedovd6fe3d02018-05-11 18:51:43 +0200255 qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
Markus Armbruster635db182017-03-03 13:32:27 +0100256}
257
Peter Xud9f25282018-06-08 11:55:07 +0800258/* Set the current CPU defined by the user. Callers must hold BQL. */
Luiz Capitulinob025c8b2011-10-06 14:02:57 -0300259int monitor_set_cpu(int cpu_index)
bellard6a00d602005-11-21 23:25:50 +0000260{
Andreas Färber55e5c282012-12-17 06:18:02 +0100261 CPUState *cpu;
bellard6a00d602005-11-21 23:25:50 +0000262
Andreas Färber1c8bb3c2013-02-15 17:01:09 +0100263 cpu = qemu_get_cpu(cpu_index);
264 if (cpu == NULL) {
265 return -1;
bellard6a00d602005-11-21 23:25:50 +0000266 }
Greg Kurz751f8cf2017-10-17 10:16:22 +0200267 g_free(cur_mon->mon_cpu_path);
268 cur_mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
Andreas Färber1c8bb3c2013-02-15 17:01:09 +0100269 return 0;
bellard6a00d602005-11-21 23:25:50 +0000270}
271
Peter Xud9f25282018-06-08 11:55:07 +0800272/* Callers must hold BQL. */
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100273static CPUState *mon_get_cpu_sync(bool synchronize)
bellard6a00d602005-11-21 23:25:50 +0000274{
Marc-André Lureaua85d0bf2019-10-04 15:18:20 +0400275 CPUState *cpu = NULL;
Greg Kurz751f8cf2017-10-17 10:16:22 +0200276
277 if (cur_mon->mon_cpu_path) {
278 cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path,
279 TYPE_CPU, NULL);
280 if (!cpu) {
281 g_free(cur_mon->mon_cpu_path);
282 cur_mon->mon_cpu_path = NULL;
283 }
284 }
285 if (!cur_mon->mon_cpu_path) {
Thomas Huth854e67f2017-01-13 13:12:35 +0100286 if (!first_cpu) {
287 return NULL;
288 }
David Gibson27a83f82016-09-21 15:29:26 +1000289 monitor_set_cpu(first_cpu->cpu_index);
Greg Kurz751f8cf2017-10-17 10:16:22 +0200290 cpu = first_cpu;
bellard6a00d602005-11-21 23:25:50 +0000291 }
Marc-André Lureaua85d0bf2019-10-04 15:18:20 +0400292 assert(cpu != NULL);
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100293 if (synchronize) {
294 cpu_synchronize_state(cpu);
295 }
Greg Kurz751f8cf2017-10-17 10:16:22 +0200296 return cpu;
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -0700297}
298
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100299CPUState *mon_get_cpu(void)
300{
301 return mon_get_cpu_sync(true);
302}
303
Pavel Butsykinbf957282015-09-10 18:38:59 +0300304CPUArchState *mon_get_cpu_env(void)
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -0700305{
Thomas Huth854e67f2017-01-13 13:12:35 +0100306 CPUState *cs = mon_get_cpu();
307
308 return cs ? cs->env_ptr : NULL;
bellard6a00d602005-11-21 23:25:50 +0000309}
310
Luiz Capitulino99b77962011-10-24 10:53:44 -0200311int monitor_get_cpu_index(void)
312{
Viktor Mihajlovski137b5cb2018-02-16 17:08:41 +0100313 CPUState *cs = mon_get_cpu_sync(false);
Thomas Huth854e67f2017-01-13 13:12:35 +0100314
315 return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
Luiz Capitulino99b77962011-10-24 10:53:44 -0200316}
317
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100318static void hmp_info_registers(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000319{
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000320 bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false);
321 CPUState *cs;
Thomas Huth854e67f2017-01-13 13:12:35 +0100322
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000323 if (all_cpus) {
324 CPU_FOREACH(cs) {
325 monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
Markus Armbruster90c84c52019-04-17 21:18:02 +0200326 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
Suraj Jitindar Singh18f08282017-06-08 15:41:16 +1000327 }
328 } else {
329 cs = mon_get_cpu();
330
331 if (!cs) {
332 monitor_printf(mon, "No CPU available\n");
333 return;
334 }
335
Markus Armbruster90c84c52019-04-17 21:18:02 +0200336 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
Thomas Huth854e67f2017-01-13 13:12:35 +0100337 }
bellard9307c4c2004-04-04 12:57:25 +0000338}
339
Paolo Bonzinif0d14a92012-09-17 13:42:41 +0200340#ifdef CONFIG_TCG
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100341static void hmp_info_jit(Monitor *mon, const QDict *qdict)
bellarde3db7222005-01-26 22:00:47 +0000342{
Thomas Huthb7da97e2017-04-26 06:11:47 +0200343 if (!tcg_enabled()) {
344 error_report("JIT information is only available with accel=tcg");
345 return;
346 }
347
Markus Armbruster3de2faa2019-04-17 21:17:52 +0200348 dump_exec_info();
Markus Armbruster76c86612019-04-17 21:17:53 +0200349 dump_drift_info();
bellarde3db7222005-01-26 22:00:47 +0000350}
351
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100352static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
Max Filippov246ae242014-11-02 11:04:18 +0300353{
Markus Armbrusterd4c51a02019-04-17 21:17:51 +0200354 dump_opcount_info();
Max Filippov246ae242014-11-02 11:04:18 +0300355}
Paolo Bonzinif0d14a92012-09-17 13:42:41 +0200356#endif
Max Filippov246ae242014-11-02 11:04:18 +0300357
Emilio G. Cota97bfafe2017-08-08 13:54:42 -0400358static void hmp_info_sync_profile(Monitor *mon, const QDict *qdict)
359{
360 int64_t max = qdict_get_try_int(qdict, "max", 10);
361 bool mean = qdict_get_try_bool(qdict, "mean", false);
362 bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false);
363 enum QSPSortBy sort_by;
364
365 sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME;
Markus Armbrusterac7ff4c2019-04-17 21:17:54 +0200366 qsp_report(max, sort_by, coalesce);
Emilio G. Cota97bfafe2017-08-08 13:54:42 -0400367}
368
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100369static void hmp_info_history(Monitor *mon, const QDict *qdict)
bellardaa455482004-04-04 13:07:25 +0000370{
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200371 MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
bellardaa455482004-04-04 13:07:25 +0000372 int i;
bellard7e2515e2004-08-01 21:52:19 +0000373 const char *str;
ths3b46e622007-09-17 08:09:54 +0000374
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200375 if (!hmp_mon->rs) {
aliguoricde76ee2009-03-05 23:01:51 +0000376 return;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200377 }
bellard7e2515e2004-08-01 21:52:19 +0000378 i = 0;
379 for(;;) {
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200380 str = readline_get_history(hmp_mon->rs, i);
381 if (!str) {
bellard7e2515e2004-08-01 21:52:19 +0000382 break;
Kevin Wolf5f9dba12019-06-13 17:33:54 +0200383 }
aliguori376253e2009-03-05 23:01:23 +0000384 monitor_printf(mon, "%d: '%s'\n", i, str);
bellard8e3a9fd2004-10-09 17:32:58 +0000385 i++;
bellardaa455482004-04-04 13:07:25 +0000386 }
387}
388
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100389static void hmp_info_cpustats(Monitor *mon, const QDict *qdict)
j_mayer76a66252007-03-07 08:32:30 +0000390{
Thomas Huth854e67f2017-01-13 13:12:35 +0100391 CPUState *cs = mon_get_cpu();
392
393 if (!cs) {
394 monitor_printf(mon, "No CPU available\n");
395 return;
396 }
Markus Armbruster11cb6c12019-04-17 21:18:00 +0200397 cpu_dump_statistics(cs, 0);
j_mayer76a66252007-03-07 08:32:30 +0000398}
j_mayer76a66252007-03-07 08:32:30 +0000399
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100400static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
Prerna Saxena22890ab2010-06-24 17:04:53 +0530401{
Lluís Vilanovabd712112016-07-11 12:53:51 +0200402 const char *name = qdict_get_try_str(qdict, "name");
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200403 bool has_vcpu = qdict_haskey(qdict, "vcpu");
404 int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
Lluís Vilanovabd712112016-07-11 12:53:51 +0200405 TraceEventInfoList *events;
Lluís Vilanova14101d02014-08-25 13:20:03 +0200406 TraceEventInfoList *elem;
Lluís Vilanovabd712112016-07-11 12:53:51 +0200407 Error *local_err = NULL;
408
409 if (name == NULL) {
410 name = "*";
411 }
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200412 if (vcpu < 0) {
413 monitor_printf(mon, "argument vcpu must be positive");
414 return;
415 }
Lluís Vilanovabd712112016-07-11 12:53:51 +0200416
Lluís Vilanova77e2b172016-07-11 12:53:57 +0200417 events = qmp_trace_event_get_state(name, has_vcpu, vcpu, &local_err);
Lluís Vilanovabd712112016-07-11 12:53:51 +0200418 if (local_err) {
419 error_report_err(local_err);
420 return;
421 }
Lluís Vilanova14101d02014-08-25 13:20:03 +0200422
423 for (elem = events; elem != NULL; elem = elem->next) {
424 monitor_printf(mon, "%s : state %u\n",
425 elem->value->name,
426 elem->value->state == TRACE_EVENT_STATE_ENABLED ? 1 : 0);
427 }
428 qapi_free_TraceEventInfoList(events);
Prerna Saxena22890ab2010-06-24 17:04:53 +0530429}
Prerna Saxena22890ab2010-06-24 17:04:53 +0530430
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100431void qmp_client_migrate_info(const char *protocol, const char *hostname,
432 bool has_port, int64_t port,
433 bool has_tls_port, int64_t tls_port,
434 bool has_cert_subject, const char *cert_subject,
435 Error **errp)
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200436{
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200437 if (strcmp(protocol, "spice") == 0) {
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100438 if (!qemu_using_spice(errp)) {
439 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200440 }
441
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100442 if (!has_port && !has_tls_port) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100443 error_setg(errp, QERR_MISSING_PARAMETER, "port/tls-port");
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100444 return;
Yonit Halperin6ec5dae2012-03-18 09:42:39 +0200445 }
446
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100447 if (qemu_spice_migrate_info(hostname,
448 has_port ? port : -1,
449 has_tls_port ? tls_port : -1,
450 cert_subject)) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100451 error_setg(errp, QERR_UNDEFINED_ERROR);
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100452 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200453 }
Markus Armbrusterb8a185b2015-03-05 17:29:02 +0100454 return;
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200455 }
456
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +0100457 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol", "spice");
Gerd Hoffmanne866e232010-04-23 13:28:21 +0200458}
459
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100460static void hmp_logfile(Monitor *mon, const QDict *qdict)
pbrooke735b912007-06-30 13:53:24 +0000461{
Markus Armbrusterdaa76aa2016-06-15 19:27:16 +0200462 Error *err = NULL;
463
464 qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err);
465 if (err) {
466 error_report_err(err);
467 }
pbrooke735b912007-06-30 13:53:24 +0000468}
469
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100470static void hmp_log(Monitor *mon, const QDict *qdict)
bellardf193c792004-03-21 17:06:25 +0000471{
472 int mask;
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300473 const char *items = qdict_get_str(qdict, "items");
ths3b46e622007-09-17 08:09:54 +0000474
bellard9307c4c2004-04-04 12:57:25 +0000475 if (!strcmp(items, "none")) {
bellardf193c792004-03-21 17:06:25 +0000476 mask = 0;
477 } else {
Peter Maydell4fde1eb2013-02-11 16:41:22 +0000478 mask = qemu_str_to_log_mask(items);
bellardf193c792004-03-21 17:06:25 +0000479 if (!mask) {
aliguori376253e2009-03-05 23:01:23 +0000480 help_cmd(mon, "log");
bellardf193c792004-03-21 17:06:25 +0000481 return;
482 }
483 }
Peter Maydell24537a02013-02-11 16:41:23 +0000484 qemu_set_log(mask);
bellardf193c792004-03-21 17:06:25 +0000485}
486
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100487static void hmp_singlestep(Monitor *mon, const QDict *qdict)
aurel321b530a62009-04-05 20:08:59 +0000488{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300489 const char *option = qdict_get_try_str(qdict, "option");
aurel321b530a62009-04-05 20:08:59 +0000490 if (!option || !strcmp(option, "on")) {
491 singlestep = 1;
492 } else if (!strcmp(option, "off")) {
493 singlestep = 0;
494 } else {
495 monitor_printf(mon, "unexpected option %s\n", option);
496 }
497}
498
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100499static void hmp_gdbserver(Monitor *mon, const QDict *qdict)
bellard8a7ddc32004-03-31 19:00:16 +0000500{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300501 const char *device = qdict_get_try_str(qdict, "device");
aliguori59030a82009-04-05 18:43:41 +0000502 if (!device)
503 device = "tcp::" DEFAULT_GDBSTUB_PORT;
504 if (gdbserver_start(device) < 0) {
505 monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
506 device);
507 } else if (strcmp(device, "none") == 0) {
aliguori36556b22009-03-28 18:05:53 +0000508 monitor_printf(mon, "Disabled gdbserver\n");
bellard8a7ddc32004-03-31 19:00:16 +0000509 } else {
aliguori59030a82009-04-05 18:43:41 +0000510 monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
511 device);
bellard8a7ddc32004-03-31 19:00:16 +0000512 }
513}
514
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100515static void hmp_watchdog_action(Monitor *mon, const QDict *qdict)
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +0100516{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300517 const char *action = qdict_get_str(qdict, "action");
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +0100518 if (select_watchdog_action(action) == -1) {
519 monitor_printf(mon, "Unknown watchdog action '%s'\n", action);
520 }
521}
522
aliguori376253e2009-03-05 23:01:23 +0000523static void monitor_printc(Monitor *mon, int c)
bellard9307c4c2004-04-04 12:57:25 +0000524{
aliguori376253e2009-03-05 23:01:23 +0000525 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +0000526 switch(c) {
527 case '\'':
aliguori376253e2009-03-05 23:01:23 +0000528 monitor_printf(mon, "\\'");
bellard9307c4c2004-04-04 12:57:25 +0000529 break;
530 case '\\':
aliguori376253e2009-03-05 23:01:23 +0000531 monitor_printf(mon, "\\\\");
bellard9307c4c2004-04-04 12:57:25 +0000532 break;
533 case '\n':
aliguori376253e2009-03-05 23:01:23 +0000534 monitor_printf(mon, "\\n");
bellard9307c4c2004-04-04 12:57:25 +0000535 break;
536 case '\r':
aliguori376253e2009-03-05 23:01:23 +0000537 monitor_printf(mon, "\\r");
bellard9307c4c2004-04-04 12:57:25 +0000538 break;
539 default:
540 if (c >= 32 && c <= 126) {
aliguori376253e2009-03-05 23:01:23 +0000541 monitor_printf(mon, "%c", c);
bellard9307c4c2004-04-04 12:57:25 +0000542 } else {
aliguori376253e2009-03-05 23:01:23 +0000543 monitor_printf(mon, "\\x%02x", c);
bellard9307c4c2004-04-04 12:57:25 +0000544 }
545 break;
546 }
aliguori376253e2009-03-05 23:01:23 +0000547 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +0000548}
549
aliguori376253e2009-03-05 23:01:23 +0000550static void memory_dump(Monitor *mon, int count, int format, int wsize,
Avi Kivitya8170e52012-10-23 12:30:10 +0200551 hwaddr addr, int is_physical)
bellard9307c4c2004-04-04 12:57:25 +0000552{
Blue Swirl23842aa2010-01-12 20:27:43 +0000553 int l, line_size, i, max_digits, len;
bellard9307c4c2004-04-04 12:57:25 +0000554 uint8_t buf[16];
555 uint64_t v;
Thomas Huth854e67f2017-01-13 13:12:35 +0100556 CPUState *cs = mon_get_cpu();
557
558 if (!cs && (format == 'i' || !is_physical)) {
559 monitor_printf(mon, "Can not dump without CPU\n");
560 return;
561 }
bellard9307c4c2004-04-04 12:57:25 +0000562
563 if (format == 'i') {
Richard Henderson1d484742017-09-14 08:38:35 -0700564 monitor_disas(mon, cs, addr, count, is_physical);
bellard9307c4c2004-04-04 12:57:25 +0000565 return;
566 }
567
568 len = wsize * count;
569 if (wsize == 1)
570 line_size = 8;
571 else
572 line_size = 16;
bellard9307c4c2004-04-04 12:57:25 +0000573 max_digits = 0;
574
575 switch(format) {
576 case 'o':
Marc-André Lureau69db8df2017-06-22 13:04:16 +0200577 max_digits = DIV_ROUND_UP(wsize * 8, 3);
bellard9307c4c2004-04-04 12:57:25 +0000578 break;
579 default:
580 case 'x':
581 max_digits = (wsize * 8) / 4;
582 break;
583 case 'u':
584 case 'd':
Marc-André Lureau69db8df2017-06-22 13:04:16 +0200585 max_digits = DIV_ROUND_UP(wsize * 8 * 10, 33);
bellard9307c4c2004-04-04 12:57:25 +0000586 break;
587 case 'c':
588 wsize = 1;
589 break;
590 }
591
592 while (len > 0) {
blueswir17743e582007-09-24 18:39:04 +0000593 if (is_physical)
aliguori376253e2009-03-05 23:01:23 +0000594 monitor_printf(mon, TARGET_FMT_plx ":", addr);
blueswir17743e582007-09-24 18:39:04 +0000595 else
aliguori376253e2009-03-05 23:01:23 +0000596 monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
bellard9307c4c2004-04-04 12:57:25 +0000597 l = len;
598 if (l > line_size)
599 l = line_size;
600 if (is_physical) {
Peter Maydell6f89ae52018-12-14 13:30:49 +0000601 AddressSpace *as = cs ? cs->as : &address_space_memory;
602 MemTxResult r = address_space_read(as, addr,
603 MEMTXATTRS_UNSPECIFIED, buf, l);
604 if (r != MEMTX_OK) {
605 monitor_printf(mon, " Cannot access memory\n");
606 break;
607 }
bellard9307c4c2004-04-04 12:57:25 +0000608 } else {
Thomas Huth854e67f2017-01-13 13:12:35 +0100609 if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
aliguori376253e2009-03-05 23:01:23 +0000610 monitor_printf(mon, " Cannot access memory\n");
aliguoric8f79b62008-08-18 14:00:20 +0000611 break;
612 }
bellard9307c4c2004-04-04 12:57:25 +0000613 }
ths5fafdf22007-09-16 21:08:06 +0000614 i = 0;
bellard9307c4c2004-04-04 12:57:25 +0000615 while (i < l) {
616 switch(wsize) {
617 default:
618 case 1:
Peter Maydell24e60302015-01-20 15:19:32 +0000619 v = ldub_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000620 break;
621 case 2:
Peter Maydell24e60302015-01-20 15:19:32 +0000622 v = lduw_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000623 break;
624 case 4:
Peter Maydell24e60302015-01-20 15:19:32 +0000625 v = (uint32_t)ldl_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000626 break;
627 case 8:
Peter Maydell24e60302015-01-20 15:19:32 +0000628 v = ldq_p(buf + i);
bellard9307c4c2004-04-04 12:57:25 +0000629 break;
630 }
aliguori376253e2009-03-05 23:01:23 +0000631 monitor_printf(mon, " ");
bellard9307c4c2004-04-04 12:57:25 +0000632 switch(format) {
633 case 'o':
aliguori376253e2009-03-05 23:01:23 +0000634 monitor_printf(mon, "%#*" PRIo64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000635 break;
636 case 'x':
aliguori376253e2009-03-05 23:01:23 +0000637 monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000638 break;
639 case 'u':
aliguori376253e2009-03-05 23:01:23 +0000640 monitor_printf(mon, "%*" PRIu64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000641 break;
642 case 'd':
aliguori376253e2009-03-05 23:01:23 +0000643 monitor_printf(mon, "%*" PRId64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +0000644 break;
645 case 'c':
aliguori376253e2009-03-05 23:01:23 +0000646 monitor_printc(mon, v);
bellard9307c4c2004-04-04 12:57:25 +0000647 break;
648 }
649 i += wsize;
650 }
aliguori376253e2009-03-05 23:01:23 +0000651 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000652 addr += l;
653 len -= l;
654 }
655}
656
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100657static void hmp_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000658{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300659 int count = qdict_get_int(qdict, "count");
660 int format = qdict_get_int(qdict, "format");
661 int size = qdict_get_int(qdict, "size");
662 target_long addr = qdict_get_int(qdict, "addr");
663
aliguori376253e2009-03-05 23:01:23 +0000664 memory_dump(mon, count, format, size, addr, 0);
bellard9307c4c2004-04-04 12:57:25 +0000665}
666
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100667static void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000668{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300669 int count = qdict_get_int(qdict, "count");
670 int format = qdict_get_int(qdict, "format");
671 int size = qdict_get_int(qdict, "size");
Avi Kivitya8170e52012-10-23 12:30:10 +0200672 hwaddr addr = qdict_get_int(qdict, "addr");
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300673
aliguori376253e2009-03-05 23:01:23 +0000674 memory_dump(mon, count, format, size, addr, 1);
bellard9307c4c2004-04-04 12:57:25 +0000675}
676
Paolo Bonzinie9628442017-04-20 15:30:58 +0200677static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
678{
679 MemoryRegionSection mrs = memory_region_find(get_system_memory(),
680 addr, 1);
681
682 if (!mrs.mr) {
683 error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
684 return NULL;
685 }
686
687 if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
688 error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr);
689 memory_region_unref(mrs.mr);
690 return NULL;
691 }
692
693 *p_mr = mrs.mr;
694 return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
695}
696
697static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
698{
699 hwaddr addr = qdict_get_int(qdict, "addr");
700 Error *local_err = NULL;
701 MemoryRegion *mr = NULL;
702 void *ptr;
703
704 ptr = gpa2hva(&mr, addr, &local_err);
705 if (local_err) {
706 error_report_err(local_err);
707 return;
708 }
709
710 monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
711 " (%s) is %p\n",
712 addr, mr->name, ptr);
713
714 memory_region_unref(mr);
715}
716
Dr. David Alan Gilbert574d9692019-04-12 16:26:52 +0100717static void hmp_gva2gpa(Monitor *mon, const QDict *qdict)
718{
719 target_ulong addr = qdict_get_int(qdict, "addr");
720 MemTxAttrs attrs;
721 CPUState *cs = mon_get_cpu();
722 hwaddr gpa;
723
724 if (!cs) {
725 monitor_printf(mon, "No cpu\n");
726 return;
727 }
728
Eduardo Habkost9d3250d2019-05-10 15:56:20 -0300729 gpa = cpu_get_phys_page_attrs_debug(cs, addr & TARGET_PAGE_MASK, &attrs);
Dr. David Alan Gilbert574d9692019-04-12 16:26:52 +0100730 if (gpa == -1) {
731 monitor_printf(mon, "Unmapped\n");
732 } else {
733 monitor_printf(mon, "gpa: %#" HWADDR_PRIx "\n",
734 gpa + (addr & ~TARGET_PAGE_MASK));
735 }
736}
737
Paolo Bonzinie9628442017-04-20 15:30:58 +0200738#ifdef CONFIG_LINUX
739static uint64_t vtop(void *ptr, Error **errp)
740{
741 uint64_t pinfo;
742 uint64_t ret = -1;
743 uintptr_t addr = (uintptr_t) ptr;
Wei Yang038adc22019-10-13 10:11:45 +0800744 uintptr_t pagesize = qemu_real_host_page_size;
Paolo Bonzinie9628442017-04-20 15:30:58 +0200745 off_t offset = addr / pagesize * sizeof(pinfo);
746 int fd;
747
748 fd = open("/proc/self/pagemap", O_RDONLY);
749 if (fd == -1) {
750 error_setg_errno(errp, errno, "Cannot open /proc/self/pagemap");
751 return -1;
752 }
753
754 /* Force copy-on-write if necessary. */
755 atomic_add((uint8_t *)ptr, 0);
756
757 if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
758 error_setg_errno(errp, errno, "Cannot read pagemap");
759 goto out;
760 }
761 if ((pinfo & (1ull << 63)) == 0) {
762 error_setg(errp, "Page not present");
763 goto out;
764 }
765 ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
766
767out:
768 close(fd);
769 return ret;
770}
771
772static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
773{
774 hwaddr addr = qdict_get_int(qdict, "addr");
775 Error *local_err = NULL;
776 MemoryRegion *mr = NULL;
777 void *ptr;
778 uint64_t physaddr;
779
780 ptr = gpa2hva(&mr, addr, &local_err);
781 if (local_err) {
782 error_report_err(local_err);
783 return;
784 }
785
786 physaddr = vtop(ptr, &local_err);
787 if (local_err) {
788 error_report_err(local_err);
789 } else {
790 monitor_printf(mon, "Host physical address for 0x%" HWADDR_PRIx
791 " (%s) is 0x%" PRIx64 "\n",
792 addr, mr->name, (uint64_t) physaddr);
793 }
794
795 memory_region_unref(mr);
796}
797#endif
798
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300799static void do_print(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +0000800{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300801 int format = qdict_get_int(qdict, "format");
Avi Kivitya8170e52012-10-23 12:30:10 +0200802 hwaddr val = qdict_get_int(qdict, "val");
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300803
bellard9307c4c2004-04-04 12:57:25 +0000804 switch(format) {
805 case 'o':
Avi Kivitya8170e52012-10-23 12:30:10 +0200806 monitor_printf(mon, "%#" HWADDR_PRIo, val);
bellard9307c4c2004-04-04 12:57:25 +0000807 break;
808 case 'x':
Avi Kivitya8170e52012-10-23 12:30:10 +0200809 monitor_printf(mon, "%#" HWADDR_PRIx, val);
bellard9307c4c2004-04-04 12:57:25 +0000810 break;
811 case 'u':
Avi Kivitya8170e52012-10-23 12:30:10 +0200812 monitor_printf(mon, "%" HWADDR_PRIu, val);
bellard9307c4c2004-04-04 12:57:25 +0000813 break;
814 default:
815 case 'd':
Avi Kivitya8170e52012-10-23 12:30:10 +0200816 monitor_printf(mon, "%" HWADDR_PRId, val);
bellard9307c4c2004-04-04 12:57:25 +0000817 break;
818 case 'c':
aliguori376253e2009-03-05 23:01:23 +0000819 monitor_printc(mon, val);
bellard9307c4c2004-04-04 12:57:25 +0000820 break;
821 }
aliguori376253e2009-03-05 23:01:23 +0000822 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000823}
824
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100825static void hmp_sum(Monitor *mon, const QDict *qdict)
bellarde4cf1ad2005-06-04 20:15:57 +0000826{
827 uint32_t addr;
bellarde4cf1ad2005-06-04 20:15:57 +0000828 uint16_t sum;
Luiz Capitulinof18c16d2009-08-28 15:27:14 -0300829 uint32_t start = qdict_get_int(qdict, "start");
830 uint32_t size = qdict_get_int(qdict, "size");
bellarde4cf1ad2005-06-04 20:15:57 +0000831
832 sum = 0;
833 for(addr = start; addr < (start + size); addr++) {
Peter Maydell42874d32015-04-26 16:49:24 +0100834 uint8_t val = address_space_ldub(&address_space_memory, addr,
835 MEMTXATTRS_UNSPECIFIED, NULL);
bellarde4cf1ad2005-06-04 20:15:57 +0000836 /* BSD sum algorithm ('sum' Unix command) */
837 sum = (sum >> 1) | (sum << 15);
Stefan Weil54f7b4a2011-04-10 18:23:39 +0200838 sum += val;
bellarde4cf1ad2005-06-04 20:15:57 +0000839 }
aliguori376253e2009-03-05 23:01:23 +0000840 monitor_printf(mon, "%05d\n", sum);
bellarde4cf1ad2005-06-04 20:15:57 +0000841}
842
bellard13224a82006-07-14 22:03:35 +0000843static int mouse_button_state;
844
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100845static void hmp_mouse_move(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +0000846{
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100847 int dx, dy, dz, button;
Luiz Capitulino1d4daa92009-08-28 15:27:15 -0300848 const char *dx_str = qdict_get_str(qdict, "dx_str");
849 const char *dy_str = qdict_get_str(qdict, "dy_str");
850 const char *dz_str = qdict_get_try_str(qdict, "dz_str");
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100851
bellard13224a82006-07-14 22:03:35 +0000852 dx = strtol(dx_str, NULL, 0);
853 dy = strtol(dy_str, NULL, 0);
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100854 qemu_input_queue_rel(NULL, INPUT_AXIS_X, dx);
855 qemu_input_queue_rel(NULL, INPUT_AXIS_Y, dy);
856
857 if (dz_str) {
bellard13224a82006-07-14 22:03:35 +0000858 dz = strtol(dz_str, NULL, 0);
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100859 if (dz != 0) {
Gerd Hoffmannf22d0af2016-01-12 12:14:12 +0100860 button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100861 qemu_input_queue_btn(NULL, button, true);
862 qemu_input_event_sync();
863 qemu_input_queue_btn(NULL, button, false);
864 }
865 }
866 qemu_input_event_sync();
bellard13224a82006-07-14 22:03:35 +0000867}
868
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100869static void hmp_mouse_button(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +0000870{
Eric Blake7fb1cf12015-11-18 01:52:57 -0700871 static uint32_t bmap[INPUT_BUTTON__MAX] = {
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100872 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
873 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
874 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
875 };
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300876 int button_state = qdict_get_int(qdict, "button_state");
Gerd Hoffmannc751a742013-12-04 15:02:28 +0100877
878 if (mouse_button_state == button_state) {
879 return;
880 }
881 qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state);
882 qemu_input_event_sync();
bellard13224a82006-07-14 22:03:35 +0000883 mouse_button_state = button_state;
bellard13224a82006-07-14 22:03:35 +0000884}
885
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100886static void hmp_ioport_read(Monitor *mon, const QDict *qdict)
bellard34405572004-06-08 00:55:58 +0000887{
Luiz Capitulinoaa93e392009-08-28 15:27:18 -0300888 int size = qdict_get_int(qdict, "size");
889 int addr = qdict_get_int(qdict, "addr");
890 int has_index = qdict_haskey(qdict, "index");
bellard34405572004-06-08 00:55:58 +0000891 uint32_t val;
892 int suffix;
893
894 if (has_index) {
Luiz Capitulinoaa93e392009-08-28 15:27:18 -0300895 int index = qdict_get_int(qdict, "index");
Blue Swirlafcea8c2009-09-20 16:05:47 +0000896 cpu_outb(addr & IOPORTS_MASK, index & 0xff);
bellard34405572004-06-08 00:55:58 +0000897 addr++;
898 }
899 addr &= 0xffff;
900
901 switch(size) {
902 default:
903 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000904 val = cpu_inb(addr);
bellard34405572004-06-08 00:55:58 +0000905 suffix = 'b';
906 break;
907 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000908 val = cpu_inw(addr);
bellard34405572004-06-08 00:55:58 +0000909 suffix = 'w';
910 break;
911 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000912 val = cpu_inl(addr);
bellard34405572004-06-08 00:55:58 +0000913 suffix = 'l';
914 break;
915 }
aliguori376253e2009-03-05 23:01:23 +0000916 monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
917 suffix, addr, size * 2, val);
bellard34405572004-06-08 00:55:58 +0000918}
bellarda3a91a32004-06-04 11:06:21 +0000919
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100920static void hmp_ioport_write(Monitor *mon, const QDict *qdict)
Jan Kiszkaf1147842009-07-14 10:20:11 +0200921{
Luiz Capitulino1bd14422009-08-28 15:27:17 -0300922 int size = qdict_get_int(qdict, "size");
923 int addr = qdict_get_int(qdict, "addr");
924 int val = qdict_get_int(qdict, "val");
925
Jan Kiszkaf1147842009-07-14 10:20:11 +0200926 addr &= IOPORTS_MASK;
927
928 switch (size) {
929 default:
930 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000931 cpu_outb(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +0200932 break;
933 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000934 cpu_outw(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +0200935 break;
936 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +0000937 cpu_outl(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +0200938 break;
939 }
940}
941
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100942static void hmp_boot_set(Monitor *mon, const QDict *qdict)
aurel320ecdffb2008-05-04 20:11:34 +0000943{
Gongleif1839932014-12-03 18:20:58 +0000944 Error *local_err = NULL;
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300945 const char *bootdevice = qdict_get_str(qdict, "bootdevice");
aurel320ecdffb2008-05-04 20:11:34 +0000946
Gongleif1839932014-12-03 18:20:58 +0000947 qemu_boot_set(bootdevice, &local_err);
948 if (local_err) {
Markus Armbruster193227f2015-12-18 16:35:06 +0100949 error_report_err(local_err);
aurel320ecdffb2008-05-04 20:11:34 +0000950 } else {
Gongleif1839932014-12-03 18:20:58 +0000951 monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
aurel320ecdffb2008-05-04 20:11:34 +0000952 }
953}
954
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100955static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
Blue Swirl314e2982011-09-11 20:22:05 +0000956{
Peter Xu57bb40c2017-01-16 16:40:05 +0800957 bool flatview = qdict_get_try_bool(qdict, "flatview", false);
Alexey Kardashevskiy5e8fd942017-09-21 18:51:06 +1000958 bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
Alexey Kardashevskiyfc051ae2018-06-04 13:25:11 +1000959 bool owner = qdict_get_try_bool(qdict, "owner", false);
Philippe Mathieu-Daudé2261d392020-05-29 14:53:25 +0200960 bool disabled = qdict_get_try_bool(qdict, "disabled", false);
Peter Xu57bb40c2017-01-16 16:40:05 +0800961
Philippe Mathieu-Daudé2261d392020-05-29 14:53:25 +0200962 mtree_info(flatview, dispatch_tree, owner, disabled);
Blue Swirl314e2982011-09-11 20:22:05 +0000963}
964
bellard5f1ce942006-02-08 22:40:15 +0000965#ifdef CONFIG_PROFILER
966
Aurelien Jarnoe9a66252009-09-30 14:09:52 +0200967int64_t dev_time;
968
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100969static void hmp_info_profile(Monitor *mon, const QDict *qdict)
bellard5f1ce942006-02-08 22:40:15 +0000970{
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -0400971 static int64_t last_cpu_exec_time;
972 int64_t cpu_exec_time;
973 int64_t delta;
974
975 cpu_exec_time = tcg_cpu_exec_time();
976 delta = cpu_exec_time - last_cpu_exec_time;
977
aliguori376253e2009-03-05 23:01:23 +0000978 monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
Rutuja Shah73bcb242016-03-21 21:32:30 +0530979 dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
aliguori376253e2009-03-05 23:01:23 +0000980 monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
Emilio G. Cota72fd2ef2018-10-10 10:48:53 -0400981 delta, delta / (double)NANOSECONDS_PER_SECOND);
982 last_cpu_exec_time = cpu_exec_time;
bellard5f1ce942006-02-08 22:40:15 +0000983 dev_time = 0;
bellard5f1ce942006-02-08 22:40:15 +0000984}
985#else
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100986static void hmp_info_profile(Monitor *mon, const QDict *qdict)
bellard5f1ce942006-02-08 22:40:15 +0000987{
aliguori376253e2009-03-05 23:01:23 +0000988 monitor_printf(mon, "Internal profiler not compiled\n");
bellard5f1ce942006-02-08 22:40:15 +0000989}
990#endif
991
bellardec36b692006-07-16 18:57:03 +0000992/* Capture support */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000993static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
bellardec36b692006-07-16 18:57:03 +0000994
Markus Armbruster1ce6be22015-02-06 14:18:24 +0100995static void hmp_info_capture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +0000996{
997 int i;
998 CaptureState *s;
999
1000 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
aliguori376253e2009-03-05 23:01:23 +00001001 monitor_printf(mon, "[%d]: ", i);
bellardec36b692006-07-16 18:57:03 +00001002 s->ops.info (s->opaque);
1003 }
1004}
1005
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001006static void hmp_stopcapture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00001007{
1008 int i;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001009 int n = qdict_get_int(qdict, "n");
bellardec36b692006-07-16 18:57:03 +00001010 CaptureState *s;
1011
1012 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
1013 if (i == n) {
1014 s->ops.destroy (s->opaque);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001015 QLIST_REMOVE (s, entries);
Anthony Liguori7267c092011-08-20 22:09:37 -05001016 g_free (s);
bellardec36b692006-07-16 18:57:03 +00001017 return;
1018 }
1019 }
1020}
1021
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001022static void hmp_wavcapture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00001023{
Luiz Capitulinoc1925482009-08-28 15:27:19 -03001024 const char *path = qdict_get_str(qdict, "path");
Kővágó, Zoltánf0b9f362019-08-19 01:06:48 +02001025 int freq = qdict_get_try_int(qdict, "freq", 44100);
1026 int bits = qdict_get_try_int(qdict, "bits", 16);
1027 int nchannels = qdict_get_try_int(qdict, "nchannels", 2);
1028 const char *audiodev = qdict_get_str(qdict, "audiodev");
bellardec36b692006-07-16 18:57:03 +00001029 CaptureState *s;
Kővágó, Zoltánf0b9f362019-08-19 01:06:48 +02001030 AudioState *as = audio_state_by_name(audiodev);
1031
1032 if (!as) {
1033 monitor_printf(mon, "Audiodev '%s' not found\n", audiodev);
1034 return;
1035 }
bellardec36b692006-07-16 18:57:03 +00001036
Anthony Liguori7267c092011-08-20 22:09:37 -05001037 s = g_malloc0 (sizeof (*s));
bellardec36b692006-07-16 18:57:03 +00001038
Kővágó, Zoltánf0b9f362019-08-19 01:06:48 +02001039 if (wav_start_capture(as, s, path, freq, bits, nchannels)) {
Isaku Yamahatad00b2612011-01-21 19:53:55 +09001040 monitor_printf(mon, "Failed to add wave capture\n");
Anthony Liguori7267c092011-08-20 22:09:37 -05001041 g_free (s);
Isaku Yamahatad00b2612011-01-21 19:53:55 +09001042 return;
bellardec36b692006-07-16 18:57:03 +00001043 }
Blue Swirl72cf2d42009-09-12 07:36:22 +00001044 QLIST_INSERT_HEAD (&capture_head, s, entries);
bellardec36b692006-07-16 18:57:03 +00001045}
bellardec36b692006-07-16 18:57:03 +00001046
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001047static QAuthZList *find_auth(Monitor *mon, const char *name)
aliguori76655d62009-03-06 20:27:37 +00001048{
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001049 Object *obj;
1050 Object *container;
aliguori76655d62009-03-06 20:27:37 +00001051
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001052 container = object_get_objects_root();
1053 obj = object_resolve_path_component(container, name);
1054 if (!obj) {
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001055 monitor_printf(mon, "acl: unknown list '%s'\n", name);
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001056 return NULL;
aliguori76655d62009-03-06 20:27:37 +00001057 }
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001058
1059 return QAUTHZ_LIST(obj);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001060}
aliguori76655d62009-03-06 20:27:37 +00001061
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001062static bool warn_acl;
1063static void hmp_warn_acl(void)
1064{
1065 if (warn_acl) {
1066 return;
1067 }
1068 error_report("The acl_show, acl_reset, acl_policy, acl_add, acl_remove "
1069 "commands are deprecated with no replacement. Authorization "
1070 "for VNC should be performed using the pluggable QAuthZ "
1071 "objects");
1072 warn_acl = true;
1073}
1074
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001075static void hmp_acl_show(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001076{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001077 const char *aclname = qdict_get_str(qdict, "aclname");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001078 QAuthZList *auth = find_auth(mon, aclname);
1079 QAuthZListRuleList *rules;
1080 size_t i = 0;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001081
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001082 hmp_warn_acl();
1083
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001084 if (!auth) {
1085 return;
1086 }
1087
1088 monitor_printf(mon, "policy: %s\n",
1089 QAuthZListPolicy_str(auth->policy));
1090
1091 rules = auth->rules;
1092 while (rules) {
1093 QAuthZListRule *rule = rules->value;
1094 i++;
1095 monitor_printf(mon, "%zu: %s %s\n", i,
1096 QAuthZListPolicy_str(rule->policy),
1097 rule->match);
1098 rules = rules->next;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001099 }
1100}
1101
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001102static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001103{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001104 const char *aclname = qdict_get_str(qdict, "aclname");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001105 QAuthZList *auth = find_auth(mon, aclname);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001106
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001107 hmp_warn_acl();
1108
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001109 if (!auth) {
1110 return;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001111 }
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001112
1113 auth->policy = QAUTHZ_LIST_POLICY_DENY;
1114 qapi_free_QAuthZListRuleList(auth->rules);
1115 auth->rules = NULL;
1116 monitor_printf(mon, "acl: removed all rules\n");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001117}
aliguori76655d62009-03-06 20:27:37 +00001118
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001119static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001120{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001121 const char *aclname = qdict_get_str(qdict, "aclname");
1122 const char *policy = qdict_get_str(qdict, "policy");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001123 QAuthZList *auth = find_auth(mon, aclname);
1124 int val;
1125 Error *err = NULL;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001126
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001127 hmp_warn_acl();
1128
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001129 if (!auth) {
1130 return;
1131 }
1132
1133 val = qapi_enum_parse(&QAuthZListPolicy_lookup,
1134 policy,
1135 QAUTHZ_LIST_POLICY_DENY,
1136 &err);
1137 if (err) {
1138 error_free(err);
1139 monitor_printf(mon, "acl: unknown policy '%s', "
1140 "expected 'deny' or 'allow'\n", policy);
1141 } else {
1142 auth->policy = val;
1143 if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) {
aliguori28a76be2009-03-06 20:27:40 +00001144 monitor_printf(mon, "acl: policy set to 'allow'\n");
aliguori28a76be2009-03-06 20:27:40 +00001145 } else {
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001146 monitor_printf(mon, "acl: policy set to 'deny'\n");
aliguori28a76be2009-03-06 20:27:40 +00001147 }
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001148 }
1149}
aliguori76655d62009-03-06 20:27:37 +00001150
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001151static QAuthZListFormat hmp_acl_get_format(const char *match)
1152{
1153 if (strchr(match, '*')) {
1154 return QAUTHZ_LIST_FORMAT_GLOB;
1155 } else {
1156 return QAUTHZ_LIST_FORMAT_EXACT;
1157 }
1158}
1159
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001160static void hmp_acl_add(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001161{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001162 const char *aclname = qdict_get_str(qdict, "aclname");
1163 const char *match = qdict_get_str(qdict, "match");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001164 const char *policystr = qdict_get_str(qdict, "policy");
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001165 int has_index = qdict_haskey(qdict, "index");
1166 int index = qdict_get_try_int(qdict, "index", -1);
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001167 QAuthZList *auth = find_auth(mon, aclname);
1168 Error *err = NULL;
1169 QAuthZListPolicy policy;
1170 QAuthZListFormat format;
1171 size_t i = 0;
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001172
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001173 hmp_warn_acl();
1174
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001175 if (!auth) {
1176 return;
1177 }
1178
1179 policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
1180 policystr,
1181 QAUTHZ_LIST_POLICY_DENY,
1182 &err);
1183 if (err) {
1184 error_free(err);
1185 monitor_printf(mon, "acl: unknown policy '%s', "
1186 "expected 'deny' or 'allow'\n", policystr);
1187 return;
1188 }
1189
1190 format = hmp_acl_get_format(match);
1191
1192 if (has_index && index == 0) {
1193 monitor_printf(mon, "acl: unable to add acl entry\n");
1194 return;
1195 }
1196
1197 if (has_index) {
1198 i = qauthz_list_insert_rule(auth, match, policy,
1199 format, index - 1, &err);
1200 } else {
1201 i = qauthz_list_append_rule(auth, match, policy,
1202 format, &err);
1203 }
1204 if (err) {
1205 monitor_printf(mon, "acl: unable to add rule: %s",
1206 error_get_pretty(err));
1207 error_free(err);
1208 } else {
1209 monitor_printf(mon, "acl: added rule at position %zu\n", i + 1);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001210 }
1211}
aliguori76655d62009-03-06 20:27:37 +00001212
Markus Armbruster3e5a50d2015-02-06 13:55:43 +01001213static void hmp_acl_remove(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02001214{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001215 const char *aclname = qdict_get_str(qdict, "aclname");
1216 const char *match = qdict_get_str(qdict, "match");
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001217 QAuthZList *auth = find_auth(mon, aclname);
1218 ssize_t i = 0;
aliguori76655d62009-03-06 20:27:37 +00001219
Daniel P. Berrangé01438402019-02-27 14:57:55 +00001220 hmp_warn_acl();
1221
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +00001222 if (!auth) {
1223 return;
1224 }
1225
1226 i = qauthz_list_delete_rule(auth, match);
1227 if (i >= 0) {
1228 monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1);
1229 } else {
1230 monitor_printf(mon, "acl: no matching acl entry\n");
aliguori76655d62009-03-06 20:27:37 +00001231 }
1232}
1233
Corey Bryant208c9d12012-06-22 14:36:09 -04001234void qmp_getfd(const char *fdname, Error **errp)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001235{
Anthony Liguoric227f092009-10-01 16:12:16 -05001236 mon_fd_t *monfd;
Peter Xu9409fc02018-06-08 11:55:06 +08001237 int fd, tmp_fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001238
Marc-André Lureau5345fdb2016-10-22 12:52:55 +03001239 fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001240 if (fd == -1) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001241 error_setg(errp, QERR_FD_NOT_SUPPLIED);
Corey Bryant208c9d12012-06-22 14:36:09 -04001242 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001243 }
1244
1245 if (qemu_isdigit(fdname[0])) {
Stefan Hajnoczi0b9f0e22014-04-24 13:58:18 +02001246 close(fd);
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001247 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdname",
1248 "a name not starting with a digit");
Corey Bryant208c9d12012-06-22 14:36:09 -04001249 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001250 }
1251
Peter Xu9409fc02018-06-08 11:55:06 +08001252 qemu_mutex_lock(&cur_mon->mon_lock);
Corey Bryant208c9d12012-06-22 14:36:09 -04001253 QLIST_FOREACH(monfd, &cur_mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001254 if (strcmp(monfd->name, fdname) != 0) {
1255 continue;
1256 }
1257
Peter Xu9409fc02018-06-08 11:55:06 +08001258 tmp_fd = monfd->fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001259 monfd->fd = fd;
Peter Xu9409fc02018-06-08 11:55:06 +08001260 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbruster774a6b62018-07-03 10:53:57 +02001261 /* Make sure close() is outside critical section */
Peter Xu9409fc02018-06-08 11:55:06 +08001262 close(tmp_fd);
Corey Bryant208c9d12012-06-22 14:36:09 -04001263 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001264 }
1265
Anthony Liguori7267c092011-08-20 22:09:37 -05001266 monfd = g_malloc0(sizeof(mon_fd_t));
1267 monfd->name = g_strdup(fdname);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001268 monfd->fd = fd;
1269
Corey Bryant208c9d12012-06-22 14:36:09 -04001270 QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next);
Peter Xu9409fc02018-06-08 11:55:06 +08001271 qemu_mutex_unlock(&cur_mon->mon_lock);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001272}
1273
Corey Bryant208c9d12012-06-22 14:36:09 -04001274void qmp_closefd(const char *fdname, Error **errp)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001275{
Anthony Liguoric227f092009-10-01 16:12:16 -05001276 mon_fd_t *monfd;
Peter Xu9409fc02018-06-08 11:55:06 +08001277 int tmp_fd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001278
Peter Xu9409fc02018-06-08 11:55:06 +08001279 qemu_mutex_lock(&cur_mon->mon_lock);
Corey Bryant208c9d12012-06-22 14:36:09 -04001280 QLIST_FOREACH(monfd, &cur_mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001281 if (strcmp(monfd->name, fdname) != 0) {
1282 continue;
1283 }
1284
Blue Swirl72cf2d42009-09-12 07:36:22 +00001285 QLIST_REMOVE(monfd, next);
Peter Xu9409fc02018-06-08 11:55:06 +08001286 tmp_fd = monfd->fd;
Anthony Liguori7267c092011-08-20 22:09:37 -05001287 g_free(monfd->name);
1288 g_free(monfd);
Peter Xu9409fc02018-06-08 11:55:06 +08001289 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbruster774a6b62018-07-03 10:53:57 +02001290 /* Make sure close() is outside critical section */
Peter Xu9409fc02018-06-08 11:55:06 +08001291 close(tmp_fd);
Corey Bryant208c9d12012-06-22 14:36:09 -04001292 return;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001293 }
1294
Peter Xu9409fc02018-06-08 11:55:06 +08001295 qemu_mutex_unlock(&cur_mon->mon_lock);
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001296 error_setg(errp, QERR_FD_NOT_FOUND, fdname);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01001297}
1298
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001299int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
Mark McLoughlin7768e042009-07-22 09:11:41 +01001300{
Anthony Liguoric227f092009-10-01 16:12:16 -05001301 mon_fd_t *monfd;
Mark McLoughlin7768e042009-07-22 09:11:41 +01001302
Peter Xu9409fc02018-06-08 11:55:06 +08001303 qemu_mutex_lock(&mon->mon_lock);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001304 QLIST_FOREACH(monfd, &mon->fds, next) {
Mark McLoughlin7768e042009-07-22 09:11:41 +01001305 int fd;
1306
1307 if (strcmp(monfd->name, fdname) != 0) {
1308 continue;
1309 }
1310
1311 fd = monfd->fd;
1312
1313 /* caller takes ownership of fd */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001314 QLIST_REMOVE(monfd, next);
Anthony Liguori7267c092011-08-20 22:09:37 -05001315 g_free(monfd->name);
1316 g_free(monfd);
Peter Xu9409fc02018-06-08 11:55:06 +08001317 qemu_mutex_unlock(&mon->mon_lock);
Mark McLoughlin7768e042009-07-22 09:11:41 +01001318
1319 return fd;
1320 }
1321
Peter Xu9409fc02018-06-08 11:55:06 +08001322 qemu_mutex_unlock(&mon->mon_lock);
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001323 error_setg(errp, "File descriptor named '%s' has not been found", fdname);
Mark McLoughlin7768e042009-07-22 09:11:41 +01001324 return -1;
1325}
1326
Corey Bryantba1c0482012-08-14 16:43:43 -04001327static void monitor_fdset_cleanup(MonFdset *mon_fdset)
1328{
1329 MonFdsetFd *mon_fdset_fd;
1330 MonFdsetFd *mon_fdset_fd_next;
1331
1332 QLIST_FOREACH_SAFE(mon_fdset_fd, &mon_fdset->fds, next, mon_fdset_fd_next) {
Corey Bryantebe52b52012-10-18 15:19:33 -04001333 if ((mon_fdset_fd->removed ||
1334 (QLIST_EMPTY(&mon_fdset->dup_fds) && mon_refcount == 0)) &&
1335 runstate_is_running()) {
Corey Bryantba1c0482012-08-14 16:43:43 -04001336 close(mon_fdset_fd->fd);
1337 g_free(mon_fdset_fd->opaque);
1338 QLIST_REMOVE(mon_fdset_fd, next);
1339 g_free(mon_fdset_fd);
1340 }
1341 }
1342
Corey Bryantadb696f2012-08-14 16:43:47 -04001343 if (QLIST_EMPTY(&mon_fdset->fds) && QLIST_EMPTY(&mon_fdset->dup_fds)) {
Corey Bryantba1c0482012-08-14 16:43:43 -04001344 QLIST_REMOVE(mon_fdset, next);
1345 g_free(mon_fdset);
1346 }
1347}
1348
Kevin Wolf7e3c0de2019-06-13 17:34:00 +02001349void monitor_fdsets_cleanup(void)
Corey Bryantefb87c12012-08-14 16:43:48 -04001350{
1351 MonFdset *mon_fdset;
1352 MonFdset *mon_fdset_next;
1353
Peter Xu47451462018-06-08 11:55:11 +08001354 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantefb87c12012-08-14 16:43:48 -04001355 QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) {
1356 monitor_fdset_cleanup(mon_fdset);
1357 }
Peter Xu47451462018-06-08 11:55:11 +08001358 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantefb87c12012-08-14 16:43:48 -04001359}
1360
Corey Bryantba1c0482012-08-14 16:43:43 -04001361AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
1362 const char *opaque, Error **errp)
1363{
1364 int fd;
1365 Monitor *mon = cur_mon;
Corey Bryantba1c0482012-08-14 16:43:43 -04001366 AddfdInfo *fdinfo;
1367
Marc-André Lureau5345fdb2016-10-22 12:52:55 +03001368 fd = qemu_chr_fe_get_msgfd(&mon->chr);
Corey Bryantba1c0482012-08-14 16:43:43 -04001369 if (fd == -1) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001370 error_setg(errp, QERR_FD_NOT_SUPPLIED);
Corey Bryantba1c0482012-08-14 16:43:43 -04001371 goto error;
1372 }
1373
Corey Bryante446f702012-10-18 15:19:32 -04001374 fdinfo = monitor_fdset_add_fd(fd, has_fdset_id, fdset_id,
1375 has_opaque, opaque, errp);
1376 if (fdinfo) {
1377 return fdinfo;
Corey Bryant9ac54af2012-10-18 15:19:31 -04001378 }
1379
Corey Bryantba1c0482012-08-14 16:43:43 -04001380error:
1381 if (fd != -1) {
1382 close(fd);
1383 }
1384 return NULL;
1385}
1386
1387void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp)
1388{
1389 MonFdset *mon_fdset;
1390 MonFdsetFd *mon_fdset_fd;
1391 char fd_str[60];
1392
Peter Xu47451462018-06-08 11:55:11 +08001393 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001394 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1395 if (mon_fdset->id != fdset_id) {
1396 continue;
1397 }
1398 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1399 if (has_fd) {
1400 if (mon_fdset_fd->fd != fd) {
1401 continue;
1402 }
1403 mon_fdset_fd->removed = true;
1404 break;
1405 } else {
1406 mon_fdset_fd->removed = true;
1407 }
1408 }
1409 if (has_fd && !mon_fdset_fd) {
1410 goto error;
1411 }
1412 monitor_fdset_cleanup(mon_fdset);
Peter Xu47451462018-06-08 11:55:11 +08001413 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001414 return;
1415 }
1416
1417error:
Peter Xu47451462018-06-08 11:55:11 +08001418 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001419 if (has_fd) {
1420 snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64,
1421 fdset_id, fd);
1422 } else {
1423 snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64, fdset_id);
1424 }
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001425 error_setg(errp, QERR_FD_NOT_FOUND, fd_str);
Corey Bryantba1c0482012-08-14 16:43:43 -04001426}
1427
1428FdsetInfoList *qmp_query_fdsets(Error **errp)
1429{
1430 MonFdset *mon_fdset;
1431 MonFdsetFd *mon_fdset_fd;
1432 FdsetInfoList *fdset_list = NULL;
1433
Peter Xu47451462018-06-08 11:55:11 +08001434 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001435 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1436 FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
1437 FdsetFdInfoList *fdsetfd_list = NULL;
1438
1439 fdset_info->value = g_malloc0(sizeof(*fdset_info->value));
1440 fdset_info->value->fdset_id = mon_fdset->id;
1441
1442 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1443 FdsetFdInfoList *fdsetfd_info;
1444
1445 fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
1446 fdsetfd_info->value = g_malloc0(sizeof(*fdsetfd_info->value));
1447 fdsetfd_info->value->fd = mon_fdset_fd->fd;
1448 if (mon_fdset_fd->opaque) {
1449 fdsetfd_info->value->has_opaque = true;
1450 fdsetfd_info->value->opaque = g_strdup(mon_fdset_fd->opaque);
1451 } else {
1452 fdsetfd_info->value->has_opaque = false;
1453 }
1454
1455 fdsetfd_info->next = fdsetfd_list;
1456 fdsetfd_list = fdsetfd_info;
1457 }
1458
1459 fdset_info->value->fds = fdsetfd_list;
1460
1461 fdset_info->next = fdset_list;
1462 fdset_list = fdset_info;
1463 }
Peter Xu47451462018-06-08 11:55:11 +08001464 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantba1c0482012-08-14 16:43:43 -04001465
1466 return fdset_list;
1467}
1468
Corey Bryante446f702012-10-18 15:19:32 -04001469AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
1470 bool has_opaque, const char *opaque,
1471 Error **errp)
1472{
1473 MonFdset *mon_fdset = NULL;
1474 MonFdsetFd *mon_fdset_fd;
1475 AddfdInfo *fdinfo;
1476
Daniel Brodsky6e8a3552020-04-03 21:21:08 -07001477 QEMU_LOCK_GUARD(&mon_fdsets_lock);
Corey Bryante446f702012-10-18 15:19:32 -04001478 if (has_fdset_id) {
1479 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1480 /* Break if match found or match impossible due to ordering by ID */
1481 if (fdset_id <= mon_fdset->id) {
1482 if (fdset_id < mon_fdset->id) {
1483 mon_fdset = NULL;
1484 }
1485 break;
1486 }
1487 }
1488 }
1489
1490 if (mon_fdset == NULL) {
1491 int64_t fdset_id_prev = -1;
1492 MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets);
1493
1494 if (has_fdset_id) {
1495 if (fdset_id < 0) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001496 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",
1497 "a non-negative value");
Corey Bryante446f702012-10-18 15:19:32 -04001498 return NULL;
1499 }
1500 /* Use specified fdset ID */
1501 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1502 mon_fdset_cur = mon_fdset;
1503 if (fdset_id < mon_fdset_cur->id) {
1504 break;
1505 }
1506 }
1507 } else {
1508 /* Use first available fdset ID */
1509 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1510 mon_fdset_cur = mon_fdset;
1511 if (fdset_id_prev == mon_fdset_cur->id - 1) {
1512 fdset_id_prev = mon_fdset_cur->id;
1513 continue;
1514 }
1515 break;
1516 }
1517 }
1518
1519 mon_fdset = g_malloc0(sizeof(*mon_fdset));
1520 if (has_fdset_id) {
1521 mon_fdset->id = fdset_id;
1522 } else {
1523 mon_fdset->id = fdset_id_prev + 1;
1524 }
1525
1526 /* The fdset list is ordered by fdset ID */
1527 if (!mon_fdset_cur) {
1528 QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next);
1529 } else if (mon_fdset->id < mon_fdset_cur->id) {
1530 QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next);
1531 } else {
1532 QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next);
1533 }
1534 }
1535
1536 mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd));
1537 mon_fdset_fd->fd = fd;
1538 mon_fdset_fd->removed = false;
1539 if (has_opaque) {
1540 mon_fdset_fd->opaque = g_strdup(opaque);
1541 }
1542 QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next);
1543
1544 fdinfo = g_malloc0(sizeof(*fdinfo));
1545 fdinfo->fdset_id = mon_fdset->id;
1546 fdinfo->fd = mon_fdset_fd->fd;
1547
1548 return fdinfo;
1549}
1550
Corey Bryantadb696f2012-08-14 16:43:47 -04001551int monitor_fdset_get_fd(int64_t fdset_id, int flags)
1552{
Peter Xu47451462018-06-08 11:55:11 +08001553#ifdef _WIN32
1554 return -ENOENT;
1555#else
Corey Bryantadb696f2012-08-14 16:43:47 -04001556 MonFdset *mon_fdset;
1557 MonFdsetFd *mon_fdset_fd;
1558 int mon_fd_flags;
Peter Xu47451462018-06-08 11:55:11 +08001559 int ret;
Corey Bryantadb696f2012-08-14 16:43:47 -04001560
Peter Xu47451462018-06-08 11:55:11 +08001561 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001562 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1563 if (mon_fdset->id != fdset_id) {
1564 continue;
1565 }
1566 QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
1567 mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
1568 if (mon_fd_flags == -1) {
Peter Xu47451462018-06-08 11:55:11 +08001569 ret = -errno;
1570 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001571 }
1572
1573 if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
Peter Xu47451462018-06-08 11:55:11 +08001574 ret = mon_fdset_fd->fd;
1575 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001576 }
1577 }
Peter Xu47451462018-06-08 11:55:11 +08001578 ret = -EACCES;
1579 goto out;
Corey Bryantadb696f2012-08-14 16:43:47 -04001580 }
Peter Xu47451462018-06-08 11:55:11 +08001581 ret = -ENOENT;
Corey Bryantadb696f2012-08-14 16:43:47 -04001582
Peter Xu47451462018-06-08 11:55:11 +08001583out:
1584 qemu_mutex_unlock(&mon_fdsets_lock);
1585 return ret;
1586#endif
Corey Bryantadb696f2012-08-14 16:43:47 -04001587}
1588
1589int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
1590{
1591 MonFdset *mon_fdset;
1592 MonFdsetFd *mon_fdset_fd_dup;
1593
Peter Xu47451462018-06-08 11:55:11 +08001594 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001595 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1596 if (mon_fdset->id != fdset_id) {
1597 continue;
1598 }
1599 QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
1600 if (mon_fdset_fd_dup->fd == dup_fd) {
Peter Xu47451462018-06-08 11:55:11 +08001601 goto err;
Corey Bryantadb696f2012-08-14 16:43:47 -04001602 }
1603 }
1604 mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
1605 mon_fdset_fd_dup->fd = dup_fd;
1606 QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
Peter Xu47451462018-06-08 11:55:11 +08001607 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001608 return 0;
1609 }
Peter Xu47451462018-06-08 11:55:11 +08001610
1611err:
1612 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001613 return -1;
1614}
1615
Yury Kotov854f63d2019-05-23 12:44:33 +03001616static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
Corey Bryantadb696f2012-08-14 16:43:47 -04001617{
1618 MonFdset *mon_fdset;
1619 MonFdsetFd *mon_fdset_fd_dup;
1620
Peter Xu47451462018-06-08 11:55:11 +08001621 qemu_mutex_lock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001622 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
1623 QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
1624 if (mon_fdset_fd_dup->fd == dup_fd) {
1625 if (remove) {
1626 QLIST_REMOVE(mon_fdset_fd_dup, next);
Chen Quna6616142020-01-15 15:20:16 +08001627 g_free(mon_fdset_fd_dup);
Corey Bryantadb696f2012-08-14 16:43:47 -04001628 if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
1629 monitor_fdset_cleanup(mon_fdset);
1630 }
Peter Xu47451462018-06-08 11:55:11 +08001631 goto err;
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001632 } else {
Peter Xu47451462018-06-08 11:55:11 +08001633 qemu_mutex_unlock(&mon_fdsets_lock);
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001634 return mon_fdset->id;
Corey Bryantadb696f2012-08-14 16:43:47 -04001635 }
Corey Bryantadb696f2012-08-14 16:43:47 -04001636 }
1637 }
1638 }
Peter Xu47451462018-06-08 11:55:11 +08001639
1640err:
1641 qemu_mutex_unlock(&mon_fdsets_lock);
Corey Bryantadb696f2012-08-14 16:43:47 -04001642 return -1;
1643}
1644
Yury Kotov854f63d2019-05-23 12:44:33 +03001645int64_t monitor_fdset_dup_fd_find(int dup_fd)
Corey Bryantadb696f2012-08-14 16:43:47 -04001646{
1647 return monitor_fdset_dup_fd_find_remove(dup_fd, false);
1648}
1649
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001650void monitor_fdset_dup_fd_remove(int dup_fd)
Corey Bryantadb696f2012-08-14 16:43:47 -04001651{
Michael S. Tsirkinb3dd1b82014-08-17 11:45:17 +02001652 monitor_fdset_dup_fd_find_remove(dup_fd, true);
Corey Bryantadb696f2012-08-14 16:43:47 -04001653}
1654
Markus Armbruster1677f4c2015-02-09 14:03:19 +01001655int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp)
Laszlo Ersek59063662014-04-10 10:24:31 +02001656{
1657 int fd;
1658 Error *local_err = NULL;
1659
1660 if (!qemu_isdigit(fdname[0]) && mon) {
Paolo Bonzinia9940fc2012-09-20 16:50:32 +02001661 fd = monitor_get_fd(mon, fdname, &local_err);
Nicholas Bellingera96ed022012-08-21 20:52:07 +00001662 } else {
1663 fd = qemu_parse_fd(fdname);
Laszlo Ersek59063662014-04-10 10:24:31 +02001664 if (fd == -1) {
1665 error_setg(&local_err, "Invalid file descriptor number '%s'",
1666 fdname);
1667 }
1668 }
1669 if (local_err) {
1670 error_propagate(errp, local_err);
1671 assert(fd == -1);
1672 } else {
1673 assert(fd != -1);
Nicholas Bellingera96ed022012-08-21 20:52:07 +00001674 }
1675
1676 return fd;
1677}
1678
Luiz Capitulinoacd0a092010-09-30 16:00:22 -03001679/* Please update hmp-commands.hx when adding or changing commands */
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02001680static HMPCommand hmp_info_cmds[] = {
Pavel Butsykinda76ee72015-09-10 18:38:58 +03001681#include "hmp-commands-info.h"
1682 { NULL, NULL, },
bellard9dc39cb2004-03-14 21:38:27 +00001683};
1684
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02001685/* hmp_cmds and hmp_info_cmds would be sorted at runtime */
Kevin Wolfed7bda52019-06-13 17:34:01 +02001686HMPCommand hmp_cmds[] = {
Wenchao Xiaa13ced52013-01-14 14:06:28 +08001687#include "hmp-commands.h"
1688 { NULL, NULL, },
1689};
1690
Kevin Wolfed7bda52019-06-13 17:34:01 +02001691/*
1692 * Set @pval to the value in the register identified by @name.
1693 * return 0 if OK, -1 if not found
1694 */
1695int get_monitor_def(int64_t *pval, const char *name)
bellard9307c4c2004-04-04 12:57:25 +00001696{
Pavel Butsykinbf957282015-09-10 18:38:59 +03001697 const MonitorDef *md = target_monitor_defs();
Thomas Huth854e67f2017-01-13 13:12:35 +01001698 CPUState *cs = mon_get_cpu();
bellard92a31b12005-02-10 22:00:52 +00001699 void *ptr;
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001700 uint64_t tmp = 0;
1701 int ret;
bellard92a31b12005-02-10 22:00:52 +00001702
Thomas Huth854e67f2017-01-13 13:12:35 +01001703 if (cs == NULL || md == NULL) {
Pavel Butsykinbf957282015-09-10 18:38:59 +03001704 return -1;
1705 }
1706
1707 for(; md->name != NULL; md++) {
Kevin Wolfed7bda52019-06-13 17:34:01 +02001708 if (hmp_compare_cmd(name, md->name)) {
bellard9307c4c2004-04-04 12:57:25 +00001709 if (md->get_value) {
bellarde95c8d52004-09-30 22:22:08 +00001710 *pval = md->get_value(md, md->offset);
bellard9307c4c2004-04-04 12:57:25 +00001711 } else {
Peter Crosthwaite5bcda5f2015-05-24 14:20:40 -07001712 CPUArchState *env = mon_get_cpu_env();
bellard6a00d602005-11-21 23:25:50 +00001713 ptr = (uint8_t *)env + md->offset;
bellard92a31b12005-02-10 22:00:52 +00001714 switch(md->type) {
1715 case MD_I32:
1716 *pval = *(int32_t *)ptr;
1717 break;
1718 case MD_TLONG:
1719 *pval = *(target_long *)ptr;
1720 break;
1721 default:
1722 *pval = 0;
1723 break;
1724 }
bellard9307c4c2004-04-04 12:57:25 +00001725 }
1726 return 0;
1727 }
1728 }
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001729
Thomas Huth854e67f2017-01-13 13:12:35 +01001730 ret = target_get_monitor_def(cs, name, &tmp);
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +11001731 if (!ret) {
1732 *pval = (target_long) tmp;
1733 }
1734
1735 return ret;
bellard9307c4c2004-04-04 12:57:25 +00001736}
1737
Hani Benhabiles40d19392014-05-07 23:41:30 +01001738static void add_completion_option(ReadLineState *rs, const char *str,
1739 const char *option)
1740{
1741 if (!str || !option) {
1742 return;
1743 }
1744 if (!strncmp(option, str, strlen(str))) {
1745 readline_add_completion(rs, option);
1746 }
1747}
1748
Hani Benhabiles13e315d2014-05-07 23:41:29 +01001749void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
1750{
1751 size_t len;
1752 ChardevBackendInfoList *list, *start;
1753
1754 if (nb_args != 2) {
1755 return;
1756 }
1757 len = strlen(str);
1758 readline_set_completion_index(rs, len);
1759
1760 start = list = qmp_query_chardev_backends(NULL);
1761 while (list) {
1762 const char *chr_name = list->value->name;
1763
1764 if (!strncmp(chr_name, str, len)) {
1765 readline_add_completion(rs, chr_name);
1766 }
1767 list = list->next;
1768 }
1769 qapi_free_ChardevBackendInfoList(start);
1770}
1771
Hani Benhabilesb162b492014-05-07 23:41:31 +01001772void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
1773{
1774 size_t len;
1775 int i;
1776
1777 if (nb_args != 2) {
1778 return;
1779 }
1780 len = strlen(str);
1781 readline_set_completion_index(rs, len);
Markus Armbruster1c236ba2017-08-24 10:46:06 +02001782 for (i = 0; i < NET_CLIENT_DRIVER__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02001783 add_completion_option(rs, str, NetClientDriver_str(i));
Hani Benhabilesb162b492014-05-07 23:41:31 +01001784 }
1785}
1786
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001787void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001788{
1789 GSList *list, *elt;
1790 size_t len;
1791
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001792 if (nb_args != 2) {
1793 return;
1794 }
1795
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001796 len = strlen(str);
1797 readline_set_completion_index(rs, len);
1798 list = elt = object_class_get_list(TYPE_DEVICE, false);
1799 while (elt) {
1800 const char *name;
1801 DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
1802 TYPE_DEVICE);
1803 name = object_class_get_name(OBJECT_CLASS(dc));
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001804
Eduardo Habkoste90f2a82017-05-03 17:35:44 -03001805 if (dc->user_creatable
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001806 && !strncmp(name, str, len)) {
Hani Benhabiles992d3e62014-02-06 23:30:11 +01001807 readline_add_completion(rs, name);
1808 }
1809 elt = elt->next;
1810 }
1811 g_slist_free(list);
1812}
1813
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001814void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabiles1094fd32014-02-06 23:30:13 +01001815{
1816 GSList *list, *elt;
1817 size_t len;
1818
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001819 if (nb_args != 2) {
1820 return;
1821 }
1822
Hani Benhabiles1094fd32014-02-06 23:30:13 +01001823 len = strlen(str);
1824 readline_set_completion_index(rs, len);
1825 list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
1826 while (elt) {
1827 const char *name;
1828
1829 name = object_class_get_name(OBJECT_CLASS(elt->data));
1830 if (!strncmp(name, str, len) && strcmp(name, TYPE_USER_CREATABLE)) {
1831 readline_add_completion(rs, name);
1832 }
1833 elt = elt->next;
1834 }
1835 g_slist_free(list);
1836}
1837
Marc-André Lureau91590152020-01-10 19:30:17 +04001838static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
1839{
1840 GSList **list = opaque;
Philippe Mathieu-Daudé688ffbb2020-05-12 09:00:19 +02001841 DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
Marc-André Lureau91590152020-01-10 19:30:17 +04001842
1843 if (dev == NULL) {
1844 return 0;
1845 }
1846
1847 if (dev->realized && object_property_get_bool(obj, "hotpluggable", NULL)) {
1848 *list = g_slist_append(*list, dev);
1849 }
1850
1851 return 0;
1852}
1853
1854static GSList *qdev_build_hotpluggable_device_list(Object *peripheral)
1855{
1856 GSList *list = NULL;
1857
1858 object_child_foreach(peripheral, qdev_add_hotpluggable_device, &list);
1859
1860 return list;
1861}
1862
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001863static void peripheral_device_del_completion(ReadLineState *rs,
1864 const char *str, size_t len)
1865{
Marcel Apfelbaum4cae4d52014-11-26 13:50:01 +02001866 Object *peripheral = container_get(qdev_get_machine(), "/peripheral");
1867 GSList *list, *item;
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001868
Marcel Apfelbaum4cae4d52014-11-26 13:50:01 +02001869 list = qdev_build_hotpluggable_device_list(peripheral);
1870 if (!list) {
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001871 return;
1872 }
1873
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001874 for (item = list; item; item = g_slist_next(item)) {
1875 DeviceState *dev = item->data;
1876
1877 if (dev->id && !strncmp(str, dev->id, len)) {
1878 readline_add_completion(rs, dev->id);
1879 }
1880 }
1881
1882 g_slist_free(list);
1883}
1884
Hani Benhabiles6297d9a2014-05-07 23:41:28 +01001885void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
1886{
1887 size_t len;
1888 ChardevInfoList *list, *start;
1889
1890 if (nb_args != 2) {
1891 return;
1892 }
1893 len = strlen(str);
1894 readline_set_completion_index(rs, len);
1895
1896 start = list = qmp_query_chardev(NULL);
1897 while (list) {
1898 ChardevInfo *chr = list->value;
1899
1900 if (!strncmp(chr->label, str, len)) {
1901 readline_add_completion(rs, chr->label);
1902 }
1903 list = list->next;
1904 }
1905 qapi_free_ChardevInfoList(start);
1906}
1907
Hani Benhabiles8e597772014-05-27 23:39:30 +01001908static void ringbuf_completion(ReadLineState *rs, const char *str)
1909{
1910 size_t len;
1911 ChardevInfoList *list, *start;
1912
1913 len = strlen(str);
1914 readline_set_completion_index(rs, len);
1915
1916 start = list = qmp_query_chardev(NULL);
1917 while (list) {
1918 ChardevInfo *chr_info = list->value;
1919
1920 if (!strncmp(chr_info->label, str, len)) {
Marc-André Lureau0ec7b3e2016-12-07 16:20:22 +03001921 Chardev *chr = qemu_chr_find(chr_info->label);
Marc-André Lureau777357d2016-12-07 18:39:10 +03001922 if (chr && CHARDEV_IS_RINGBUF(chr)) {
Hani Benhabiles8e597772014-05-27 23:39:30 +01001923 readline_add_completion(rs, chr_info->label);
1924 }
1925 }
1926 list = list->next;
1927 }
1928 qapi_free_ChardevInfoList(start);
1929}
1930
Hani Benhabiles8e597772014-05-27 23:39:30 +01001931void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
1932{
1933 if (nb_args != 2) {
1934 return;
1935 }
1936 ringbuf_completion(rs, str);
1937}
1938
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001939void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
1940{
1941 size_t len;
1942
1943 if (nb_args != 2) {
1944 return;
1945 }
1946
1947 len = strlen(str);
1948 readline_set_completion_index(rs, len);
Zhu Guihua6a1fa9f2014-10-21 19:46:05 +08001949 peripheral_device_del_completion(rs, str, len);
Hani Benhabiles2da1b3a2014-04-13 16:25:07 +01001950}
1951
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001952void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
Hani Benhabilesb48fa072014-02-06 23:30:12 +01001953{
1954 ObjectPropertyInfoList *list, *start;
1955 size_t len;
1956
Hani Benhabilesbfa40f72014-04-13 16:25:06 +01001957 if (nb_args != 2) {
1958 return;
1959 }
Hani Benhabilesb48fa072014-02-06 23:30:12 +01001960 len = strlen(str);
1961 readline_set_completion_index(rs, len);
1962
1963 start = list = qmp_qom_list("/objects", NULL);
1964 while (list) {
1965 ObjectPropertyInfo *info = list->value;
1966
1967 if (!strncmp(info->type, "child<", 5)
1968 && !strncmp(info->name, str, len)) {
1969 readline_add_completion(rs, info->name);
1970 }
1971 list = list->next;
1972 }
1973 qapi_free_ObjectPropertyInfoList(start);
1974}
1975
Hani Benhabiles29136cd2014-05-07 23:41:27 +01001976void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
1977{
1978 int i;
1979 char *sep;
1980 size_t len;
1981
1982 if (nb_args != 2) {
1983 return;
1984 }
1985 sep = strrchr(str, '-');
1986 if (sep) {
1987 str = sep + 1;
1988 }
1989 len = strlen(str);
1990 readline_set_completion_index(rs, len);
Eric Blake7fb1cf12015-11-18 01:52:57 -07001991 for (i = 0; i < Q_KEY_CODE__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02001992 if (!strncmp(str, QKeyCode_str(i), len)) {
1993 readline_add_completion(rs, QKeyCode_str(i));
Hani Benhabiles29136cd2014-05-07 23:41:27 +01001994 }
1995 }
1996}
1997
Hani Benhabiles40d19392014-05-07 23:41:30 +01001998void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
1999{
2000 size_t len;
2001
2002 len = strlen(str);
2003 readline_set_completion_index(rs, len);
2004 if (nb_args == 2) {
Jason Wangeaed4832015-04-23 14:21:38 +08002005 NetClientState *ncs[MAX_QUEUE_NUM];
Hani Benhabiles40d19392014-05-07 23:41:30 +01002006 int count, i;
2007 count = qemu_find_net_clients_except(NULL, ncs,
Eric Blakef394b2e2016-07-13 21:50:23 -06002008 NET_CLIENT_DRIVER_NONE,
Jason Wangeaed4832015-04-23 14:21:38 +08002009 MAX_QUEUE_NUM);
Jason Wangbcfa4d62015-04-23 14:21:39 +08002010 for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
Hani Benhabiles40d19392014-05-07 23:41:30 +01002011 const char *name = ncs[i]->name;
2012 if (!strncmp(str, name, len)) {
2013 readline_add_completion(rs, name);
2014 }
2015 }
2016 } else if (nb_args == 3) {
2017 add_completion_option(rs, str, "on");
2018 add_completion_option(rs, str, "off");
2019 }
2020}
2021
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002022void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
2023{
2024 int len, count, i;
Jason Wangeaed4832015-04-23 14:21:38 +08002025 NetClientState *ncs[MAX_QUEUE_NUM];
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002026
2027 if (nb_args != 2) {
2028 return;
2029 }
2030
2031 len = strlen(str);
2032 readline_set_completion_index(rs, len);
Eric Blakef394b2e2016-07-13 21:50:23 -06002033 count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_DRIVER_NIC,
Jason Wangeaed4832015-04-23 14:21:38 +08002034 MAX_QUEUE_NUM);
Jason Wangbcfa4d62015-04-23 14:21:39 +08002035 for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002036 const char *name = ncs[i]->name;
2037 if (strncmp(str, name, len)) {
2038 continue;
2039 }
Eric Blake08712fc2020-03-17 15:17:11 -05002040 if (ncs[i]->is_netdev) {
Hani Benhabiles11b389f2014-05-07 23:41:32 +01002041 readline_add_completion(rs, name);
2042 }
2043 }
2044}
2045
Lluís Vilanovabd712112016-07-11 12:53:51 +02002046void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *str)
2047{
2048 size_t len;
2049
2050 len = strlen(str);
2051 readline_set_completion_index(rs, len);
2052 if (nb_args == 2) {
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002053 TraceEventIter iter;
2054 TraceEvent *ev;
2055 char *pattern = g_strdup_printf("%s*", str);
2056 trace_event_iter_init(&iter, pattern);
2057 while ((ev = trace_event_iter_next(&iter)) != NULL) {
2058 readline_add_completion(rs, trace_event_get_name(ev));
Lluís Vilanovabd712112016-07-11 12:53:51 +02002059 }
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002060 g_free(pattern);
Lluís Vilanovabd712112016-07-11 12:53:51 +02002061 }
2062}
2063
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002064void trace_event_completion(ReadLineState *rs, int nb_args, const char *str)
2065{
2066 size_t len;
2067
2068 len = strlen(str);
2069 readline_set_completion_index(rs, len);
2070 if (nb_args == 2) {
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002071 TraceEventIter iter;
2072 TraceEvent *ev;
2073 char *pattern = g_strdup_printf("%s*", str);
2074 trace_event_iter_init(&iter, pattern);
2075 while ((ev = trace_event_iter_next(&iter)) != NULL) {
2076 readline_add_completion(rs, trace_event_get_name(ev));
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002077 }
Daniel P. Berrange0d4e9952016-10-04 14:35:43 +01002078 g_free(pattern);
Dr. David Alan Gilbert987bd272015-08-14 11:27:43 +01002079 } else if (nb_args == 3) {
2080 add_completion_option(rs, str, "on");
2081 add_completion_option(rs, str, "off");
2082 }
2083}
2084
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002085void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
2086{
Hani Benhabiles4bb08af2014-07-29 23:22:40 +01002087 int i;
2088
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002089 if (nb_args != 2) {
2090 return;
2091 }
2092 readline_set_completion_index(rs, strlen(str));
Michal Privoznik14d53b42017-09-07 10:05:24 +02002093 for (i = 0; i < WATCHDOG_ACTION__MAX; i++) {
2094 add_completion_option(rs, str, WatchdogAction_str(i));
Hani Benhabiles4bb08af2014-07-29 23:22:40 +01002095 }
Hani Benhabilesd0ece342014-05-27 23:39:31 +01002096}
2097
Hani Benhabilesc68a0402014-05-27 23:39:32 +01002098void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
2099 const char *str)
2100{
2101 size_t len;
2102
2103 len = strlen(str);
2104 readline_set_completion_index(rs, len);
2105 if (nb_args == 2) {
2106 int i;
Eric Blake7fb1cf12015-11-18 01:52:57 -07002107 for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02002108 const char *name = MigrationCapability_str(i);
Hani Benhabilesc68a0402014-05-27 23:39:32 +01002109 if (!strncmp(str, name, len)) {
2110 readline_add_completion(rs, name);
2111 }
2112 }
2113 } else if (nb_args == 3) {
2114 add_completion_option(rs, str, "on");
2115 add_completion_option(rs, str, "off");
2116 }
2117}
2118
Liang Li50e9a622015-03-23 16:32:29 +08002119void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
2120 const char *str)
2121{
2122 size_t len;
2123
2124 len = strlen(str);
2125 readline_set_completion_index(rs, len);
2126 if (nb_args == 2) {
2127 int i;
Eric Blake7fb1cf12015-11-18 01:52:57 -07002128 for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
Markus Armbruster977c7362017-08-24 10:46:08 +02002129 const char *name = MigrationParameter_str(i);
Liang Li50e9a622015-03-23 16:32:29 +08002130 if (!strncmp(str, name, len)) {
2131 readline_add_completion(rs, name);
2132 }
2133 }
2134 }
2135}
2136
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002137static void vm_completion(ReadLineState *rs, const char *str)
2138{
2139 size_t len;
Kevin Wolf7c8eece2016-03-22 18:58:50 +01002140 BlockDriverState *bs;
Kevin Wolf88be7b42016-05-20 18:49:07 +02002141 BdrvNextIterator it;
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002142
2143 len = strlen(str);
2144 readline_set_completion_index(rs, len);
Kevin Wolf7c8eece2016-03-22 18:58:50 +01002145
Kevin Wolf88be7b42016-05-20 18:49:07 +02002146 for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002147 SnapshotInfoList *snapshots, *snapshot;
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002148 AioContext *ctx = bdrv_get_aio_context(bs);
2149 bool ok = false;
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002150
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002151 aio_context_acquire(ctx);
2152 if (bdrv_can_snapshot(bs)) {
2153 ok = bdrv_query_snapshot_info_list(bs, &snapshots, NULL) == 0;
2154 }
2155 aio_context_release(ctx);
2156 if (!ok) {
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002157 continue;
2158 }
Denis V. Lunev6bf1faa2015-11-04 20:19:42 +03002159
Hani Benhabilesb21631f2014-05-27 23:39:37 +01002160 snapshot = snapshots;
2161 while (snapshot) {
2162 char *completion = snapshot->value->name;
2163 if (!strncmp(str, completion, len)) {
2164 readline_add_completion(rs, completion);
2165 }
2166 completion = snapshot->value->id;
2167 if (!strncmp(str, completion, len)) {
2168 readline_add_completion(rs, completion);
2169 }
2170 snapshot = snapshot->next;
2171 }
2172 qapi_free_SnapshotInfoList(snapshots);
2173 }
2174
2175}
2176
2177void delvm_completion(ReadLineState *rs, int nb_args, const char *str)
2178{
2179 if (nb_args == 2) {
2180 vm_completion(rs, str);
2181 }
2182}
2183
2184void loadvm_completion(ReadLineState *rs, int nb_args, const char *str)
2185{
2186 if (nb_args == 2) {
2187 vm_completion(rs, str);
2188 }
2189}
2190
Wayne Xia816f8922011-10-12 11:32:41 +08002191static int
2192compare_mon_cmd(const void *a, const void *b)
2193{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02002194 return strcmp(((const HMPCommand *)a)->name,
2195 ((const HMPCommand *)b)->name);
Wayne Xia816f8922011-10-12 11:32:41 +08002196}
2197
2198static void sortcmdlist(void)
2199{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +02002200 qsort(hmp_cmds, ARRAY_SIZE(hmp_cmds) - 1,
2201 sizeof(*hmp_cmds),
2202 compare_mon_cmd);
2203 qsort(hmp_info_cmds, ARRAY_SIZE(hmp_info_cmds) - 1,
2204 sizeof(*hmp_info_cmds),
2205 compare_mon_cmd);
Wayne Xia816f8922011-10-12 11:32:41 +08002206}
2207
Peter Xu6adf08d2018-03-09 16:59:50 +08002208void monitor_init_globals(void)
2209{
Kevin Wolf1d95db72019-06-13 17:34:02 +02002210 monitor_init_globals_core();
Peter Xu6adf08d2018-03-09 16:59:50 +08002211 monitor_init_qmp_commands();
Peter Xu6adf08d2018-03-09 16:59:50 +08002212 sortcmdlist();
Peter Xu47451462018-06-08 11:55:11 +08002213 qemu_mutex_init(&mon_fdsets_lock);
Peter Xu6adf08d2018-03-09 16:59:50 +08002214}