blob: 381f348562ab8b72c79089f68cb77415d2b4f9d1 [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 */
blueswir1511d2b12009-03-07 15:32:56 +000024#include <dirent.h>
pbrook87ecb682007-11-17 17:14:51 +000025#include "hw/hw.h"
Gerd Hoffmanncae49562009-06-05 15:53:17 +010026#include "hw/qdev.h"
pbrook87ecb682007-11-17 17:14:51 +000027#include "hw/usb.h"
28#include "hw/pcmcia.h"
29#include "hw/pc.h"
30#include "hw/pci.h"
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +010031#include "hw/watchdog.h"
Gerd Hoffmann45a50b12009-10-01 16:42:33 +020032#include "hw/loader.h"
pbrook87ecb682007-11-17 17:14:51 +000033#include "gdbstub.h"
34#include "net.h"
Mark McLoughlin68ac40d2009-11-25 18:48:54 +000035#include "net/slirp.h"
pbrook87ecb682007-11-17 17:14:51 +000036#include "qemu-char.h"
37#include "sysemu.h"
aliguori376253e2009-03-05 23:01:23 +000038#include "monitor.h"
39#include "readline.h"
pbrook87ecb682007-11-17 17:14:51 +000040#include "console.h"
41#include "block.h"
42#include "audio/audio.h"
bellard9307c4c2004-04-04 12:57:25 +000043#include "disas.h"
aliguoridf751fa2008-12-04 20:19:35 +000044#include "balloon.h"
balrogc8256f92008-06-08 22:45:01 +000045#include "qemu-timer.h"
aliguori5bb79102008-10-13 03:12:02 +000046#include "migration.h"
aliguori7ba1e612008-11-05 16:04:33 +000047#include "kvm.h"
aliguori76655d62009-03-06 20:27:37 +000048#include "acl.h"
Luiz Capitulinof7188bb2009-08-28 15:27:10 -030049#include "qint.h"
Luiz Capitulino8f3cec02009-10-07 13:42:04 -030050#include "qlist.h"
Luiz Capitulinof7188bb2009-08-28 15:27:10 -030051#include "qdict.h"
Luiz Capitulino5fa737a2009-11-26 22:59:01 -020052#include "qbool.h"
Luiz Capitulinof7188bb2009-08-28 15:27:10 -030053#include "qstring.h"
Luiz Capitulino8204a912009-11-18 23:05:31 -020054#include "qerror.h"
Luiz Capitulino9b57c022009-11-26 22:58:58 -020055#include "qjson.h"
Luiz Capitulino5fa737a2009-11-26 22:59:01 -020056#include "json-streamer.h"
57#include "json-parser.h"
Blue Swirld08d6f02009-12-04 18:06:39 +000058#include "osdep.h"
ths6a5bd302007-12-03 17:05:38 +000059
bellard9dc39cb2004-03-14 21:38:27 +000060//#define DEBUG
bellard81d09122004-07-14 17:21:37 +000061//#define DEBUG_COMPLETION
bellard9dc39cb2004-03-14 21:38:27 +000062
bellard9307c4c2004-04-04 12:57:25 +000063/*
64 * Supported types:
ths5fafdf22007-09-16 21:08:06 +000065 *
bellard9307c4c2004-04-04 12:57:25 +000066 * 'F' filename
bellard81d09122004-07-14 17:21:37 +000067 * 'B' block device name
bellard9307c4c2004-04-04 12:57:25 +000068 * 's' string (accept optional quote)
bellard92a31b12005-02-10 22:00:52 +000069 * 'i' 32 bit integer
70 * 'l' target long (32 or 64 bit)
Markus Armbruster9fec5432010-01-25 14:23:01 +010071 * 'M' just like 'l', except in user mode the value is
72 * multiplied by 2^20 (think Mebibyte)
bellard9307c4c2004-04-04 12:57:25 +000073 * '/' optional gdb-like print format (like "/10x")
74 *
Luiz Capitulinofb466602009-08-28 15:27:27 -030075 * '?' optional type (for all types, except '/')
76 * '.' other form of optional type (for 'i' and 'l')
77 * '-' optional parameter (eg. '-f')
bellard9307c4c2004-04-04 12:57:25 +000078 *
79 */
80
Adam Litke940cc302010-01-25 12:18:44 -060081typedef struct MonitorCompletionData MonitorCompletionData;
82struct MonitorCompletionData {
83 Monitor *mon;
84 void (*user_print)(Monitor *mon, const QObject *data);
85};
86
Anthony Liguoric227f092009-10-01 16:12:16 -050087typedef struct mon_cmd_t {
bellard9dc39cb2004-03-14 21:38:27 +000088 const char *name;
bellard9307c4c2004-04-04 12:57:25 +000089 const char *args_type;
bellard9dc39cb2004-03-14 21:38:27 +000090 const char *params;
91 const char *help;
Luiz Capitulinoa2876f52009-10-07 13:41:53 -030092 void (*user_print)(Monitor *mon, const QObject *data);
Luiz Capitulino910df892009-10-07 13:41:51 -030093 union {
94 void (*info)(Monitor *mon);
Luiz Capitulino13c74252009-10-07 13:41:55 -030095 void (*info_new)(Monitor *mon, QObject **ret_data);
Adam Litke940cc302010-01-25 12:18:44 -060096 int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque);
Luiz Capitulinoaf4ce882009-10-07 13:41:52 -030097 void (*cmd)(Monitor *mon, const QDict *qdict);
Luiz Capitulino13917be2009-10-07 13:41:54 -030098 void (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
Adam Litke940cc302010-01-25 12:18:44 -060099 int (*cmd_async)(Monitor *mon, const QDict *params,
100 MonitorCompletion *cb, void *opaque);
Luiz Capitulino910df892009-10-07 13:41:51 -0300101 } mhandler;
Adam Litke940cc302010-01-25 12:18:44 -0600102 int async;
Anthony Liguoric227f092009-10-01 16:12:16 -0500103} mon_cmd_t;
bellard9dc39cb2004-03-14 21:38:27 +0000104
Mark McLoughlinf07918f2009-07-22 09:11:40 +0100105/* file descriptors passed via SCM_RIGHTS */
Anthony Liguoric227f092009-10-01 16:12:16 -0500106typedef struct mon_fd_t mon_fd_t;
107struct mon_fd_t {
Mark McLoughlinf07918f2009-07-22 09:11:40 +0100108 char *name;
109 int fd;
Anthony Liguoric227f092009-10-01 16:12:16 -0500110 QLIST_ENTRY(mon_fd_t) next;
Mark McLoughlinf07918f2009-07-22 09:11:40 +0100111};
112
Luiz Capitulino5fa737a2009-11-26 22:59:01 -0200113typedef struct MonitorControl {
114 QObject *id;
Luiz Capitulino4a29a852009-11-26 22:59:05 -0200115 int print_enabled;
Luiz Capitulino5fa737a2009-11-26 22:59:01 -0200116 JSONMessageParser parser;
117} MonitorControl;
118
aliguori87127162009-03-05 23:01:29 +0000119struct Monitor {
120 CharDriverState *chr;
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +0200121 int mux_out;
122 int reset_seen;
aliguori731b0362009-03-05 23:01:42 +0000123 int flags;
124 int suspend_cnt;
125 uint8_t outbuf[1024];
126 int outbuf_index;
127 ReadLineState *rs;
Luiz Capitulino5fa737a2009-11-26 22:59:01 -0200128 MonitorControl *mc;
aliguori731b0362009-03-05 23:01:42 +0000129 CPUState *mon_cpu;
130 BlockDriverCompletionFunc *password_completion_cb;
131 void *password_opaque;
Luiz Capitulino8204a912009-11-18 23:05:31 -0200132 QError *error;
Anthony Liguoric227f092009-10-01 16:12:16 -0500133 QLIST_HEAD(,mon_fd_t) fds;
Blue Swirl72cf2d42009-09-12 07:36:22 +0000134 QLIST_ENTRY(Monitor) entry;
aliguori87127162009-03-05 23:01:29 +0000135};
136
Blue Swirl72cf2d42009-09-12 07:36:22 +0000137static QLIST_HEAD(mon_list, Monitor) mon_list;
bellard7e2515e2004-08-01 21:52:19 +0000138
Anthony Liguoric227f092009-10-01 16:12:16 -0500139static const mon_cmd_t mon_cmds[];
140static const mon_cmd_t info_cmds[];
bellard9dc39cb2004-03-14 21:38:27 +0000141
aliguori87127162009-03-05 23:01:29 +0000142Monitor *cur_mon = NULL;
aliguori376253e2009-03-05 23:01:23 +0000143
aliguori731b0362009-03-05 23:01:42 +0000144static void monitor_command_cb(Monitor *mon, const char *cmdline,
145 void *opaque);
aliguori83ab7952008-08-19 14:44:22 +0000146
Luiz Capitulino418173c2009-11-26 22:58:51 -0200147/* Return true if in control mode, false otherwise */
148static inline int monitor_ctrl_mode(const Monitor *mon)
149{
150 return (mon->flags & MONITOR_USE_CONTROL);
151}
152
aliguori731b0362009-03-05 23:01:42 +0000153static void monitor_read_command(Monitor *mon, int show_prompt)
154{
Luiz Capitulino183e6e52009-12-14 18:53:23 -0200155 if (!mon->rs)
156 return;
157
aliguori731b0362009-03-05 23:01:42 +0000158 readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
159 if (show_prompt)
160 readline_show_prompt(mon->rs);
161}
bellard6a00d602005-11-21 23:25:50 +0000162
aliguoricde76ee2009-03-05 23:01:51 +0000163static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
164 void *opaque)
aliguoribb5fc202009-03-05 23:01:15 +0000165{
Luiz Capitulino94171e12009-12-07 21:37:00 +0100166 if (monitor_ctrl_mode(mon)) {
167 qemu_error_new(QERR_MISSING_PARAMETER, "password");
168 return -EINVAL;
169 } else if (mon->rs) {
aliguoricde76ee2009-03-05 23:01:51 +0000170 readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
171 /* prompt is printed on return from the command handler */
172 return 0;
173 } else {
174 monitor_printf(mon, "terminal does not support password prompting\n");
175 return -ENOTTY;
176 }
aliguoribb5fc202009-03-05 23:01:15 +0000177}
178
aliguori376253e2009-03-05 23:01:23 +0000179void monitor_flush(Monitor *mon)
bellard9dc39cb2004-03-14 21:38:27 +0000180{
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +0200181 if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
aliguori731b0362009-03-05 23:01:42 +0000182 qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
183 mon->outbuf_index = 0;
bellard7e2515e2004-08-01 21:52:19 +0000184 }
185}
186
187/* flush at every end of line or if the buffer is full */
aliguori376253e2009-03-05 23:01:23 +0000188static void monitor_puts(Monitor *mon, const char *str)
bellard7e2515e2004-08-01 21:52:19 +0000189{
ths60fe76f2007-12-16 03:02:09 +0000190 char c;
aliguori731b0362009-03-05 23:01:42 +0000191
bellard7e2515e2004-08-01 21:52:19 +0000192 for(;;) {
193 c = *str++;
194 if (c == '\0')
195 break;
bellard7ba12602006-07-14 20:26:42 +0000196 if (c == '\n')
aliguori731b0362009-03-05 23:01:42 +0000197 mon->outbuf[mon->outbuf_index++] = '\r';
198 mon->outbuf[mon->outbuf_index++] = c;
199 if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
200 || c == '\n')
aliguori376253e2009-03-05 23:01:23 +0000201 monitor_flush(mon);
bellard7e2515e2004-08-01 21:52:19 +0000202 }
203}
204
aliguori376253e2009-03-05 23:01:23 +0000205void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
bellard7e2515e2004-08-01 21:52:19 +0000206{
Luiz Capitulino2daa1192009-12-14 18:53:24 -0200207 if (!mon)
208 return;
209
Luiz Capitulino4a29a852009-11-26 22:59:05 -0200210 if (mon->mc && !mon->mc->print_enabled) {
211 qemu_error_new(QERR_UNDEFINED_ERROR);
212 } else {
213 char buf[4096];
214 vsnprintf(buf, sizeof(buf), fmt, ap);
215 monitor_puts(mon, buf);
216 }
bellard7e2515e2004-08-01 21:52:19 +0000217}
218
aliguori376253e2009-03-05 23:01:23 +0000219void monitor_printf(Monitor *mon, const char *fmt, ...)
bellard7e2515e2004-08-01 21:52:19 +0000220{
221 va_list ap;
222 va_start(ap, fmt);
aliguori376253e2009-03-05 23:01:23 +0000223 monitor_vprintf(mon, fmt, ap);
bellard7e2515e2004-08-01 21:52:19 +0000224 va_end(ap);
bellard9dc39cb2004-03-14 21:38:27 +0000225}
226
aliguori376253e2009-03-05 23:01:23 +0000227void monitor_print_filename(Monitor *mon, const char *filename)
thsfef30742006-12-22 14:11:32 +0000228{
229 int i;
230
231 for (i = 0; filename[i]; i++) {
aliguori28a76be2009-03-06 20:27:40 +0000232 switch (filename[i]) {
233 case ' ':
234 case '"':
235 case '\\':
236 monitor_printf(mon, "\\%c", filename[i]);
237 break;
238 case '\t':
239 monitor_printf(mon, "\\t");
240 break;
241 case '\r':
242 monitor_printf(mon, "\\r");
243 break;
244 case '\n':
245 monitor_printf(mon, "\\n");
246 break;
247 default:
248 monitor_printf(mon, "%c", filename[i]);
249 break;
250 }
thsfef30742006-12-22 14:11:32 +0000251 }
252}
253
bellard7fe48482004-10-09 18:08:01 +0000254static int monitor_fprintf(FILE *stream, const char *fmt, ...)
255{
256 va_list ap;
257 va_start(ap, fmt);
aliguori376253e2009-03-05 23:01:23 +0000258 monitor_vprintf((Monitor *)stream, fmt, ap);
bellard7fe48482004-10-09 18:08:01 +0000259 va_end(ap);
260 return 0;
261}
262
Luiz Capitulino13c74252009-10-07 13:41:55 -0300263static void monitor_user_noop(Monitor *mon, const QObject *data) { }
264
Luiz Capitulino13917be2009-10-07 13:41:54 -0300265static inline int monitor_handler_ported(const mon_cmd_t *cmd)
266{
267 return cmd->user_print != NULL;
268}
269
Adam Litke940cc302010-01-25 12:18:44 -0600270static inline bool monitor_handler_is_async(const mon_cmd_t *cmd)
271{
272 return cmd->async != 0;
273}
274
Luiz Capitulino8204a912009-11-18 23:05:31 -0200275static inline int monitor_has_error(const Monitor *mon)
276{
277 return mon->error != NULL;
278}
279
Luiz Capitulino9b57c022009-11-26 22:58:58 -0200280static void monitor_json_emitter(Monitor *mon, const QObject *data)
281{
282 QString *json;
283
284 json = qobject_to_json(data);
285 assert(json != NULL);
286
Luiz Capitulino4a29a852009-11-26 22:59:05 -0200287 mon->mc->print_enabled = 1;
Luiz Capitulino9b57c022009-11-26 22:58:58 -0200288 monitor_printf(mon, "%s\n", qstring_get_str(json));
Luiz Capitulino4a29a852009-11-26 22:59:05 -0200289 mon->mc->print_enabled = 0;
290
Luiz Capitulino9b57c022009-11-26 22:58:58 -0200291 QDECREF(json);
292}
293
Luiz Capitulino25b422e2009-11-26 22:58:59 -0200294static void monitor_protocol_emitter(Monitor *mon, QObject *data)
295{
296 QDict *qmp;
297
298 qmp = qdict_new();
299
300 if (!monitor_has_error(mon)) {
301 /* success response */
302 if (data) {
303 qobject_incref(data);
304 qdict_put_obj(qmp, "return", data);
305 } else {
Luiz Capitulino0abc6572009-12-18 13:25:00 -0200306 /* return an empty QDict by default */
307 qdict_put(qmp, "return", qdict_new());
Luiz Capitulino25b422e2009-11-26 22:58:59 -0200308 }
309 } else {
310 /* error response */
Markus Armbruster77e595e2009-12-07 21:37:16 +0100311 qdict_put(mon->error->error, "desc", qerror_human(mon->error));
Luiz Capitulino25b422e2009-11-26 22:58:59 -0200312 qdict_put(qmp, "error", mon->error->error);
313 QINCREF(mon->error->error);
314 QDECREF(mon->error);
315 mon->error = NULL;
316 }
317
Luiz Capitulino5fa737a2009-11-26 22:59:01 -0200318 if (mon->mc->id) {
319 qdict_put_obj(qmp, "id", mon->mc->id);
320 mon->mc->id = NULL;
321 }
322
Luiz Capitulino25b422e2009-11-26 22:58:59 -0200323 monitor_json_emitter(mon, QOBJECT(qmp));
324 QDECREF(qmp);
325}
326
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200327static void timestamp_put(QDict *qdict)
328{
329 int err;
330 QObject *obj;
Blue Swirld08d6f02009-12-04 18:06:39 +0000331 qemu_timeval tv;
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200332
Blue Swirld08d6f02009-12-04 18:06:39 +0000333 err = qemu_gettimeofday(&tv);
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200334 if (err < 0)
335 return;
336
337 obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
338 "'microseconds': %" PRId64 " }",
339 (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
340 assert(obj != NULL);
341
342 qdict_put_obj(qdict, "timestamp", obj);
343}
344
345/**
346 * monitor_protocol_event(): Generate a Monitor event
347 *
348 * Event-specific data can be emitted through the (optional) 'data' parameter.
349 */
350void monitor_protocol_event(MonitorEvent event, QObject *data)
351{
352 QDict *qmp;
353 const char *event_name;
Adam Litkef039a562010-01-15 08:34:02 -0600354 Monitor *mon;
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200355
Blue Swirl242cd002009-12-04 18:05:45 +0000356 assert(event < QEVENT_MAX);
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200357
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200358 switch (event) {
Blue Swirl242cd002009-12-04 18:05:45 +0000359 case QEVENT_DEBUG:
Luiz Capitulinob1a15e72009-11-26 22:59:04 -0200360 event_name = "DEBUG";
361 break;
Blue Swirl242cd002009-12-04 18:05:45 +0000362 case QEVENT_SHUTDOWN:
Luiz Capitulinob1a15e72009-11-26 22:59:04 -0200363 event_name = "SHUTDOWN";
364 break;
Blue Swirl242cd002009-12-04 18:05:45 +0000365 case QEVENT_RESET:
Luiz Capitulinob1a15e72009-11-26 22:59:04 -0200366 event_name = "RESET";
367 break;
Blue Swirl242cd002009-12-04 18:05:45 +0000368 case QEVENT_POWERDOWN:
Luiz Capitulinob1a15e72009-11-26 22:59:04 -0200369 event_name = "POWERDOWN";
370 break;
Blue Swirl242cd002009-12-04 18:05:45 +0000371 case QEVENT_STOP:
Luiz Capitulinob1a15e72009-11-26 22:59:04 -0200372 event_name = "STOP";
373 break;
Luiz Capitulino586153d2010-01-14 14:50:57 -0200374 case QEVENT_VNC_CONNECTED:
375 event_name = "VNC_CONNECTED";
376 break;
Luiz Capitulino0d2ed462010-01-14 14:50:59 -0200377 case QEVENT_VNC_INITIALIZED:
378 event_name = "VNC_INITIALIZED";
379 break;
Luiz Capitulino0d72f3d2010-01-14 14:50:58 -0200380 case QEVENT_VNC_DISCONNECTED:
381 event_name = "VNC_DISCONNECTED";
382 break;
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200383 default:
384 abort();
385 break;
386 }
387
388 qmp = qdict_new();
389 timestamp_put(qmp);
390 qdict_put(qmp, "event", qstring_from_str(event_name));
Luiz Capitulino3d72f9a2010-01-08 16:45:53 -0200391 if (data) {
392 qobject_incref(data);
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200393 qdict_put_obj(qmp, "data", data);
Luiz Capitulino3d72f9a2010-01-08 16:45:53 -0200394 }
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200395
Adam Litkef039a562010-01-15 08:34:02 -0600396 QLIST_FOREACH(mon, &mon_list, entry) {
Luiz Capitulino23fabed2010-01-20 10:37:59 -0200397 if (monitor_ctrl_mode(mon)) {
398 monitor_json_emitter(mon, QOBJECT(qmp));
399 }
Adam Litkef039a562010-01-15 08:34:02 -0600400 }
Luiz Capitulino0d1ea872009-11-26 22:59:03 -0200401 QDECREF(qmp);
402}
403
bellard9dc39cb2004-03-14 21:38:27 +0000404static int compare_cmd(const char *name, const char *list)
405{
406 const char *p, *pstart;
407 int len;
408 len = strlen(name);
409 p = list;
410 for(;;) {
411 pstart = p;
412 p = strchr(p, '|');
413 if (!p)
414 p = pstart + strlen(pstart);
415 if ((p - pstart) == len && !memcmp(pstart, name, len))
416 return 1;
417 if (*p == '\0')
418 break;
419 p++;
420 }
421 return 0;
422}
423
Anthony Liguoric227f092009-10-01 16:12:16 -0500424static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
aliguori376253e2009-03-05 23:01:23 +0000425 const char *prefix, const char *name)
bellard9dc39cb2004-03-14 21:38:27 +0000426{
Anthony Liguoric227f092009-10-01 16:12:16 -0500427 const mon_cmd_t *cmd;
bellard9dc39cb2004-03-14 21:38:27 +0000428
429 for(cmd = cmds; cmd->name != NULL; cmd++) {
430 if (!name || !strcmp(name, cmd->name))
aliguori376253e2009-03-05 23:01:23 +0000431 monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name,
432 cmd->params, cmd->help);
bellard9dc39cb2004-03-14 21:38:27 +0000433 }
434}
435
aliguori376253e2009-03-05 23:01:23 +0000436static void help_cmd(Monitor *mon, const char *name)
bellard9dc39cb2004-03-14 21:38:27 +0000437{
438 if (name && !strcmp(name, "info")) {
aliguori376253e2009-03-05 23:01:23 +0000439 help_cmd_dump(mon, info_cmds, "info ", NULL);
bellard9dc39cb2004-03-14 21:38:27 +0000440 } else {
aliguori376253e2009-03-05 23:01:23 +0000441 help_cmd_dump(mon, mon_cmds, "", name);
bellardf193c792004-03-21 17:06:25 +0000442 if (name && !strcmp(name, "log")) {
blueswir18662d652008-10-02 18:32:44 +0000443 const CPULogItem *item;
aliguori376253e2009-03-05 23:01:23 +0000444 monitor_printf(mon, "Log items (comma separated):\n");
445 monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
bellardf193c792004-03-21 17:06:25 +0000446 for(item = cpu_log_items; item->mask != 0; item++) {
aliguori376253e2009-03-05 23:01:23 +0000447 monitor_printf(mon, "%-10s %s\n", item->name, item->help);
bellardf193c792004-03-21 17:06:25 +0000448 }
449 }
bellard9dc39cb2004-03-14 21:38:27 +0000450 }
451}
452
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300453static void do_help_cmd(Monitor *mon, const QDict *qdict)
Luiz Capitulino38183182009-08-28 15:27:08 -0300454{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300455 help_cmd(mon, qdict_get_try_str(qdict, "name"));
Luiz Capitulino38183182009-08-28 15:27:08 -0300456}
457
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300458static void do_commit(Monitor *mon, const QDict *qdict)
bellard9dc39cb2004-03-14 21:38:27 +0000459{
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200460 int all_devices;
461 DriveInfo *dinfo;
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300462 const char *device = qdict_get_str(qdict, "device");
balrog2dc7b602007-05-24 18:53:22 +0000463
bellard7954c732006-08-01 15:52:40 +0000464 all_devices = !strcmp(device, "all");
Blue Swirl72cf2d42009-09-12 07:36:22 +0000465 QTAILQ_FOREACH(dinfo, &drives, next) {
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200466 if (!all_devices)
Luiz Capitulino73006d22009-07-31 15:15:41 -0300467 if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200468 continue;
469 bdrv_commit(dinfo->bdrv);
bellard9dc39cb2004-03-14 21:38:27 +0000470 }
471}
472
Adam Litke940cc302010-01-25 12:18:44 -0600473static void user_monitor_complete(void *opaque, QObject *ret_data)
474{
475 MonitorCompletionData *data = (MonitorCompletionData *)opaque;
476
477 if (ret_data) {
478 data->user_print(data->mon, ret_data);
479 }
480 monitor_resume(data->mon);
481 qemu_free(data);
482}
483
484static void qmp_monitor_complete(void *opaque, QObject *ret_data)
485{
486 monitor_protocol_emitter(opaque, ret_data);
487}
488
489static void qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
490 const QDict *params)
491{
492 cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon);
493}
494
495static void qmp_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
496{
497 cmd->mhandler.info_async(mon, qmp_monitor_complete, mon);
498}
499
500static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
501 const QDict *params)
502{
503 int ret;
504
505 MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data));
506 cb_data->mon = mon;
507 cb_data->user_print = cmd->user_print;
508 monitor_suspend(mon);
509 ret = cmd->mhandler.cmd_async(mon, params,
510 user_monitor_complete, cb_data);
511 if (ret < 0) {
512 monitor_resume(mon);
513 qemu_free(cb_data);
514 }
515}
516
517static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
518{
519 int ret;
520
521 MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data));
522 cb_data->mon = mon;
523 cb_data->user_print = cmd->user_print;
524 monitor_suspend(mon);
525 ret = cmd->mhandler.info_async(mon, user_monitor_complete, cb_data);
526 if (ret < 0) {
527 monitor_resume(mon);
528 qemu_free(cb_data);
529 }
530}
531
Luiz Capitulino13c74252009-10-07 13:41:55 -0300532static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellard9dc39cb2004-03-14 21:38:27 +0000533{
Anthony Liguoric227f092009-10-01 16:12:16 -0500534 const mon_cmd_t *cmd;
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300535 const char *item = qdict_get_try_str(qdict, "item");
bellard9dc39cb2004-03-14 21:38:27 +0000536
Luiz Capitulino956f1a02009-11-26 22:59:00 -0200537 if (!item) {
538 assert(monitor_ctrl_mode(mon) == 0);
bellard9dc39cb2004-03-14 21:38:27 +0000539 goto help;
Luiz Capitulino956f1a02009-11-26 22:59:00 -0200540 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300541
542 for (cmd = info_cmds; cmd->name != NULL; cmd++) {
ths5fafdf22007-09-16 21:08:06 +0000543 if (compare_cmd(item, cmd->name))
Luiz Capitulino13c74252009-10-07 13:41:55 -0300544 break;
bellard9dc39cb2004-03-14 21:38:27 +0000545 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300546
Luiz Capitulino956f1a02009-11-26 22:59:00 -0200547 if (cmd->name == NULL) {
548 if (monitor_ctrl_mode(mon)) {
549 qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
550 return;
551 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300552 goto help;
Luiz Capitulino956f1a02009-11-26 22:59:00 -0200553 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300554
Adam Litke940cc302010-01-25 12:18:44 -0600555 if (monitor_handler_is_async(cmd)) {
556 if (monitor_ctrl_mode(mon)) {
557 qmp_async_info_handler(mon, cmd);
558 } else {
559 user_async_info_handler(mon, cmd);
560 }
561 /*
562 * Indicate that this command is asynchronous and will not return any
563 * data (not even empty). Instead, the data will be returned via a
564 * completion callback.
565 */
566 *ret_data = qobject_from_jsonf("{ '__mon_async': 'return' }");
567 } else if (monitor_handler_ported(cmd)) {
Luiz Capitulino13c74252009-10-07 13:41:55 -0300568 cmd->mhandler.info_new(mon, ret_data);
Luiz Capitulino25b422e2009-11-26 22:58:59 -0200569
570 if (!monitor_ctrl_mode(mon)) {
571 /*
572 * User Protocol function is called here, Monitor Protocol is
573 * handled by monitor_call_handler()
574 */
575 if (*ret_data)
576 cmd->user_print(mon, *ret_data);
577 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300578 } else {
Luiz Capitulino956f1a02009-11-26 22:59:00 -0200579 if (monitor_ctrl_mode(mon)) {
580 /* handler not converted yet */
581 qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
582 } else {
583 cmd->mhandler.info(mon);
584 }
Luiz Capitulino13c74252009-10-07 13:41:55 -0300585 }
586
bellard9dc39cb2004-03-14 21:38:27 +0000587 return;
Luiz Capitulino13c74252009-10-07 13:41:55 -0300588
589help:
590 help_cmd(mon, "info");
bellard9dc39cb2004-03-14 21:38:27 +0000591}
592
Luiz Capitulino45e914c2009-12-10 17:15:58 -0200593static void do_info_version_print(Monitor *mon, const QObject *data)
594{
595 QDict *qdict;
596
597 qdict = qobject_to_qdict(data);
598
599 monitor_printf(mon, "%s%s\n", qdict_get_str(qdict, "qemu"),
600 qdict_get_str(qdict, "package"));
601}
602
Luiz Capitulinoab2d3182009-10-07 13:42:02 -0300603/**
604 * do_info_version(): Show QEMU version
Luiz Capitulino45e914c2009-12-10 17:15:58 -0200605 *
606 * Return a QDict with the following information:
607 *
608 * - "qemu": QEMU's version
609 * - "package": package's version
610 *
611 * Example:
612 *
613 * { "qemu": "0.11.50", "package": "" }
Luiz Capitulinoab2d3182009-10-07 13:42:02 -0300614 */
615static void do_info_version(Monitor *mon, QObject **ret_data)
bellard9bc9d1c2004-10-10 15:15:51 +0000616{
Luiz Capitulino45e914c2009-12-10 17:15:58 -0200617 *ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
618 QEMU_VERSION, QEMU_PKGVERSION);
bellard9bc9d1c2004-10-10 15:15:51 +0000619}
620
Luiz Capitulinoe05486c2009-12-10 17:16:01 -0200621static void do_info_name_print(Monitor *mon, const QObject *data)
thsc35734b2007-03-19 15:17:08 +0000622{
Luiz Capitulinoe05486c2009-12-10 17:16:01 -0200623 QDict *qdict;
624
625 qdict = qobject_to_qdict(data);
626 if (qdict_size(qdict) == 0) {
627 return;
628 }
629
630 monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
631}
632
633/**
634 * do_info_name(): Show VM name
635 *
636 * Return a QDict with the following information:
637 *
638 * - "name": VM's name (optional)
639 *
640 * Example:
641 *
642 * { "name": "qemu-name" }
643 */
644static void do_info_name(Monitor *mon, QObject **ret_data)
645{
646 *ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
647 qobject_from_jsonf("{}");
thsc35734b2007-03-19 15:17:08 +0000648}
649
Luiz Capitulino1a728672009-12-10 17:15:56 -0200650static QObject *get_cmd_dict(const char *name)
651{
652 const char *p;
653
654 /* Remove '|' from some commands */
655 p = strchr(name, '|');
656 if (p) {
657 p++;
658 } else {
659 p = name;
660 }
661
662 return qobject_from_jsonf("{ 'name': %s }", p);
663}
664
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200665/**
666 * do_info_commands(): List QMP available commands
667 *
Luiz Capitulino1a728672009-12-10 17:15:56 -0200668 * Each command is represented by a QDict, the returned QObject is a QList
669 * of all commands.
670 *
671 * The QDict contains:
672 *
673 * - "name": command's name
674 *
675 * Example:
676 *
677 * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200678 */
679static void do_info_commands(Monitor *mon, QObject **ret_data)
680{
681 QList *cmd_list;
682 const mon_cmd_t *cmd;
683
684 cmd_list = qlist_new();
685
686 for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
687 if (monitor_handler_ported(cmd) && !compare_cmd(cmd->name, "info")) {
Luiz Capitulino1a728672009-12-10 17:15:56 -0200688 qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200689 }
690 }
691
692 for (cmd = info_cmds; cmd->name != NULL; cmd++) {
693 if (monitor_handler_ported(cmd)) {
694 char buf[128];
695 snprintf(buf, sizeof(buf), "query-%s", cmd->name);
Luiz Capitulino1a728672009-12-10 17:15:56 -0200696 qlist_append_obj(cmd_list, get_cmd_dict(buf));
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -0200697 }
698 }
699
700 *ret_data = QOBJECT(cmd_list);
701}
702
aurel32bf4f74c2008-12-18 22:42:34 +0000703#if defined(TARGET_I386)
Luiz Capitulino14f07202009-12-10 17:16:02 -0200704static void do_info_hpet_print(Monitor *mon, const QObject *data)
aliguori16b29ae2008-12-17 23:28:44 +0000705{
aliguori376253e2009-03-05 23:01:23 +0000706 monitor_printf(mon, "HPET is %s by QEMU\n",
Luiz Capitulino14f07202009-12-10 17:16:02 -0200707 qdict_get_bool(qobject_to_qdict(data), "enabled") ?
708 "enabled" : "disabled");
709}
710
711/**
712 * do_info_hpet(): Show HPET state
713 *
714 * Return a QDict with the following information:
715 *
716 * - "enabled": true if hpet if enabled, false otherwise
717 *
718 * Example:
719 *
720 * { "enabled": true }
721 */
722static void do_info_hpet(Monitor *mon, QObject **ret_data)
723{
724 *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
aliguori16b29ae2008-12-17 23:28:44 +0000725}
aurel32bf4f74c2008-12-18 22:42:34 +0000726#endif
aliguori16b29ae2008-12-17 23:28:44 +0000727
Luiz Capitulino9603ceb2009-12-10 17:16:03 -0200728static void do_info_uuid_print(Monitor *mon, const QObject *data)
blueswir1f1f23ad2008-09-18 18:30:20 +0000729{
Luiz Capitulino9603ceb2009-12-10 17:16:03 -0200730 monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
731}
732
733/**
734 * do_info_uuid(): Show VM UUID
735 *
736 * Return a QDict with the following information:
737 *
738 * - "UUID": Universally Unique Identifier
739 *
740 * Example:
741 *
742 * { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
743 */
744static void do_info_uuid(Monitor *mon, QObject **ret_data)
745{
746 char uuid[64];
747
748 snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
aliguori376253e2009-03-05 23:01:23 +0000749 qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
750 qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
751 qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
752 qemu_uuid[14], qemu_uuid[15]);
Luiz Capitulino9603ceb2009-12-10 17:16:03 -0200753 *ret_data = qobject_from_jsonf("{ 'UUID': %s }", uuid);
thsa36e69d2007-12-02 05:18:19 +0000754}
755
bellard6a00d602005-11-21 23:25:50 +0000756/* get the current CPU defined by the user */
pbrook9596ebb2007-11-18 01:44:38 +0000757static int mon_set_cpu(int cpu_index)
bellard6a00d602005-11-21 23:25:50 +0000758{
759 CPUState *env;
760
761 for(env = first_cpu; env != NULL; env = env->next_cpu) {
762 if (env->cpu_index == cpu_index) {
aliguori731b0362009-03-05 23:01:42 +0000763 cur_mon->mon_cpu = env;
bellard6a00d602005-11-21 23:25:50 +0000764 return 0;
765 }
766 }
767 return -1;
768}
769
pbrook9596ebb2007-11-18 01:44:38 +0000770static CPUState *mon_get_cpu(void)
bellard6a00d602005-11-21 23:25:50 +0000771{
aliguori731b0362009-03-05 23:01:42 +0000772 if (!cur_mon->mon_cpu) {
bellard6a00d602005-11-21 23:25:50 +0000773 mon_set_cpu(0);
774 }
Avi Kivity4c0960c2009-08-17 23:19:53 +0300775 cpu_synchronize_state(cur_mon->mon_cpu);
aliguori731b0362009-03-05 23:01:42 +0000776 return cur_mon->mon_cpu;
bellard6a00d602005-11-21 23:25:50 +0000777}
778
aliguori376253e2009-03-05 23:01:23 +0000779static void do_info_registers(Monitor *mon)
bellard9307c4c2004-04-04 12:57:25 +0000780{
bellard6a00d602005-11-21 23:25:50 +0000781 CPUState *env;
782 env = mon_get_cpu();
bellard9307c4c2004-04-04 12:57:25 +0000783#ifdef TARGET_I386
aliguori376253e2009-03-05 23:01:23 +0000784 cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
bellardd24b15a2005-07-03 21:28:00 +0000785 X86_DUMP_FPU);
bellard9307c4c2004-04-04 12:57:25 +0000786#else
aliguori376253e2009-03-05 23:01:23 +0000787 cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
bellard7fe48482004-10-09 18:08:01 +0000788 0);
bellard9307c4c2004-04-04 12:57:25 +0000789#endif
790}
791
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300792static void print_cpu_iter(QObject *obj, void *opaque)
793{
794 QDict *cpu;
795 int active = ' ';
796 Monitor *mon = opaque;
797
798 assert(qobject_type(obj) == QTYPE_QDICT);
799 cpu = qobject_to_qdict(obj);
800
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200801 if (qdict_get_bool(cpu, "current")) {
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300802 active = '*';
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200803 }
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300804
805 monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
806
807#if defined(TARGET_I386)
808 monitor_printf(mon, "pc=0x" TARGET_FMT_lx,
809 (target_ulong) qdict_get_int(cpu, "pc"));
810#elif defined(TARGET_PPC)
811 monitor_printf(mon, "nip=0x" TARGET_FMT_lx,
812 (target_long) qdict_get_int(cpu, "nip"));
813#elif defined(TARGET_SPARC)
814 monitor_printf(mon, "pc=0x " TARGET_FMT_lx,
815 (target_long) qdict_get_int(cpu, "pc"));
816 monitor_printf(mon, "npc=0x" TARGET_FMT_lx,
817 (target_long) qdict_get_int(cpu, "npc"));
818#elif defined(TARGET_MIPS)
819 monitor_printf(mon, "PC=0x" TARGET_FMT_lx,
820 (target_long) qdict_get_int(cpu, "PC"));
821#endif
822
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200823 if (qdict_get_bool(cpu, "halted")) {
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300824 monitor_printf(mon, " (halted)");
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200825 }
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300826
827 monitor_printf(mon, "\n");
828}
829
830static void monitor_print_cpus(Monitor *mon, const QObject *data)
831{
832 QList *cpu_list;
833
834 assert(qobject_type(data) == QTYPE_QLIST);
835 cpu_list = qobject_to_qlist(data);
836 qlist_iter(cpu_list, print_cpu_iter, mon);
837}
838
839/**
840 * do_info_cpus(): Show CPU information
841 *
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200842 * Return a QList. Each CPU is represented by a QDict, which contains:
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300843 *
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200844 * - "cpu": CPU index
845 * - "current": true if this is the current CPU, false otherwise
846 * - "halted": true if the cpu is halted, false otherwise
847 * - Current program counter. The key's name depends on the architecture:
848 * "pc": i386/x86)64
849 * "nip": PPC
850 * "pc" and "npc": sparc
851 * "PC": mips
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300852 *
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200853 * Example:
854 *
855 * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
856 * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300857 */
858static void do_info_cpus(Monitor *mon, QObject **ret_data)
bellard6a00d602005-11-21 23:25:50 +0000859{
860 CPUState *env;
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300861 QList *cpu_list;
862
863 cpu_list = qlist_new();
bellard6a00d602005-11-21 23:25:50 +0000864
865 /* just to set the default cpu if not already done */
866 mon_get_cpu();
867
868 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200869 QDict *cpu;
870 QObject *obj;
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300871
Avi Kivity4c0960c2009-08-17 23:19:53 +0300872 cpu_synchronize_state(env);
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300873
Luiz Capitulino55483ad2009-12-10 17:15:57 -0200874 obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
875 env->cpu_index, env == mon->mon_cpu,
876 env->halted);
877 assert(obj != NULL);
878
879 cpu = qobject_to_qdict(obj);
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300880
bellard6a00d602005-11-21 23:25:50 +0000881#if defined(TARGET_I386)
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300882 qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
bellarde80e1cc2005-11-23 22:05:28 +0000883#elif defined(TARGET_PPC)
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300884 qdict_put(cpu, "nip", qint_from_int(env->nip));
bellardba3c64f2005-12-05 20:31:52 +0000885#elif defined(TARGET_SPARC)
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300886 qdict_put(cpu, "pc", qint_from_int(env->pc));
887 qdict_put(cpu, "npc", qint_from_int(env->npc));
thsead93602007-09-06 00:18:15 +0000888#elif defined(TARGET_MIPS)
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300889 qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
bellardce5232c2008-05-28 17:14:10 +0000890#endif
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300891
892 qlist_append(cpu_list, cpu);
bellard6a00d602005-11-21 23:25:50 +0000893 }
Luiz Capitulino8f3cec02009-10-07 13:42:04 -0300894
895 *ret_data = QOBJECT(cpu_list);
bellard6a00d602005-11-21 23:25:50 +0000896}
897
Markus Armbruster81a1b452010-01-20 13:07:35 +0100898static void do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellard6a00d602005-11-21 23:25:50 +0000899{
Luiz Capitulinod54908a2009-08-28 15:27:13 -0300900 int index = qdict_get_int(qdict, "index");
bellard6a00d602005-11-21 23:25:50 +0000901 if (mon_set_cpu(index) < 0)
Markus Armbruster81a1b452010-01-20 13:07:35 +0100902 qemu_error_new(QERR_INVALID_CPU_INDEX);
bellard6a00d602005-11-21 23:25:50 +0000903}
904
aliguori376253e2009-03-05 23:01:23 +0000905static void do_info_jit(Monitor *mon)
bellarde3db7222005-01-26 22:00:47 +0000906{
aliguori376253e2009-03-05 23:01:23 +0000907 dump_exec_info((FILE *)mon, monitor_fprintf);
bellarde3db7222005-01-26 22:00:47 +0000908}
909
aliguori376253e2009-03-05 23:01:23 +0000910static void do_info_history(Monitor *mon)
bellardaa455482004-04-04 13:07:25 +0000911{
912 int i;
bellard7e2515e2004-08-01 21:52:19 +0000913 const char *str;
ths3b46e622007-09-17 08:09:54 +0000914
aliguoricde76ee2009-03-05 23:01:51 +0000915 if (!mon->rs)
916 return;
bellard7e2515e2004-08-01 21:52:19 +0000917 i = 0;
918 for(;;) {
aliguori731b0362009-03-05 23:01:42 +0000919 str = readline_get_history(mon->rs, i);
bellard7e2515e2004-08-01 21:52:19 +0000920 if (!str)
921 break;
aliguori376253e2009-03-05 23:01:23 +0000922 monitor_printf(mon, "%d: '%s'\n", i, str);
bellard8e3a9fd2004-10-09 17:32:58 +0000923 i++;
bellardaa455482004-04-04 13:07:25 +0000924 }
925}
926
j_mayer76a66252007-03-07 08:32:30 +0000927#if defined(TARGET_PPC)
928/* XXX: not implemented in other targets */
aliguori376253e2009-03-05 23:01:23 +0000929static void do_info_cpu_stats(Monitor *mon)
j_mayer76a66252007-03-07 08:32:30 +0000930{
931 CPUState *env;
932
933 env = mon_get_cpu();
aliguori376253e2009-03-05 23:01:23 +0000934 cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
j_mayer76a66252007-03-07 08:32:30 +0000935}
936#endif
937
Luiz Capitulinob223f352009-10-07 13:41:56 -0300938/**
939 * do_quit(): Quit QEMU execution
940 */
941static void do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellard9dc39cb2004-03-14 21:38:27 +0000942{
943 exit(0);
944}
945
aliguori376253e2009-03-05 23:01:23 +0000946static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
bellard9dc39cb2004-03-14 21:38:27 +0000947{
948 if (bdrv_is_inserted(bs)) {
949 if (!force) {
950 if (!bdrv_is_removable(bs)) {
Markus Armbruster2c2a6bb2009-12-07 21:37:05 +0100951 qemu_error_new(QERR_DEVICE_NOT_REMOVABLE,
952 bdrv_get_device_name(bs));
bellard9dc39cb2004-03-14 21:38:27 +0000953 return -1;
954 }
955 if (bdrv_is_locked(bs)) {
Markus Armbruster2c2a6bb2009-12-07 21:37:05 +0100956 qemu_error_new(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
bellard9dc39cb2004-03-14 21:38:27 +0000957 return -1;
958 }
959 }
960 bdrv_close(bs);
961 }
962 return 0;
963}
964
Luiz Capitulinoe1c923a2009-10-16 12:23:49 -0300965static void do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellard9dc39cb2004-03-14 21:38:27 +0000966{
967 BlockDriverState *bs;
Luiz Capitulinof18c16d2009-08-28 15:27:14 -0300968 int force = qdict_get_int(qdict, "force");
Luiz Capitulino78d714e2009-12-14 18:53:21 -0200969 const char *filename = qdict_get_str(qdict, "device");
bellard9dc39cb2004-03-14 21:38:27 +0000970
bellard9307c4c2004-04-04 12:57:25 +0000971 bs = bdrv_find(filename);
bellard9dc39cb2004-03-14 21:38:27 +0000972 if (!bs) {
Markus Armbruster2c2a6bb2009-12-07 21:37:05 +0100973 qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
bellard9dc39cb2004-03-14 21:38:27 +0000974 return;
975 }
aliguori376253e2009-03-05 23:01:23 +0000976 eject_device(mon, bs, force);
bellard9dc39cb2004-03-14 21:38:27 +0000977}
978
Luiz Capitulinoa3a55a22009-12-04 15:24:09 -0200979static void do_block_set_passwd(Monitor *mon, const QDict *qdict,
980 QObject **ret_data)
981{
982 BlockDriverState *bs;
983
984 bs = bdrv_find(qdict_get_str(qdict, "device"));
985 if (!bs) {
986 qemu_error_new(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
987 return;
988 }
989
990 if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) {
991 qemu_error_new(QERR_INVALID_PASSWORD);
992 }
993}
994
aliguori376253e2009-03-05 23:01:23 +0000995static void do_change_block(Monitor *mon, const char *device,
996 const char *filename, const char *fmt)
bellard9dc39cb2004-03-14 21:38:27 +0000997{
998 BlockDriverState *bs;
aurel322ecea9b2008-06-18 22:10:01 +0000999 BlockDriver *drv = NULL;
bellard9dc39cb2004-03-14 21:38:27 +00001000
bellard9307c4c2004-04-04 12:57:25 +00001001 bs = bdrv_find(device);
bellard9dc39cb2004-03-14 21:38:27 +00001002 if (!bs) {
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001003 qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
bellard9dc39cb2004-03-14 21:38:27 +00001004 return;
1005 }
aurel322ecea9b2008-06-18 22:10:01 +00001006 if (fmt) {
Markus Armbrustereb852012009-10-27 18:41:44 +01001007 drv = bdrv_find_whitelisted_format(fmt);
aurel322ecea9b2008-06-18 22:10:01 +00001008 if (!drv) {
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001009 qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt);
aurel322ecea9b2008-06-18 22:10:01 +00001010 return;
1011 }
1012 }
aliguori376253e2009-03-05 23:01:23 +00001013 if (eject_device(mon, bs, 0) < 0)
bellard9dc39cb2004-03-14 21:38:27 +00001014 return;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001015 bdrv_open2(bs, filename, BDRV_O_RDWR, drv);
aliguori376253e2009-03-05 23:01:23 +00001016 monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
aliguoribb5fc202009-03-05 23:01:15 +00001017}
1018
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001019static void change_vnc_password(const char *password)
aliguoribb5fc202009-03-05 23:01:15 +00001020{
1021 if (vnc_display_password(NULL, password) < 0)
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001022 qemu_error_new(QERR_SET_PASSWD_FAILED);
aliguoribb5fc202009-03-05 23:01:15 +00001023
Markus Armbruster2895e072009-12-07 21:37:01 +01001024}
1025
1026static void change_vnc_password_cb(Monitor *mon, const char *password,
1027 void *opaque)
1028{
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001029 change_vnc_password(password);
aliguori731b0362009-03-05 23:01:42 +00001030 monitor_read_command(mon, 1);
bellard9dc39cb2004-03-14 21:38:27 +00001031}
1032
aliguori376253e2009-03-05 23:01:23 +00001033static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
thse25a5822007-08-25 01:36:20 +00001034{
ths70848512007-08-25 01:37:05 +00001035 if (strcmp(target, "passwd") == 0 ||
aliguori28a76be2009-03-06 20:27:40 +00001036 strcmp(target, "password") == 0) {
1037 if (arg) {
aliguoribb5fc202009-03-05 23:01:15 +00001038 char password[9];
aliguori28a76be2009-03-06 20:27:40 +00001039 strncpy(password, arg, sizeof(password));
1040 password[sizeof(password) - 1] = '\0';
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001041 change_vnc_password(password);
aliguoribb5fc202009-03-05 23:01:15 +00001042 } else {
aliguori376253e2009-03-05 23:01:23 +00001043 monitor_read_password(mon, change_vnc_password_cb, NULL);
aliguoribb5fc202009-03-05 23:01:15 +00001044 }
ths70848512007-08-25 01:37:05 +00001045 } else {
aliguori28a76be2009-03-06 20:27:40 +00001046 if (vnc_display_open(NULL, target) < 0)
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001047 qemu_error_new(QERR_VNC_SERVER_FAILED, target);
ths70848512007-08-25 01:37:05 +00001048 }
thse25a5822007-08-25 01:36:20 +00001049}
1050
Markus Armbrusterec3b82a2009-12-07 21:37:09 +01001051/**
1052 * do_change(): Change a removable medium, or VNC configuration
1053 */
1054static void do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
thse25a5822007-08-25 01:36:20 +00001055{
Luiz Capitulino1d4daa92009-08-28 15:27:15 -03001056 const char *device = qdict_get_str(qdict, "device");
1057 const char *target = qdict_get_str(qdict, "target");
1058 const char *arg = qdict_get_try_str(qdict, "arg");
thse25a5822007-08-25 01:36:20 +00001059 if (strcmp(device, "vnc") == 0) {
aliguori28a76be2009-03-06 20:27:40 +00001060 do_change_vnc(mon, target, arg);
thse25a5822007-08-25 01:36:20 +00001061 } else {
aliguori28a76be2009-03-06 20:27:40 +00001062 do_change_block(mon, device, target, arg);
thse25a5822007-08-25 01:36:20 +00001063 }
1064}
1065
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001066static void do_screen_dump(Monitor *mon, const QDict *qdict)
bellard59a983b2004-03-17 23:17:16 +00001067{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001068 vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
bellard59a983b2004-03-17 23:17:16 +00001069}
1070
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001071static void do_logfile(Monitor *mon, const QDict *qdict)
pbrooke735b912007-06-30 13:53:24 +00001072{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001073 cpu_set_log_filename(qdict_get_str(qdict, "filename"));
pbrooke735b912007-06-30 13:53:24 +00001074}
1075
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001076static void do_log(Monitor *mon, const QDict *qdict)
bellardf193c792004-03-21 17:06:25 +00001077{
1078 int mask;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001079 const char *items = qdict_get_str(qdict, "items");
ths3b46e622007-09-17 08:09:54 +00001080
bellard9307c4c2004-04-04 12:57:25 +00001081 if (!strcmp(items, "none")) {
bellardf193c792004-03-21 17:06:25 +00001082 mask = 0;
1083 } else {
bellard9307c4c2004-04-04 12:57:25 +00001084 mask = cpu_str_to_log_mask(items);
bellardf193c792004-03-21 17:06:25 +00001085 if (!mask) {
aliguori376253e2009-03-05 23:01:23 +00001086 help_cmd(mon, "log");
bellardf193c792004-03-21 17:06:25 +00001087 return;
1088 }
1089 }
1090 cpu_set_log(mask);
1091}
1092
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001093static void do_singlestep(Monitor *mon, const QDict *qdict)
aurel321b530a62009-04-05 20:08:59 +00001094{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001095 const char *option = qdict_get_try_str(qdict, "option");
aurel321b530a62009-04-05 20:08:59 +00001096 if (!option || !strcmp(option, "on")) {
1097 singlestep = 1;
1098 } else if (!strcmp(option, "off")) {
1099 singlestep = 0;
1100 } else {
1101 monitor_printf(mon, "unexpected option %s\n", option);
1102 }
1103}
1104
Luiz Capitulinoe0c97bd2009-10-07 13:41:57 -03001105/**
1106 * do_stop(): Stop VM execution
1107 */
1108static void do_stop(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellard8a7ddc32004-03-31 19:00:16 +00001109{
1110 vm_stop(EXCP_INTERRUPT);
1111}
1112
aliguoribb5fc202009-03-05 23:01:15 +00001113static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
aliguoric0f4ce72009-03-05 23:01:01 +00001114
aliguori376253e2009-03-05 23:01:23 +00001115struct bdrv_iterate_context {
1116 Monitor *mon;
1117 int err;
1118};
aliguoric0f4ce72009-03-05 23:01:01 +00001119
Luiz Capitulinoa1f896a2009-10-07 13:42:00 -03001120/**
1121 * do_cont(): Resume emulation.
1122 */
1123static void do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
aliguori376253e2009-03-05 23:01:23 +00001124{
1125 struct bdrv_iterate_context context = { mon, 0 };
1126
1127 bdrv_iterate(encrypted_bdrv_it, &context);
aliguoric0f4ce72009-03-05 23:01:01 +00001128 /* only resume the vm if all keys are set and valid */
aliguori376253e2009-03-05 23:01:23 +00001129 if (!context.err)
aliguoric0f4ce72009-03-05 23:01:01 +00001130 vm_start();
bellard8a7ddc32004-03-31 19:00:16 +00001131}
1132
aliguoribb5fc202009-03-05 23:01:15 +00001133static void bdrv_key_cb(void *opaque, int err)
1134{
aliguori376253e2009-03-05 23:01:23 +00001135 Monitor *mon = opaque;
1136
aliguoribb5fc202009-03-05 23:01:15 +00001137 /* another key was set successfully, retry to continue */
1138 if (!err)
Luiz Capitulinoa1f896a2009-10-07 13:42:00 -03001139 do_cont(mon, NULL, NULL);
aliguoribb5fc202009-03-05 23:01:15 +00001140}
1141
1142static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
1143{
aliguori376253e2009-03-05 23:01:23 +00001144 struct bdrv_iterate_context *context = opaque;
aliguoribb5fc202009-03-05 23:01:15 +00001145
aliguori376253e2009-03-05 23:01:23 +00001146 if (!context->err && bdrv_key_required(bs)) {
1147 context->err = -EBUSY;
1148 monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
1149 context->mon);
aliguoribb5fc202009-03-05 23:01:15 +00001150 }
1151}
1152
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001153static void do_gdbserver(Monitor *mon, const QDict *qdict)
bellard8a7ddc32004-03-31 19:00:16 +00001154{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001155 const char *device = qdict_get_try_str(qdict, "device");
aliguori59030a82009-04-05 18:43:41 +00001156 if (!device)
1157 device = "tcp::" DEFAULT_GDBSTUB_PORT;
1158 if (gdbserver_start(device) < 0) {
1159 monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
1160 device);
1161 } else if (strcmp(device, "none") == 0) {
aliguori36556b22009-03-28 18:05:53 +00001162 monitor_printf(mon, "Disabled gdbserver\n");
bellard8a7ddc32004-03-31 19:00:16 +00001163 } else {
aliguori59030a82009-04-05 18:43:41 +00001164 monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
1165 device);
bellard8a7ddc32004-03-31 19:00:16 +00001166 }
1167}
1168
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001169static void do_watchdog_action(Monitor *mon, const QDict *qdict)
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +01001170{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001171 const char *action = qdict_get_str(qdict, "action");
Richard W.M. Jones9dd986c2009-04-25 13:56:19 +01001172 if (select_watchdog_action(action) == -1) {
1173 monitor_printf(mon, "Unknown watchdog action '%s'\n", action);
1174 }
1175}
1176
aliguori376253e2009-03-05 23:01:23 +00001177static void monitor_printc(Monitor *mon, int c)
bellard9307c4c2004-04-04 12:57:25 +00001178{
aliguori376253e2009-03-05 23:01:23 +00001179 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +00001180 switch(c) {
1181 case '\'':
aliguori376253e2009-03-05 23:01:23 +00001182 monitor_printf(mon, "\\'");
bellard9307c4c2004-04-04 12:57:25 +00001183 break;
1184 case '\\':
aliguori376253e2009-03-05 23:01:23 +00001185 monitor_printf(mon, "\\\\");
bellard9307c4c2004-04-04 12:57:25 +00001186 break;
1187 case '\n':
aliguori376253e2009-03-05 23:01:23 +00001188 monitor_printf(mon, "\\n");
bellard9307c4c2004-04-04 12:57:25 +00001189 break;
1190 case '\r':
aliguori376253e2009-03-05 23:01:23 +00001191 monitor_printf(mon, "\\r");
bellard9307c4c2004-04-04 12:57:25 +00001192 break;
1193 default:
1194 if (c >= 32 && c <= 126) {
aliguori376253e2009-03-05 23:01:23 +00001195 monitor_printf(mon, "%c", c);
bellard9307c4c2004-04-04 12:57:25 +00001196 } else {
aliguori376253e2009-03-05 23:01:23 +00001197 monitor_printf(mon, "\\x%02x", c);
bellard9307c4c2004-04-04 12:57:25 +00001198 }
1199 break;
1200 }
aliguori376253e2009-03-05 23:01:23 +00001201 monitor_printf(mon, "'");
bellard9307c4c2004-04-04 12:57:25 +00001202}
1203
aliguori376253e2009-03-05 23:01:23 +00001204static void memory_dump(Monitor *mon, int count, int format, int wsize,
Anthony Liguoric227f092009-10-01 16:12:16 -05001205 target_phys_addr_t addr, int is_physical)
bellard9307c4c2004-04-04 12:57:25 +00001206{
bellard6a00d602005-11-21 23:25:50 +00001207 CPUState *env;
Blue Swirl23842aa2010-01-12 20:27:43 +00001208 int l, line_size, i, max_digits, len;
bellard9307c4c2004-04-04 12:57:25 +00001209 uint8_t buf[16];
1210 uint64_t v;
1211
1212 if (format == 'i') {
1213 int flags;
1214 flags = 0;
bellard6a00d602005-11-21 23:25:50 +00001215 env = mon_get_cpu();
Markus Armbruster09b94182010-01-20 13:07:30 +01001216 if (!is_physical)
bellard6a00d602005-11-21 23:25:50 +00001217 return;
bellard9307c4c2004-04-04 12:57:25 +00001218#ifdef TARGET_I386
bellard4c27ba22004-04-25 18:05:08 +00001219 if (wsize == 2) {
bellard9307c4c2004-04-04 12:57:25 +00001220 flags = 1;
bellard4c27ba22004-04-25 18:05:08 +00001221 } else if (wsize == 4) {
1222 flags = 0;
1223 } else {
bellard6a15fd12006-04-12 21:07:07 +00001224 /* as default we use the current CS size */
bellard4c27ba22004-04-25 18:05:08 +00001225 flags = 0;
bellard6a15fd12006-04-12 21:07:07 +00001226 if (env) {
1227#ifdef TARGET_X86_64
ths5fafdf22007-09-16 21:08:06 +00001228 if ((env->efer & MSR_EFER_LMA) &&
bellard6a15fd12006-04-12 21:07:07 +00001229 (env->segs[R_CS].flags & DESC_L_MASK))
1230 flags = 2;
1231 else
1232#endif
1233 if (!(env->segs[R_CS].flags & DESC_B_MASK))
1234 flags = 1;
1235 }
bellard4c27ba22004-04-25 18:05:08 +00001236 }
1237#endif
aliguori376253e2009-03-05 23:01:23 +00001238 monitor_disas(mon, env, addr, count, is_physical, flags);
bellard9307c4c2004-04-04 12:57:25 +00001239 return;
1240 }
1241
1242 len = wsize * count;
1243 if (wsize == 1)
1244 line_size = 8;
1245 else
1246 line_size = 16;
bellard9307c4c2004-04-04 12:57:25 +00001247 max_digits = 0;
1248
1249 switch(format) {
1250 case 'o':
1251 max_digits = (wsize * 8 + 2) / 3;
1252 break;
1253 default:
1254 case 'x':
1255 max_digits = (wsize * 8) / 4;
1256 break;
1257 case 'u':
1258 case 'd':
1259 max_digits = (wsize * 8 * 10 + 32) / 33;
1260 break;
1261 case 'c':
1262 wsize = 1;
1263 break;
1264 }
1265
1266 while (len > 0) {
blueswir17743e582007-09-24 18:39:04 +00001267 if (is_physical)
aliguori376253e2009-03-05 23:01:23 +00001268 monitor_printf(mon, TARGET_FMT_plx ":", addr);
blueswir17743e582007-09-24 18:39:04 +00001269 else
aliguori376253e2009-03-05 23:01:23 +00001270 monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
bellard9307c4c2004-04-04 12:57:25 +00001271 l = len;
1272 if (l > line_size)
1273 l = line_size;
1274 if (is_physical) {
1275 cpu_physical_memory_rw(addr, buf, l, 0);
1276 } else {
bellard6a00d602005-11-21 23:25:50 +00001277 env = mon_get_cpu();
aliguoric8f79b62008-08-18 14:00:20 +00001278 if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
aliguori376253e2009-03-05 23:01:23 +00001279 monitor_printf(mon, " Cannot access memory\n");
aliguoric8f79b62008-08-18 14:00:20 +00001280 break;
1281 }
bellard9307c4c2004-04-04 12:57:25 +00001282 }
ths5fafdf22007-09-16 21:08:06 +00001283 i = 0;
bellard9307c4c2004-04-04 12:57:25 +00001284 while (i < l) {
1285 switch(wsize) {
1286 default:
1287 case 1:
1288 v = ldub_raw(buf + i);
1289 break;
1290 case 2:
1291 v = lduw_raw(buf + i);
1292 break;
1293 case 4:
bellard92a31b12005-02-10 22:00:52 +00001294 v = (uint32_t)ldl_raw(buf + i);
bellard9307c4c2004-04-04 12:57:25 +00001295 break;
1296 case 8:
1297 v = ldq_raw(buf + i);
1298 break;
1299 }
aliguori376253e2009-03-05 23:01:23 +00001300 monitor_printf(mon, " ");
bellard9307c4c2004-04-04 12:57:25 +00001301 switch(format) {
1302 case 'o':
aliguori376253e2009-03-05 23:01:23 +00001303 monitor_printf(mon, "%#*" PRIo64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +00001304 break;
1305 case 'x':
aliguori376253e2009-03-05 23:01:23 +00001306 monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +00001307 break;
1308 case 'u':
aliguori376253e2009-03-05 23:01:23 +00001309 monitor_printf(mon, "%*" PRIu64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +00001310 break;
1311 case 'd':
aliguori376253e2009-03-05 23:01:23 +00001312 monitor_printf(mon, "%*" PRId64, max_digits, v);
bellard9307c4c2004-04-04 12:57:25 +00001313 break;
1314 case 'c':
aliguori376253e2009-03-05 23:01:23 +00001315 monitor_printc(mon, v);
bellard9307c4c2004-04-04 12:57:25 +00001316 break;
1317 }
1318 i += wsize;
1319 }
aliguori376253e2009-03-05 23:01:23 +00001320 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +00001321 addr += l;
1322 len -= l;
1323 }
1324}
1325
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001326static void do_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +00001327{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001328 int count = qdict_get_int(qdict, "count");
1329 int format = qdict_get_int(qdict, "format");
1330 int size = qdict_get_int(qdict, "size");
1331 target_long addr = qdict_get_int(qdict, "addr");
1332
aliguori376253e2009-03-05 23:01:23 +00001333 memory_dump(mon, count, format, size, addr, 0);
bellard9307c4c2004-04-04 12:57:25 +00001334}
1335
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001336static void do_physical_memory_dump(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +00001337{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001338 int count = qdict_get_int(qdict, "count");
1339 int format = qdict_get_int(qdict, "format");
1340 int size = qdict_get_int(qdict, "size");
Anthony Liguoric227f092009-10-01 16:12:16 -05001341 target_phys_addr_t addr = qdict_get_int(qdict, "addr");
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001342
aliguori376253e2009-03-05 23:01:23 +00001343 memory_dump(mon, count, format, size, addr, 1);
bellard9307c4c2004-04-04 12:57:25 +00001344}
1345
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001346static void do_print(Monitor *mon, const QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +00001347{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001348 int format = qdict_get_int(qdict, "format");
Anthony Liguoric227f092009-10-01 16:12:16 -05001349 target_phys_addr_t val = qdict_get_int(qdict, "val");
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001350
blueswir17743e582007-09-24 18:39:04 +00001351#if TARGET_PHYS_ADDR_BITS == 32
bellard9307c4c2004-04-04 12:57:25 +00001352 switch(format) {
1353 case 'o':
aliguori376253e2009-03-05 23:01:23 +00001354 monitor_printf(mon, "%#o", val);
bellard9307c4c2004-04-04 12:57:25 +00001355 break;
1356 case 'x':
aliguori376253e2009-03-05 23:01:23 +00001357 monitor_printf(mon, "%#x", val);
bellard9307c4c2004-04-04 12:57:25 +00001358 break;
1359 case 'u':
aliguori376253e2009-03-05 23:01:23 +00001360 monitor_printf(mon, "%u", val);
bellard9307c4c2004-04-04 12:57:25 +00001361 break;
1362 default:
1363 case 'd':
aliguori376253e2009-03-05 23:01:23 +00001364 monitor_printf(mon, "%d", val);
bellard9307c4c2004-04-04 12:57:25 +00001365 break;
1366 case 'c':
aliguori376253e2009-03-05 23:01:23 +00001367 monitor_printc(mon, val);
bellard9307c4c2004-04-04 12:57:25 +00001368 break;
1369 }
bellard92a31b12005-02-10 22:00:52 +00001370#else
1371 switch(format) {
1372 case 'o':
aliguori376253e2009-03-05 23:01:23 +00001373 monitor_printf(mon, "%#" PRIo64, val);
bellard92a31b12005-02-10 22:00:52 +00001374 break;
1375 case 'x':
aliguori376253e2009-03-05 23:01:23 +00001376 monitor_printf(mon, "%#" PRIx64, val);
bellard92a31b12005-02-10 22:00:52 +00001377 break;
1378 case 'u':
aliguori376253e2009-03-05 23:01:23 +00001379 monitor_printf(mon, "%" PRIu64, val);
bellard92a31b12005-02-10 22:00:52 +00001380 break;
1381 default:
1382 case 'd':
aliguori376253e2009-03-05 23:01:23 +00001383 monitor_printf(mon, "%" PRId64, val);
bellard92a31b12005-02-10 22:00:52 +00001384 break;
1385 case 'c':
aliguori376253e2009-03-05 23:01:23 +00001386 monitor_printc(mon, val);
bellard92a31b12005-02-10 22:00:52 +00001387 break;
1388 }
1389#endif
aliguori376253e2009-03-05 23:01:23 +00001390 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +00001391}
1392
Luiz Capitulino57e09452009-10-16 12:23:43 -03001393static void do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
bellardb371dc52007-01-03 15:20:39 +00001394{
1395 FILE *f;
Luiz Capitulinoafe67ef2009-08-28 15:27:16 -03001396 uint32_t size = qdict_get_int(qdict, "size");
1397 const char *filename = qdict_get_str(qdict, "filename");
1398 target_long addr = qdict_get_int(qdict, "val");
bellardb371dc52007-01-03 15:20:39 +00001399 uint32_t l;
1400 CPUState *env;
1401 uint8_t buf[1024];
1402
1403 env = mon_get_cpu();
bellardb371dc52007-01-03 15:20:39 +00001404
1405 f = fopen(filename, "wb");
1406 if (!f) {
Markus Armbrusterc34ed282010-01-20 13:07:32 +01001407 qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
bellardb371dc52007-01-03 15:20:39 +00001408 return;
1409 }
1410 while (size != 0) {
1411 l = sizeof(buf);
1412 if (l > size)
1413 l = size;
1414 cpu_memory_rw_debug(env, addr, buf, l, 0);
Kirill A. Shutemov27e3ddd2010-01-20 00:56:19 +01001415 if (fwrite(buf, 1, l, f) != l) {
1416 monitor_printf(mon, "fwrite() error in do_memory_save\n");
1417 goto exit;
1418 }
bellardb371dc52007-01-03 15:20:39 +00001419 addr += l;
1420 size -= l;
1421 }
Kirill A. Shutemov27e3ddd2010-01-20 00:56:19 +01001422exit:
bellardb371dc52007-01-03 15:20:39 +00001423 fclose(f);
1424}
1425
Luiz Capitulino18f5a8b2009-10-16 12:23:44 -03001426static void do_physical_memory_save(Monitor *mon, const QDict *qdict,
1427 QObject **ret_data)
aurel32a8bdf7a2008-04-11 21:36:14 +00001428{
1429 FILE *f;
1430 uint32_t l;
1431 uint8_t buf[1024];
Luiz Capitulinoafe67ef2009-08-28 15:27:16 -03001432 uint32_t size = qdict_get_int(qdict, "size");
1433 const char *filename = qdict_get_str(qdict, "filename");
Anthony Liguoric227f092009-10-01 16:12:16 -05001434 target_phys_addr_t addr = qdict_get_int(qdict, "val");
aurel32a8bdf7a2008-04-11 21:36:14 +00001435
1436 f = fopen(filename, "wb");
1437 if (!f) {
Markus Armbruster95fada82010-01-20 13:07:33 +01001438 qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
aurel32a8bdf7a2008-04-11 21:36:14 +00001439 return;
1440 }
1441 while (size != 0) {
1442 l = sizeof(buf);
1443 if (l > size)
1444 l = size;
1445 cpu_physical_memory_rw(addr, buf, l, 0);
Kirill A. Shutemov27e3ddd2010-01-20 00:56:19 +01001446 if (fwrite(buf, 1, l, f) != l) {
1447 monitor_printf(mon, "fwrite() error in do_physical_memory_save\n");
1448 goto exit;
1449 }
aurel32a8bdf7a2008-04-11 21:36:14 +00001450 fflush(f);
1451 addr += l;
1452 size -= l;
1453 }
Kirill A. Shutemov27e3ddd2010-01-20 00:56:19 +01001454exit:
aurel32a8bdf7a2008-04-11 21:36:14 +00001455 fclose(f);
1456}
1457
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001458static void do_sum(Monitor *mon, const QDict *qdict)
bellarde4cf1ad2005-06-04 20:15:57 +00001459{
1460 uint32_t addr;
1461 uint8_t buf[1];
1462 uint16_t sum;
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03001463 uint32_t start = qdict_get_int(qdict, "start");
1464 uint32_t size = qdict_get_int(qdict, "size");
bellarde4cf1ad2005-06-04 20:15:57 +00001465
1466 sum = 0;
1467 for(addr = start; addr < (start + size); addr++) {
1468 cpu_physical_memory_rw(addr, buf, 1, 0);
1469 /* BSD sum algorithm ('sum' Unix command) */
1470 sum = (sum >> 1) | (sum << 15);
1471 sum += buf[0];
1472 }
aliguori376253e2009-03-05 23:01:23 +00001473 monitor_printf(mon, "%05d\n", sum);
bellarde4cf1ad2005-06-04 20:15:57 +00001474}
1475
bellarda3a91a32004-06-04 11:06:21 +00001476typedef struct {
1477 int keycode;
1478 const char *name;
1479} KeyDef;
1480
1481static const KeyDef key_defs[] = {
1482 { 0x2a, "shift" },
1483 { 0x36, "shift_r" },
ths3b46e622007-09-17 08:09:54 +00001484
bellarda3a91a32004-06-04 11:06:21 +00001485 { 0x38, "alt" },
1486 { 0xb8, "alt_r" },
ths2ba27c72008-08-13 12:54:23 +00001487 { 0x64, "altgr" },
1488 { 0xe4, "altgr_r" },
bellarda3a91a32004-06-04 11:06:21 +00001489 { 0x1d, "ctrl" },
1490 { 0x9d, "ctrl_r" },
1491
1492 { 0xdd, "menu" },
1493
1494 { 0x01, "esc" },
1495
1496 { 0x02, "1" },
1497 { 0x03, "2" },
1498 { 0x04, "3" },
1499 { 0x05, "4" },
1500 { 0x06, "5" },
1501 { 0x07, "6" },
1502 { 0x08, "7" },
1503 { 0x09, "8" },
1504 { 0x0a, "9" },
1505 { 0x0b, "0" },
bellard64866c32006-05-07 18:03:31 +00001506 { 0x0c, "minus" },
1507 { 0x0d, "equal" },
bellarda3a91a32004-06-04 11:06:21 +00001508 { 0x0e, "backspace" },
1509
1510 { 0x0f, "tab" },
1511 { 0x10, "q" },
1512 { 0x11, "w" },
1513 { 0x12, "e" },
1514 { 0x13, "r" },
1515 { 0x14, "t" },
1516 { 0x15, "y" },
1517 { 0x16, "u" },
1518 { 0x17, "i" },
1519 { 0x18, "o" },
1520 { 0x19, "p" },
1521
1522 { 0x1c, "ret" },
1523
1524 { 0x1e, "a" },
1525 { 0x1f, "s" },
1526 { 0x20, "d" },
1527 { 0x21, "f" },
1528 { 0x22, "g" },
1529 { 0x23, "h" },
1530 { 0x24, "j" },
1531 { 0x25, "k" },
1532 { 0x26, "l" },
1533
1534 { 0x2c, "z" },
1535 { 0x2d, "x" },
1536 { 0x2e, "c" },
1537 { 0x2f, "v" },
1538 { 0x30, "b" },
1539 { 0x31, "n" },
1540 { 0x32, "m" },
aurel329155fc42008-10-01 21:46:15 +00001541 { 0x33, "comma" },
1542 { 0x34, "dot" },
1543 { 0x35, "slash" },
ths3b46e622007-09-17 08:09:54 +00001544
balrog4d3b6f62008-02-10 16:33:14 +00001545 { 0x37, "asterisk" },
1546
bellarda3a91a32004-06-04 11:06:21 +00001547 { 0x39, "spc" },
bellard00ffa622004-06-04 13:25:15 +00001548 { 0x3a, "caps_lock" },
bellarda3a91a32004-06-04 11:06:21 +00001549 { 0x3b, "f1" },
1550 { 0x3c, "f2" },
1551 { 0x3d, "f3" },
1552 { 0x3e, "f4" },
1553 { 0x3f, "f5" },
1554 { 0x40, "f6" },
1555 { 0x41, "f7" },
1556 { 0x42, "f8" },
1557 { 0x43, "f9" },
1558 { 0x44, "f10" },
bellard00ffa622004-06-04 13:25:15 +00001559 { 0x45, "num_lock" },
bellarda3a91a32004-06-04 11:06:21 +00001560 { 0x46, "scroll_lock" },
1561
bellard64866c32006-05-07 18:03:31 +00001562 { 0xb5, "kp_divide" },
1563 { 0x37, "kp_multiply" },
ths0cfec832007-06-23 16:02:43 +00001564 { 0x4a, "kp_subtract" },
bellard64866c32006-05-07 18:03:31 +00001565 { 0x4e, "kp_add" },
1566 { 0x9c, "kp_enter" },
1567 { 0x53, "kp_decimal" },
balrogf2289cb2008-06-04 10:14:16 +00001568 { 0x54, "sysrq" },
bellard64866c32006-05-07 18:03:31 +00001569
1570 { 0x52, "kp_0" },
1571 { 0x4f, "kp_1" },
1572 { 0x50, "kp_2" },
1573 { 0x51, "kp_3" },
1574 { 0x4b, "kp_4" },
1575 { 0x4c, "kp_5" },
1576 { 0x4d, "kp_6" },
1577 { 0x47, "kp_7" },
1578 { 0x48, "kp_8" },
1579 { 0x49, "kp_9" },
ths3b46e622007-09-17 08:09:54 +00001580
bellarda3a91a32004-06-04 11:06:21 +00001581 { 0x56, "<" },
1582
1583 { 0x57, "f11" },
1584 { 0x58, "f12" },
1585
1586 { 0xb7, "print" },
1587
1588 { 0xc7, "home" },
1589 { 0xc9, "pgup" },
1590 { 0xd1, "pgdn" },
1591 { 0xcf, "end" },
1592
1593 { 0xcb, "left" },
1594 { 0xc8, "up" },
1595 { 0xd0, "down" },
1596 { 0xcd, "right" },
1597
1598 { 0xd2, "insert" },
1599 { 0xd3, "delete" },
blueswir1c0b5b102008-06-22 07:45:42 +00001600#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
1601 { 0xf0, "stop" },
1602 { 0xf1, "again" },
1603 { 0xf2, "props" },
1604 { 0xf3, "undo" },
1605 { 0xf4, "front" },
1606 { 0xf5, "copy" },
1607 { 0xf6, "open" },
1608 { 0xf7, "paste" },
1609 { 0xf8, "find" },
1610 { 0xf9, "cut" },
1611 { 0xfa, "lf" },
1612 { 0xfb, "help" },
1613 { 0xfc, "meta_l" },
1614 { 0xfd, "meta_r" },
1615 { 0xfe, "compose" },
1616#endif
bellarda3a91a32004-06-04 11:06:21 +00001617 { 0, NULL },
1618};
1619
1620static int get_keycode(const char *key)
1621{
1622 const KeyDef *p;
bellard64866c32006-05-07 18:03:31 +00001623 char *endp;
1624 int ret;
bellarda3a91a32004-06-04 11:06:21 +00001625
1626 for(p = key_defs; p->name != NULL; p++) {
1627 if (!strcmp(key, p->name))
1628 return p->keycode;
1629 }
bellard64866c32006-05-07 18:03:31 +00001630 if (strstart(key, "0x", NULL)) {
1631 ret = strtoul(key, &endp, 0);
1632 if (*endp == '\0' && ret >= 0x01 && ret <= 0xff)
1633 return ret;
1634 }
bellarda3a91a32004-06-04 11:06:21 +00001635 return -1;
1636}
1637
balrogc8256f92008-06-08 22:45:01 +00001638#define MAX_KEYCODES 16
1639static uint8_t keycodes[MAX_KEYCODES];
1640static int nb_pending_keycodes;
1641static QEMUTimer *key_timer;
1642
1643static void release_keys(void *opaque)
bellarda3a91a32004-06-04 11:06:21 +00001644{
balrogc8256f92008-06-08 22:45:01 +00001645 int keycode;
1646
1647 while (nb_pending_keycodes > 0) {
1648 nb_pending_keycodes--;
1649 keycode = keycodes[nb_pending_keycodes];
1650 if (keycode & 0x80)
1651 kbd_put_keycode(0xe0);
1652 kbd_put_keycode(keycode | 0x80);
1653 }
1654}
1655
Luiz Capitulino1d4daa92009-08-28 15:27:15 -03001656static void do_sendkey(Monitor *mon, const QDict *qdict)
balrogc8256f92008-06-08 22:45:01 +00001657{
balrog3401c0d2008-06-04 10:05:59 +00001658 char keyname_buf[16];
1659 char *separator;
1660 int keyname_len, keycode, i;
Luiz Capitulino1d4daa92009-08-28 15:27:15 -03001661 const char *string = qdict_get_str(qdict, "string");
1662 int has_hold_time = qdict_haskey(qdict, "hold_time");
1663 int hold_time = qdict_get_try_int(qdict, "hold_time", -1);
ths3b46e622007-09-17 08:09:54 +00001664
balrogc8256f92008-06-08 22:45:01 +00001665 if (nb_pending_keycodes > 0) {
1666 qemu_del_timer(key_timer);
1667 release_keys(NULL);
1668 }
1669 if (!has_hold_time)
1670 hold_time = 100;
1671 i = 0;
balrog3401c0d2008-06-04 10:05:59 +00001672 while (1) {
1673 separator = strchr(string, '-');
1674 keyname_len = separator ? separator - string : strlen(string);
1675 if (keyname_len > 0) {
1676 pstrcpy(keyname_buf, sizeof(keyname_buf), string);
1677 if (keyname_len > sizeof(keyname_buf) - 1) {
aliguori376253e2009-03-05 23:01:23 +00001678 monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
balrog3401c0d2008-06-04 10:05:59 +00001679 return;
bellarda3a91a32004-06-04 11:06:21 +00001680 }
balrogc8256f92008-06-08 22:45:01 +00001681 if (i == MAX_KEYCODES) {
aliguori376253e2009-03-05 23:01:23 +00001682 monitor_printf(mon, "too many keys\n");
balrog3401c0d2008-06-04 10:05:59 +00001683 return;
1684 }
1685 keyname_buf[keyname_len] = 0;
1686 keycode = get_keycode(keyname_buf);
1687 if (keycode < 0) {
aliguori376253e2009-03-05 23:01:23 +00001688 monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
balrog3401c0d2008-06-04 10:05:59 +00001689 return;
1690 }
balrogc8256f92008-06-08 22:45:01 +00001691 keycodes[i++] = keycode;
bellarda3a91a32004-06-04 11:06:21 +00001692 }
balrog3401c0d2008-06-04 10:05:59 +00001693 if (!separator)
bellarda3a91a32004-06-04 11:06:21 +00001694 break;
balrog3401c0d2008-06-04 10:05:59 +00001695 string = separator + 1;
bellarda3a91a32004-06-04 11:06:21 +00001696 }
balrogc8256f92008-06-08 22:45:01 +00001697 nb_pending_keycodes = i;
bellarda3a91a32004-06-04 11:06:21 +00001698 /* key down events */
balrogc8256f92008-06-08 22:45:01 +00001699 for (i = 0; i < nb_pending_keycodes; i++) {
bellarda3a91a32004-06-04 11:06:21 +00001700 keycode = keycodes[i];
1701 if (keycode & 0x80)
1702 kbd_put_keycode(0xe0);
1703 kbd_put_keycode(keycode & 0x7f);
1704 }
balrogc8256f92008-06-08 22:45:01 +00001705 /* delayed key up events */
balrogf227f172008-06-09 00:03:47 +00001706 qemu_mod_timer(key_timer, qemu_get_clock(vm_clock) +
Juan Quintela6ee093c2009-09-10 03:04:26 +02001707 muldiv64(get_ticks_per_sec(), hold_time, 1000));
bellarda3a91a32004-06-04 11:06:21 +00001708}
1709
bellard13224a82006-07-14 22:03:35 +00001710static int mouse_button_state;
1711
Luiz Capitulino1d4daa92009-08-28 15:27:15 -03001712static void do_mouse_move(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +00001713{
1714 int dx, dy, dz;
Luiz Capitulino1d4daa92009-08-28 15:27:15 -03001715 const char *dx_str = qdict_get_str(qdict, "dx_str");
1716 const char *dy_str = qdict_get_str(qdict, "dy_str");
1717 const char *dz_str = qdict_get_try_str(qdict, "dz_str");
bellard13224a82006-07-14 22:03:35 +00001718 dx = strtol(dx_str, NULL, 0);
1719 dy = strtol(dy_str, NULL, 0);
1720 dz = 0;
ths5fafdf22007-09-16 21:08:06 +00001721 if (dz_str)
bellard13224a82006-07-14 22:03:35 +00001722 dz = strtol(dz_str, NULL, 0);
1723 kbd_mouse_event(dx, dy, dz, mouse_button_state);
1724}
1725
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001726static void do_mouse_button(Monitor *mon, const QDict *qdict)
bellard13224a82006-07-14 22:03:35 +00001727{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001728 int button_state = qdict_get_int(qdict, "button_state");
bellard13224a82006-07-14 22:03:35 +00001729 mouse_button_state = button_state;
1730 kbd_mouse_event(0, 0, 0, mouse_button_state);
1731}
1732
Luiz Capitulinoaa93e392009-08-28 15:27:18 -03001733static void do_ioport_read(Monitor *mon, const QDict *qdict)
bellard34405572004-06-08 00:55:58 +00001734{
Luiz Capitulinoaa93e392009-08-28 15:27:18 -03001735 int size = qdict_get_int(qdict, "size");
1736 int addr = qdict_get_int(qdict, "addr");
1737 int has_index = qdict_haskey(qdict, "index");
bellard34405572004-06-08 00:55:58 +00001738 uint32_t val;
1739 int suffix;
1740
1741 if (has_index) {
Luiz Capitulinoaa93e392009-08-28 15:27:18 -03001742 int index = qdict_get_int(qdict, "index");
Blue Swirlafcea8c2009-09-20 16:05:47 +00001743 cpu_outb(addr & IOPORTS_MASK, index & 0xff);
bellard34405572004-06-08 00:55:58 +00001744 addr++;
1745 }
1746 addr &= 0xffff;
1747
1748 switch(size) {
1749 default:
1750 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001751 val = cpu_inb(addr);
bellard34405572004-06-08 00:55:58 +00001752 suffix = 'b';
1753 break;
1754 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001755 val = cpu_inw(addr);
bellard34405572004-06-08 00:55:58 +00001756 suffix = 'w';
1757 break;
1758 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001759 val = cpu_inl(addr);
bellard34405572004-06-08 00:55:58 +00001760 suffix = 'l';
1761 break;
1762 }
aliguori376253e2009-03-05 23:01:23 +00001763 monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
1764 suffix, addr, size * 2, val);
bellard34405572004-06-08 00:55:58 +00001765}
bellarda3a91a32004-06-04 11:06:21 +00001766
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001767static void do_ioport_write(Monitor *mon, const QDict *qdict)
Jan Kiszkaf1147842009-07-14 10:20:11 +02001768{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03001769 int size = qdict_get_int(qdict, "size");
1770 int addr = qdict_get_int(qdict, "addr");
1771 int val = qdict_get_int(qdict, "val");
1772
Jan Kiszkaf1147842009-07-14 10:20:11 +02001773 addr &= IOPORTS_MASK;
1774
1775 switch (size) {
1776 default:
1777 case 1:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001778 cpu_outb(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001779 break;
1780 case 2:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001781 cpu_outw(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001782 break;
1783 case 4:
Blue Swirlafcea8c2009-09-20 16:05:47 +00001784 cpu_outl(addr, val);
Jan Kiszkaf1147842009-07-14 10:20:11 +02001785 break;
1786 }
1787}
1788
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001789static void do_boot_set(Monitor *mon, const QDict *qdict)
aurel320ecdffb2008-05-04 20:11:34 +00001790{
1791 int res;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03001792 const char *bootdevice = qdict_get_str(qdict, "bootdevice");
aurel320ecdffb2008-05-04 20:11:34 +00001793
Jan Kiszka76e30d02009-07-02 00:19:02 +02001794 res = qemu_boot_set(bootdevice);
1795 if (res == 0) {
1796 monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
1797 } else if (res > 0) {
1798 monitor_printf(mon, "setting boot device list failed\n");
aurel320ecdffb2008-05-04 20:11:34 +00001799 } else {
aliguori376253e2009-03-05 23:01:23 +00001800 monitor_printf(mon, "no function defined to set boot device list for "
1801 "this architecture\n");
aurel320ecdffb2008-05-04 20:11:34 +00001802 }
1803}
1804
Luiz Capitulinoc80d2592009-10-07 13:41:58 -03001805/**
1806 * do_system_reset(): Issue a machine reset
1807 */
1808static void do_system_reset(Monitor *mon, const QDict *qdict,
1809 QObject **ret_data)
bellarde4f90822004-06-20 12:35:44 +00001810{
1811 qemu_system_reset_request();
1812}
1813
Luiz Capitulino43076662009-10-07 13:41:59 -03001814/**
1815 * do_system_powerdown(): Issue a machine powerdown
1816 */
1817static void do_system_powerdown(Monitor *mon, const QDict *qdict,
1818 QObject **ret_data)
bellard34751872005-07-02 14:31:34 +00001819{
1820 qemu_system_powerdown_request();
1821}
1822
bellardb86bda52004-09-18 19:32:46 +00001823#if defined(TARGET_I386)
aliguori376253e2009-03-05 23:01:23 +00001824static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
bellardb86bda52004-09-18 19:32:46 +00001825{
aliguori376253e2009-03-05 23:01:23 +00001826 monitor_printf(mon, "%08x: %08x %c%c%c%c%c%c%c%c\n",
1827 addr,
1828 pte & mask,
1829 pte & PG_GLOBAL_MASK ? 'G' : '-',
1830 pte & PG_PSE_MASK ? 'P' : '-',
1831 pte & PG_DIRTY_MASK ? 'D' : '-',
1832 pte & PG_ACCESSED_MASK ? 'A' : '-',
1833 pte & PG_PCD_MASK ? 'C' : '-',
1834 pte & PG_PWT_MASK ? 'T' : '-',
1835 pte & PG_USER_MASK ? 'U' : '-',
1836 pte & PG_RW_MASK ? 'W' : '-');
bellardb86bda52004-09-18 19:32:46 +00001837}
1838
aliguori376253e2009-03-05 23:01:23 +00001839static void tlb_info(Monitor *mon)
bellardb86bda52004-09-18 19:32:46 +00001840{
bellard6a00d602005-11-21 23:25:50 +00001841 CPUState *env;
bellardb86bda52004-09-18 19:32:46 +00001842 int l1, l2;
1843 uint32_t pgd, pde, pte;
1844
bellard6a00d602005-11-21 23:25:50 +00001845 env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00001846
bellardb86bda52004-09-18 19:32:46 +00001847 if (!(env->cr[0] & CR0_PG_MASK)) {
aliguori376253e2009-03-05 23:01:23 +00001848 monitor_printf(mon, "PG disabled\n");
bellardb86bda52004-09-18 19:32:46 +00001849 return;
1850 }
1851 pgd = env->cr[3] & ~0xfff;
1852 for(l1 = 0; l1 < 1024; l1++) {
1853 cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
1854 pde = le32_to_cpu(pde);
1855 if (pde & PG_PRESENT_MASK) {
1856 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
aliguori376253e2009-03-05 23:01:23 +00001857 print_pte(mon, (l1 << 22), pde, ~((1 << 20) - 1));
bellardb86bda52004-09-18 19:32:46 +00001858 } else {
1859 for(l2 = 0; l2 < 1024; l2++) {
ths5fafdf22007-09-16 21:08:06 +00001860 cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
bellardb86bda52004-09-18 19:32:46 +00001861 (uint8_t *)&pte, 4);
1862 pte = le32_to_cpu(pte);
1863 if (pte & PG_PRESENT_MASK) {
aliguori376253e2009-03-05 23:01:23 +00001864 print_pte(mon, (l1 << 22) + (l2 << 12),
ths5fafdf22007-09-16 21:08:06 +00001865 pte & ~PG_PSE_MASK,
bellardb86bda52004-09-18 19:32:46 +00001866 ~0xfff);
1867 }
1868 }
1869 }
1870 }
1871 }
1872}
1873
aliguori376253e2009-03-05 23:01:23 +00001874static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
bellardb86bda52004-09-18 19:32:46 +00001875 uint32_t end, int prot)
1876{
bellard9746b152004-11-11 18:30:24 +00001877 int prot1;
1878 prot1 = *plast_prot;
1879 if (prot != prot1) {
bellardb86bda52004-09-18 19:32:46 +00001880 if (*pstart != -1) {
aliguori376253e2009-03-05 23:01:23 +00001881 monitor_printf(mon, "%08x-%08x %08x %c%c%c\n",
1882 *pstart, end, end - *pstart,
1883 prot1 & PG_USER_MASK ? 'u' : '-',
1884 'r',
1885 prot1 & PG_RW_MASK ? 'w' : '-');
bellardb86bda52004-09-18 19:32:46 +00001886 }
1887 if (prot != 0)
1888 *pstart = end;
1889 else
1890 *pstart = -1;
1891 *plast_prot = prot;
1892 }
1893}
1894
aliguori376253e2009-03-05 23:01:23 +00001895static void mem_info(Monitor *mon)
bellardb86bda52004-09-18 19:32:46 +00001896{
bellard6a00d602005-11-21 23:25:50 +00001897 CPUState *env;
bellardb86bda52004-09-18 19:32:46 +00001898 int l1, l2, prot, last_prot;
1899 uint32_t pgd, pde, pte, start, end;
1900
bellard6a00d602005-11-21 23:25:50 +00001901 env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00001902
bellardb86bda52004-09-18 19:32:46 +00001903 if (!(env->cr[0] & CR0_PG_MASK)) {
aliguori376253e2009-03-05 23:01:23 +00001904 monitor_printf(mon, "PG disabled\n");
bellardb86bda52004-09-18 19:32:46 +00001905 return;
1906 }
1907 pgd = env->cr[3] & ~0xfff;
1908 last_prot = 0;
1909 start = -1;
1910 for(l1 = 0; l1 < 1024; l1++) {
1911 cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
1912 pde = le32_to_cpu(pde);
1913 end = l1 << 22;
1914 if (pde & PG_PRESENT_MASK) {
1915 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1916 prot = pde & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
aliguori376253e2009-03-05 23:01:23 +00001917 mem_print(mon, &start, &last_prot, end, prot);
bellardb86bda52004-09-18 19:32:46 +00001918 } else {
1919 for(l2 = 0; l2 < 1024; l2++) {
ths5fafdf22007-09-16 21:08:06 +00001920 cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
bellardb86bda52004-09-18 19:32:46 +00001921 (uint8_t *)&pte, 4);
1922 pte = le32_to_cpu(pte);
1923 end = (l1 << 22) + (l2 << 12);
1924 if (pte & PG_PRESENT_MASK) {
1925 prot = pte & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
1926 } else {
1927 prot = 0;
1928 }
aliguori376253e2009-03-05 23:01:23 +00001929 mem_print(mon, &start, &last_prot, end, prot);
bellardb86bda52004-09-18 19:32:46 +00001930 }
1931 }
1932 } else {
1933 prot = 0;
aliguori376253e2009-03-05 23:01:23 +00001934 mem_print(mon, &start, &last_prot, end, prot);
bellardb86bda52004-09-18 19:32:46 +00001935 }
1936 }
1937}
1938#endif
1939
aurel327c664e22009-03-03 06:12:22 +00001940#if defined(TARGET_SH4)
1941
aliguori376253e2009-03-05 23:01:23 +00001942static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
aurel327c664e22009-03-03 06:12:22 +00001943{
aliguori376253e2009-03-05 23:01:23 +00001944 monitor_printf(mon, " tlb%i:\t"
1945 "asid=%hhu vpn=%x\tppn=%x\tsz=%hhu size=%u\t"
1946 "v=%hhu shared=%hhu cached=%hhu prot=%hhu "
1947 "dirty=%hhu writethrough=%hhu\n",
1948 idx,
1949 tlb->asid, tlb->vpn, tlb->ppn, tlb->sz, tlb->size,
1950 tlb->v, tlb->sh, tlb->c, tlb->pr,
1951 tlb->d, tlb->wt);
aurel327c664e22009-03-03 06:12:22 +00001952}
1953
aliguori376253e2009-03-05 23:01:23 +00001954static void tlb_info(Monitor *mon)
aurel327c664e22009-03-03 06:12:22 +00001955{
1956 CPUState *env = mon_get_cpu();
1957 int i;
1958
aliguori376253e2009-03-05 23:01:23 +00001959 monitor_printf (mon, "ITLB:\n");
aurel327c664e22009-03-03 06:12:22 +00001960 for (i = 0 ; i < ITLB_SIZE ; i++)
aliguori376253e2009-03-05 23:01:23 +00001961 print_tlb (mon, i, &env->itlb[i]);
1962 monitor_printf (mon, "UTLB:\n");
aurel327c664e22009-03-03 06:12:22 +00001963 for (i = 0 ; i < UTLB_SIZE ; i++)
aliguori376253e2009-03-05 23:01:23 +00001964 print_tlb (mon, i, &env->utlb[i]);
aurel327c664e22009-03-03 06:12:22 +00001965}
1966
1967#endif
1968
Luiz Capitulino2af5ba72009-12-10 17:16:00 -02001969static void do_info_kvm_print(Monitor *mon, const QObject *data)
1970{
1971 QDict *qdict;
1972
1973 qdict = qobject_to_qdict(data);
1974
1975 monitor_printf(mon, "kvm support: ");
1976 if (qdict_get_bool(qdict, "present")) {
1977 monitor_printf(mon, "%s\n", qdict_get_bool(qdict, "enabled") ?
1978 "enabled" : "disabled");
1979 } else {
1980 monitor_printf(mon, "not compiled\n");
1981 }
1982}
1983
1984/**
1985 * do_info_kvm(): Show KVM information
1986 *
1987 * Return a QDict with the following information:
1988 *
1989 * - "enabled": true if KVM support is enabled, false otherwise
1990 * - "present": true if QEMU has KVM support, false otherwise
1991 *
1992 * Example:
1993 *
1994 * { "enabled": true, "present": true }
1995 */
1996static void do_info_kvm(Monitor *mon, QObject **ret_data)
aliguori7ba1e612008-11-05 16:04:33 +00001997{
1998#ifdef CONFIG_KVM
Luiz Capitulino2af5ba72009-12-10 17:16:00 -02001999 *ret_data = qobject_from_jsonf("{ 'enabled': %i, 'present': true }",
2000 kvm_enabled());
aliguori7ba1e612008-11-05 16:04:33 +00002001#else
Luiz Capitulino2af5ba72009-12-10 17:16:00 -02002002 *ret_data = qobject_from_jsonf("{ 'enabled': false, 'present': false }");
aliguori7ba1e612008-11-05 16:04:33 +00002003#endif
2004}
2005
aliguori030ea372009-04-21 22:30:47 +00002006static void do_info_numa(Monitor *mon)
2007{
aliguorib28b6232009-04-22 20:20:29 +00002008 int i;
aliguori030ea372009-04-21 22:30:47 +00002009 CPUState *env;
2010
2011 monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
2012 for (i = 0; i < nb_numa_nodes; i++) {
2013 monitor_printf(mon, "node %d cpus:", i);
2014 for (env = first_cpu; env != NULL; env = env->next_cpu) {
2015 if (env->numa_node == i) {
2016 monitor_printf(mon, " %d", env->cpu_index);
2017 }
2018 }
2019 monitor_printf(mon, "\n");
2020 monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
2021 node_mem[i] >> 20);
2022 }
2023}
2024
bellard5f1ce942006-02-08 22:40:15 +00002025#ifdef CONFIG_PROFILER
2026
Aurelien Jarnoe9a66252009-09-30 14:09:52 +02002027int64_t qemu_time;
2028int64_t dev_time;
2029
aliguori376253e2009-03-05 23:01:23 +00002030static void do_info_profile(Monitor *mon)
bellard5f1ce942006-02-08 22:40:15 +00002031{
2032 int64_t total;
2033 total = qemu_time;
2034 if (total == 0)
2035 total = 1;
aliguori376253e2009-03-05 23:01:23 +00002036 monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
Juan Quintela6ee093c2009-09-10 03:04:26 +02002037 dev_time, dev_time / (double)get_ticks_per_sec());
aliguori376253e2009-03-05 23:01:23 +00002038 monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
Juan Quintela6ee093c2009-09-10 03:04:26 +02002039 qemu_time, qemu_time / (double)get_ticks_per_sec());
bellard5f1ce942006-02-08 22:40:15 +00002040 qemu_time = 0;
bellard5f1ce942006-02-08 22:40:15 +00002041 dev_time = 0;
bellard5f1ce942006-02-08 22:40:15 +00002042}
2043#else
aliguori376253e2009-03-05 23:01:23 +00002044static void do_info_profile(Monitor *mon)
bellard5f1ce942006-02-08 22:40:15 +00002045{
aliguori376253e2009-03-05 23:01:23 +00002046 monitor_printf(mon, "Internal profiler not compiled\n");
bellard5f1ce942006-02-08 22:40:15 +00002047}
2048#endif
2049
bellardec36b692006-07-16 18:57:03 +00002050/* Capture support */
Blue Swirl72cf2d42009-09-12 07:36:22 +00002051static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
bellardec36b692006-07-16 18:57:03 +00002052
aliguori376253e2009-03-05 23:01:23 +00002053static void do_info_capture(Monitor *mon)
bellardec36b692006-07-16 18:57:03 +00002054{
2055 int i;
2056 CaptureState *s;
2057
2058 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
aliguori376253e2009-03-05 23:01:23 +00002059 monitor_printf(mon, "[%d]: ", i);
bellardec36b692006-07-16 18:57:03 +00002060 s->ops.info (s->opaque);
2061 }
2062}
2063
Blue Swirl23130862009-06-06 08:22:04 +00002064#ifdef HAS_AUDIO
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002065static void do_stop_capture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00002066{
2067 int i;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002068 int n = qdict_get_int(qdict, "n");
bellardec36b692006-07-16 18:57:03 +00002069 CaptureState *s;
2070
2071 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
2072 if (i == n) {
2073 s->ops.destroy (s->opaque);
Blue Swirl72cf2d42009-09-12 07:36:22 +00002074 QLIST_REMOVE (s, entries);
bellardec36b692006-07-16 18:57:03 +00002075 qemu_free (s);
2076 return;
2077 }
2078 }
2079}
2080
Luiz Capitulinoc1925482009-08-28 15:27:19 -03002081static void do_wav_capture(Monitor *mon, const QDict *qdict)
bellardec36b692006-07-16 18:57:03 +00002082{
Luiz Capitulinoc1925482009-08-28 15:27:19 -03002083 const char *path = qdict_get_str(qdict, "path");
2084 int has_freq = qdict_haskey(qdict, "freq");
2085 int freq = qdict_get_try_int(qdict, "freq", -1);
2086 int has_bits = qdict_haskey(qdict, "bits");
2087 int bits = qdict_get_try_int(qdict, "bits", -1);
2088 int has_channels = qdict_haskey(qdict, "nchannels");
2089 int nchannels = qdict_get_try_int(qdict, "nchannels", -1);
bellardec36b692006-07-16 18:57:03 +00002090 CaptureState *s;
2091
2092 s = qemu_mallocz (sizeof (*s));
bellardec36b692006-07-16 18:57:03 +00002093
2094 freq = has_freq ? freq : 44100;
2095 bits = has_bits ? bits : 16;
2096 nchannels = has_channels ? nchannels : 2;
2097
2098 if (wav_start_capture (s, path, freq, bits, nchannels)) {
aliguori376253e2009-03-05 23:01:23 +00002099 monitor_printf(mon, "Faied to add wave capture\n");
bellardec36b692006-07-16 18:57:03 +00002100 qemu_free (s);
2101 }
Blue Swirl72cf2d42009-09-12 07:36:22 +00002102 QLIST_INSERT_HEAD (&capture_head, s, entries);
bellardec36b692006-07-16 18:57:03 +00002103}
2104#endif
2105
aurel32dc1c0b72008-04-27 23:52:12 +00002106#if defined(TARGET_I386)
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002107static void do_inject_nmi(Monitor *mon, const QDict *qdict)
aurel32dc1c0b72008-04-27 23:52:12 +00002108{
2109 CPUState *env;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002110 int cpu_index = qdict_get_int(qdict, "cpu_index");
aurel32dc1c0b72008-04-27 23:52:12 +00002111
2112 for (env = first_cpu; env != NULL; env = env->next_cpu)
2113 if (env->cpu_index == cpu_index) {
2114 cpu_interrupt(env, CPU_INTERRUPT_NMI);
2115 break;
2116 }
2117}
2118#endif
2119
Luiz Capitulinoc0e85202009-12-10 17:15:59 -02002120static void do_info_status_print(Monitor *mon, const QObject *data)
aurel326f9c5ee2008-12-18 22:43:56 +00002121{
Luiz Capitulinoc0e85202009-12-10 17:15:59 -02002122 QDict *qdict;
2123
2124 qdict = qobject_to_qdict(data);
2125
2126 monitor_printf(mon, "VM status: ");
2127 if (qdict_get_bool(qdict, "running")) {
2128 monitor_printf(mon, "running");
2129 if (qdict_get_bool(qdict, "singlestep")) {
2130 monitor_printf(mon, " (single step mode)");
aurel321b530a62009-04-05 20:08:59 +00002131 }
Luiz Capitulinoc0e85202009-12-10 17:15:59 -02002132 } else {
2133 monitor_printf(mon, "paused");
2134 }
2135
2136 monitor_printf(mon, "\n");
2137}
2138
2139/**
2140 * do_info_status(): VM status
2141 *
2142 * Return a QDict with the following information:
2143 *
2144 * - "running": true if the VM is running, or false if it is paused
2145 * - "singlestep": true if the VM is in single step mode, false otherwise
2146 *
2147 * Example:
2148 *
2149 * { "running": true, "singlestep": false }
2150 */
2151static void do_info_status(Monitor *mon, QObject **ret_data)
2152{
2153 *ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
2154 vm_running, singlestep);
aurel326f9c5ee2008-12-18 22:43:56 +00002155}
2156
Adam Litke625a5be2010-01-26 14:17:35 -06002157static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
Luiz Capitulinocfdf2c42009-12-14 18:53:22 -02002158{
Adam Litke625a5be2010-01-26 14:17:35 -06002159 Monitor *mon = opaque;
Luiz Capitulinocfdf2c42009-12-14 18:53:22 -02002160
Adam Litke625a5be2010-01-26 14:17:35 -06002161 if (strcmp(key, "actual"))
2162 monitor_printf(mon, ",%s=%" PRId64, key,
2163 qint_get_int(qobject_to_qint(obj)));
aliguoridf751fa2008-12-04 20:19:35 +00002164}
2165
Luiz Capitulinocc1d9c72009-10-07 13:42:03 -03002166static void monitor_print_balloon(Monitor *mon, const QObject *data)
2167{
Luiz Capitulino7f179672009-12-10 17:15:55 -02002168 QDict *qdict;
2169
2170 qdict = qobject_to_qdict(data);
Adam Litke625a5be2010-01-26 14:17:35 -06002171 if (!qdict_haskey(qdict, "actual"))
2172 return;
Luiz Capitulino7f179672009-12-10 17:15:55 -02002173
Adam Litke625a5be2010-01-26 14:17:35 -06002174 monitor_printf(mon, "balloon: actual=%" PRId64,
2175 qdict_get_int(qdict, "actual") >> 20);
2176 qdict_iter(qdict, print_balloon_stat, mon);
2177 monitor_printf(mon, "\n");
Luiz Capitulinocc1d9c72009-10-07 13:42:03 -03002178}
2179
2180/**
2181 * do_info_balloon(): Balloon information
Luiz Capitulino7f179672009-12-10 17:15:55 -02002182 *
Adam Litke625a5be2010-01-26 14:17:35 -06002183 * Make an asynchronous request for balloon info. When the request completes
2184 * a QDict will be returned according to the following specification:
Luiz Capitulino7f179672009-12-10 17:15:55 -02002185 *
Adam Litke625a5be2010-01-26 14:17:35 -06002186 * - "actual": current balloon value in bytes
2187 * The following fields may or may not be present:
2188 * - "mem_swapped_in": Amount of memory swapped in (bytes)
2189 * - "mem_swapped_out": Amount of memory swapped out (bytes)
2190 * - "major_page_faults": Number of major faults
2191 * - "minor_page_faults": Number of minor faults
2192 * - "free_mem": Total amount of free and unused memory (bytes)
2193 * - "total_mem": Total amount of available memory (bytes)
Luiz Capitulino7f179672009-12-10 17:15:55 -02002194 *
2195 * Example:
2196 *
Adam Litke625a5be2010-01-26 14:17:35 -06002197 * { "actual": 1073741824, "mem_swapped_in": 0, "mem_swapped_out": 0,
2198 * "major_page_faults": 142, "minor_page_faults": 239245,
2199 * "free_mem": 1014185984, "total_mem": 1044668416 }
Luiz Capitulinocc1d9c72009-10-07 13:42:03 -03002200 */
Adam Litke625a5be2010-01-26 14:17:35 -06002201static int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
aliguoridf751fa2008-12-04 20:19:35 +00002202{
Adam Litke625a5be2010-01-26 14:17:35 -06002203 int ret;
aliguoridf751fa2008-12-04 20:19:35 +00002204
Adam Litke625a5be2010-01-26 14:17:35 -06002205 if (kvm_enabled() && !kvm_has_sync_mmu()) {
2206 qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
2207 return -1;
Luiz Capitulinocfdf2c42009-12-14 18:53:22 -02002208 }
Adam Litke625a5be2010-01-26 14:17:35 -06002209
2210 ret = qemu_balloon_status(cb, opaque);
2211 if (!ret) {
2212 qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
2213 return -1;
2214 }
2215
2216 return 0;
2217}
2218
2219/**
2220 * do_balloon(): Request VM to change its memory allocation
2221 */
2222static int do_balloon(Monitor *mon, const QDict *params,
2223 MonitorCompletion cb, void *opaque)
2224{
2225 int ret;
2226
2227 if (kvm_enabled() && !kvm_has_sync_mmu()) {
2228 qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
2229 return -1;
2230 }
2231
2232 ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
2233 if (ret == 0) {
2234 qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
2235 return -1;
2236 }
2237
2238 return 0;
aliguoridf751fa2008-12-04 20:19:35 +00002239}
2240
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002241static qemu_acl *find_acl(Monitor *mon, const char *name)
aliguori76655d62009-03-06 20:27:37 +00002242{
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002243 qemu_acl *acl = qemu_acl_find(name);
aliguori76655d62009-03-06 20:27:37 +00002244
aliguori76655d62009-03-06 20:27:37 +00002245 if (!acl) {
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002246 monitor_printf(mon, "acl: unknown list '%s'\n", name);
aliguori76655d62009-03-06 20:27:37 +00002247 }
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002248 return acl;
2249}
aliguori76655d62009-03-06 20:27:37 +00002250
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002251static void do_acl_show(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002252{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002253 const char *aclname = qdict_get_str(qdict, "aclname");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002254 qemu_acl *acl = find_acl(mon, aclname);
2255 qemu_acl_entry *entry;
2256 int i = 0;
2257
2258 if (acl) {
aliguori28a76be2009-03-06 20:27:40 +00002259 monitor_printf(mon, "policy: %s\n",
aliguori76655d62009-03-06 20:27:37 +00002260 acl->defaultDeny ? "deny" : "allow");
Blue Swirl72cf2d42009-09-12 07:36:22 +00002261 QTAILQ_FOREACH(entry, &acl->entries, next) {
aliguori28a76be2009-03-06 20:27:40 +00002262 i++;
2263 monitor_printf(mon, "%d: %s %s\n", i,
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002264 entry->deny ? "deny" : "allow", entry->match);
aliguori28a76be2009-03-06 20:27:40 +00002265 }
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002266 }
2267}
2268
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002269static void do_acl_reset(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002270{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002271 const char *aclname = qdict_get_str(qdict, "aclname");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002272 qemu_acl *acl = find_acl(mon, aclname);
2273
2274 if (acl) {
aliguori28a76be2009-03-06 20:27:40 +00002275 qemu_acl_reset(acl);
2276 monitor_printf(mon, "acl: removed all rules\n");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002277 }
2278}
aliguori76655d62009-03-06 20:27:37 +00002279
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03002280static void do_acl_policy(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002281{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03002282 const char *aclname = qdict_get_str(qdict, "aclname");
2283 const char *policy = qdict_get_str(qdict, "policy");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002284 qemu_acl *acl = find_acl(mon, aclname);
2285
2286 if (acl) {
2287 if (strcmp(policy, "allow") == 0) {
aliguori28a76be2009-03-06 20:27:40 +00002288 acl->defaultDeny = 0;
2289 monitor_printf(mon, "acl: policy set to 'allow'\n");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002290 } else if (strcmp(policy, "deny") == 0) {
aliguori28a76be2009-03-06 20:27:40 +00002291 acl->defaultDeny = 1;
2292 monitor_printf(mon, "acl: policy set to 'deny'\n");
2293 } else {
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002294 monitor_printf(mon, "acl: unknown policy '%s', "
2295 "expected 'deny' or 'allow'\n", policy);
aliguori28a76be2009-03-06 20:27:40 +00002296 }
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002297 }
2298}
aliguori76655d62009-03-06 20:27:37 +00002299
Luiz Capitulino1bd14422009-08-28 15:27:17 -03002300static void do_acl_add(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002301{
Luiz Capitulino1bd14422009-08-28 15:27:17 -03002302 const char *aclname = qdict_get_str(qdict, "aclname");
2303 const char *match = qdict_get_str(qdict, "match");
2304 const char *policy = qdict_get_str(qdict, "policy");
2305 int has_index = qdict_haskey(qdict, "index");
2306 int index = qdict_get_try_int(qdict, "index", -1);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002307 qemu_acl *acl = find_acl(mon, aclname);
2308 int deny, ret;
2309
2310 if (acl) {
2311 if (strcmp(policy, "allow") == 0) {
2312 deny = 0;
2313 } else if (strcmp(policy, "deny") == 0) {
2314 deny = 1;
2315 } else {
2316 monitor_printf(mon, "acl: unknown policy '%s', "
2317 "expected 'deny' or 'allow'\n", policy);
aliguori28a76be2009-03-06 20:27:40 +00002318 return;
2319 }
aliguori28a76be2009-03-06 20:27:40 +00002320 if (has_index)
2321 ret = qemu_acl_insert(acl, deny, match, index);
2322 else
2323 ret = qemu_acl_append(acl, deny, match);
2324 if (ret < 0)
2325 monitor_printf(mon, "acl: unable to add acl entry\n");
2326 else
2327 monitor_printf(mon, "acl: added rule at position %d\n", ret);
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002328 }
2329}
aliguori76655d62009-03-06 20:27:37 +00002330
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03002331static void do_acl_remove(Monitor *mon, const QDict *qdict)
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002332{
Luiz Capitulinof18c16d2009-08-28 15:27:14 -03002333 const char *aclname = qdict_get_str(qdict, "aclname");
2334 const char *match = qdict_get_str(qdict, "match");
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002335 qemu_acl *acl = find_acl(mon, aclname);
2336 int ret;
aliguori76655d62009-03-06 20:27:37 +00002337
Jan Kiszka15dfcd42009-06-25 08:22:08 +02002338 if (acl) {
aliguori28a76be2009-03-06 20:27:40 +00002339 ret = qemu_acl_remove(acl, match);
2340 if (ret < 0)
2341 monitor_printf(mon, "acl: no matching acl entry\n");
2342 else
2343 monitor_printf(mon, "acl: removed rule at position %d\n", ret);
aliguori76655d62009-03-06 20:27:37 +00002344 }
2345}
2346
Huang Ying79c4f6b2009-06-23 10:05:14 +08002347#if defined(TARGET_I386)
Luiz Capitulino37b7ad42009-08-28 15:27:21 -03002348static void do_inject_mce(Monitor *mon, const QDict *qdict)
Huang Ying79c4f6b2009-06-23 10:05:14 +08002349{
2350 CPUState *cenv;
Luiz Capitulino37b7ad42009-08-28 15:27:21 -03002351 int cpu_index = qdict_get_int(qdict, "cpu_index");
2352 int bank = qdict_get_int(qdict, "bank");
2353 uint64_t status = qdict_get_int(qdict, "status");
2354 uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
2355 uint64_t addr = qdict_get_int(qdict, "addr");
2356 uint64_t misc = qdict_get_int(qdict, "misc");
Huang Ying79c4f6b2009-06-23 10:05:14 +08002357
2358 for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu)
2359 if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
2360 cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
2361 break;
2362 }
2363}
2364#endif
2365
Luiz Capitulinof0d60002009-10-16 12:23:50 -03002366static void do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002367{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002368 const char *fdname = qdict_get_str(qdict, "fdname");
Anthony Liguoric227f092009-10-01 16:12:16 -05002369 mon_fd_t *monfd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002370 int fd;
2371
2372 fd = qemu_chr_get_msgfd(mon->chr);
2373 if (fd == -1) {
Markus Armbruster7cdfcfe2009-12-07 21:37:15 +01002374 qemu_error_new(QERR_FD_NOT_SUPPLIED);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002375 return;
2376 }
2377
2378 if (qemu_isdigit(fdname[0])) {
Markus Armbruster7cdfcfe2009-12-07 21:37:15 +01002379 qemu_error_new(QERR_INVALID_PARAMETER, "fdname");
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002380 return;
2381 }
2382
2383 fd = dup(fd);
2384 if (fd == -1) {
Markus Armbruster7cdfcfe2009-12-07 21:37:15 +01002385 if (errno == EMFILE)
2386 qemu_error_new(QERR_TOO_MANY_FILES);
2387 else
2388 qemu_error_new(QERR_UNDEFINED_ERROR);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002389 return;
2390 }
2391
Blue Swirl72cf2d42009-09-12 07:36:22 +00002392 QLIST_FOREACH(monfd, &mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002393 if (strcmp(monfd->name, fdname) != 0) {
2394 continue;
2395 }
2396
2397 close(monfd->fd);
2398 monfd->fd = fd;
2399 return;
2400 }
2401
Anthony Liguoric227f092009-10-01 16:12:16 -05002402 monfd = qemu_mallocz(sizeof(mon_fd_t));
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002403 monfd->name = qemu_strdup(fdname);
2404 monfd->fd = fd;
2405
Blue Swirl72cf2d42009-09-12 07:36:22 +00002406 QLIST_INSERT_HEAD(&mon->fds, monfd, next);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002407}
2408
Luiz Capitulino18f3a512009-10-16 12:23:51 -03002409static void do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data)
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002410{
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002411 const char *fdname = qdict_get_str(qdict, "fdname");
Anthony Liguoric227f092009-10-01 16:12:16 -05002412 mon_fd_t *monfd;
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002413
Blue Swirl72cf2d42009-09-12 07:36:22 +00002414 QLIST_FOREACH(monfd, &mon->fds, next) {
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002415 if (strcmp(monfd->name, fdname) != 0) {
2416 continue;
2417 }
2418
Blue Swirl72cf2d42009-09-12 07:36:22 +00002419 QLIST_REMOVE(monfd, next);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002420 close(monfd->fd);
2421 qemu_free(monfd->name);
2422 qemu_free(monfd);
2423 return;
2424 }
2425
Markus Armbruster063c1a02009-12-07 21:37:11 +01002426 qemu_error_new(QERR_FD_NOT_FOUND, fdname);
Mark McLoughlinf07918f2009-07-22 09:11:40 +01002427}
2428
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002429static void do_loadvm(Monitor *mon, const QDict *qdict)
Juan Quintelac8d41b22009-08-20 19:42:21 +02002430{
2431 int saved_vm_running = vm_running;
Luiz Capitulinod54908a2009-08-28 15:27:13 -03002432 const char *name = qdict_get_str(qdict, "name");
Juan Quintelac8d41b22009-08-20 19:42:21 +02002433
2434 vm_stop(0);
2435
Juan Quintela05f24012009-08-20 19:42:22 +02002436 if (load_vmstate(mon, name) >= 0 && saved_vm_running)
Juan Quintelac8d41b22009-08-20 19:42:21 +02002437 vm_start();
2438}
2439
Mark McLoughlin7768e042009-07-22 09:11:41 +01002440int monitor_get_fd(Monitor *mon, const char *fdname)
2441{
Anthony Liguoric227f092009-10-01 16:12:16 -05002442 mon_fd_t *monfd;
Mark McLoughlin7768e042009-07-22 09:11:41 +01002443
Blue Swirl72cf2d42009-09-12 07:36:22 +00002444 QLIST_FOREACH(monfd, &mon->fds, next) {
Mark McLoughlin7768e042009-07-22 09:11:41 +01002445 int fd;
2446
2447 if (strcmp(monfd->name, fdname) != 0) {
2448 continue;
2449 }
2450
2451 fd = monfd->fd;
2452
2453 /* caller takes ownership of fd */
Blue Swirl72cf2d42009-09-12 07:36:22 +00002454 QLIST_REMOVE(monfd, next);
Mark McLoughlin7768e042009-07-22 09:11:41 +01002455 qemu_free(monfd->name);
2456 qemu_free(monfd);
2457
2458 return fd;
2459 }
2460
2461 return -1;
2462}
2463
Anthony Liguoric227f092009-10-01 16:12:16 -05002464static const mon_cmd_t mon_cmds[] = {
Blue Swirl23130862009-06-06 08:22:04 +00002465#include "qemu-monitor.h"
ths5fafdf22007-09-16 21:08:06 +00002466 { NULL, NULL, },
bellard9dc39cb2004-03-14 21:38:27 +00002467};
2468
Blue Swirl23130862009-06-06 08:22:04 +00002469/* Please update qemu-monitor.hx when adding or changing commands */
Anthony Liguoric227f092009-10-01 16:12:16 -05002470static const mon_cmd_t info_cmds[] = {
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002471 {
2472 .name = "version",
2473 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002474 .params = "",
2475 .help = "show the version of QEMU",
Luiz Capitulino45e914c2009-12-10 17:15:58 -02002476 .user_print = do_info_version_print,
Luiz Capitulinoab2d3182009-10-07 13:42:02 -03002477 .mhandler.info_new = do_info_version,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002478 },
2479 {
Luiz Capitulinoe3bba9d2009-11-26 22:58:56 -02002480 .name = "commands",
2481 .args_type = "",
2482 .params = "",
2483 .help = "list QMP available commands",
2484 .user_print = monitor_user_noop,
2485 .mhandler.info_new = do_info_commands,
2486 },
2487 {
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002488 .name = "network",
2489 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002490 .params = "",
2491 .help = "show the network state",
Luiz Capitulino910df892009-10-07 13:41:51 -03002492 .mhandler.info = do_info_network,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002493 },
2494 {
2495 .name = "chardev",
2496 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002497 .params = "",
2498 .help = "show the character devices",
Luiz Capitulino588b3832009-12-10 17:16:08 -02002499 .user_print = qemu_chr_info_print,
2500 .mhandler.info_new = qemu_chr_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002501 },
2502 {
2503 .name = "block",
2504 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002505 .params = "",
2506 .help = "show the block devices",
Luiz Capitulinod15e5462009-12-10 17:16:06 -02002507 .user_print = bdrv_info_print,
2508 .mhandler.info_new = bdrv_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002509 },
2510 {
2511 .name = "blockstats",
2512 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002513 .params = "",
2514 .help = "show block device statistics",
Luiz Capitulino218a5362009-12-10 17:16:07 -02002515 .user_print = bdrv_stats_print,
2516 .mhandler.info_new = bdrv_info_stats,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002517 },
2518 {
2519 .name = "registers",
2520 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002521 .params = "",
2522 .help = "show the cpu registers",
Luiz Capitulino910df892009-10-07 13:41:51 -03002523 .mhandler.info = do_info_registers,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002524 },
2525 {
2526 .name = "cpus",
2527 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002528 .params = "",
2529 .help = "show infos for each CPU",
Luiz Capitulino8f3cec02009-10-07 13:42:04 -03002530 .user_print = monitor_print_cpus,
2531 .mhandler.info_new = do_info_cpus,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002532 },
2533 {
2534 .name = "history",
2535 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002536 .params = "",
2537 .help = "show the command line history",
Luiz Capitulino910df892009-10-07 13:41:51 -03002538 .mhandler.info = do_info_history,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002539 },
2540 {
2541 .name = "irq",
2542 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002543 .params = "",
2544 .help = "show the interrupts statistics (if available)",
Luiz Capitulino910df892009-10-07 13:41:51 -03002545 .mhandler.info = irq_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002546 },
2547 {
2548 .name = "pic",
2549 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002550 .params = "",
2551 .help = "show i8259 (PIC) state",
Luiz Capitulino910df892009-10-07 13:41:51 -03002552 .mhandler.info = pic_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002553 },
2554 {
2555 .name = "pci",
2556 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002557 .params = "",
2558 .help = "show PCI info",
Luiz Capitulino163c8a52010-01-21 19:15:40 -02002559 .user_print = do_pci_info_print,
2560 .mhandler.info_new = do_pci_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002561 },
aurel327c664e22009-03-03 06:12:22 +00002562#if defined(TARGET_I386) || defined(TARGET_SH4)
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002563 {
2564 .name = "tlb",
2565 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002566 .params = "",
2567 .help = "show virtual to physical memory mappings",
Luiz Capitulino910df892009-10-07 13:41:51 -03002568 .mhandler.info = tlb_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002569 },
aurel327c664e22009-03-03 06:12:22 +00002570#endif
2571#if defined(TARGET_I386)
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002572 {
2573 .name = "mem",
2574 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002575 .params = "",
2576 .help = "show the active virtual memory mappings",
Luiz Capitulino910df892009-10-07 13:41:51 -03002577 .mhandler.info = mem_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002578 },
2579 {
2580 .name = "hpet",
2581 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002582 .params = "",
2583 .help = "show state of HPET",
Luiz Capitulino14f07202009-12-10 17:16:02 -02002584 .user_print = do_info_hpet_print,
2585 .mhandler.info_new = do_info_hpet,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002586 },
bellardb86bda52004-09-18 19:32:46 +00002587#endif
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002588 {
2589 .name = "jit",
2590 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002591 .params = "",
2592 .help = "show dynamic compiler info",
Luiz Capitulino910df892009-10-07 13:41:51 -03002593 .mhandler.info = do_info_jit,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002594 },
2595 {
2596 .name = "kvm",
2597 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002598 .params = "",
2599 .help = "show KVM information",
Luiz Capitulino2af5ba72009-12-10 17:16:00 -02002600 .user_print = do_info_kvm_print,
2601 .mhandler.info_new = do_info_kvm,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002602 },
2603 {
2604 .name = "numa",
2605 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002606 .params = "",
2607 .help = "show NUMA information",
Luiz Capitulino910df892009-10-07 13:41:51 -03002608 .mhandler.info = do_info_numa,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002609 },
2610 {
2611 .name = "usb",
2612 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002613 .params = "",
2614 .help = "show guest USB devices",
Luiz Capitulino910df892009-10-07 13:41:51 -03002615 .mhandler.info = usb_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002616 },
2617 {
2618 .name = "usbhost",
2619 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002620 .params = "",
2621 .help = "show host USB devices",
Luiz Capitulino910df892009-10-07 13:41:51 -03002622 .mhandler.info = usb_host_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002623 },
2624 {
2625 .name = "profile",
2626 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002627 .params = "",
2628 .help = "show profiling information",
Luiz Capitulino910df892009-10-07 13:41:51 -03002629 .mhandler.info = do_info_profile,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002630 },
2631 {
2632 .name = "capture",
2633 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002634 .params = "",
2635 .help = "show capture information",
Luiz Capitulino910df892009-10-07 13:41:51 -03002636 .mhandler.info = do_info_capture,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002637 },
2638 {
2639 .name = "snapshots",
2640 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002641 .params = "",
2642 .help = "show the currently saved VM snapshots",
Luiz Capitulino910df892009-10-07 13:41:51 -03002643 .mhandler.info = do_info_snapshots,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002644 },
2645 {
2646 .name = "status",
2647 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002648 .params = "",
2649 .help = "show the current VM status (running|paused)",
Luiz Capitulinoc0e85202009-12-10 17:15:59 -02002650 .user_print = do_info_status_print,
2651 .mhandler.info_new = do_info_status,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002652 },
2653 {
2654 .name = "pcmcia",
2655 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002656 .params = "",
2657 .help = "show guest PCMCIA status",
Luiz Capitulino910df892009-10-07 13:41:51 -03002658 .mhandler.info = pcmcia_info,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002659 },
2660 {
2661 .name = "mice",
2662 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002663 .params = "",
2664 .help = "show which guest mouse is receiving events",
Luiz Capitulinoe78c48e2009-12-10 17:16:04 -02002665 .user_print = do_info_mice_print,
2666 .mhandler.info_new = do_info_mice,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002667 },
2668 {
2669 .name = "vnc",
2670 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002671 .params = "",
2672 .help = "show the vnc server status",
Luiz Capitulinod96fd292009-12-10 17:16:10 -02002673 .user_print = do_info_vnc_print,
2674 .mhandler.info_new = do_info_vnc,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002675 },
2676 {
2677 .name = "name",
2678 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002679 .params = "",
2680 .help = "show the current VM name",
Luiz Capitulinoe05486c2009-12-10 17:16:01 -02002681 .user_print = do_info_name_print,
2682 .mhandler.info_new = do_info_name,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002683 },
2684 {
2685 .name = "uuid",
2686 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002687 .params = "",
2688 .help = "show the current VM UUID",
Luiz Capitulino9603ceb2009-12-10 17:16:03 -02002689 .user_print = do_info_uuid_print,
2690 .mhandler.info_new = do_info_uuid,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002691 },
j_mayer76a66252007-03-07 08:32:30 +00002692#if defined(TARGET_PPC)
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002693 {
2694 .name = "cpustats",
2695 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002696 .params = "",
2697 .help = "show CPU statistics",
Luiz Capitulino910df892009-10-07 13:41:51 -03002698 .mhandler.info = do_info_cpu_stats,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002699 },
j_mayer76a66252007-03-07 08:32:30 +00002700#endif
blueswir131a60e22007-10-26 18:42:59 +00002701#if defined(CONFIG_SLIRP)
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002702 {
2703 .name = "usernet",
2704 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002705 .params = "",
2706 .help = "show user network stack connection states",
Luiz Capitulino910df892009-10-07 13:41:51 -03002707 .mhandler.info = do_info_usernet,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002708 },
blueswir131a60e22007-10-26 18:42:59 +00002709#endif
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002710 {
2711 .name = "migrate",
2712 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002713 .params = "",
2714 .help = "show migration status",
Luiz Capitulinoc86a6682009-12-10 17:16:05 -02002715 .user_print = do_info_migrate_print,
2716 .mhandler.info_new = do_info_migrate,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002717 },
2718 {
2719 .name = "balloon",
2720 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002721 .params = "",
2722 .help = "show balloon information",
Luiz Capitulinocc1d9c72009-10-07 13:42:03 -03002723 .user_print = monitor_print_balloon,
Adam Litke625a5be2010-01-26 14:17:35 -06002724 .mhandler.info_async = do_info_balloon,
2725 .async = 1,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002726 },
2727 {
2728 .name = "qtree",
2729 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002730 .params = "",
2731 .help = "show device tree",
Luiz Capitulino910df892009-10-07 13:41:51 -03002732 .mhandler.info = do_info_qtree,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002733 },
2734 {
2735 .name = "qdm",
2736 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002737 .params = "",
2738 .help = "show qdev device model list",
Luiz Capitulino910df892009-10-07 13:41:51 -03002739 .mhandler.info = do_info_qdm,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002740 },
2741 {
2742 .name = "roms",
2743 .args_type = "",
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002744 .params = "",
2745 .help = "show roms",
Luiz Capitulino910df892009-10-07 13:41:51 -03002746 .mhandler.info = do_info_roms,
Luiz Capitulinod7f9b682009-10-07 13:41:50 -03002747 },
2748 {
2749 .name = NULL,
2750 },
bellard9dc39cb2004-03-14 21:38:27 +00002751};
2752
bellard9307c4c2004-04-04 12:57:25 +00002753/*******************************************************************/
2754
2755static const char *pch;
2756static jmp_buf expr_env;
2757
bellard92a31b12005-02-10 22:00:52 +00002758#define MD_TLONG 0
2759#define MD_I32 1
2760
bellard9307c4c2004-04-04 12:57:25 +00002761typedef struct MonitorDef {
2762 const char *name;
2763 int offset;
blueswir18662d652008-10-02 18:32:44 +00002764 target_long (*get_value)(const struct MonitorDef *md, int val);
bellard92a31b12005-02-10 22:00:52 +00002765 int type;
bellard9307c4c2004-04-04 12:57:25 +00002766} MonitorDef;
2767
bellard57206fd2004-04-25 18:54:52 +00002768#if defined(TARGET_I386)
blueswir18662d652008-10-02 18:32:44 +00002769static target_long monitor_get_pc (const struct MonitorDef *md, int val)
bellard57206fd2004-04-25 18:54:52 +00002770{
bellard6a00d602005-11-21 23:25:50 +00002771 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002772 return env->eip + env->segs[R_CS].base;
bellard57206fd2004-04-25 18:54:52 +00002773}
2774#endif
2775
bellarda541f292004-04-12 20:39:29 +00002776#if defined(TARGET_PPC)
blueswir18662d652008-10-02 18:32:44 +00002777static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
bellarda541f292004-04-12 20:39:29 +00002778{
bellard6a00d602005-11-21 23:25:50 +00002779 CPUState *env = mon_get_cpu();
bellarda541f292004-04-12 20:39:29 +00002780 unsigned int u;
2781 int i;
2782
2783 u = 0;
2784 for (i = 0; i < 8; i++)
aliguori28a76be2009-03-06 20:27:40 +00002785 u |= env->crf[i] << (32 - (4 * i));
bellarda541f292004-04-12 20:39:29 +00002786
2787 return u;
2788}
2789
blueswir18662d652008-10-02 18:32:44 +00002790static target_long monitor_get_msr (const struct MonitorDef *md, int val)
bellarda541f292004-04-12 20:39:29 +00002791{
bellard6a00d602005-11-21 23:25:50 +00002792 CPUState *env = mon_get_cpu();
j_mayer0411a972007-10-25 21:35:50 +00002793 return env->msr;
bellarda541f292004-04-12 20:39:29 +00002794}
2795
blueswir18662d652008-10-02 18:32:44 +00002796static target_long monitor_get_xer (const struct MonitorDef *md, int val)
bellarda541f292004-04-12 20:39:29 +00002797{
bellard6a00d602005-11-21 23:25:50 +00002798 CPUState *env = mon_get_cpu();
aurel323d7b4172008-10-21 11:28:46 +00002799 return env->xer;
bellarda541f292004-04-12 20:39:29 +00002800}
bellard9fddaa02004-05-21 12:59:32 +00002801
blueswir18662d652008-10-02 18:32:44 +00002802static target_long monitor_get_decr (const struct MonitorDef *md, int val)
bellard9fddaa02004-05-21 12:59:32 +00002803{
bellard6a00d602005-11-21 23:25:50 +00002804 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002805 return cpu_ppc_load_decr(env);
bellard9fddaa02004-05-21 12:59:32 +00002806}
2807
blueswir18662d652008-10-02 18:32:44 +00002808static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
bellard9fddaa02004-05-21 12:59:32 +00002809{
bellard6a00d602005-11-21 23:25:50 +00002810 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002811 return cpu_ppc_load_tbu(env);
bellard9fddaa02004-05-21 12:59:32 +00002812}
2813
blueswir18662d652008-10-02 18:32:44 +00002814static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
bellard9fddaa02004-05-21 12:59:32 +00002815{
bellard6a00d602005-11-21 23:25:50 +00002816 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002817 return cpu_ppc_load_tbl(env);
bellard9fddaa02004-05-21 12:59:32 +00002818}
bellarda541f292004-04-12 20:39:29 +00002819#endif
2820
bellarde95c8d52004-09-30 22:22:08 +00002821#if defined(TARGET_SPARC)
bellard7b936c02005-10-30 17:05:13 +00002822#ifndef TARGET_SPARC64
blueswir18662d652008-10-02 18:32:44 +00002823static target_long monitor_get_psr (const struct MonitorDef *md, int val)
bellarde95c8d52004-09-30 22:22:08 +00002824{
bellard6a00d602005-11-21 23:25:50 +00002825 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002826 return GET_PSR(env);
bellarde95c8d52004-09-30 22:22:08 +00002827}
bellard7b936c02005-10-30 17:05:13 +00002828#endif
bellarde95c8d52004-09-30 22:22:08 +00002829
blueswir18662d652008-10-02 18:32:44 +00002830static target_long monitor_get_reg(const struct MonitorDef *md, int val)
bellarde95c8d52004-09-30 22:22:08 +00002831{
bellard6a00d602005-11-21 23:25:50 +00002832 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00002833 return env->regwptr[val];
bellarde95c8d52004-09-30 22:22:08 +00002834}
2835#endif
2836
blueswir18662d652008-10-02 18:32:44 +00002837static const MonitorDef monitor_defs[] = {
bellard9307c4c2004-04-04 12:57:25 +00002838#ifdef TARGET_I386
bellard57206fd2004-04-25 18:54:52 +00002839
2840#define SEG(name, seg) \
bellard92a31b12005-02-10 22:00:52 +00002841 { name, offsetof(CPUState, segs[seg].selector), NULL, MD_I32 },\
bellard57206fd2004-04-25 18:54:52 +00002842 { name ".base", offsetof(CPUState, segs[seg].base) },\
bellard92a31b12005-02-10 22:00:52 +00002843 { name ".limit", offsetof(CPUState, segs[seg].limit), NULL, MD_I32 },
bellard57206fd2004-04-25 18:54:52 +00002844
bellard9307c4c2004-04-04 12:57:25 +00002845 { "eax", offsetof(CPUState, regs[0]) },
2846 { "ecx", offsetof(CPUState, regs[1]) },
2847 { "edx", offsetof(CPUState, regs[2]) },
2848 { "ebx", offsetof(CPUState, regs[3]) },
2849 { "esp|sp", offsetof(CPUState, regs[4]) },
2850 { "ebp|fp", offsetof(CPUState, regs[5]) },
2851 { "esi", offsetof(CPUState, regs[6]) },
bellard01038d22004-09-13 21:36:46 +00002852 { "edi", offsetof(CPUState, regs[7]) },
bellard92a31b12005-02-10 22:00:52 +00002853#ifdef TARGET_X86_64
2854 { "r8", offsetof(CPUState, regs[8]) },
2855 { "r9", offsetof(CPUState, regs[9]) },
2856 { "r10", offsetof(CPUState, regs[10]) },
2857 { "r11", offsetof(CPUState, regs[11]) },
2858 { "r12", offsetof(CPUState, regs[12]) },
2859 { "r13", offsetof(CPUState, regs[13]) },
2860 { "r14", offsetof(CPUState, regs[14]) },
2861 { "r15", offsetof(CPUState, regs[15]) },
2862#endif
bellard9307c4c2004-04-04 12:57:25 +00002863 { "eflags", offsetof(CPUState, eflags) },
bellard57206fd2004-04-25 18:54:52 +00002864 { "eip", offsetof(CPUState, eip) },
2865 SEG("cs", R_CS)
2866 SEG("ds", R_DS)
2867 SEG("es", R_ES)
bellard01038d22004-09-13 21:36:46 +00002868 SEG("ss", R_SS)
bellard57206fd2004-04-25 18:54:52 +00002869 SEG("fs", R_FS)
2870 SEG("gs", R_GS)
2871 { "pc", 0, monitor_get_pc, },
bellarda541f292004-04-12 20:39:29 +00002872#elif defined(TARGET_PPC)
j_mayerff937db2007-09-19 05:49:13 +00002873 /* General purpose registers */
bellarda541f292004-04-12 20:39:29 +00002874 { "r0", offsetof(CPUState, gpr[0]) },
2875 { "r1", offsetof(CPUState, gpr[1]) },
2876 { "r2", offsetof(CPUState, gpr[2]) },
2877 { "r3", offsetof(CPUState, gpr[3]) },
2878 { "r4", offsetof(CPUState, gpr[4]) },
2879 { "r5", offsetof(CPUState, gpr[5]) },
2880 { "r6", offsetof(CPUState, gpr[6]) },
2881 { "r7", offsetof(CPUState, gpr[7]) },
2882 { "r8", offsetof(CPUState, gpr[8]) },
2883 { "r9", offsetof(CPUState, gpr[9]) },
2884 { "r10", offsetof(CPUState, gpr[10]) },
2885 { "r11", offsetof(CPUState, gpr[11]) },
2886 { "r12", offsetof(CPUState, gpr[12]) },
2887 { "r13", offsetof(CPUState, gpr[13]) },
2888 { "r14", offsetof(CPUState, gpr[14]) },
2889 { "r15", offsetof(CPUState, gpr[15]) },
2890 { "r16", offsetof(CPUState, gpr[16]) },
2891 { "r17", offsetof(CPUState, gpr[17]) },
2892 { "r18", offsetof(CPUState, gpr[18]) },
2893 { "r19", offsetof(CPUState, gpr[19]) },
2894 { "r20", offsetof(CPUState, gpr[20]) },
2895 { "r21", offsetof(CPUState, gpr[21]) },
2896 { "r22", offsetof(CPUState, gpr[22]) },
2897 { "r23", offsetof(CPUState, gpr[23]) },
2898 { "r24", offsetof(CPUState, gpr[24]) },
2899 { "r25", offsetof(CPUState, gpr[25]) },
2900 { "r26", offsetof(CPUState, gpr[26]) },
2901 { "r27", offsetof(CPUState, gpr[27]) },
2902 { "r28", offsetof(CPUState, gpr[28]) },
2903 { "r29", offsetof(CPUState, gpr[29]) },
2904 { "r30", offsetof(CPUState, gpr[30]) },
2905 { "r31", offsetof(CPUState, gpr[31]) },
j_mayerff937db2007-09-19 05:49:13 +00002906 /* Floating point registers */
2907 { "f0", offsetof(CPUState, fpr[0]) },
2908 { "f1", offsetof(CPUState, fpr[1]) },
2909 { "f2", offsetof(CPUState, fpr[2]) },
2910 { "f3", offsetof(CPUState, fpr[3]) },
2911 { "f4", offsetof(CPUState, fpr[4]) },
2912 { "f5", offsetof(CPUState, fpr[5]) },
2913 { "f6", offsetof(CPUState, fpr[6]) },
2914 { "f7", offsetof(CPUState, fpr[7]) },
2915 { "f8", offsetof(CPUState, fpr[8]) },
2916 { "f9", offsetof(CPUState, fpr[9]) },
2917 { "f10", offsetof(CPUState, fpr[10]) },
2918 { "f11", offsetof(CPUState, fpr[11]) },
2919 { "f12", offsetof(CPUState, fpr[12]) },
2920 { "f13", offsetof(CPUState, fpr[13]) },
2921 { "f14", offsetof(CPUState, fpr[14]) },
2922 { "f15", offsetof(CPUState, fpr[15]) },
2923 { "f16", offsetof(CPUState, fpr[16]) },
2924 { "f17", offsetof(CPUState, fpr[17]) },
2925 { "f18", offsetof(CPUState, fpr[18]) },
2926 { "f19", offsetof(CPUState, fpr[19]) },
2927 { "f20", offsetof(CPUState, fpr[20]) },
2928 { "f21", offsetof(CPUState, fpr[21]) },
2929 { "f22", offsetof(CPUState, fpr[22]) },
2930 { "f23", offsetof(CPUState, fpr[23]) },
2931 { "f24", offsetof(CPUState, fpr[24]) },
2932 { "f25", offsetof(CPUState, fpr[25]) },
2933 { "f26", offsetof(CPUState, fpr[26]) },
2934 { "f27", offsetof(CPUState, fpr[27]) },
2935 { "f28", offsetof(CPUState, fpr[28]) },
2936 { "f29", offsetof(CPUState, fpr[29]) },
2937 { "f30", offsetof(CPUState, fpr[30]) },
2938 { "f31", offsetof(CPUState, fpr[31]) },
2939 { "fpscr", offsetof(CPUState, fpscr) },
2940 /* Next instruction pointer */
bellard57206fd2004-04-25 18:54:52 +00002941 { "nip|pc", offsetof(CPUState, nip) },
bellarda541f292004-04-12 20:39:29 +00002942 { "lr", offsetof(CPUState, lr) },
2943 { "ctr", offsetof(CPUState, ctr) },
bellard9fddaa02004-05-21 12:59:32 +00002944 { "decr", 0, &monitor_get_decr, },
bellarda541f292004-04-12 20:39:29 +00002945 { "ccr", 0, &monitor_get_ccr, },
j_mayerff937db2007-09-19 05:49:13 +00002946 /* Machine state register */
bellarda541f292004-04-12 20:39:29 +00002947 { "msr", 0, &monitor_get_msr, },
2948 { "xer", 0, &monitor_get_xer, },
bellard9fddaa02004-05-21 12:59:32 +00002949 { "tbu", 0, &monitor_get_tbu, },
2950 { "tbl", 0, &monitor_get_tbl, },
j_mayerff937db2007-09-19 05:49:13 +00002951#if defined(TARGET_PPC64)
2952 /* Address space register */
2953 { "asr", offsetof(CPUState, asr) },
2954#endif
2955 /* Segment registers */
bellarda541f292004-04-12 20:39:29 +00002956 { "sdr1", offsetof(CPUState, sdr1) },
2957 { "sr0", offsetof(CPUState, sr[0]) },
2958 { "sr1", offsetof(CPUState, sr[1]) },
2959 { "sr2", offsetof(CPUState, sr[2]) },
2960 { "sr3", offsetof(CPUState, sr[3]) },
2961 { "sr4", offsetof(CPUState, sr[4]) },
2962 { "sr5", offsetof(CPUState, sr[5]) },
2963 { "sr6", offsetof(CPUState, sr[6]) },
2964 { "sr7", offsetof(CPUState, sr[7]) },
2965 { "sr8", offsetof(CPUState, sr[8]) },
2966 { "sr9", offsetof(CPUState, sr[9]) },
2967 { "sr10", offsetof(CPUState, sr[10]) },
2968 { "sr11", offsetof(CPUState, sr[11]) },
2969 { "sr12", offsetof(CPUState, sr[12]) },
2970 { "sr13", offsetof(CPUState, sr[13]) },
2971 { "sr14", offsetof(CPUState, sr[14]) },
2972 { "sr15", offsetof(CPUState, sr[15]) },
2973 /* Too lazy to put BATs and SPRs ... */
bellarde95c8d52004-09-30 22:22:08 +00002974#elif defined(TARGET_SPARC)
2975 { "g0", offsetof(CPUState, gregs[0]) },
2976 { "g1", offsetof(CPUState, gregs[1]) },
2977 { "g2", offsetof(CPUState, gregs[2]) },
2978 { "g3", offsetof(CPUState, gregs[3]) },
2979 { "g4", offsetof(CPUState, gregs[4]) },
2980 { "g5", offsetof(CPUState, gregs[5]) },
2981 { "g6", offsetof(CPUState, gregs[6]) },
2982 { "g7", offsetof(CPUState, gregs[7]) },
2983 { "o0", 0, monitor_get_reg },
2984 { "o1", 1, monitor_get_reg },
2985 { "o2", 2, monitor_get_reg },
2986 { "o3", 3, monitor_get_reg },
2987 { "o4", 4, monitor_get_reg },
2988 { "o5", 5, monitor_get_reg },
2989 { "o6", 6, monitor_get_reg },
2990 { "o7", 7, monitor_get_reg },
2991 { "l0", 8, monitor_get_reg },
2992 { "l1", 9, monitor_get_reg },
2993 { "l2", 10, monitor_get_reg },
2994 { "l3", 11, monitor_get_reg },
2995 { "l4", 12, monitor_get_reg },
2996 { "l5", 13, monitor_get_reg },
2997 { "l6", 14, monitor_get_reg },
2998 { "l7", 15, monitor_get_reg },
2999 { "i0", 16, monitor_get_reg },
3000 { "i1", 17, monitor_get_reg },
3001 { "i2", 18, monitor_get_reg },
3002 { "i3", 19, monitor_get_reg },
3003 { "i4", 20, monitor_get_reg },
3004 { "i5", 21, monitor_get_reg },
3005 { "i6", 22, monitor_get_reg },
3006 { "i7", 23, monitor_get_reg },
3007 { "pc", offsetof(CPUState, pc) },
3008 { "npc", offsetof(CPUState, npc) },
3009 { "y", offsetof(CPUState, y) },
bellard7b936c02005-10-30 17:05:13 +00003010#ifndef TARGET_SPARC64
bellarde95c8d52004-09-30 22:22:08 +00003011 { "psr", 0, &monitor_get_psr, },
3012 { "wim", offsetof(CPUState, wim) },
bellard7b936c02005-10-30 17:05:13 +00003013#endif
bellarde95c8d52004-09-30 22:22:08 +00003014 { "tbr", offsetof(CPUState, tbr) },
3015 { "fsr", offsetof(CPUState, fsr) },
3016 { "f0", offsetof(CPUState, fpr[0]) },
3017 { "f1", offsetof(CPUState, fpr[1]) },
3018 { "f2", offsetof(CPUState, fpr[2]) },
3019 { "f3", offsetof(CPUState, fpr[3]) },
3020 { "f4", offsetof(CPUState, fpr[4]) },
3021 { "f5", offsetof(CPUState, fpr[5]) },
3022 { "f6", offsetof(CPUState, fpr[6]) },
3023 { "f7", offsetof(CPUState, fpr[7]) },
3024 { "f8", offsetof(CPUState, fpr[8]) },
3025 { "f9", offsetof(CPUState, fpr[9]) },
3026 { "f10", offsetof(CPUState, fpr[10]) },
3027 { "f11", offsetof(CPUState, fpr[11]) },
3028 { "f12", offsetof(CPUState, fpr[12]) },
3029 { "f13", offsetof(CPUState, fpr[13]) },
3030 { "f14", offsetof(CPUState, fpr[14]) },
3031 { "f15", offsetof(CPUState, fpr[15]) },
3032 { "f16", offsetof(CPUState, fpr[16]) },
3033 { "f17", offsetof(CPUState, fpr[17]) },
3034 { "f18", offsetof(CPUState, fpr[18]) },
3035 { "f19", offsetof(CPUState, fpr[19]) },
3036 { "f20", offsetof(CPUState, fpr[20]) },
3037 { "f21", offsetof(CPUState, fpr[21]) },
3038 { "f22", offsetof(CPUState, fpr[22]) },
3039 { "f23", offsetof(CPUState, fpr[23]) },
3040 { "f24", offsetof(CPUState, fpr[24]) },
3041 { "f25", offsetof(CPUState, fpr[25]) },
3042 { "f26", offsetof(CPUState, fpr[26]) },
3043 { "f27", offsetof(CPUState, fpr[27]) },
3044 { "f28", offsetof(CPUState, fpr[28]) },
3045 { "f29", offsetof(CPUState, fpr[29]) },
3046 { "f30", offsetof(CPUState, fpr[30]) },
3047 { "f31", offsetof(CPUState, fpr[31]) },
bellard7b936c02005-10-30 17:05:13 +00003048#ifdef TARGET_SPARC64
3049 { "f32", offsetof(CPUState, fpr[32]) },
3050 { "f34", offsetof(CPUState, fpr[34]) },
3051 { "f36", offsetof(CPUState, fpr[36]) },
3052 { "f38", offsetof(CPUState, fpr[38]) },
3053 { "f40", offsetof(CPUState, fpr[40]) },
3054 { "f42", offsetof(CPUState, fpr[42]) },
3055 { "f44", offsetof(CPUState, fpr[44]) },
3056 { "f46", offsetof(CPUState, fpr[46]) },
3057 { "f48", offsetof(CPUState, fpr[48]) },
3058 { "f50", offsetof(CPUState, fpr[50]) },
3059 { "f52", offsetof(CPUState, fpr[52]) },
3060 { "f54", offsetof(CPUState, fpr[54]) },
3061 { "f56", offsetof(CPUState, fpr[56]) },
3062 { "f58", offsetof(CPUState, fpr[58]) },
3063 { "f60", offsetof(CPUState, fpr[60]) },
3064 { "f62", offsetof(CPUState, fpr[62]) },
3065 { "asi", offsetof(CPUState, asi) },
3066 { "pstate", offsetof(CPUState, pstate) },
3067 { "cansave", offsetof(CPUState, cansave) },
3068 { "canrestore", offsetof(CPUState, canrestore) },
3069 { "otherwin", offsetof(CPUState, otherwin) },
3070 { "wstate", offsetof(CPUState, wstate) },
3071 { "cleanwin", offsetof(CPUState, cleanwin) },
3072 { "fprs", offsetof(CPUState, fprs) },
3073#endif
bellard9307c4c2004-04-04 12:57:25 +00003074#endif
3075 { NULL },
3076};
3077
aliguori376253e2009-03-05 23:01:23 +00003078static void expr_error(Monitor *mon, const char *msg)
bellard9dc39cb2004-03-14 21:38:27 +00003079{
aliguori376253e2009-03-05 23:01:23 +00003080 monitor_printf(mon, "%s\n", msg);
bellard9307c4c2004-04-04 12:57:25 +00003081 longjmp(expr_env, 1);
3082}
3083
Markus Armbruster09b94182010-01-20 13:07:30 +01003084/* return 0 if OK, -1 if not found */
bellard92a31b12005-02-10 22:00:52 +00003085static int get_monitor_def(target_long *pval, const char *name)
bellard9307c4c2004-04-04 12:57:25 +00003086{
blueswir18662d652008-10-02 18:32:44 +00003087 const MonitorDef *md;
bellard92a31b12005-02-10 22:00:52 +00003088 void *ptr;
3089
bellard9307c4c2004-04-04 12:57:25 +00003090 for(md = monitor_defs; md->name != NULL; md++) {
3091 if (compare_cmd(name, md->name)) {
3092 if (md->get_value) {
bellarde95c8d52004-09-30 22:22:08 +00003093 *pval = md->get_value(md, md->offset);
bellard9307c4c2004-04-04 12:57:25 +00003094 } else {
bellard6a00d602005-11-21 23:25:50 +00003095 CPUState *env = mon_get_cpu();
bellard6a00d602005-11-21 23:25:50 +00003096 ptr = (uint8_t *)env + md->offset;
bellard92a31b12005-02-10 22:00:52 +00003097 switch(md->type) {
3098 case MD_I32:
3099 *pval = *(int32_t *)ptr;
3100 break;
3101 case MD_TLONG:
3102 *pval = *(target_long *)ptr;
3103 break;
3104 default:
3105 *pval = 0;
3106 break;
3107 }
bellard9307c4c2004-04-04 12:57:25 +00003108 }
3109 return 0;
3110 }
3111 }
3112 return -1;
3113}
3114
3115static void next(void)
3116{
Blue Swirl660f11b2009-07-31 21:16:51 +00003117 if (*pch != '\0') {
bellard9307c4c2004-04-04 12:57:25 +00003118 pch++;
blueswir1cd390082008-11-16 13:53:32 +00003119 while (qemu_isspace(*pch))
bellard9307c4c2004-04-04 12:57:25 +00003120 pch++;
3121 }
3122}
3123
aliguori376253e2009-03-05 23:01:23 +00003124static int64_t expr_sum(Monitor *mon);
bellard9307c4c2004-04-04 12:57:25 +00003125
aliguori376253e2009-03-05 23:01:23 +00003126static int64_t expr_unary(Monitor *mon)
bellard9307c4c2004-04-04 12:57:25 +00003127{
blueswir1c2efc952007-09-25 17:28:42 +00003128 int64_t n;
bellard9307c4c2004-04-04 12:57:25 +00003129 char *p;
bellard6a00d602005-11-21 23:25:50 +00003130 int ret;
bellard9307c4c2004-04-04 12:57:25 +00003131
3132 switch(*pch) {
3133 case '+':
3134 next();
aliguori376253e2009-03-05 23:01:23 +00003135 n = expr_unary(mon);
bellard9307c4c2004-04-04 12:57:25 +00003136 break;
3137 case '-':
3138 next();
aliguori376253e2009-03-05 23:01:23 +00003139 n = -expr_unary(mon);
bellard9307c4c2004-04-04 12:57:25 +00003140 break;
3141 case '~':
3142 next();
aliguori376253e2009-03-05 23:01:23 +00003143 n = ~expr_unary(mon);
bellard9307c4c2004-04-04 12:57:25 +00003144 break;
3145 case '(':
3146 next();
aliguori376253e2009-03-05 23:01:23 +00003147 n = expr_sum(mon);
bellard9307c4c2004-04-04 12:57:25 +00003148 if (*pch != ')') {
aliguori376253e2009-03-05 23:01:23 +00003149 expr_error(mon, "')' expected");
bellard9307c4c2004-04-04 12:57:25 +00003150 }
3151 next();
3152 break;
bellard81d09122004-07-14 17:21:37 +00003153 case '\'':
3154 pch++;
3155 if (*pch == '\0')
aliguori376253e2009-03-05 23:01:23 +00003156 expr_error(mon, "character constant expected");
bellard81d09122004-07-14 17:21:37 +00003157 n = *pch;
3158 pch++;
3159 if (*pch != '\'')
aliguori376253e2009-03-05 23:01:23 +00003160 expr_error(mon, "missing terminating \' character");
bellard81d09122004-07-14 17:21:37 +00003161 next();
3162 break;
bellard9307c4c2004-04-04 12:57:25 +00003163 case '$':
3164 {
3165 char buf[128], *q;
ths69b34972007-12-17 03:15:52 +00003166 target_long reg=0;
ths3b46e622007-09-17 08:09:54 +00003167
bellard9307c4c2004-04-04 12:57:25 +00003168 pch++;
3169 q = buf;
3170 while ((*pch >= 'a' && *pch <= 'z') ||
3171 (*pch >= 'A' && *pch <= 'Z') ||
3172 (*pch >= '0' && *pch <= '9') ||
bellard57206fd2004-04-25 18:54:52 +00003173 *pch == '_' || *pch == '.') {
bellard9307c4c2004-04-04 12:57:25 +00003174 if ((q - buf) < sizeof(buf) - 1)
3175 *q++ = *pch;
3176 pch++;
3177 }
blueswir1cd390082008-11-16 13:53:32 +00003178 while (qemu_isspace(*pch))
bellard9307c4c2004-04-04 12:57:25 +00003179 pch++;
3180 *q = 0;
blueswir17743e582007-09-24 18:39:04 +00003181 ret = get_monitor_def(&reg, buf);
Markus Armbruster09b94182010-01-20 13:07:30 +01003182 if (ret < 0)
aliguori376253e2009-03-05 23:01:23 +00003183 expr_error(mon, "unknown register");
blueswir17743e582007-09-24 18:39:04 +00003184 n = reg;
bellard9307c4c2004-04-04 12:57:25 +00003185 }
3186 break;
3187 case '\0':
aliguori376253e2009-03-05 23:01:23 +00003188 expr_error(mon, "unexpected end of expression");
bellard9307c4c2004-04-04 12:57:25 +00003189 n = 0;
3190 break;
3191 default:
blueswir17743e582007-09-24 18:39:04 +00003192#if TARGET_PHYS_ADDR_BITS > 32
bellard4f4fbf72006-06-25 18:28:12 +00003193 n = strtoull(pch, &p, 0);
3194#else
bellard9307c4c2004-04-04 12:57:25 +00003195 n = strtoul(pch, &p, 0);
bellard4f4fbf72006-06-25 18:28:12 +00003196#endif
bellard9307c4c2004-04-04 12:57:25 +00003197 if (pch == p) {
aliguori376253e2009-03-05 23:01:23 +00003198 expr_error(mon, "invalid char in expression");
bellard9307c4c2004-04-04 12:57:25 +00003199 }
3200 pch = p;
blueswir1cd390082008-11-16 13:53:32 +00003201 while (qemu_isspace(*pch))
bellard9307c4c2004-04-04 12:57:25 +00003202 pch++;
3203 break;
3204 }
3205 return n;
3206}
3207
3208
aliguori376253e2009-03-05 23:01:23 +00003209static int64_t expr_prod(Monitor *mon)
bellard9307c4c2004-04-04 12:57:25 +00003210{
blueswir1c2efc952007-09-25 17:28:42 +00003211 int64_t val, val2;
bellard92a31b12005-02-10 22:00:52 +00003212 int op;
ths3b46e622007-09-17 08:09:54 +00003213
aliguori376253e2009-03-05 23:01:23 +00003214 val = expr_unary(mon);
bellard9307c4c2004-04-04 12:57:25 +00003215 for(;;) {
3216 op = *pch;
3217 if (op != '*' && op != '/' && op != '%')
3218 break;
3219 next();
aliguori376253e2009-03-05 23:01:23 +00003220 val2 = expr_unary(mon);
bellard9307c4c2004-04-04 12:57:25 +00003221 switch(op) {
3222 default:
3223 case '*':
3224 val *= val2;
3225 break;
3226 case '/':
3227 case '%':
ths5fafdf22007-09-16 21:08:06 +00003228 if (val2 == 0)
aliguori376253e2009-03-05 23:01:23 +00003229 expr_error(mon, "division by zero");
bellard9307c4c2004-04-04 12:57:25 +00003230 if (op == '/')
3231 val /= val2;
3232 else
3233 val %= val2;
3234 break;
3235 }
3236 }
3237 return val;
3238}
3239
aliguori376253e2009-03-05 23:01:23 +00003240static int64_t expr_logic(Monitor *mon)
bellard9307c4c2004-04-04 12:57:25 +00003241{
blueswir1c2efc952007-09-25 17:28:42 +00003242 int64_t val, val2;
bellard92a31b12005-02-10 22:00:52 +00003243 int op;
bellard9307c4c2004-04-04 12:57:25 +00003244
aliguori376253e2009-03-05 23:01:23 +00003245 val = expr_prod(mon);
bellard9307c4c2004-04-04 12:57:25 +00003246 for(;;) {
3247 op = *pch;
3248 if (op != '&' && op != '|' && op != '^')
3249 break;
3250 next();
aliguori376253e2009-03-05 23:01:23 +00003251 val2 = expr_prod(mon);
bellard9307c4c2004-04-04 12:57:25 +00003252 switch(op) {
3253 default:
3254 case '&':
3255 val &= val2;
3256 break;
3257 case '|':
3258 val |= val2;
3259 break;
3260 case '^':
3261 val ^= val2;
3262 break;
3263 }
3264 }
3265 return val;
3266}
3267
aliguori376253e2009-03-05 23:01:23 +00003268static int64_t expr_sum(Monitor *mon)
bellard9307c4c2004-04-04 12:57:25 +00003269{
blueswir1c2efc952007-09-25 17:28:42 +00003270 int64_t val, val2;
bellard92a31b12005-02-10 22:00:52 +00003271 int op;
bellard9307c4c2004-04-04 12:57:25 +00003272
aliguori376253e2009-03-05 23:01:23 +00003273 val = expr_logic(mon);
bellard9307c4c2004-04-04 12:57:25 +00003274 for(;;) {
3275 op = *pch;
3276 if (op != '+' && op != '-')
3277 break;
3278 next();
aliguori376253e2009-03-05 23:01:23 +00003279 val2 = expr_logic(mon);
bellard9307c4c2004-04-04 12:57:25 +00003280 if (op == '+')
3281 val += val2;
3282 else
3283 val -= val2;
3284 }
3285 return val;
3286}
3287
aliguori376253e2009-03-05 23:01:23 +00003288static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
bellard9307c4c2004-04-04 12:57:25 +00003289{
3290 pch = *pp;
3291 if (setjmp(expr_env)) {
3292 *pp = pch;
3293 return -1;
3294 }
blueswir1cd390082008-11-16 13:53:32 +00003295 while (qemu_isspace(*pch))
bellard9307c4c2004-04-04 12:57:25 +00003296 pch++;
aliguori376253e2009-03-05 23:01:23 +00003297 *pval = expr_sum(mon);
bellard9307c4c2004-04-04 12:57:25 +00003298 *pp = pch;
3299 return 0;
3300}
3301
3302static int get_str(char *buf, int buf_size, const char **pp)
3303{
3304 const char *p;
3305 char *q;
3306 int c;
3307
bellard81d09122004-07-14 17:21:37 +00003308 q = buf;
bellard9307c4c2004-04-04 12:57:25 +00003309 p = *pp;
blueswir1cd390082008-11-16 13:53:32 +00003310 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003311 p++;
3312 if (*p == '\0') {
3313 fail:
bellard81d09122004-07-14 17:21:37 +00003314 *q = '\0';
bellard9307c4c2004-04-04 12:57:25 +00003315 *pp = p;
3316 return -1;
3317 }
bellard9307c4c2004-04-04 12:57:25 +00003318 if (*p == '\"') {
3319 p++;
3320 while (*p != '\0' && *p != '\"') {
3321 if (*p == '\\') {
3322 p++;
3323 c = *p++;
3324 switch(c) {
3325 case 'n':
3326 c = '\n';
3327 break;
3328 case 'r':
3329 c = '\r';
3330 break;
3331 case '\\':
3332 case '\'':
3333 case '\"':
3334 break;
3335 default:
3336 qemu_printf("unsupported escape code: '\\%c'\n", c);
3337 goto fail;
3338 }
3339 if ((q - buf) < buf_size - 1) {
3340 *q++ = c;
3341 }
3342 } else {
3343 if ((q - buf) < buf_size - 1) {
3344 *q++ = *p;
3345 }
3346 p++;
3347 }
3348 }
3349 if (*p != '\"') {
bellard5b602122004-05-22 21:41:05 +00003350 qemu_printf("unterminated string\n");
bellard9307c4c2004-04-04 12:57:25 +00003351 goto fail;
3352 }
3353 p++;
3354 } else {
blueswir1cd390082008-11-16 13:53:32 +00003355 while (*p != '\0' && !qemu_isspace(*p)) {
bellard9307c4c2004-04-04 12:57:25 +00003356 if ((q - buf) < buf_size - 1) {
3357 *q++ = *p;
3358 }
3359 p++;
3360 }
bellard9307c4c2004-04-04 12:57:25 +00003361 }
bellard81d09122004-07-14 17:21:37 +00003362 *q = '\0';
bellard9307c4c2004-04-04 12:57:25 +00003363 *pp = p;
3364 return 0;
3365}
3366
Luiz Capitulino4590fd82009-06-09 18:21:30 -03003367/*
3368 * Store the command-name in cmdname, and return a pointer to
3369 * the remaining of the command string.
3370 */
3371static const char *get_command_name(const char *cmdline,
3372 char *cmdname, size_t nlen)
3373{
3374 size_t len;
3375 const char *p, *pstart;
3376
3377 p = cmdline;
3378 while (qemu_isspace(*p))
3379 p++;
3380 if (*p == '\0')
3381 return NULL;
3382 pstart = p;
3383 while (*p != '\0' && *p != '/' && !qemu_isspace(*p))
3384 p++;
3385 len = p - pstart;
3386 if (len > nlen - 1)
3387 len = nlen - 1;
3388 memcpy(cmdname, pstart, len);
3389 cmdname[len] = '\0';
3390 return p;
3391}
3392
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003393/**
3394 * Read key of 'type' into 'key' and return the current
3395 * 'type' pointer.
3396 */
3397static char *key_get_info(const char *type, char **key)
3398{
3399 size_t len;
3400 char *p, *str;
3401
3402 if (*type == ',')
3403 type++;
3404
3405 p = strchr(type, ':');
3406 if (!p) {
3407 *key = NULL;
3408 return NULL;
3409 }
3410 len = p - type;
3411
3412 str = qemu_malloc(len + 1);
3413 memcpy(str, type, len);
3414 str[len] = '\0';
3415
3416 *key = str;
3417 return ++p;
3418}
3419
bellard9307c4c2004-04-04 12:57:25 +00003420static int default_fmt_format = 'x';
3421static int default_fmt_size = 4;
3422
3423#define MAX_ARGS 16
3424
lirans@il.ibm.comfbc3d962009-11-02 15:41:13 +02003425static int is_valid_option(const char *c, const char *typestr)
3426{
3427 char option[3];
3428
3429 option[0] = '-';
3430 option[1] = *c;
3431 option[2] = '\0';
3432
3433 typestr = strstr(typestr, option);
3434 return (typestr != NULL);
3435}
3436
Luiz Capitulino7fd669a2009-11-26 22:58:54 -02003437static const mon_cmd_t *monitor_find_command(const char *cmdname)
3438{
3439 const mon_cmd_t *cmd;
3440
3441 for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
3442 if (compare_cmd(cmdname, cmd->name)) {
3443 return cmd;
3444 }
3445 }
3446
3447 return NULL;
3448}
3449
Anthony Liguoric227f092009-10-01 16:12:16 -05003450static const mon_cmd_t *monitor_parse_command(Monitor *mon,
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003451 const char *cmdline,
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003452 QDict *qdict)
bellard9307c4c2004-04-04 12:57:25 +00003453{
Luiz Capitulino4590fd82009-06-09 18:21:30 -03003454 const char *p, *typestr;
Luiz Capitulino53773582009-08-28 15:27:25 -03003455 int c;
Anthony Liguoric227f092009-10-01 16:12:16 -05003456 const mon_cmd_t *cmd;
bellard9307c4c2004-04-04 12:57:25 +00003457 char cmdname[256];
3458 char buf[1024];
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003459 char *key;
bellard9dc39cb2004-03-14 21:38:27 +00003460
3461#ifdef DEBUG
aliguori376253e2009-03-05 23:01:23 +00003462 monitor_printf(mon, "command='%s'\n", cmdline);
bellard9dc39cb2004-03-14 21:38:27 +00003463#endif
ths3b46e622007-09-17 08:09:54 +00003464
bellard9307c4c2004-04-04 12:57:25 +00003465 /* extract the command name */
Luiz Capitulino4590fd82009-06-09 18:21:30 -03003466 p = get_command_name(cmdline, cmdname, sizeof(cmdname));
3467 if (!p)
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003468 return NULL;
ths3b46e622007-09-17 08:09:54 +00003469
Luiz Capitulino7fd669a2009-11-26 22:58:54 -02003470 cmd = monitor_find_command(cmdname);
3471 if (!cmd) {
Luiz Capitulinod91d9bf2009-06-09 18:21:54 -03003472 monitor_printf(mon, "unknown command: '%s'\n", cmdname);
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003473 return NULL;
Luiz Capitulinod91d9bf2009-06-09 18:21:54 -03003474 }
bellard9307c4c2004-04-04 12:57:25 +00003475
bellard9307c4c2004-04-04 12:57:25 +00003476 /* parse the parameters */
3477 typestr = cmd->args_type;
bellard9307c4c2004-04-04 12:57:25 +00003478 for(;;) {
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003479 typestr = key_get_info(typestr, &key);
3480 if (!typestr)
bellard9307c4c2004-04-04 12:57:25 +00003481 break;
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003482 c = *typestr;
bellard9307c4c2004-04-04 12:57:25 +00003483 typestr++;
3484 switch(c) {
3485 case 'F':
bellard81d09122004-07-14 17:21:37 +00003486 case 'B':
bellard9307c4c2004-04-04 12:57:25 +00003487 case 's':
3488 {
3489 int ret;
ths3b46e622007-09-17 08:09:54 +00003490
blueswir1cd390082008-11-16 13:53:32 +00003491 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003492 p++;
3493 if (*typestr == '?') {
3494 typestr++;
3495 if (*p == '\0') {
3496 /* no optional string: NULL argument */
Luiz Capitulino53773582009-08-28 15:27:25 -03003497 break;
bellard9307c4c2004-04-04 12:57:25 +00003498 }
3499 }
3500 ret = get_str(buf, sizeof(buf), &p);
3501 if (ret < 0) {
bellard81d09122004-07-14 17:21:37 +00003502 switch(c) {
3503 case 'F':
aliguori376253e2009-03-05 23:01:23 +00003504 monitor_printf(mon, "%s: filename expected\n",
3505 cmdname);
bellard81d09122004-07-14 17:21:37 +00003506 break;
3507 case 'B':
aliguori376253e2009-03-05 23:01:23 +00003508 monitor_printf(mon, "%s: block device name expected\n",
3509 cmdname);
bellard81d09122004-07-14 17:21:37 +00003510 break;
3511 default:
aliguori376253e2009-03-05 23:01:23 +00003512 monitor_printf(mon, "%s: string expected\n", cmdname);
bellard81d09122004-07-14 17:21:37 +00003513 break;
3514 }
bellard9307c4c2004-04-04 12:57:25 +00003515 goto fail;
3516 }
Luiz Capitulino53773582009-08-28 15:27:25 -03003517 qdict_put(qdict, key, qstring_from_str(buf));
bellard9307c4c2004-04-04 12:57:25 +00003518 }
3519 break;
3520 case '/':
3521 {
3522 int count, format, size;
ths3b46e622007-09-17 08:09:54 +00003523
blueswir1cd390082008-11-16 13:53:32 +00003524 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003525 p++;
3526 if (*p == '/') {
3527 /* format found */
3528 p++;
3529 count = 1;
blueswir1cd390082008-11-16 13:53:32 +00003530 if (qemu_isdigit(*p)) {
bellard9307c4c2004-04-04 12:57:25 +00003531 count = 0;
blueswir1cd390082008-11-16 13:53:32 +00003532 while (qemu_isdigit(*p)) {
bellard9307c4c2004-04-04 12:57:25 +00003533 count = count * 10 + (*p - '0');
3534 p++;
3535 }
3536 }
3537 size = -1;
3538 format = -1;
3539 for(;;) {
3540 switch(*p) {
3541 case 'o':
3542 case 'd':
3543 case 'u':
3544 case 'x':
3545 case 'i':
3546 case 'c':
3547 format = *p++;
3548 break;
3549 case 'b':
3550 size = 1;
3551 p++;
3552 break;
3553 case 'h':
3554 size = 2;
3555 p++;
3556 break;
3557 case 'w':
3558 size = 4;
3559 p++;
3560 break;
3561 case 'g':
3562 case 'L':
3563 size = 8;
3564 p++;
3565 break;
3566 default:
3567 goto next;
3568 }
3569 }
3570 next:
blueswir1cd390082008-11-16 13:53:32 +00003571 if (*p != '\0' && !qemu_isspace(*p)) {
aliguori376253e2009-03-05 23:01:23 +00003572 monitor_printf(mon, "invalid char in format: '%c'\n",
3573 *p);
bellard9307c4c2004-04-04 12:57:25 +00003574 goto fail;
3575 }
bellard9307c4c2004-04-04 12:57:25 +00003576 if (format < 0)
3577 format = default_fmt_format;
bellard4c27ba22004-04-25 18:05:08 +00003578 if (format != 'i') {
3579 /* for 'i', not specifying a size gives -1 as size */
3580 if (size < 0)
3581 size = default_fmt_size;
aurel32e90f0092008-10-01 21:45:51 +00003582 default_fmt_size = size;
bellard4c27ba22004-04-25 18:05:08 +00003583 }
bellard9307c4c2004-04-04 12:57:25 +00003584 default_fmt_format = format;
3585 } else {
3586 count = 1;
3587 format = default_fmt_format;
bellard4c27ba22004-04-25 18:05:08 +00003588 if (format != 'i') {
3589 size = default_fmt_size;
3590 } else {
3591 size = -1;
3592 }
bellard9307c4c2004-04-04 12:57:25 +00003593 }
Luiz Capitulinof7188bb2009-08-28 15:27:10 -03003594 qdict_put(qdict, "count", qint_from_int(count));
3595 qdict_put(qdict, "format", qint_from_int(format));
3596 qdict_put(qdict, "size", qint_from_int(size));
bellard9307c4c2004-04-04 12:57:25 +00003597 }
3598 break;
3599 case 'i':
bellard92a31b12005-02-10 22:00:52 +00003600 case 'l':
Luiz Capitulinob6e098d2009-12-18 13:25:04 -02003601 case 'M':
bellard9307c4c2004-04-04 12:57:25 +00003602 {
blueswir1c2efc952007-09-25 17:28:42 +00003603 int64_t val;
blueswir17743e582007-09-24 18:39:04 +00003604
blueswir1cd390082008-11-16 13:53:32 +00003605 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003606 p++;
bellard34405572004-06-08 00:55:58 +00003607 if (*typestr == '?' || *typestr == '.') {
bellard34405572004-06-08 00:55:58 +00003608 if (*typestr == '?') {
Luiz Capitulino53773582009-08-28 15:27:25 -03003609 if (*p == '\0') {
3610 typestr++;
3611 break;
3612 }
bellard34405572004-06-08 00:55:58 +00003613 } else {
3614 if (*p == '.') {
3615 p++;
blueswir1cd390082008-11-16 13:53:32 +00003616 while (qemu_isspace(*p))
bellard34405572004-06-08 00:55:58 +00003617 p++;
bellard34405572004-06-08 00:55:58 +00003618 } else {
Luiz Capitulino53773582009-08-28 15:27:25 -03003619 typestr++;
3620 break;
bellard34405572004-06-08 00:55:58 +00003621 }
3622 }
bellard13224a82006-07-14 22:03:35 +00003623 typestr++;
bellard9307c4c2004-04-04 12:57:25 +00003624 }
aliguori376253e2009-03-05 23:01:23 +00003625 if (get_expr(mon, &val, &p))
bellard9307c4c2004-04-04 12:57:25 +00003626 goto fail;
Luiz Capitulino675ebef2009-08-28 15:27:26 -03003627 /* Check if 'i' is greater than 32-bit */
3628 if ((c == 'i') && ((val >> 32) & 0xffffffff)) {
3629 monitor_printf(mon, "\'%s\' has failed: ", cmdname);
3630 monitor_printf(mon, "integer is for 32-bit values\n");
3631 goto fail;
Luiz Capitulinob6e098d2009-12-18 13:25:04 -02003632 } else if (c == 'M') {
3633 val <<= 20;
Luiz Capitulino675ebef2009-08-28 15:27:26 -03003634 }
Luiz Capitulino53773582009-08-28 15:27:25 -03003635 qdict_put(qdict, key, qint_from_int(val));
bellard9307c4c2004-04-04 12:57:25 +00003636 }
3637 break;
3638 case '-':
3639 {
lirans@il.ibm.comfbc3d962009-11-02 15:41:13 +02003640 const char *tmp = p;
3641 int has_option, skip_key = 0;
bellard9307c4c2004-04-04 12:57:25 +00003642 /* option */
ths3b46e622007-09-17 08:09:54 +00003643
bellard9307c4c2004-04-04 12:57:25 +00003644 c = *typestr++;
3645 if (c == '\0')
3646 goto bad_type;
blueswir1cd390082008-11-16 13:53:32 +00003647 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003648 p++;
3649 has_option = 0;
3650 if (*p == '-') {
3651 p++;
lirans@il.ibm.comfbc3d962009-11-02 15:41:13 +02003652 if(c != *p) {
3653 if(!is_valid_option(p, typestr)) {
3654
3655 monitor_printf(mon, "%s: unsupported option -%c\n",
3656 cmdname, *p);
3657 goto fail;
3658 } else {
3659 skip_key = 1;
3660 }
bellard9307c4c2004-04-04 12:57:25 +00003661 }
lirans@il.ibm.comfbc3d962009-11-02 15:41:13 +02003662 if(skip_key) {
3663 p = tmp;
3664 } else {
3665 p++;
3666 has_option = 1;
3667 }
bellard9307c4c2004-04-04 12:57:25 +00003668 }
Luiz Capitulinof7188bb2009-08-28 15:27:10 -03003669 qdict_put(qdict, key, qint_from_int(has_option));
bellard9307c4c2004-04-04 12:57:25 +00003670 }
3671 break;
3672 default:
3673 bad_type:
aliguori376253e2009-03-05 23:01:23 +00003674 monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
bellard9307c4c2004-04-04 12:57:25 +00003675 goto fail;
3676 }
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003677 qemu_free(key);
3678 key = NULL;
bellard9307c4c2004-04-04 12:57:25 +00003679 }
3680 /* check that all arguments were parsed */
blueswir1cd390082008-11-16 13:53:32 +00003681 while (qemu_isspace(*p))
bellard9307c4c2004-04-04 12:57:25 +00003682 p++;
3683 if (*p != '\0') {
aliguori376253e2009-03-05 23:01:23 +00003684 monitor_printf(mon, "%s: extraneous characters at the end of line\n",
3685 cmdname);
bellard9307c4c2004-04-04 12:57:25 +00003686 goto fail;
3687 }
3688
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003689 return cmd;
Gerd Hoffmannac7531e2009-08-14 10:36:06 +02003690
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003691fail:
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003692 qemu_free(key);
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003693 return NULL;
3694}
3695
Luiz Capitulino8204a912009-11-18 23:05:31 -02003696static void monitor_print_error(Monitor *mon)
3697{
3698 qerror_print(mon->error);
3699 QDECREF(mon->error);
3700 mon->error = NULL;
3701}
3702
Adam Litke940cc302010-01-25 12:18:44 -06003703static int is_async_return(const QObject *data)
3704{
Luiz Capitulino82617d72010-01-27 18:01:17 -02003705 if (data && qobject_type(data) == QTYPE_QDICT) {
3706 return qdict_haskey(qobject_to_qdict(data), "__mon_async");
3707 }
3708
3709 return 0;
Adam Litke940cc302010-01-25 12:18:44 -06003710}
3711
Luiz Capitulino99e2fc12009-11-26 22:58:53 -02003712static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
3713 const QDict *params)
3714{
3715 QObject *data = NULL;
3716
3717 cmd->mhandler.cmd_new(mon, params, &data);
Luiz Capitulino25b422e2009-11-26 22:58:59 -02003718
Adam Litke940cc302010-01-25 12:18:44 -06003719 if (is_async_return(data)) {
3720 /*
3721 * Asynchronous commands have no initial return data but they can
3722 * generate errors. Data is returned via the async completion handler.
3723 */
3724 if (monitor_ctrl_mode(mon) && monitor_has_error(mon)) {
3725 monitor_protocol_emitter(mon, NULL);
3726 }
3727 } else if (monitor_ctrl_mode(mon)) {
Luiz Capitulino25b422e2009-11-26 22:58:59 -02003728 /* Monitor Protocol */
3729 monitor_protocol_emitter(mon, data);
3730 } else {
3731 /* User Protocol */
3732 if (data)
3733 cmd->user_print(mon, data);
3734 }
Luiz Capitulino99e2fc12009-11-26 22:58:53 -02003735
3736 qobject_decref(data);
3737}
3738
Luiz Capitulinof3c157c2009-11-26 22:58:55 -02003739static void handle_user_command(Monitor *mon, const char *cmdline)
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003740{
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003741 QDict *qdict;
Anthony Liguoric227f092009-10-01 16:12:16 -05003742 const mon_cmd_t *cmd;
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003743
3744 qdict = qdict_new();
3745
Luiz Capitulino590fb3b2009-08-28 15:27:24 -03003746 cmd = monitor_parse_command(mon, cmdline, qdict);
Luiz Capitulino13917be2009-10-07 13:41:54 -03003747 if (!cmd)
3748 goto out;
3749
3750 qemu_errors_to_mon(mon);
3751
Adam Litke940cc302010-01-25 12:18:44 -06003752 if (monitor_handler_is_async(cmd)) {
3753 user_async_cmd_handler(mon, cmd, qdict);
3754 } else if (monitor_handler_ported(cmd)) {
Luiz Capitulino99e2fc12009-11-26 22:58:53 -02003755 monitor_call_handler(mon, cmd, qdict);
Luiz Capitulino13917be2009-10-07 13:41:54 -03003756 } else {
Luiz Capitulinoaf4ce882009-10-07 13:41:52 -03003757 cmd->mhandler.cmd(mon, qdict);
Luiz Capitulino55f81d92009-08-28 15:27:22 -03003758 }
3759
Luiz Capitulino8204a912009-11-18 23:05:31 -02003760 if (monitor_has_error(mon))
3761 monitor_print_error(mon);
3762
3763 qemu_errors_to_previous();
Luiz Capitulino13917be2009-10-07 13:41:54 -03003764
3765out:
Luiz Capitulinof7188bb2009-08-28 15:27:10 -03003766 QDECREF(qdict);
bellard9dc39cb2004-03-14 21:38:27 +00003767}
3768
bellard81d09122004-07-14 17:21:37 +00003769static void cmd_completion(const char *name, const char *list)
3770{
3771 const char *p, *pstart;
3772 char cmd[128];
3773 int len;
3774
3775 p = list;
3776 for(;;) {
3777 pstart = p;
3778 p = strchr(p, '|');
3779 if (!p)
3780 p = pstart + strlen(pstart);
3781 len = p - pstart;
3782 if (len > sizeof(cmd) - 2)
3783 len = sizeof(cmd) - 2;
3784 memcpy(cmd, pstart, len);
3785 cmd[len] = '\0';
3786 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
aliguori731b0362009-03-05 23:01:42 +00003787 readline_add_completion(cur_mon->rs, cmd);
bellard81d09122004-07-14 17:21:37 +00003788 }
3789 if (*p == '\0')
3790 break;
3791 p++;
3792 }
3793}
3794
3795static void file_completion(const char *input)
3796{
3797 DIR *ffs;
3798 struct dirent *d;
3799 char path[1024];
3800 char file[1024], file_prefix[1024];
3801 int input_path_len;
3802 const char *p;
3803
ths5fafdf22007-09-16 21:08:06 +00003804 p = strrchr(input, '/');
bellard81d09122004-07-14 17:21:37 +00003805 if (!p) {
3806 input_path_len = 0;
3807 pstrcpy(file_prefix, sizeof(file_prefix), input);
blueswir1363a37d2008-08-21 17:58:08 +00003808 pstrcpy(path, sizeof(path), ".");
bellard81d09122004-07-14 17:21:37 +00003809 } else {
3810 input_path_len = p - input + 1;
3811 memcpy(path, input, input_path_len);
3812 if (input_path_len > sizeof(path) - 1)
3813 input_path_len = sizeof(path) - 1;
3814 path[input_path_len] = '\0';
3815 pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
3816 }
3817#ifdef DEBUG_COMPLETION
aliguori376253e2009-03-05 23:01:23 +00003818 monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n",
3819 input, path, file_prefix);
bellard81d09122004-07-14 17:21:37 +00003820#endif
3821 ffs = opendir(path);
3822 if (!ffs)
3823 return;
3824 for(;;) {
3825 struct stat sb;
3826 d = readdir(ffs);
3827 if (!d)
3828 break;
3829 if (strstart(d->d_name, file_prefix, NULL)) {
3830 memcpy(file, input, input_path_len);
blueswir1363a37d2008-08-21 17:58:08 +00003831 if (input_path_len < sizeof(file))
3832 pstrcpy(file + input_path_len, sizeof(file) - input_path_len,
3833 d->d_name);
bellard81d09122004-07-14 17:21:37 +00003834 /* stat the file to find out if it's a directory.
3835 * In that case add a slash to speed up typing long paths
3836 */
3837 stat(file, &sb);
3838 if(S_ISDIR(sb.st_mode))
blueswir1363a37d2008-08-21 17:58:08 +00003839 pstrcat(file, sizeof(file), "/");
aliguori731b0362009-03-05 23:01:42 +00003840 readline_add_completion(cur_mon->rs, file);
bellard81d09122004-07-14 17:21:37 +00003841 }
3842 }
3843 closedir(ffs);
3844}
3845
aliguori51de9762009-03-05 23:00:43 +00003846static void block_completion_it(void *opaque, BlockDriverState *bs)
bellard81d09122004-07-14 17:21:37 +00003847{
aliguori51de9762009-03-05 23:00:43 +00003848 const char *name = bdrv_get_device_name(bs);
bellard81d09122004-07-14 17:21:37 +00003849 const char *input = opaque;
3850
3851 if (input[0] == '\0' ||
3852 !strncmp(name, (char *)input, strlen(input))) {
aliguori731b0362009-03-05 23:01:42 +00003853 readline_add_completion(cur_mon->rs, name);
bellard81d09122004-07-14 17:21:37 +00003854 }
3855}
3856
3857/* NOTE: this parser is an approximate form of the real command parser */
3858static void parse_cmdline(const char *cmdline,
3859 int *pnb_args, char **args)
3860{
3861 const char *p;
3862 int nb_args, ret;
3863 char buf[1024];
3864
3865 p = cmdline;
3866 nb_args = 0;
3867 for(;;) {
blueswir1cd390082008-11-16 13:53:32 +00003868 while (qemu_isspace(*p))
bellard81d09122004-07-14 17:21:37 +00003869 p++;
3870 if (*p == '\0')
3871 break;
3872 if (nb_args >= MAX_ARGS)
3873 break;
3874 ret = get_str(buf, sizeof(buf), &p);
3875 args[nb_args] = qemu_strdup(buf);
3876 nb_args++;
3877 if (ret < 0)
3878 break;
3879 }
3880 *pnb_args = nb_args;
3881}
3882
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003883static const char *next_arg_type(const char *typestr)
3884{
3885 const char *p = strchr(typestr, ':');
3886 return (p != NULL ? ++p : typestr);
3887}
3888
aliguori4c36ba32009-03-05 23:01:37 +00003889static void monitor_find_completion(const char *cmdline)
bellard81d09122004-07-14 17:21:37 +00003890{
3891 const char *cmdname;
3892 char *args[MAX_ARGS];
3893 int nb_args, i, len;
3894 const char *ptype, *str;
Anthony Liguoric227f092009-10-01 16:12:16 -05003895 const mon_cmd_t *cmd;
bellard64866c32006-05-07 18:03:31 +00003896 const KeyDef *key;
bellard81d09122004-07-14 17:21:37 +00003897
3898 parse_cmdline(cmdline, &nb_args, args);
3899#ifdef DEBUG_COMPLETION
3900 for(i = 0; i < nb_args; i++) {
aliguori376253e2009-03-05 23:01:23 +00003901 monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
bellard81d09122004-07-14 17:21:37 +00003902 }
3903#endif
3904
3905 /* if the line ends with a space, it means we want to complete the
3906 next arg */
3907 len = strlen(cmdline);
blueswir1cd390082008-11-16 13:53:32 +00003908 if (len > 0 && qemu_isspace(cmdline[len - 1])) {
bellard81d09122004-07-14 17:21:37 +00003909 if (nb_args >= MAX_ARGS)
3910 return;
3911 args[nb_args++] = qemu_strdup("");
3912 }
3913 if (nb_args <= 1) {
3914 /* command completion */
3915 if (nb_args == 0)
3916 cmdname = "";
3917 else
3918 cmdname = args[0];
aliguori731b0362009-03-05 23:01:42 +00003919 readline_set_completion_index(cur_mon->rs, strlen(cmdname));
aliguori376253e2009-03-05 23:01:23 +00003920 for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
bellard81d09122004-07-14 17:21:37 +00003921 cmd_completion(cmdname, cmd->name);
3922 }
3923 } else {
3924 /* find the command */
aliguori376253e2009-03-05 23:01:23 +00003925 for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
bellard81d09122004-07-14 17:21:37 +00003926 if (compare_cmd(args[0], cmd->name))
3927 goto found;
3928 }
3929 return;
3930 found:
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003931 ptype = next_arg_type(cmd->args_type);
bellard81d09122004-07-14 17:21:37 +00003932 for(i = 0; i < nb_args - 2; i++) {
3933 if (*ptype != '\0') {
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003934 ptype = next_arg_type(ptype);
bellard81d09122004-07-14 17:21:37 +00003935 while (*ptype == '?')
Luiz Capitulino4d76d2b2009-08-28 15:27:09 -03003936 ptype = next_arg_type(ptype);
bellard81d09122004-07-14 17:21:37 +00003937 }
3938 }
3939 str = args[nb_args - 1];
Blue Swirl2a1704a2009-08-23 20:10:28 +00003940 if (*ptype == '-' && ptype[1] != '\0') {
3941 ptype += 2;
3942 }
bellard81d09122004-07-14 17:21:37 +00003943 switch(*ptype) {
3944 case 'F':
3945 /* file completion */
aliguori731b0362009-03-05 23:01:42 +00003946 readline_set_completion_index(cur_mon->rs, strlen(str));
bellard81d09122004-07-14 17:21:37 +00003947 file_completion(str);
3948 break;
3949 case 'B':
3950 /* block device name completion */
aliguori731b0362009-03-05 23:01:42 +00003951 readline_set_completion_index(cur_mon->rs, strlen(str));
bellard81d09122004-07-14 17:21:37 +00003952 bdrv_iterate(block_completion_it, (void *)str);
3953 break;
bellard7fe48482004-10-09 18:08:01 +00003954 case 's':
3955 /* XXX: more generic ? */
3956 if (!strcmp(cmd->name, "info")) {
aliguori731b0362009-03-05 23:01:42 +00003957 readline_set_completion_index(cur_mon->rs, strlen(str));
bellard7fe48482004-10-09 18:08:01 +00003958 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
3959 cmd_completion(str, cmd->name);
3960 }
bellard64866c32006-05-07 18:03:31 +00003961 } else if (!strcmp(cmd->name, "sendkey")) {
blueswir1e600d1e2009-03-08 17:42:02 +00003962 char *sep = strrchr(str, '-');
3963 if (sep)
3964 str = sep + 1;
aliguori731b0362009-03-05 23:01:42 +00003965 readline_set_completion_index(cur_mon->rs, strlen(str));
bellard64866c32006-05-07 18:03:31 +00003966 for(key = key_defs; key->name != NULL; key++) {
3967 cmd_completion(str, key->name);
3968 }
Jan Kiszkaf3353c62009-06-25 08:22:02 +02003969 } else if (!strcmp(cmd->name, "help|?")) {
3970 readline_set_completion_index(cur_mon->rs, strlen(str));
3971 for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
3972 cmd_completion(str, cmd->name);
3973 }
bellard7fe48482004-10-09 18:08:01 +00003974 }
3975 break;
bellard81d09122004-07-14 17:21:37 +00003976 default:
3977 break;
3978 }
3979 }
3980 for(i = 0; i < nb_args; i++)
3981 qemu_free(args[i]);
3982}
3983
aliguori731b0362009-03-05 23:01:42 +00003984static int monitor_can_read(void *opaque)
bellard9dc39cb2004-03-14 21:38:27 +00003985{
aliguori731b0362009-03-05 23:01:42 +00003986 Monitor *mon = opaque;
3987
Jan Kiszkac62313b2009-12-04 14:05:29 +01003988 return (mon->suspend_cnt == 0) ? 1 : 0;
bellard9dc39cb2004-03-14 21:38:27 +00003989}
3990
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02003991typedef struct CmdArgs {
3992 QString *name;
3993 int type;
3994 int flag;
3995 int optional;
3996} CmdArgs;
3997
3998static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args)
3999{
4000 if (!cmd_args->optional) {
4001 qemu_error_new(QERR_MISSING_PARAMETER, name);
4002 return -1;
4003 }
4004
4005 if (cmd_args->type == '-') {
4006 /* handlers expect a value, they need to be changed */
4007 qdict_put(args, name, qint_from_int(0));
4008 }
4009
4010 return 0;
4011}
4012
4013static int check_arg(const CmdArgs *cmd_args, QDict *args)
4014{
4015 QObject *value;
4016 const char *name;
4017
4018 name = qstring_get_str(cmd_args->name);
4019
4020 if (!args) {
4021 return check_opt(cmd_args, name, args);
4022 }
4023
4024 value = qdict_get(args, name);
4025 if (!value) {
4026 return check_opt(cmd_args, name, args);
4027 }
4028
4029 switch (cmd_args->type) {
4030 case 'F':
4031 case 'B':
4032 case 's':
4033 if (qobject_type(value) != QTYPE_QSTRING) {
4034 qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "string");
4035 return -1;
4036 }
4037 break;
4038 case '/': {
4039 int i;
4040 const char *keys[] = { "count", "format", "size", NULL };
4041
4042 for (i = 0; keys[i]; i++) {
4043 QObject *obj = qdict_get(args, keys[i]);
4044 if (!obj) {
4045 qemu_error_new(QERR_MISSING_PARAMETER, name);
4046 return -1;
4047 }
4048 if (qobject_type(obj) != QTYPE_QINT) {
4049 qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
4050 return -1;
4051 }
4052 }
4053 break;
4054 }
4055 case 'i':
4056 case 'l':
Luiz Capitulinob6e098d2009-12-18 13:25:04 -02004057 case 'M':
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004058 if (qobject_type(value) != QTYPE_QINT) {
4059 qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
4060 return -1;
4061 }
4062 break;
4063 case '-':
4064 if (qobject_type(value) != QTYPE_QINT &&
4065 qobject_type(value) != QTYPE_QBOOL) {
4066 qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "bool");
4067 return -1;
4068 }
4069 if (qobject_type(value) == QTYPE_QBOOL) {
4070 /* handlers expect a QInt, they need to be changed */
4071 qdict_put(args, name,
4072 qint_from_int(qbool_get_int(qobject_to_qbool(value))));
4073 }
4074 break;
4075 default:
4076 /* impossible */
4077 abort();
4078 }
4079
4080 return 0;
4081}
4082
4083static void cmd_args_init(CmdArgs *cmd_args)
4084{
4085 cmd_args->name = qstring_new();
4086 cmd_args->type = cmd_args->flag = cmd_args->optional = 0;
4087}
4088
4089/*
4090 * This is not trivial, we have to parse Monitor command's argument
4091 * type syntax to be able to check the arguments provided by clients.
4092 *
4093 * In the near future we will be using an array for that and will be
4094 * able to drop all this parsing...
4095 */
4096static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
4097{
4098 int err;
4099 const char *p;
4100 CmdArgs cmd_args;
4101
Blue Swirldd5121b2009-12-04 20:52:02 +00004102 if (cmd->args_type == NULL) {
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004103 return (qdict_size(args) == 0 ? 0 : -1);
4104 }
4105
4106 err = 0;
4107 cmd_args_init(&cmd_args);
4108
4109 for (p = cmd->args_type;; p++) {
4110 if (*p == ':') {
4111 cmd_args.type = *++p;
4112 p++;
4113 if (cmd_args.type == '-') {
4114 cmd_args.flag = *p++;
4115 cmd_args.optional = 1;
4116 } else if (*p == '?') {
4117 cmd_args.optional = 1;
4118 p++;
4119 }
4120
4121 assert(*p == ',' || *p == '\0');
4122 err = check_arg(&cmd_args, args);
4123
4124 QDECREF(cmd_args.name);
4125 cmd_args_init(&cmd_args);
4126
4127 if (err < 0) {
4128 break;
4129 }
4130 } else {
4131 qstring_append_chr(cmd_args.name, *p);
4132 }
4133
4134 if (*p == '\0') {
4135 break;
4136 }
4137 }
4138
4139 QDECREF(cmd_args.name);
4140 return err;
4141}
4142
4143static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
4144{
4145 int err;
4146 QObject *obj;
4147 QDict *input, *args;
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004148 const mon_cmd_t *cmd;
4149 Monitor *mon = cur_mon;
Luiz Capitulino5e23f482009-11-26 22:59:02 -02004150 const char *cmd_name, *info_item;
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004151
4152 args = NULL;
4153 qemu_errors_to_mon(mon);
4154
4155 obj = json_parser_parse(tokens, NULL);
4156 if (!obj) {
4157 // FIXME: should be triggered in json_parser_parse()
4158 qemu_error_new(QERR_JSON_PARSING);
4159 goto err_out;
4160 } else if (qobject_type(obj) != QTYPE_QDICT) {
4161 qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "object");
4162 qobject_decref(obj);
4163 goto err_out;
4164 }
4165
4166 input = qobject_to_qdict(obj);
4167
4168 mon->mc->id = qdict_get(input, "id");
4169 qobject_incref(mon->mc->id);
4170
4171 obj = qdict_get(input, "execute");
4172 if (!obj) {
4173 qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "execute");
4174 goto err_input;
4175 } else if (qobject_type(obj) != QTYPE_QSTRING) {
4176 qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "string");
4177 goto err_input;
4178 }
4179
4180 cmd_name = qstring_get_str(qobject_to_qstring(obj));
Luiz Capitulino5e23f482009-11-26 22:59:02 -02004181
4182 /*
4183 * XXX: We need this special case until we get info handlers
4184 * converted into 'query-' commands
4185 */
4186 if (compare_cmd(cmd_name, "info")) {
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004187 qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
4188 goto err_input;
Luiz Capitulino5e23f482009-11-26 22:59:02 -02004189 } else if (strstart(cmd_name, "query-", &info_item)) {
4190 cmd = monitor_find_command("info");
4191 qdict_put_obj(input, "arguments",
4192 qobject_from_jsonf("{ 'item': %s }", info_item));
4193 } else {
4194 cmd = monitor_find_command(cmd_name);
Luiz Capitulino43e713c2009-12-18 13:24:59 -02004195 if (!cmd || !monitor_handler_ported(cmd)) {
Luiz Capitulino5e23f482009-11-26 22:59:02 -02004196 qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
4197 goto err_input;
4198 }
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004199 }
4200
4201 obj = qdict_get(input, "arguments");
4202 if (!obj) {
4203 args = qdict_new();
4204 } else {
4205 args = qobject_to_qdict(obj);
4206 QINCREF(args);
4207 }
4208
4209 QDECREF(input);
4210
4211 err = monitor_check_qmp_args(cmd, args);
4212 if (err < 0) {
4213 goto err_out;
4214 }
4215
Adam Litke940cc302010-01-25 12:18:44 -06004216 if (monitor_handler_is_async(cmd)) {
4217 qmp_async_cmd_handler(mon, cmd, args);
4218 } else {
4219 monitor_call_handler(mon, cmd, args);
4220 }
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004221 goto out;
4222
4223err_input:
4224 QDECREF(input);
4225err_out:
4226 monitor_protocol_emitter(mon, NULL);
4227out:
4228 QDECREF(args);
4229 qemu_errors_to_previous();
4230}
4231
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004232/**
4233 * monitor_control_read(): Read and handle QMP input
4234 */
4235static void monitor_control_read(void *opaque, const uint8_t *buf, int size)
4236{
4237 Monitor *old_mon = cur_mon;
4238
4239 cur_mon = opaque;
4240
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004241 json_message_parser_feed(&cur_mon->mc->parser, (const char *) buf, size);
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004242
4243 cur_mon = old_mon;
4244}
4245
aliguori731b0362009-03-05 23:01:42 +00004246static void monitor_read(void *opaque, const uint8_t *buf, int size)
bellard9dc39cb2004-03-14 21:38:27 +00004247{
aliguori731b0362009-03-05 23:01:42 +00004248 Monitor *old_mon = cur_mon;
bellard9dc39cb2004-03-14 21:38:27 +00004249 int i;
aliguori376253e2009-03-05 23:01:23 +00004250
aliguori731b0362009-03-05 23:01:42 +00004251 cur_mon = opaque;
bellard7e2515e2004-08-01 21:52:19 +00004252
aliguoricde76ee2009-03-05 23:01:51 +00004253 if (cur_mon->rs) {
4254 for (i = 0; i < size; i++)
4255 readline_handle_byte(cur_mon->rs, buf[i]);
4256 } else {
4257 if (size == 0 || buf[size - 1] != 0)
4258 monitor_printf(cur_mon, "corrupted command\n");
4259 else
Luiz Capitulinof3c157c2009-11-26 22:58:55 -02004260 handle_user_command(cur_mon, (char *)buf);
aliguoricde76ee2009-03-05 23:01:51 +00004261 }
aliguori731b0362009-03-05 23:01:42 +00004262
4263 cur_mon = old_mon;
4264}
aliguorid8f44602008-10-06 13:52:44 +00004265
aliguori376253e2009-03-05 23:01:23 +00004266static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
bellard7e2515e2004-08-01 21:52:19 +00004267{
aliguori731b0362009-03-05 23:01:42 +00004268 monitor_suspend(mon);
Luiz Capitulinof3c157c2009-11-26 22:58:55 -02004269 handle_user_command(mon, cmdline);
aliguori731b0362009-03-05 23:01:42 +00004270 monitor_resume(mon);
aliguorid8f44602008-10-06 13:52:44 +00004271}
4272
aliguoricde76ee2009-03-05 23:01:51 +00004273int monitor_suspend(Monitor *mon)
aliguorid8f44602008-10-06 13:52:44 +00004274{
aliguoricde76ee2009-03-05 23:01:51 +00004275 if (!mon->rs)
4276 return -ENOTTY;
aliguori731b0362009-03-05 23:01:42 +00004277 mon->suspend_cnt++;
aliguoricde76ee2009-03-05 23:01:51 +00004278 return 0;
aliguorid8f44602008-10-06 13:52:44 +00004279}
4280
aliguori376253e2009-03-05 23:01:23 +00004281void monitor_resume(Monitor *mon)
aliguorid8f44602008-10-06 13:52:44 +00004282{
aliguoricde76ee2009-03-05 23:01:51 +00004283 if (!mon->rs)
4284 return;
aliguori731b0362009-03-05 23:01:42 +00004285 if (--mon->suspend_cnt == 0)
4286 readline_show_prompt(mon->rs);
bellard7e2515e2004-08-01 21:52:19 +00004287}
4288
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004289/**
4290 * monitor_control_event(): Print QMP gretting
4291 */
4292static void monitor_control_event(void *opaque, int event)
4293{
4294 if (event == CHR_EVENT_OPENED) {
4295 QObject *data;
4296 Monitor *mon = opaque;
4297
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004298 json_message_parser_init(&mon->mc->parser, handle_qmp_command);
4299
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004300 data = qobject_from_jsonf("{ 'QMP': { 'capabilities': [] } }");
4301 assert(data != NULL);
4302
4303 monitor_json_emitter(mon, data);
4304 qobject_decref(data);
4305 }
4306}
4307
aliguori731b0362009-03-05 23:01:42 +00004308static void monitor_event(void *opaque, int event)
ths86e94de2007-01-05 22:01:59 +00004309{
aliguori376253e2009-03-05 23:01:23 +00004310 Monitor *mon = opaque;
4311
aliguori2724b182009-03-05 23:01:47 +00004312 switch (event) {
4313 case CHR_EVENT_MUX_IN:
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +02004314 mon->mux_out = 0;
4315 if (mon->reset_seen) {
4316 readline_restart(mon->rs);
4317 monitor_resume(mon);
4318 monitor_flush(mon);
4319 } else {
4320 mon->suspend_cnt = 0;
4321 }
aliguori2724b182009-03-05 23:01:47 +00004322 break;
ths86e94de2007-01-05 22:01:59 +00004323
aliguori2724b182009-03-05 23:01:47 +00004324 case CHR_EVENT_MUX_OUT:
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +02004325 if (mon->reset_seen) {
4326 if (mon->suspend_cnt == 0) {
4327 monitor_printf(mon, "\n");
4328 }
4329 monitor_flush(mon);
4330 monitor_suspend(mon);
4331 } else {
4332 mon->suspend_cnt++;
4333 }
4334 mon->mux_out = 1;
aliguori2724b182009-03-05 23:01:47 +00004335 break;
4336
Amit Shahb6b8df52009-10-07 18:31:16 +05304337 case CHR_EVENT_OPENED:
aliguori2724b182009-03-05 23:01:47 +00004338 monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
4339 "information\n", QEMU_VERSION);
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +02004340 if (!mon->mux_out) {
aliguori2724b182009-03-05 23:01:47 +00004341 readline_show_prompt(mon->rs);
Gerd Hoffmanna7aec5d2009-09-10 10:58:54 +02004342 }
4343 mon->reset_seen = 1;
aliguori2724b182009-03-05 23:01:47 +00004344 break;
4345 }
ths86e94de2007-01-05 22:01:59 +00004346}
4347
aliguori76655d62009-03-06 20:27:37 +00004348
4349/*
4350 * Local variables:
4351 * c-indent-level: 4
4352 * c-basic-offset: 4
4353 * tab-width: 8
4354 * End:
4355 */
4356
aliguori731b0362009-03-05 23:01:42 +00004357void monitor_init(CharDriverState *chr, int flags)
bellard9dc39cb2004-03-14 21:38:27 +00004358{
aliguori731b0362009-03-05 23:01:42 +00004359 static int is_first_init = 1;
aliguori87127162009-03-05 23:01:29 +00004360 Monitor *mon;
ths20d8a3e2007-02-18 17:04:49 +00004361
4362 if (is_first_init) {
balrogc8256f92008-06-08 22:45:01 +00004363 key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
ths20d8a3e2007-02-18 17:04:49 +00004364 is_first_init = 0;
4365 }
aliguori87127162009-03-05 23:01:29 +00004366
4367 mon = qemu_mallocz(sizeof(*mon));
ths20d8a3e2007-02-18 17:04:49 +00004368
aliguori87127162009-03-05 23:01:29 +00004369 mon->chr = chr;
aliguori731b0362009-03-05 23:01:42 +00004370 mon->flags = flags;
aliguoricde76ee2009-03-05 23:01:51 +00004371 if (flags & MONITOR_USE_READLINE) {
4372 mon->rs = readline_init(mon, monitor_find_completion);
4373 monitor_read_command(mon, 0);
4374 }
aliguori87127162009-03-05 23:01:29 +00004375
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004376 if (monitor_ctrl_mode(mon)) {
Luiz Capitulino5fa737a2009-11-26 22:59:01 -02004377 mon->mc = qemu_mallocz(sizeof(MonitorControl));
Luiz Capitulino9b57c022009-11-26 22:58:58 -02004378 /* Control mode requires special handlers */
4379 qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
4380 monitor_control_event, mon);
4381 } else {
4382 qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
4383 monitor_event, mon);
4384 }
aliguori87127162009-03-05 23:01:29 +00004385
Blue Swirl72cf2d42009-09-12 07:36:22 +00004386 QLIST_INSERT_HEAD(&mon_list, mon, entry);
aliguori731b0362009-03-05 23:01:42 +00004387 if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
aliguori87127162009-03-05 23:01:29 +00004388 cur_mon = mon;
bellard7e2515e2004-08-01 21:52:19 +00004389}
4390
aliguori376253e2009-03-05 23:01:23 +00004391static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
bellard7e2515e2004-08-01 21:52:19 +00004392{
aliguoribb5fc202009-03-05 23:01:15 +00004393 BlockDriverState *bs = opaque;
4394 int ret = 0;
bellard7e2515e2004-08-01 21:52:19 +00004395
aliguoribb5fc202009-03-05 23:01:15 +00004396 if (bdrv_set_key(bs, password) != 0) {
aliguori376253e2009-03-05 23:01:23 +00004397 monitor_printf(mon, "invalid password\n");
aliguoribb5fc202009-03-05 23:01:15 +00004398 ret = -EPERM;
bellard7e2515e2004-08-01 21:52:19 +00004399 }
aliguori731b0362009-03-05 23:01:42 +00004400 if (mon->password_completion_cb)
4401 mon->password_completion_cb(mon->password_opaque, ret);
aliguoribb5fc202009-03-05 23:01:15 +00004402
aliguori731b0362009-03-05 23:01:42 +00004403 monitor_read_command(mon, 1);
bellard9dc39cb2004-03-14 21:38:27 +00004404}
aliguoric0f4ce72009-03-05 23:01:01 +00004405
aliguori376253e2009-03-05 23:01:23 +00004406void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
aliguoribb5fc202009-03-05 23:01:15 +00004407 BlockDriverCompletionFunc *completion_cb,
4408 void *opaque)
aliguoric0f4ce72009-03-05 23:01:01 +00004409{
aliguoricde76ee2009-03-05 23:01:51 +00004410 int err;
4411
aliguoribb5fc202009-03-05 23:01:15 +00004412 if (!bdrv_key_required(bs)) {
4413 if (completion_cb)
4414 completion_cb(opaque, 0);
4415 return;
4416 }
aliguoric0f4ce72009-03-05 23:01:01 +00004417
Luiz Capitulino94171e12009-12-07 21:37:00 +01004418 if (monitor_ctrl_mode(mon)) {
4419 qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
4420 return;
4421 }
4422
aliguori376253e2009-03-05 23:01:23 +00004423 monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
4424 bdrv_get_encrypted_filename(bs));
aliguoribb5fc202009-03-05 23:01:15 +00004425
aliguori731b0362009-03-05 23:01:42 +00004426 mon->password_completion_cb = completion_cb;
4427 mon->password_opaque = opaque;
aliguoribb5fc202009-03-05 23:01:15 +00004428
aliguoricde76ee2009-03-05 23:01:51 +00004429 err = monitor_read_password(mon, bdrv_password_cb, bs);
4430
4431 if (err && completion_cb)
4432 completion_cb(opaque, err);
aliguoric0f4ce72009-03-05 23:01:01 +00004433}
Gerd Hoffmannac7531e2009-08-14 10:36:06 +02004434
4435typedef struct QemuErrorSink QemuErrorSink;
4436struct QemuErrorSink {
4437 enum {
4438 ERR_SINK_FILE,
4439 ERR_SINK_MONITOR,
4440 } dest;
4441 union {
4442 FILE *fp;
4443 Monitor *mon;
4444 };
4445 QemuErrorSink *previous;
4446};
4447
Blue Swirl528e93a2009-08-31 15:14:40 +00004448static QemuErrorSink *qemu_error_sink;
Gerd Hoffmannac7531e2009-08-14 10:36:06 +02004449
4450void qemu_errors_to_file(FILE *fp)
4451{
4452 QemuErrorSink *sink;
4453
4454 sink = qemu_mallocz(sizeof(*sink));
4455 sink->dest = ERR_SINK_FILE;
4456 sink->fp = fp;
4457 sink->previous = qemu_error_sink;
4458 qemu_error_sink = sink;
4459}
4460
4461void qemu_errors_to_mon(Monitor *mon)
4462{
4463 QemuErrorSink *sink;
4464
4465 sink = qemu_mallocz(sizeof(*sink));
4466 sink->dest = ERR_SINK_MONITOR;
4467 sink->mon = mon;
4468 sink->previous = qemu_error_sink;
4469 qemu_error_sink = sink;
4470}
4471
4472void qemu_errors_to_previous(void)
4473{
4474 QemuErrorSink *sink;
4475
4476 assert(qemu_error_sink != NULL);
4477 sink = qemu_error_sink;
4478 qemu_error_sink = sink->previous;
4479 qemu_free(sink);
4480}
4481
4482void qemu_error(const char *fmt, ...)
4483{
4484 va_list args;
4485
4486 assert(qemu_error_sink != NULL);
4487 switch (qemu_error_sink->dest) {
4488 case ERR_SINK_FILE:
4489 va_start(args, fmt);
4490 vfprintf(qemu_error_sink->fp, fmt, args);
4491 va_end(args);
4492 break;
4493 case ERR_SINK_MONITOR:
4494 va_start(args, fmt);
4495 monitor_vprintf(qemu_error_sink->mon, fmt, args);
4496 va_end(args);
4497 break;
4498 }
4499}
Luiz Capitulino8204a912009-11-18 23:05:31 -02004500
4501void qemu_error_internal(const char *file, int linenr, const char *func,
4502 const char *fmt, ...)
4503{
4504 va_list va;
4505 QError *qerror;
4506
4507 assert(qemu_error_sink != NULL);
4508
4509 va_start(va, fmt);
4510 qerror = qerror_from_info(file, linenr, func, fmt, &va);
4511 va_end(va);
4512
4513 switch (qemu_error_sink->dest) {
4514 case ERR_SINK_FILE:
4515 qerror_print(qerror);
4516 QDECREF(qerror);
4517 break;
4518 case ERR_SINK_MONITOR:
4519 assert(qemu_error_sink->mon->error == NULL);
4520 qemu_error_sink->mon->error = qerror;
4521 break;
4522 }
4523}