monitor.c 86.6 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU monitor
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24
#include <dirent.h>
P
pbrook 已提交
25 26 27 28 29 30 31 32 33
#include "hw/hw.h"
#include "hw/usb.h"
#include "hw/pcmcia.h"
#include "hw/pc.h"
#include "hw/pci.h"
#include "gdbstub.h"
#include "net.h"
#include "qemu-char.h"
#include "sysemu.h"
A
aliguori 已提交
34 35
#include "monitor.h"
#include "readline.h"
P
pbrook 已提交
36 37 38
#include "console.h"
#include "block.h"
#include "audio/audio.h"
39
#include "disas.h"
A
aliguori 已提交
40
#include "balloon.h"
41
#include "qemu-timer.h"
A
aliguori 已提交
42
#include "migration.h"
A
aliguori 已提交
43
#include "kvm.h"
44
#include "acl.h"
T
ths 已提交
45

B
bellard 已提交
46
//#define DEBUG
B
bellard 已提交
47
//#define DEBUG_COMPLETION
B
bellard 已提交
48

49 50
/*
 * Supported types:
51
 *
52
 * 'F'          filename
B
bellard 已提交
53
 * 'B'          block device name
54
 * 's'          string (accept optional quote)
B
bellard 已提交
55 56
 * 'i'          32 bit integer
 * 'l'          target long (32 or 64 bit)
57 58 59 60 61 62
 * '/'          optional gdb-like print format (like "/10x")
 *
 * '?'          optional type (for 'F', 's' and 'i')
 *
 */

A
aliguori 已提交
63
typedef struct mon_cmd_t {
B
bellard 已提交
64
    const char *name;
65
    const char *args_type;
66
    void *handler;
B
bellard 已提交
67 68
    const char *params;
    const char *help;
A
aliguori 已提交
69
} mon_cmd_t;
B
bellard 已提交
70

71 72
struct Monitor {
    CharDriverState *chr;
73 74 75 76 77 78 79 80
    int flags;
    int suspend_cnt;
    uint8_t outbuf[1024];
    int outbuf_index;
    ReadLineState *rs;
    CPUState *mon_cpu;
    BlockDriverCompletionFunc *password_completion_cb;
    void *password_opaque;
81 82 83 84
    LIST_ENTRY(Monitor) entry;
};

static LIST_HEAD(mon_list, Monitor) mon_list;
85

A
aliguori 已提交
86 87
static const mon_cmd_t mon_cmds[];
static const mon_cmd_t info_cmds[];
B
bellard 已提交
88

89
Monitor *cur_mon = NULL;
A
aliguori 已提交
90

91 92
static void monitor_command_cb(Monitor *mon, const char *cmdline,
                               void *opaque);
93

94 95 96 97 98 99
static void monitor_read_command(Monitor *mon, int show_prompt)
{
    readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
    if (show_prompt)
        readline_show_prompt(mon->rs);
}
B
bellard 已提交
100

101 102
static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
                                 void *opaque)
103
{
104 105 106 107 108 109 110 111
    if (mon->rs) {
        readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
        /* prompt is printed on return from the command handler */
        return 0;
    } else {
        monitor_printf(mon, "terminal does not support password prompting\n");
        return -ENOTTY;
    }
112 113
}

A
aliguori 已提交
114
void monitor_flush(Monitor *mon)
115
{
116 117 118
    if (mon && mon->outbuf_index != 0 && mon->chr->focus == 0) {
        qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
        mon->outbuf_index = 0;
119 120 121 122
    }
}

/* flush at every end of line or if the buffer is full */
A
aliguori 已提交
123
static void monitor_puts(Monitor *mon, const char *str)
124
{
T
ths 已提交
125
    char c;
126 127 128 129

    if (!mon)
        return;

130 131 132 133
    for(;;) {
        c = *str++;
        if (c == '\0')
            break;
B
bellard 已提交
134
        if (c == '\n')
135 136 137 138
            mon->outbuf[mon->outbuf_index++] = '\r';
        mon->outbuf[mon->outbuf_index++] = c;
        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
            || c == '\n')
A
aliguori 已提交
139
            monitor_flush(mon);
140 141 142
    }
}

A
aliguori 已提交
143
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
B
bellard 已提交
144
{
B
bellard 已提交
145 146
    char buf[4096];
    vsnprintf(buf, sizeof(buf), fmt, ap);
A
aliguori 已提交
147
    monitor_puts(mon, buf);
B
bellard 已提交
148 149
}

A
aliguori 已提交
150
void monitor_printf(Monitor *mon, const char *fmt, ...)
B
bellard 已提交
151
{
152 153
    va_list ap;
    va_start(ap, fmt);
A
aliguori 已提交
154
    monitor_vprintf(mon, fmt, ap);
155
    va_end(ap);
B
bellard 已提交
156 157
}

A
aliguori 已提交
158
void monitor_print_filename(Monitor *mon, const char *filename)
159 160 161 162
{
    int i;

    for (i = 0; filename[i]; i++) {
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        switch (filename[i]) {
        case ' ':
        case '"':
        case '\\':
            monitor_printf(mon, "\\%c", filename[i]);
            break;
        case '\t':
            monitor_printf(mon, "\\t");
            break;
        case '\r':
            monitor_printf(mon, "\\r");
            break;
        case '\n':
            monitor_printf(mon, "\\n");
            break;
        default:
            monitor_printf(mon, "%c", filename[i]);
            break;
        }
182 183 184
    }
}

B
bellard 已提交
185 186 187 188
static int monitor_fprintf(FILE *stream, const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
A
aliguori 已提交
189
    monitor_vprintf((Monitor *)stream, fmt, ap);
B
bellard 已提交
190 191 192 193
    va_end(ap);
    return 0;
}

B
bellard 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
static int compare_cmd(const char *name, const char *list)
{
    const char *p, *pstart;
    int len;
    len = strlen(name);
    p = list;
    for(;;) {
        pstart = p;
        p = strchr(p, '|');
        if (!p)
            p = pstart + strlen(pstart);
        if ((p - pstart) == len && !memcmp(pstart, name, len))
            return 1;
        if (*p == '\0')
            break;
        p++;
    }
    return 0;
}

A
aliguori 已提交
214 215
static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
                          const char *prefix, const char *name)
B
bellard 已提交
216
{
A
aliguori 已提交
217
    const mon_cmd_t *cmd;
B
bellard 已提交
218 219 220

    for(cmd = cmds; cmd->name != NULL; cmd++) {
        if (!name || !strcmp(name, cmd->name))
A
aliguori 已提交
221 222
            monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name,
                           cmd->params, cmd->help);
B
bellard 已提交
223 224 225
    }
}

A
aliguori 已提交
226
static void help_cmd(Monitor *mon, const char *name)
B
bellard 已提交
227 228
{
    if (name && !strcmp(name, "info")) {
A
aliguori 已提交
229
        help_cmd_dump(mon, info_cmds, "info ", NULL);
B
bellard 已提交
230
    } else {
A
aliguori 已提交
231
        help_cmd_dump(mon, mon_cmds, "", name);
232
        if (name && !strcmp(name, "log")) {
B
blueswir1 已提交
233
            const CPULogItem *item;
A
aliguori 已提交
234 235
            monitor_printf(mon, "Log items (comma separated):\n");
            monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
236
            for(item = cpu_log_items; item->mask != 0; item++) {
A
aliguori 已提交
237
                monitor_printf(mon, "%-10s %s\n", item->name, item->help);
238 239
            }
        }
B
bellard 已提交
240 241 242
    }
}

A
aliguori 已提交
243
static void do_commit(Monitor *mon, const char *device)
B
bellard 已提交
244
{
B
bellard 已提交
245
    int i, all_devices;
246

B
bellard 已提交
247
    all_devices = !strcmp(device, "all");
T
ths 已提交
248
    for (i = 0; i < nb_drives; i++) {
249
            if (all_devices ||
T
ths 已提交
250 251
                !strcmp(bdrv_get_device_name(drives_table[i].bdrv), device))
                bdrv_commit(drives_table[i].bdrv);
B
bellard 已提交
252 253 254
    }
}

A
aliguori 已提交
255
static void do_info(Monitor *mon, const char *item)
B
bellard 已提交
256
{
A
aliguori 已提交
257 258
    const mon_cmd_t *cmd;
    void (*handler)(Monitor *);
B
bellard 已提交
259

260
    if (!item)
B
bellard 已提交
261 262
        goto help;
    for(cmd = info_cmds; cmd->name != NULL; cmd++) {
263
        if (compare_cmd(item, cmd->name))
B
bellard 已提交
264 265 266
            goto found;
    }
 help:
A
aliguori 已提交
267
    help_cmd(mon, "info");
B
bellard 已提交
268 269
    return;
 found:
270
    handler = cmd->handler;
A
aliguori 已提交
271
    handler(mon);
B
bellard 已提交
272 273
}

A
aliguori 已提交
274
static void do_info_version(Monitor *mon)
B
bellard 已提交
275
{
A
aliguori 已提交
276
    monitor_printf(mon, "%s\n", QEMU_VERSION);
B
bellard 已提交
277 278
}

A
aliguori 已提交
279
static void do_info_name(Monitor *mon)
T
ths 已提交
280 281
{
    if (qemu_name)
A
aliguori 已提交
282
        monitor_printf(mon, "%s\n", qemu_name);
T
ths 已提交
283 284
}

A
aurel32 已提交
285
#if defined(TARGET_I386)
A
aliguori 已提交
286
static void do_info_hpet(Monitor *mon)
A
aliguori 已提交
287
{
A
aliguori 已提交
288 289
    monitor_printf(mon, "HPET is %s by QEMU\n",
                   (no_hpet) ? "disabled" : "enabled");
A
aliguori 已提交
290
}
A
aurel32 已提交
291
#endif
A
aliguori 已提交
292

A
aliguori 已提交
293
static void do_info_uuid(Monitor *mon)
294
{
A
aliguori 已提交
295 296 297 298 299
    monitor_printf(mon, UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1],
                   qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
                   qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
                   qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
                   qemu_uuid[14], qemu_uuid[15]);
300 301
}

B
bellard 已提交
302
/* get the current CPU defined by the user */
303
static int mon_set_cpu(int cpu_index)
B
bellard 已提交
304 305 306 307 308
{
    CPUState *env;

    for(env = first_cpu; env != NULL; env = env->next_cpu) {
        if (env->cpu_index == cpu_index) {
309
            cur_mon->mon_cpu = env;
B
bellard 已提交
310 311 312 313 314 315
            return 0;
        }
    }
    return -1;
}

316
static CPUState *mon_get_cpu(void)
B
bellard 已提交
317
{
318
    if (!cur_mon->mon_cpu) {
B
bellard 已提交
319 320
        mon_set_cpu(0);
    }
321
    cpu_synchronize_state(cur_mon->mon_cpu, 0);
322
    return cur_mon->mon_cpu;
B
bellard 已提交
323 324
}

A
aliguori 已提交
325
static void do_info_registers(Monitor *mon)
326
{
B
bellard 已提交
327 328 329 330
    CPUState *env;
    env = mon_get_cpu();
    if (!env)
        return;
331
#ifdef TARGET_I386
A
aliguori 已提交
332
    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
B
bellard 已提交
333
                   X86_DUMP_FPU);
334
#else
A
aliguori 已提交
335
    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
B
bellard 已提交
336
                   0);
337 338 339
#endif
}

A
aliguori 已提交
340
static void do_info_cpus(Monitor *mon)
B
bellard 已提交
341 342 343 344 345 346 347
{
    CPUState *env;

    /* just to set the default cpu if not already done */
    mon_get_cpu();

    for(env = first_cpu; env != NULL; env = env->next_cpu) {
348
        cpu_synchronize_state(env, 0);
A
aliguori 已提交
349
        monitor_printf(mon, "%c CPU #%d:",
350
                       (env == mon->mon_cpu) ? '*' : ' ',
A
aliguori 已提交
351
                       env->cpu_index);
B
bellard 已提交
352
#if defined(TARGET_I386)
A
aliguori 已提交
353 354
        monitor_printf(mon, " pc=0x" TARGET_FMT_lx,
                       env->eip + env->segs[R_CS].base);
B
bellard 已提交
355
#elif defined(TARGET_PPC)
A
aliguori 已提交
356
        monitor_printf(mon, " nip=0x" TARGET_FMT_lx, env->nip);
B
bellard 已提交
357
#elif defined(TARGET_SPARC)
A
aliguori 已提交
358 359
        monitor_printf(mon, " pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx,
                       env->pc, env->npc);
360
#elif defined(TARGET_MIPS)
A
aliguori 已提交
361
        monitor_printf(mon, " PC=0x" TARGET_FMT_lx, env->active_tc.PC);
B
bellard 已提交
362
#endif
363
        if (env->halted)
A
aliguori 已提交
364 365
            monitor_printf(mon, " (halted)");
        monitor_printf(mon, "\n");
B
bellard 已提交
366 367 368
    }
}

A
aliguori 已提交
369
static void do_cpu_set(Monitor *mon, int index)
B
bellard 已提交
370 371
{
    if (mon_set_cpu(index) < 0)
A
aliguori 已提交
372
        monitor_printf(mon, "Invalid CPU index\n");
B
bellard 已提交
373 374
}

A
aliguori 已提交
375
static void do_info_jit(Monitor *mon)
B
bellard 已提交
376
{
A
aliguori 已提交
377
    dump_exec_info((FILE *)mon, monitor_fprintf);
B
bellard 已提交
378 379
}

A
aliguori 已提交
380
static void do_info_history(Monitor *mon)
B
bellard 已提交
381 382
{
    int i;
383
    const char *str;
384

385 386
    if (!mon->rs)
        return;
387 388
    i = 0;
    for(;;) {
389
        str = readline_get_history(mon->rs, i);
390 391
        if (!str)
            break;
A
aliguori 已提交
392
        monitor_printf(mon, "%d: '%s'\n", i, str);
B
bellard 已提交
393
        i++;
B
bellard 已提交
394 395 396
    }
}

397 398
#if defined(TARGET_PPC)
/* XXX: not implemented in other targets */
A
aliguori 已提交
399
static void do_info_cpu_stats(Monitor *mon)
400 401 402 403
{
    CPUState *env;

    env = mon_get_cpu();
A
aliguori 已提交
404
    cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
405 406 407
}
#endif

A
aliguori 已提交
408
static void do_quit(Monitor *mon)
B
bellard 已提交
409 410 411 412
{
    exit(0);
}

A
aliguori 已提交
413
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
B
bellard 已提交
414 415 416 417
{
    if (bdrv_is_inserted(bs)) {
        if (!force) {
            if (!bdrv_is_removable(bs)) {
A
aliguori 已提交
418
                monitor_printf(mon, "device is not removable\n");
B
bellard 已提交
419 420 421
                return -1;
            }
            if (bdrv_is_locked(bs)) {
A
aliguori 已提交
422
                monitor_printf(mon, "device is locked\n");
B
bellard 已提交
423 424 425 426 427 428 429 430
                return -1;
            }
        }
        bdrv_close(bs);
    }
    return 0;
}

A
aliguori 已提交
431
static void do_eject(Monitor *mon, int force, const char *filename)
B
bellard 已提交
432 433 434
{
    BlockDriverState *bs;

435
    bs = bdrv_find(filename);
B
bellard 已提交
436
    if (!bs) {
A
aliguori 已提交
437
        monitor_printf(mon, "device not found\n");
B
bellard 已提交
438 439
        return;
    }
A
aliguori 已提交
440
    eject_device(mon, bs, force);
B
bellard 已提交
441 442
}

A
aliguori 已提交
443 444
static void do_change_block(Monitor *mon, const char *device,
                            const char *filename, const char *fmt)
B
bellard 已提交
445 446
{
    BlockDriverState *bs;
447
    BlockDriver *drv = NULL;
B
bellard 已提交
448

449
    bs = bdrv_find(device);
B
bellard 已提交
450
    if (!bs) {
A
aliguori 已提交
451
        monitor_printf(mon, "device not found\n");
B
bellard 已提交
452 453
        return;
    }
454 455 456
    if (fmt) {
        drv = bdrv_find_format(fmt);
        if (!drv) {
A
aliguori 已提交
457
            monitor_printf(mon, "invalid format %s\n", fmt);
458 459 460
            return;
        }
    }
A
aliguori 已提交
461
    if (eject_device(mon, bs, 0) < 0)
B
bellard 已提交
462
        return;
463
    bdrv_open2(bs, filename, 0, drv);
A
aliguori 已提交
464
    monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
465 466
}

A
aliguori 已提交
467 468
static void change_vnc_password_cb(Monitor *mon, const char *password,
                                   void *opaque)
469 470
{
    if (vnc_display_password(NULL, password) < 0)
A
aliguori 已提交
471
        monitor_printf(mon, "could not set VNC server password\n");
472

473
    monitor_read_command(mon, 1);
B
bellard 已提交
474 475
}

A
aliguori 已提交
476
static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
477
{
478
    if (strcmp(target, "passwd") == 0 ||
479 480
        strcmp(target, "password") == 0) {
        if (arg) {
481
            char password[9];
482 483
            strncpy(password, arg, sizeof(password));
            password[sizeof(password) - 1] = '\0';
A
aliguori 已提交
484
            change_vnc_password_cb(mon, password, NULL);
485
        } else {
A
aliguori 已提交
486
            monitor_read_password(mon, change_vnc_password_cb, NULL);
487
        }
488
    } else {
489
        if (vnc_display_open(NULL, target) < 0)
A
aliguori 已提交
490
            monitor_printf(mon, "could not start VNC server on %s\n", target);
491
    }
492 493
}

A
aliguori 已提交
494 495
static void do_change(Monitor *mon, const char *device, const char *target,
                      const char *arg)
496 497
{
    if (strcmp(device, "vnc") == 0) {
498
        do_change_vnc(mon, target, arg);
499
    } else {
500
        do_change_block(mon, device, target, arg);
501 502 503
    }
}

A
aliguori 已提交
504
static void do_screen_dump(Monitor *mon, const char *filename)
B
bellard 已提交
505
{
P
pbrook 已提交
506
    vga_hw_screen_dump(filename);
B
bellard 已提交
507 508
}

A
aliguori 已提交
509
static void do_logfile(Monitor *mon, const char *filename)
P
pbrook 已提交
510 511 512 513
{
    cpu_set_log_filename(filename);
}

A
aliguori 已提交
514
static void do_log(Monitor *mon, const char *items)
515 516
{
    int mask;
517

518
    if (!strcmp(items, "none")) {
519 520
        mask = 0;
    } else {
521
        mask = cpu_str_to_log_mask(items);
522
        if (!mask) {
A
aliguori 已提交
523
            help_cmd(mon, "log");
524 525 526 527 528 529
            return;
        }
    }
    cpu_set_log(mask);
}

A
aliguori 已提交
530
static void do_stop(Monitor *mon)
531 532 533 534
{
    vm_stop(EXCP_INTERRUPT);
}

535
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
536

A
aliguori 已提交
537 538 539 540 541 542
struct bdrv_iterate_context {
    Monitor *mon;
    int err;
};

static void do_cont(Monitor *mon)
543
{
A
aliguori 已提交
544
    struct bdrv_iterate_context context = { mon, 0 };
545

A
aliguori 已提交
546
    bdrv_iterate(encrypted_bdrv_it, &context);
547
    /* only resume the vm if all keys are set and valid */
A
aliguori 已提交
548
    if (!context.err)
549
        vm_start();
550 551
}

552 553
static void bdrv_key_cb(void *opaque, int err)
{
A
aliguori 已提交
554 555
    Monitor *mon = opaque;

556 557
    /* another key was set successfully, retry to continue */
    if (!err)
A
aliguori 已提交
558
        do_cont(mon);
559 560 561 562
}

static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
{
A
aliguori 已提交
563
    struct bdrv_iterate_context *context = opaque;
564

A
aliguori 已提交
565 566 567 568
    if (!context->err && bdrv_key_required(bs)) {
        context->err = -EBUSY;
        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
                                    context->mon);
569 570 571
    }
}

B
bellard 已提交
572
#ifdef CONFIG_GDBSTUB
573 574 575 576 577 578 579 580
static void do_gdbserver(Monitor *mon, const char *device)
{
    if (!device)
        device = "tcp::" DEFAULT_GDBSTUB_PORT;
    if (gdbserver_start(device) < 0) {
        monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
                       device);
    } else if (strcmp(device, "none") == 0) {
581
        monitor_printf(mon, "Disabled gdbserver\n");
582
    } else {
583 584
        monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
                       device);
585 586
    }
}
B
bellard 已提交
587
#endif
588

A
aliguori 已提交
589
static void monitor_printc(Monitor *mon, int c)
590
{
A
aliguori 已提交
591
    monitor_printf(mon, "'");
592 593
    switch(c) {
    case '\'':
A
aliguori 已提交
594
        monitor_printf(mon, "\\'");
595 596
        break;
    case '\\':
A
aliguori 已提交
597
        monitor_printf(mon, "\\\\");
598 599
        break;
    case '\n':
A
aliguori 已提交
600
        monitor_printf(mon, "\\n");
601 602
        break;
    case '\r':
A
aliguori 已提交
603
        monitor_printf(mon, "\\r");
604 605 606
        break;
    default:
        if (c >= 32 && c <= 126) {
A
aliguori 已提交
607
            monitor_printf(mon, "%c", c);
608
        } else {
A
aliguori 已提交
609
            monitor_printf(mon, "\\x%02x", c);
610 611 612
        }
        break;
    }
A
aliguori 已提交
613
    monitor_printf(mon, "'");
614 615
}

A
aliguori 已提交
616
static void memory_dump(Monitor *mon, int count, int format, int wsize,
617
                        target_phys_addr_t addr, int is_physical)
618
{
B
bellard 已提交
619
    CPUState *env;
620 621 622 623 624 625 626
    int nb_per_line, l, line_size, i, max_digits, len;
    uint8_t buf[16];
    uint64_t v;

    if (format == 'i') {
        int flags;
        flags = 0;
B
bellard 已提交
627 628 629
        env = mon_get_cpu();
        if (!env && !is_physical)
            return;
630
#ifdef TARGET_I386
631
        if (wsize == 2) {
632
            flags = 1;
633 634 635
        } else if (wsize == 4) {
            flags = 0;
        } else {
B
bellard 已提交
636
            /* as default we use the current CS size */
637
            flags = 0;
B
bellard 已提交
638 639
            if (env) {
#ifdef TARGET_X86_64
640
                if ((env->efer & MSR_EFER_LMA) &&
B
bellard 已提交
641 642 643 644 645 646 647
                    (env->segs[R_CS].flags & DESC_L_MASK))
                    flags = 2;
                else
#endif
                if (!(env->segs[R_CS].flags & DESC_B_MASK))
                    flags = 1;
            }
648 649
        }
#endif
A
aliguori 已提交
650
        monitor_disas(mon, env, addr, count, is_physical, flags);
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
        return;
    }

    len = wsize * count;
    if (wsize == 1)
        line_size = 8;
    else
        line_size = 16;
    nb_per_line = line_size / wsize;
    max_digits = 0;

    switch(format) {
    case 'o':
        max_digits = (wsize * 8 + 2) / 3;
        break;
    default:
    case 'x':
        max_digits = (wsize * 8) / 4;
        break;
    case 'u':
    case 'd':
        max_digits = (wsize * 8 * 10 + 32) / 33;
        break;
    case 'c':
        wsize = 1;
        break;
    }

    while (len > 0) {
680
        if (is_physical)
A
aliguori 已提交
681
            monitor_printf(mon, TARGET_FMT_plx ":", addr);
682
        else
A
aliguori 已提交
683
            monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
684 685 686 687 688 689
        l = len;
        if (l > line_size)
            l = line_size;
        if (is_physical) {
            cpu_physical_memory_rw(addr, buf, l, 0);
        } else {
B
bellard 已提交
690 691 692
            env = mon_get_cpu();
            if (!env)
                break;
693
            if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
A
aliguori 已提交
694
                monitor_printf(mon, " Cannot access memory\n");
695 696
                break;
            }
697
        }
698
        i = 0;
699 700 701 702 703 704 705 706 707 708
        while (i < l) {
            switch(wsize) {
            default:
            case 1:
                v = ldub_raw(buf + i);
                break;
            case 2:
                v = lduw_raw(buf + i);
                break;
            case 4:
B
bellard 已提交
709
                v = (uint32_t)ldl_raw(buf + i);
710 711 712 713 714
                break;
            case 8:
                v = ldq_raw(buf + i);
                break;
            }
A
aliguori 已提交
715
            monitor_printf(mon, " ");
716 717
            switch(format) {
            case 'o':
A
aliguori 已提交
718
                monitor_printf(mon, "%#*" PRIo64, max_digits, v);
719 720
                break;
            case 'x':
A
aliguori 已提交
721
                monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
722 723
                break;
            case 'u':
A
aliguori 已提交
724
                monitor_printf(mon, "%*" PRIu64, max_digits, v);
725 726
                break;
            case 'd':
A
aliguori 已提交
727
                monitor_printf(mon, "%*" PRId64, max_digits, v);
728 729
                break;
            case 'c':
A
aliguori 已提交
730
                monitor_printc(mon, v);
731 732 733 734
                break;
            }
            i += wsize;
        }
A
aliguori 已提交
735
        monitor_printf(mon, "\n");
736 737 738 739 740
        addr += l;
        len -= l;
    }
}

B
bellard 已提交
741 742 743 744 745 746
#if TARGET_LONG_BITS == 64
#define GET_TLONG(h, l) (((uint64_t)(h) << 32) | (l))
#else
#define GET_TLONG(h, l) (l)
#endif

A
aliguori 已提交
747
static void do_memory_dump(Monitor *mon, int count, int format, int size,
B
bellard 已提交
748
                           uint32_t addrh, uint32_t addrl)
749
{
B
bellard 已提交
750
    target_long addr = GET_TLONG(addrh, addrl);
A
aliguori 已提交
751
    memory_dump(mon, count, format, size, addr, 0);
752 753
}

754 755 756 757 758 759
#if TARGET_PHYS_ADDR_BITS > 32
#define GET_TPHYSADDR(h, l) (((uint64_t)(h) << 32) | (l))
#else
#define GET_TPHYSADDR(h, l) (l)
#endif

A
aliguori 已提交
760 761
static void do_physical_memory_dump(Monitor *mon, int count, int format,
                                    int size, uint32_t addrh, uint32_t addrl)
B
bellard 已提交
762

763
{
764
    target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
A
aliguori 已提交
765
    memory_dump(mon, count, format, size, addr, 1);
766 767
}

A
aliguori 已提交
768 769
static void do_print(Monitor *mon, int count, int format, int size,
                     unsigned int valh, unsigned int vall)
770
{
771 772
    target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
#if TARGET_PHYS_ADDR_BITS == 32
773 774
    switch(format) {
    case 'o':
A
aliguori 已提交
775
        monitor_printf(mon, "%#o", val);
776 777
        break;
    case 'x':
A
aliguori 已提交
778
        monitor_printf(mon, "%#x", val);
779 780
        break;
    case 'u':
A
aliguori 已提交
781
        monitor_printf(mon, "%u", val);
782 783 784
        break;
    default:
    case 'd':
A
aliguori 已提交
785
        monitor_printf(mon, "%d", val);
786 787
        break;
    case 'c':
A
aliguori 已提交
788
        monitor_printc(mon, val);
789 790
        break;
    }
B
bellard 已提交
791 792 793
#else
    switch(format) {
    case 'o':
A
aliguori 已提交
794
        monitor_printf(mon, "%#" PRIo64, val);
B
bellard 已提交
795 796
        break;
    case 'x':
A
aliguori 已提交
797
        monitor_printf(mon, "%#" PRIx64, val);
B
bellard 已提交
798 799
        break;
    case 'u':
A
aliguori 已提交
800
        monitor_printf(mon, "%" PRIu64, val);
B
bellard 已提交
801 802 803
        break;
    default:
    case 'd':
A
aliguori 已提交
804
        monitor_printf(mon, "%" PRId64, val);
B
bellard 已提交
805 806
        break;
    case 'c':
A
aliguori 已提交
807
        monitor_printc(mon, val);
B
bellard 已提交
808 809 810
        break;
    }
#endif
A
aliguori 已提交
811
    monitor_printf(mon, "\n");
812 813
}

A
aliguori 已提交
814
static void do_memory_save(Monitor *mon, unsigned int valh, unsigned int vall,
B
bellard 已提交
815 816 817 818 819 820 821 822 823 824 825 826 827 828
                           uint32_t size, const char *filename)
{
    FILE *f;
    target_long addr = GET_TLONG(valh, vall);
    uint32_t l;
    CPUState *env;
    uint8_t buf[1024];

    env = mon_get_cpu();
    if (!env)
        return;

    f = fopen(filename, "wb");
    if (!f) {
A
aliguori 已提交
829
        monitor_printf(mon, "could not open '%s'\n", filename);
B
bellard 已提交
830 831 832 833 834 835 836 837 838 839 840 841 842 843
        return;
    }
    while (size != 0) {
        l = sizeof(buf);
        if (l > size)
            l = size;
        cpu_memory_rw_debug(env, addr, buf, l, 0);
        fwrite(buf, 1, l, f);
        addr += l;
        size -= l;
    }
    fclose(f);
}

A
aliguori 已提交
844 845 846
static void do_physical_memory_save(Monitor *mon, unsigned int valh,
                                    unsigned int vall, uint32_t size,
                                    const char *filename)
A
aurel32 已提交
847 848 849 850
{
    FILE *f;
    uint32_t l;
    uint8_t buf[1024];
851
    target_phys_addr_t addr = GET_TPHYSADDR(valh, vall); 
A
aurel32 已提交
852 853 854

    f = fopen(filename, "wb");
    if (!f) {
A
aliguori 已提交
855
        monitor_printf(mon, "could not open '%s'\n", filename);
A
aurel32 已提交
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
        return;
    }
    while (size != 0) {
        l = sizeof(buf);
        if (l > size)
            l = size;
        cpu_physical_memory_rw(addr, buf, l, 0);
        fwrite(buf, 1, l, f);
        fflush(f);
        addr += l;
        size -= l;
    }
    fclose(f);
}

A
aliguori 已提交
871
static void do_sum(Monitor *mon, uint32_t start, uint32_t size)
B
bellard 已提交
872 873 874 875 876 877 878 879 880 881 882 883
{
    uint32_t addr;
    uint8_t buf[1];
    uint16_t sum;

    sum = 0;
    for(addr = start; addr < (start + size); addr++) {
        cpu_physical_memory_rw(addr, buf, 1, 0);
        /* BSD sum algorithm ('sum' Unix command) */
        sum = (sum >> 1) | (sum << 15);
        sum += buf[0];
    }
A
aliguori 已提交
884
    monitor_printf(mon, "%05d\n", sum);
B
bellard 已提交
885 886
}

B
bellard 已提交
887 888 889 890 891 892 893 894
typedef struct {
    int keycode;
    const char *name;
} KeyDef;

static const KeyDef key_defs[] = {
    { 0x2a, "shift" },
    { 0x36, "shift_r" },
895

B
bellard 已提交
896 897
    { 0x38, "alt" },
    { 0xb8, "alt_r" },
898 899
    { 0x64, "altgr" },
    { 0xe4, "altgr_r" },
B
bellard 已提交
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
    { 0x1d, "ctrl" },
    { 0x9d, "ctrl_r" },

    { 0xdd, "menu" },

    { 0x01, "esc" },

    { 0x02, "1" },
    { 0x03, "2" },
    { 0x04, "3" },
    { 0x05, "4" },
    { 0x06, "5" },
    { 0x07, "6" },
    { 0x08, "7" },
    { 0x09, "8" },
    { 0x0a, "9" },
    { 0x0b, "0" },
917 918
    { 0x0c, "minus" },
    { 0x0d, "equal" },
B
bellard 已提交
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
    { 0x0e, "backspace" },

    { 0x0f, "tab" },
    { 0x10, "q" },
    { 0x11, "w" },
    { 0x12, "e" },
    { 0x13, "r" },
    { 0x14, "t" },
    { 0x15, "y" },
    { 0x16, "u" },
    { 0x17, "i" },
    { 0x18, "o" },
    { 0x19, "p" },

    { 0x1c, "ret" },

    { 0x1e, "a" },
    { 0x1f, "s" },
    { 0x20, "d" },
    { 0x21, "f" },
    { 0x22, "g" },
    { 0x23, "h" },
    { 0x24, "j" },
    { 0x25, "k" },
    { 0x26, "l" },

    { 0x2c, "z" },
    { 0x2d, "x" },
    { 0x2e, "c" },
    { 0x2f, "v" },
    { 0x30, "b" },
    { 0x31, "n" },
    { 0x32, "m" },
952 953 954
    { 0x33, "comma" },
    { 0x34, "dot" },
    { 0x35, "slash" },
955

B
balrog 已提交
956 957
    { 0x37, "asterisk" },

B
bellard 已提交
958
    { 0x39, "spc" },
B
bellard 已提交
959
    { 0x3a, "caps_lock" },
B
bellard 已提交
960 961 962 963 964 965 966 967 968 969
    { 0x3b, "f1" },
    { 0x3c, "f2" },
    { 0x3d, "f3" },
    { 0x3e, "f4" },
    { 0x3f, "f5" },
    { 0x40, "f6" },
    { 0x41, "f7" },
    { 0x42, "f8" },
    { 0x43, "f9" },
    { 0x44, "f10" },
B
bellard 已提交
970
    { 0x45, "num_lock" },
B
bellard 已提交
971 972
    { 0x46, "scroll_lock" },

973 974
    { 0xb5, "kp_divide" },
    { 0x37, "kp_multiply" },
T
ths 已提交
975
    { 0x4a, "kp_subtract" },
976 977 978
    { 0x4e, "kp_add" },
    { 0x9c, "kp_enter" },
    { 0x53, "kp_decimal" },
979
    { 0x54, "sysrq" },
980 981 982 983 984 985 986 987 988 989 990

    { 0x52, "kp_0" },
    { 0x4f, "kp_1" },
    { 0x50, "kp_2" },
    { 0x51, "kp_3" },
    { 0x4b, "kp_4" },
    { 0x4c, "kp_5" },
    { 0x4d, "kp_6" },
    { 0x47, "kp_7" },
    { 0x48, "kp_8" },
    { 0x49, "kp_9" },
991

B
bellard 已提交
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
    { 0x56, "<" },

    { 0x57, "f11" },
    { 0x58, "f12" },

    { 0xb7, "print" },

    { 0xc7, "home" },
    { 0xc9, "pgup" },
    { 0xd1, "pgdn" },
    { 0xcf, "end" },

    { 0xcb, "left" },
    { 0xc8, "up" },
    { 0xd0, "down" },
    { 0xcd, "right" },

    { 0xd2, "insert" },
    { 0xd3, "delete" },
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
    { 0xf0, "stop" },
    { 0xf1, "again" },
    { 0xf2, "props" },
    { 0xf3, "undo" },
    { 0xf4, "front" },
    { 0xf5, "copy" },
    { 0xf6, "open" },
    { 0xf7, "paste" },
    { 0xf8, "find" },
    { 0xf9, "cut" },
    { 0xfa, "lf" },
    { 0xfb, "help" },
    { 0xfc, "meta_l" },
    { 0xfd, "meta_r" },
    { 0xfe, "compose" },
#endif
B
bellard 已提交
1028 1029 1030 1031 1032 1033
    { 0, NULL },
};

static int get_keycode(const char *key)
{
    const KeyDef *p;
1034 1035
    char *endp;
    int ret;
B
bellard 已提交
1036 1037 1038 1039 1040

    for(p = key_defs; p->name != NULL; p++) {
        if (!strcmp(key, p->name))
            return p->keycode;
    }
1041 1042 1043 1044 1045
    if (strstart(key, "0x", NULL)) {
        ret = strtoul(key, &endp, 0);
        if (*endp == '\0' && ret >= 0x01 && ret <= 0xff)
            return ret;
    }
B
bellard 已提交
1046 1047 1048
    return -1;
}

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
#define MAX_KEYCODES 16
static uint8_t keycodes[MAX_KEYCODES];
static int nb_pending_keycodes;
static QEMUTimer *key_timer;

static void release_keys(void *opaque)
{
    int keycode;

    while (nb_pending_keycodes > 0) {
        nb_pending_keycodes--;
        keycode = keycodes[nb_pending_keycodes];
        if (keycode & 0x80)
            kbd_put_keycode(0xe0);
        kbd_put_keycode(keycode | 0x80);
    }
}

A
aliguori 已提交
1067 1068
static void do_sendkey(Monitor *mon, const char *string, int has_hold_time,
                       int hold_time)
B
bellard 已提交
1069
{
1070 1071 1072 1073
    char keyname_buf[16];
    char *separator;
    int keyname_len, keycode, i;

1074 1075 1076 1077 1078 1079 1080
    if (nb_pending_keycodes > 0) {
        qemu_del_timer(key_timer);
        release_keys(NULL);
    }
    if (!has_hold_time)
        hold_time = 100;
    i = 0;
1081 1082 1083 1084 1085 1086
    while (1) {
        separator = strchr(string, '-');
        keyname_len = separator ? separator - string : strlen(string);
        if (keyname_len > 0) {
            pstrcpy(keyname_buf, sizeof(keyname_buf), string);
            if (keyname_len > sizeof(keyname_buf) - 1) {
A
aliguori 已提交
1087
                monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
1088
                return;
B
bellard 已提交
1089
            }
1090
            if (i == MAX_KEYCODES) {
A
aliguori 已提交
1091
                monitor_printf(mon, "too many keys\n");
1092 1093 1094 1095 1096
                return;
            }
            keyname_buf[keyname_len] = 0;
            keycode = get_keycode(keyname_buf);
            if (keycode < 0) {
A
aliguori 已提交
1097
                monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
1098 1099
                return;
            }
1100
            keycodes[i++] = keycode;
B
bellard 已提交
1101
        }
1102
        if (!separator)
B
bellard 已提交
1103
            break;
1104
        string = separator + 1;
B
bellard 已提交
1105
    }
1106
    nb_pending_keycodes = i;
B
bellard 已提交
1107
    /* key down events */
1108
    for (i = 0; i < nb_pending_keycodes; i++) {
B
bellard 已提交
1109 1110 1111 1112 1113
        keycode = keycodes[i];
        if (keycode & 0x80)
            kbd_put_keycode(0xe0);
        kbd_put_keycode(keycode & 0x7f);
    }
1114
    /* delayed key up events */
1115 1116
    qemu_mod_timer(key_timer, qemu_get_clock(vm_clock) +
                    muldiv64(ticks_per_sec, hold_time, 1000));
B
bellard 已提交
1117 1118
}

B
bellard 已提交
1119 1120
static int mouse_button_state;

A
aliguori 已提交
1121
static void do_mouse_move(Monitor *mon, const char *dx_str, const char *dy_str,
B
bellard 已提交
1122 1123 1124 1125 1126 1127
                          const char *dz_str)
{
    int dx, dy, dz;
    dx = strtol(dx_str, NULL, 0);
    dy = strtol(dy_str, NULL, 0);
    dz = 0;
1128
    if (dz_str)
B
bellard 已提交
1129 1130 1131 1132
        dz = strtol(dz_str, NULL, 0);
    kbd_mouse_event(dx, dy, dz, mouse_button_state);
}

A
aliguori 已提交
1133
static void do_mouse_button(Monitor *mon, int button_state)
B
bellard 已提交
1134 1135 1136 1137 1138
{
    mouse_button_state = button_state;
    kbd_mouse_event(0, 0, 0, mouse_button_state);
}

A
aliguori 已提交
1139 1140
static void do_ioport_read(Monitor *mon, int count, int format, int size,
                           int addr, int has_index, int index)
B
bellard 已提交
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
{
    uint32_t val;
    int suffix;

    if (has_index) {
        cpu_outb(NULL, addr & 0xffff, index & 0xff);
        addr++;
    }
    addr &= 0xffff;

    switch(size) {
    default:
    case 1:
        val = cpu_inb(NULL, addr);
        suffix = 'b';
        break;
    case 2:
        val = cpu_inw(NULL, addr);
        suffix = 'w';
        break;
    case 4:
        val = cpu_inl(NULL, addr);
        suffix = 'l';
        break;
    }
A
aliguori 已提交
1166 1167
    monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
                   suffix, addr, size * 2, val);
B
bellard 已提交
1168
}
B
bellard 已提交
1169

1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
/* boot_set handler */
static QEMUBootSetHandler *qemu_boot_set_handler = NULL;
static void *boot_opaque;

void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
{
    qemu_boot_set_handler = func;
    boot_opaque = opaque;
}

A
aliguori 已提交
1180
static void do_boot_set(Monitor *mon, const char *bootdevice)
1181 1182 1183 1184
{
    int res;

    if (qemu_boot_set_handler)  {
1185
        res = qemu_boot_set_handler(boot_opaque, bootdevice);
1186
        if (res == 0)
A
aliguori 已提交
1187 1188
            monitor_printf(mon, "boot device list now set to %s\n",
                           bootdevice);
1189
        else
A
aliguori 已提交
1190 1191
            monitor_printf(mon, "setting boot device list failed with "
                           "error %i\n", res);
1192
    } else {
A
aliguori 已提交
1193 1194
        monitor_printf(mon, "no function defined to set boot device list for "
                       "this architecture\n");
1195 1196 1197
    }
}

A
aliguori 已提交
1198
static void do_system_reset(Monitor *mon)
B
bellard 已提交
1199 1200 1201 1202
{
    qemu_system_reset_request();
}

A
aliguori 已提交
1203
static void do_system_powerdown(Monitor *mon)
B
bellard 已提交
1204 1205 1206 1207
{
    qemu_system_powerdown_request();
}

B
bellard 已提交
1208
#if defined(TARGET_I386)
A
aliguori 已提交
1209
static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
B
bellard 已提交
1210
{
A
aliguori 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
    monitor_printf(mon, "%08x: %08x %c%c%c%c%c%c%c%c\n",
                   addr,
                   pte & mask,
                   pte & PG_GLOBAL_MASK ? 'G' : '-',
                   pte & PG_PSE_MASK ? 'P' : '-',
                   pte & PG_DIRTY_MASK ? 'D' : '-',
                   pte & PG_ACCESSED_MASK ? 'A' : '-',
                   pte & PG_PCD_MASK ? 'C' : '-',
                   pte & PG_PWT_MASK ? 'T' : '-',
                   pte & PG_USER_MASK ? 'U' : '-',
                   pte & PG_RW_MASK ? 'W' : '-');
B
bellard 已提交
1222 1223
}

A
aliguori 已提交
1224
static void tlb_info(Monitor *mon)
B
bellard 已提交
1225
{
B
bellard 已提交
1226
    CPUState *env;
B
bellard 已提交
1227 1228 1229
    int l1, l2;
    uint32_t pgd, pde, pte;

B
bellard 已提交
1230 1231 1232 1233
    env = mon_get_cpu();
    if (!env)
        return;

B
bellard 已提交
1234
    if (!(env->cr[0] & CR0_PG_MASK)) {
A
aliguori 已提交
1235
        monitor_printf(mon, "PG disabled\n");
B
bellard 已提交
1236 1237 1238 1239 1240 1241 1242 1243
        return;
    }
    pgd = env->cr[3] & ~0xfff;
    for(l1 = 0; l1 < 1024; l1++) {
        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
        pde = le32_to_cpu(pde);
        if (pde & PG_PRESENT_MASK) {
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
A
aliguori 已提交
1244
                print_pte(mon, (l1 << 22), pde, ~((1 << 20) - 1));
B
bellard 已提交
1245 1246
            } else {
                for(l2 = 0; l2 < 1024; l2++) {
1247
                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
B
bellard 已提交
1248 1249 1250
                                             (uint8_t *)&pte, 4);
                    pte = le32_to_cpu(pte);
                    if (pte & PG_PRESENT_MASK) {
A
aliguori 已提交
1251
                        print_pte(mon, (l1 << 22) + (l2 << 12),
1252
                                  pte & ~PG_PSE_MASK,
B
bellard 已提交
1253 1254 1255 1256 1257 1258 1259 1260
                                  ~0xfff);
                    }
                }
            }
        }
    }
}

A
aliguori 已提交
1261
static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
B
bellard 已提交
1262 1263
                      uint32_t end, int prot)
{
B
bellard 已提交
1264 1265 1266
    int prot1;
    prot1 = *plast_prot;
    if (prot != prot1) {
B
bellard 已提交
1267
        if (*pstart != -1) {
A
aliguori 已提交
1268 1269 1270 1271 1272
            monitor_printf(mon, "%08x-%08x %08x %c%c%c\n",
                           *pstart, end, end - *pstart,
                           prot1 & PG_USER_MASK ? 'u' : '-',
                           'r',
                           prot1 & PG_RW_MASK ? 'w' : '-');
B
bellard 已提交
1273 1274 1275 1276 1277 1278 1279 1280 1281
        }
        if (prot != 0)
            *pstart = end;
        else
            *pstart = -1;
        *plast_prot = prot;
    }
}

A
aliguori 已提交
1282
static void mem_info(Monitor *mon)
B
bellard 已提交
1283
{
B
bellard 已提交
1284
    CPUState *env;
B
bellard 已提交
1285 1286 1287
    int l1, l2, prot, last_prot;
    uint32_t pgd, pde, pte, start, end;

B
bellard 已提交
1288 1289 1290 1291
    env = mon_get_cpu();
    if (!env)
        return;

B
bellard 已提交
1292
    if (!(env->cr[0] & CR0_PG_MASK)) {
A
aliguori 已提交
1293
        monitor_printf(mon, "PG disabled\n");
B
bellard 已提交
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
        return;
    }
    pgd = env->cr[3] & ~0xfff;
    last_prot = 0;
    start = -1;
    for(l1 = 0; l1 < 1024; l1++) {
        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
        pde = le32_to_cpu(pde);
        end = l1 << 22;
        if (pde & PG_PRESENT_MASK) {
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
                prot = pde & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
A
aliguori 已提交
1306
                mem_print(mon, &start, &last_prot, end, prot);
B
bellard 已提交
1307 1308
            } else {
                for(l2 = 0; l2 < 1024; l2++) {
1309
                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
B
bellard 已提交
1310 1311 1312 1313 1314 1315 1316 1317
                                             (uint8_t *)&pte, 4);
                    pte = le32_to_cpu(pte);
                    end = (l1 << 22) + (l2 << 12);
                    if (pte & PG_PRESENT_MASK) {
                        prot = pte & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
                    } else {
                        prot = 0;
                    }
A
aliguori 已提交
1318
                    mem_print(mon, &start, &last_prot, end, prot);
B
bellard 已提交
1319 1320 1321 1322
                }
            }
        } else {
            prot = 0;
A
aliguori 已提交
1323
            mem_print(mon, &start, &last_prot, end, prot);
B
bellard 已提交
1324 1325 1326 1327 1328
        }
    }
}
#endif

A
aurel32 已提交
1329 1330
#if defined(TARGET_SH4)

A
aliguori 已提交
1331
static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
A
aurel32 已提交
1332
{
A
aliguori 已提交
1333 1334 1335 1336 1337 1338 1339 1340
    monitor_printf(mon, " tlb%i:\t"
                   "asid=%hhu vpn=%x\tppn=%x\tsz=%hhu size=%u\t"
                   "v=%hhu shared=%hhu cached=%hhu prot=%hhu "
                   "dirty=%hhu writethrough=%hhu\n",
                   idx,
                   tlb->asid, tlb->vpn, tlb->ppn, tlb->sz, tlb->size,
                   tlb->v, tlb->sh, tlb->c, tlb->pr,
                   tlb->d, tlb->wt);
A
aurel32 已提交
1341 1342
}

A
aliguori 已提交
1343
static void tlb_info(Monitor *mon)
A
aurel32 已提交
1344 1345 1346 1347
{
    CPUState *env = mon_get_cpu();
    int i;

A
aliguori 已提交
1348
    monitor_printf (mon, "ITLB:\n");
A
aurel32 已提交
1349
    for (i = 0 ; i < ITLB_SIZE ; i++)
A
aliguori 已提交
1350 1351
        print_tlb (mon, i, &env->itlb[i]);
    monitor_printf (mon, "UTLB:\n");
A
aurel32 已提交
1352
    for (i = 0 ; i < UTLB_SIZE ; i++)
A
aliguori 已提交
1353
        print_tlb (mon, i, &env->utlb[i]);
A
aurel32 已提交
1354 1355 1356 1357
}

#endif

A
aliguori 已提交
1358
static void do_info_kqemu(Monitor *mon)
B
bellard 已提交
1359 1360
{
#ifdef USE_KQEMU
B
bellard 已提交
1361
    CPUState *env;
B
bellard 已提交
1362 1363
    int val;
    val = 0;
B
bellard 已提交
1364 1365
    env = mon_get_cpu();
    if (!env) {
A
aliguori 已提交
1366
        monitor_printf(mon, "No cpu initialized yet");
B
bellard 已提交
1367 1368 1369
        return;
    }
    val = env->kqemu_enabled;
A
aliguori 已提交
1370
    monitor_printf(mon, "kqemu support: ");
B
bellard 已提交
1371 1372 1373
    switch(val) {
    default:
    case 0:
A
aliguori 已提交
1374
        monitor_printf(mon, "disabled\n");
B
bellard 已提交
1375 1376
        break;
    case 1:
A
aliguori 已提交
1377
        monitor_printf(mon, "enabled for user code\n");
B
bellard 已提交
1378 1379
        break;
    case 2:
A
aliguori 已提交
1380
        monitor_printf(mon, "enabled for user and kernel code\n");
B
bellard 已提交
1381 1382
        break;
    }
B
bellard 已提交
1383
#else
A
aliguori 已提交
1384
    monitor_printf(mon, "kqemu support: not compiled\n");
B
bellard 已提交
1385
#endif
1386
}
B
bellard 已提交
1387

A
aliguori 已提交
1388
static void do_info_kvm(Monitor *mon)
A
aliguori 已提交
1389 1390
{
#ifdef CONFIG_KVM
A
aliguori 已提交
1391
    monitor_printf(mon, "kvm support: ");
A
aliguori 已提交
1392
    if (kvm_enabled())
A
aliguori 已提交
1393
        monitor_printf(mon, "enabled\n");
A
aliguori 已提交
1394
    else
A
aliguori 已提交
1395
        monitor_printf(mon, "disabled\n");
A
aliguori 已提交
1396
#else
A
aliguori 已提交
1397
    monitor_printf(mon, "kvm support: not compiled\n");
A
aliguori 已提交
1398 1399 1400
#endif
}

B
bellard 已提交
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
#ifdef CONFIG_PROFILER

int64_t kqemu_time;
int64_t qemu_time;
int64_t kqemu_exec_count;
int64_t dev_time;
int64_t kqemu_ret_int_count;
int64_t kqemu_ret_excp_count;
int64_t kqemu_ret_intr_count;

A
aliguori 已提交
1411
static void do_info_profile(Monitor *mon)
B
bellard 已提交
1412 1413 1414 1415 1416
{
    int64_t total;
    total = qemu_time;
    if (total == 0)
        total = 1;
A
aliguori 已提交
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
    monitor_printf(mon, "async time  %" PRId64 " (%0.3f)\n",
                   dev_time, dev_time / (double)ticks_per_sec);
    monitor_printf(mon, "qemu time   %" PRId64 " (%0.3f)\n",
                   qemu_time, qemu_time / (double)ticks_per_sec);
    monitor_printf(mon, "kqemu time  %" PRId64 " (%0.3f %0.1f%%) count=%"
                        PRId64 " int=%" PRId64 " excp=%" PRId64 " intr=%"
                        PRId64 "\n",
                   kqemu_time, kqemu_time / (double)ticks_per_sec,
                   kqemu_time / (double)total * 100.0,
                   kqemu_exec_count,
                   kqemu_ret_int_count,
                   kqemu_ret_excp_count,
                   kqemu_ret_intr_count);
B
bellard 已提交
1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
    qemu_time = 0;
    kqemu_time = 0;
    kqemu_exec_count = 0;
    dev_time = 0;
    kqemu_ret_int_count = 0;
    kqemu_ret_excp_count = 0;
    kqemu_ret_intr_count = 0;
#ifdef USE_KQEMU
    kqemu_record_dump();
#endif
}
#else
A
aliguori 已提交
1442
static void do_info_profile(Monitor *mon)
B
bellard 已提交
1443
{
A
aliguori 已提交
1444
    monitor_printf(mon, "Internal profiler not compiled\n");
B
bellard 已提交
1445 1446 1447
}
#endif

B
bellard 已提交
1448 1449 1450
/* Capture support */
static LIST_HEAD (capture_list_head, CaptureState) capture_head;

A
aliguori 已提交
1451
static void do_info_capture(Monitor *mon)
B
bellard 已提交
1452 1453 1454 1455 1456
{
    int i;
    CaptureState *s;

    for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
A
aliguori 已提交
1457
        monitor_printf(mon, "[%d]: ", i);
B
bellard 已提交
1458 1459 1460 1461
        s->ops.info (s->opaque);
    }
}

A
aliguori 已提交
1462
static void do_stop_capture(Monitor *mon, int n)
B
bellard 已提交
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
{
    int i;
    CaptureState *s;

    for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
        if (i == n) {
            s->ops.destroy (s->opaque);
            LIST_REMOVE (s, entries);
            qemu_free (s);
            return;
        }
    }
}

#ifdef HAS_AUDIO
A
aliguori 已提交
1478 1479 1480 1481
static void do_wav_capture(Monitor *mon, const char *path,
                           int has_freq, int freq,
                           int has_bits, int bits,
                           int has_channels, int nchannels)
B
bellard 已提交
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
{
    CaptureState *s;

    s = qemu_mallocz (sizeof (*s));

    freq = has_freq ? freq : 44100;
    bits = has_bits ? bits : 16;
    nchannels = has_channels ? nchannels : 2;

    if (wav_start_capture (s, path, freq, bits, nchannels)) {
A
aliguori 已提交
1492
        monitor_printf(mon, "Faied to add wave capture\n");
B
bellard 已提交
1493 1494 1495 1496 1497 1498
        qemu_free (s);
    }
    LIST_INSERT_HEAD (&capture_head, s, entries);
}
#endif

A
aurel32 已提交
1499
#if defined(TARGET_I386)
A
aliguori 已提交
1500
static void do_inject_nmi(Monitor *mon, int cpu_index)
A
aurel32 已提交
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
{
    CPUState *env;

    for (env = first_cpu; env != NULL; env = env->next_cpu)
        if (env->cpu_index == cpu_index) {
            cpu_interrupt(env, CPU_INTERRUPT_NMI);
            break;
        }
}
#endif

A
aliguori 已提交
1512
static void do_info_status(Monitor *mon)
A
aurel32 已提交
1513 1514
{
    if (vm_running)
A
aliguori 已提交
1515
       monitor_printf(mon, "VM status: running\n");
A
aurel32 已提交
1516
    else
A
aliguori 已提交
1517
       monitor_printf(mon, "VM status: paused\n");
A
aurel32 已提交
1518 1519 1520
}


A
aliguori 已提交
1521
static void do_balloon(Monitor *mon, int value)
A
aliguori 已提交
1522 1523 1524 1525 1526
{
    ram_addr_t target = value;
    qemu_balloon(target << 20);
}

A
aliguori 已提交
1527
static void do_info_balloon(Monitor *mon)
A
aliguori 已提交
1528 1529 1530 1531
{
    ram_addr_t actual;

    actual = qemu_balloon_status();
A
aliguori 已提交
1532
    if (kvm_enabled() && !kvm_has_sync_mmu())
A
aliguori 已提交
1533 1534
        monitor_printf(mon, "Using KVM without synchronous MMU, "
                       "ballooning disabled\n");
A
aliguori 已提交
1535
    else if (actual == 0)
A
aliguori 已提交
1536
        monitor_printf(mon, "Ballooning not activated in VM\n");
A
aliguori 已提交
1537
    else
A
aliguori 已提交
1538
        monitor_printf(mon, "balloon: actual=%d\n", (int)(actual >> 20));
A
aliguori 已提交
1539 1540
}

1541 1542
static void do_acl(Monitor *mon,
                   const char *command,
1543 1544 1545 1546
                   const char *aclname,
                   const char *match,
                   int has_index,
                   int index)
1547 1548 1549 1550 1551
{
    qemu_acl *acl;

    acl = qemu_acl_find(aclname);
    if (!acl) {
1552 1553
        monitor_printf(mon, "acl: unknown list '%s'\n", aclname);
        return;
1554 1555 1556
    }

    if (strcmp(command, "show") == 0) {
1557 1558 1559
        int i = 0;
        qemu_acl_entry *entry;
        monitor_printf(mon, "policy: %s\n",
1560
                       acl->defaultDeny ? "deny" : "allow");
1561 1562 1563
        TAILQ_FOREACH(entry, &acl->entries, next) {
            i++;
            monitor_printf(mon, "%d: %s %s\n", i,
1564 1565
                           entry->deny ? "deny" : "allow",
                           entry->match);
1566
        }
1567
    } else if (strcmp(command, "reset") == 0) {
1568 1569
        qemu_acl_reset(acl);
        monitor_printf(mon, "acl: removed all rules\n");
1570
    } else if (strcmp(command, "policy") == 0) {
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
        if (!match) {
            monitor_printf(mon, "acl: missing policy parameter\n");
            return;
        }

        if (strcmp(match, "allow") == 0) {
            acl->defaultDeny = 0;
            monitor_printf(mon, "acl: policy set to 'allow'\n");
        } else if (strcmp(match, "deny") == 0) {
            acl->defaultDeny = 1;
            monitor_printf(mon, "acl: policy set to 'deny'\n");
        } else {
            monitor_printf(mon, "acl: unknown policy '%s', expected 'deny' or 'allow'\n", match);
        }
1585
    } else if ((strcmp(command, "allow") == 0) ||
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
               (strcmp(command, "deny") == 0)) {
        int deny = strcmp(command, "deny") == 0 ? 1 : 0;
        int ret;

        if (!match) {
            monitor_printf(mon, "acl: missing match parameter\n");
            return;
        }

        if (has_index)
            ret = qemu_acl_insert(acl, deny, match, index);
        else
            ret = qemu_acl_append(acl, deny, match);
        if (ret < 0)
            monitor_printf(mon, "acl: unable to add acl entry\n");
        else
            monitor_printf(mon, "acl: added rule at position %d\n", ret);
1603
    } else if (strcmp(command, "remove") == 0) {
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
        int ret;

        if (!match) {
            monitor_printf(mon, "acl: missing match parameter\n");
            return;
        }

        ret = qemu_acl_remove(acl, match);
        if (ret < 0)
            monitor_printf(mon, "acl: no matching acl entry\n");
        else
            monitor_printf(mon, "acl: removed rule at position %d\n", ret);
1616
    } else {
1617
        monitor_printf(mon, "acl: unknown command '%s'\n", command);
1618 1619 1620
    }
}

B
blueswir1 已提交
1621
/* Please update qemu-doc.texi when adding or changing commands */
A
aliguori 已提交
1622 1623
static const mon_cmd_t mon_cmds[] = {
    { "help|?", "s?", help_cmd,
B
bellard 已提交
1624
      "[cmd]", "show the help" },
1625
    { "commit", "s", do_commit,
B
bellard 已提交
1626
      "device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
1627
    { "info", "s?", do_info,
B
bellard 已提交
1628
      "subcommand", "show various information about the system state" },
1629
    { "q|quit", "", do_quit,
B
bellard 已提交
1630
      "", "quit the emulator" },
B
bellard 已提交
1631
    { "eject", "-fB", do_eject,
T
ths 已提交
1632
      "[-f] device", "eject a removable medium (use -f to force it)" },
1633 1634
    { "change", "BFs?", do_change,
      "device filename [format]", "change a removable medium, optional format" },
1635
    { "screendump", "F", do_screen_dump,
B
bellard 已提交
1636
      "filename", "save screen into PPM image 'filename'" },
1637
    { "logfile", "F", do_logfile,
P
pbrook 已提交
1638
      "filename", "output logs to 'filename'" },
1639
    { "log", "s", do_log,
1640
      "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
B
bellard 已提交
1641
    { "savevm", "s?", do_savevm,
1642
      "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" },
B
bellard 已提交
1643
    { "loadvm", "s", do_loadvm,
1644
      "tag|id", "restore a VM snapshot from its tag or id" },
B
bellard 已提交
1645
    { "delvm", "s", do_delvm,
1646 1647
      "tag|id", "delete a VM snapshot from its tag or id" },
    { "stop", "", do_stop,
1648
      "", "stop emulation", },
1649
    { "c|cont", "", do_cont,
1650
      "", "resume emulation", },
B
bellard 已提交
1651
#ifdef CONFIG_GDBSTUB
1652
    { "gdbserver", "s?", do_gdbserver,
1653
      "[port]", "start gdbserver session (default port=1234)", },
B
bellard 已提交
1654
#endif
1655
    { "x", "/l", do_memory_dump,
1656
      "/fmt addr", "virtual memory dump starting at 'addr'", },
1657
    { "xp", "/l", do_physical_memory_dump,
1658
      "/fmt addr", "physical memory dump starting at 'addr'", },
1659
    { "p|print", "/l", do_print,
1660
      "/fmt expr", "print expression value (use $reg for CPU register access)", },
1661
    { "i", "/ii.", do_ioport_read,
B
bellard 已提交
1662 1663
      "/fmt addr", "I/O port read" },

1664 1665
    { "sendkey", "si?", do_sendkey,
      "keys [hold_ms]", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)" },
1666
    { "system_reset", "", do_system_reset,
B
bellard 已提交
1667
      "", "reset the system" },
1668
    { "system_powerdown", "", do_system_powerdown,
B
bellard 已提交
1669
      "", "send system power down event" },
1670
    { "sum", "ii", do_sum,
B
bellard 已提交
1671
      "addr size", "compute the checksum of a memory region" },
B
bellard 已提交
1672 1673 1674 1675
    { "usb_add", "s", do_usb_add,
      "device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" },
    { "usb_del", "s", do_usb_del,
      "device", "remove USB device 'bus.addr'" },
1676
    { "cpu", "i", do_cpu_set,
B
bellard 已提交
1677
      "index", "set the default CPU" },
1678
    { "mouse_move", "sss?", do_mouse_move,
B
bellard 已提交
1679
      "dx dy [dz]", "send mouse move events" },
1680
    { "mouse_button", "i", do_mouse_button,
B
bellard 已提交
1681
      "state", "change mouse button state (1=L, 2=M, 4=R)" },
1682 1683
    { "mouse_set", "i", do_mouse_set,
      "index", "set which mouse device receives events" },
B
bellard 已提交
1684 1685 1686 1687 1688
#ifdef HAS_AUDIO
    { "wavcapture", "si?i?i?", do_wav_capture,
      "path [frequency bits channels]",
      "capture audio to a wave file (default frequency=44100 bits=16 channels=2)" },
#endif
B
blueswir1 已提交
1689 1690
    { "stopcapture", "i", do_stop_capture,
      "capture index", "stop capture" },
1691
    { "memsave", "lis", do_memory_save,
B
bellard 已提交
1692
      "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
A
aurel32 已提交
1693 1694
    { "pmemsave", "lis", do_physical_memory_save,
      "addr size file", "save to disk physical memory dump starting at 'addr' of size 'size'", },
1695 1696
    { "boot_set", "s", do_boot_set,
      "bootdevice", "define new values for the boot device list" },
A
aurel32 已提交
1697 1698 1699 1700
#if defined(TARGET_I386)
    { "nmi", "i", do_inject_nmi,
      "cpu", "inject an NMI on the given CPU", },
#endif
A
aliguori 已提交
1701 1702 1703 1704 1705 1706
    { "migrate", "-ds", do_migrate,
      "[-d] uri", "migrate to URI (using -d to not wait for completion)" },
    { "migrate_cancel", "", do_migrate_cancel,
      "", "cancel the current VM migration" },
    { "migrate_set_speed", "s", do_migrate_set_speed,
      "value", "set maximum speed (in bytes) for migrations" },
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720
#if defined(TARGET_I386)
    { "drive_add", "ss", drive_hot_add, "pci_addr=[[<domain>:]<bus>:]<slot>\n"
                                         "[file=file][,if=type][,bus=n]\n"
                                        "[,unit=m][,media=d][index=i]\n"
                                        "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
                                        "[snapshot=on|off][,cache=on|off]",
                                        "add drive to PCI storage controller" },
    { "pci_add", "sss", pci_device_hot_add, "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
    { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
    { "host_net_add", "ss", net_host_device_add,
      "[tap,user,socket,vde] options", "add host VLAN client" },
    { "host_net_remove", "is", net_host_device_remove,
      "vlan_id name", "remove host VLAN client" },
#endif
A
aliguori 已提交
1721 1722
    { "balloon", "i", do_balloon,
      "target", "request VM to change it's memory allocation (in MB)" },
1723 1724
    { "set_link", "ss", do_set_link,
      "name [up|down]", "change the link status of a network adapter" },
1725 1726 1727 1728 1729 1730
    { "acl", "sss?i?", do_acl, "<command> <aclname> [<match>] [<index>]\n",
                               "acl show vnc.username\n"
                               "acl policy vnc.username deny\n"
                               "acl allow vnc.username fred\n"
                               "acl deny vnc.username bob\n"
                               "acl reset vnc.username\n" },
1731
    { NULL, NULL, },
B
bellard 已提交
1732 1733
};

B
blueswir1 已提交
1734
/* Please update qemu-doc.texi when adding or changing commands */
A
aliguori 已提交
1735
static const mon_cmd_t info_cmds[] = {
B
bellard 已提交
1736
    { "version", "", do_info_version,
B
blueswir1 已提交
1737
      "", "show the version of QEMU" },
1738
    { "network", "", do_info_network,
B
bellard 已提交
1739
      "", "show the network state" },
1740 1741
    { "chardev", "", qemu_chr_info,
      "", "show the character devices" },
A
aliguori 已提交
1742
    { "block", "", bdrv_info,
B
bellard 已提交
1743
      "", "show the block devices" },
A
aliguori 已提交
1744
    { "blockstats", "", bdrv_info_stats,
1745
      "", "show block device statistics" },
1746 1747
    { "registers", "", do_info_registers,
      "", "show the cpu registers" },
B
bellard 已提交
1748 1749
    { "cpus", "", do_info_cpus,
      "", "show infos for each CPU" },
B
bellard 已提交
1750 1751
    { "history", "", do_info_history,
      "", "show the command line history", },
1752 1753
    { "irq", "", irq_info,
      "", "show the interrupts statistics (if available)", },
1754 1755
    { "pic", "", pic_info,
      "", "show i8259 (PIC) state", },
B
bellard 已提交
1756 1757
    { "pci", "", pci_info,
      "", "show PCI info", },
A
aurel32 已提交
1758
#if defined(TARGET_I386) || defined(TARGET_SH4)
B
bellard 已提交
1759 1760
    { "tlb", "", tlb_info,
      "", "show virtual to physical memory mappings", },
A
aurel32 已提交
1761 1762
#endif
#if defined(TARGET_I386)
B
bellard 已提交
1763 1764
    { "mem", "", mem_info,
      "", "show the active virtual memory mappings", },
A
aliguori 已提交
1765 1766
    { "hpet", "", do_info_hpet,
      "", "show state of HPET", },
B
bellard 已提交
1767
#endif
B
bellard 已提交
1768 1769
    { "jit", "", do_info_jit,
      "", "show dynamic compiler info", },
B
bellard 已提交
1770
    { "kqemu", "", do_info_kqemu,
B
blueswir1 已提交
1771
      "", "show KQEMU information", },
A
aliguori 已提交
1772
    { "kvm", "", do_info_kvm,
B
blueswir1 已提交
1773
      "", "show KVM information", },
B
bellard 已提交
1774 1775 1776 1777
    { "usb", "", usb_info,
      "", "show guest USB devices", },
    { "usbhost", "", usb_host_info,
      "", "show host USB devices", },
B
bellard 已提交
1778 1779
    { "profile", "", do_info_profile,
      "", "show profiling information", },
B
bellard 已提交
1780
    { "capture", "", do_info_capture,
B
bellard 已提交
1781
      "", "show capture information" },
B
bellard 已提交
1782
    { "snapshots", "", do_info_snapshots,
B
bellard 已提交
1783
      "", "show the currently saved VM snapshots" },
A
aurel32 已提交
1784 1785
    { "status", "", do_info_status,
      "", "show the current VM status (running|paused)" },
1786 1787
    { "pcmcia", "", pcmcia_info,
      "", "show guest PCMCIA status" },
1788 1789
    { "mice", "", do_info_mice,
      "", "show which guest mouse is receiving events" },
B
bellard 已提交
1790 1791
    { "vnc", "", do_info_vnc,
      "", "show the vnc server status"},
T
ths 已提交
1792 1793
    { "name", "", do_info_name,
      "", "show the current VM name" },
1794 1795
    { "uuid", "", do_info_uuid,
      "", "show the current VM UUID" },
1796 1797 1798 1799
#if defined(TARGET_PPC)
    { "cpustats", "", do_info_cpu_stats,
      "", "show CPU statistics", },
#endif
1800 1801 1802 1803
#if defined(CONFIG_SLIRP)
    { "slirp", "", do_info_slirp,
      "", "show SLIRP statistics", },
#endif
A
aliguori 已提交
1804
    { "migrate", "", do_info_migrate, "", "show migration status" },
A
aliguori 已提交
1805 1806
    { "balloon", "", do_info_balloon,
      "", "show balloon information" },
B
bellard 已提交
1807 1808 1809
    { NULL, NULL, },
};

1810 1811 1812 1813 1814
/*******************************************************************/

static const char *pch;
static jmp_buf expr_env;

B
bellard 已提交
1815 1816 1817
#define MD_TLONG 0
#define MD_I32   1

1818 1819 1820
typedef struct MonitorDef {
    const char *name;
    int offset;
B
blueswir1 已提交
1821
    target_long (*get_value)(const struct MonitorDef *md, int val);
B
bellard 已提交
1822
    int type;
1823 1824
} MonitorDef;

B
bellard 已提交
1825
#if defined(TARGET_I386)
B
blueswir1 已提交
1826
static target_long monitor_get_pc (const struct MonitorDef *md, int val)
B
bellard 已提交
1827
{
B
bellard 已提交
1828 1829 1830 1831
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return env->eip + env->segs[R_CS].base;
B
bellard 已提交
1832 1833 1834
}
#endif

1835
#if defined(TARGET_PPC)
B
blueswir1 已提交
1836
static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
1837
{
B
bellard 已提交
1838
    CPUState *env = mon_get_cpu();
1839 1840 1841
    unsigned int u;
    int i;

B
bellard 已提交
1842 1843 1844
    if (!env)
        return 0;

1845 1846
    u = 0;
    for (i = 0; i < 8; i++)
1847
        u |= env->crf[i] << (32 - (4 * i));
1848 1849 1850 1851

    return u;
}

B
blueswir1 已提交
1852
static target_long monitor_get_msr (const struct MonitorDef *md, int val)
1853
{
B
bellard 已提交
1854 1855 1856
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
1857
    return env->msr;
1858 1859
}

B
blueswir1 已提交
1860
static target_long monitor_get_xer (const struct MonitorDef *md, int val)
1861
{
B
bellard 已提交
1862 1863 1864
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
A
aurel32 已提交
1865
    return env->xer;
1866
}
1867

B
blueswir1 已提交
1868
static target_long monitor_get_decr (const struct MonitorDef *md, int val)
1869
{
B
bellard 已提交
1870 1871 1872 1873
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return cpu_ppc_load_decr(env);
1874 1875
}

B
blueswir1 已提交
1876
static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
1877
{
B
bellard 已提交
1878 1879 1880 1881
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return cpu_ppc_load_tbu(env);
1882 1883
}

B
blueswir1 已提交
1884
static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
1885
{
B
bellard 已提交
1886 1887 1888 1889
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return cpu_ppc_load_tbl(env);
1890
}
1891 1892
#endif

1893
#if defined(TARGET_SPARC)
B
bellard 已提交
1894
#ifndef TARGET_SPARC64
B
blueswir1 已提交
1895
static target_long monitor_get_psr (const struct MonitorDef *md, int val)
1896
{
B
bellard 已提交
1897 1898 1899 1900
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return GET_PSR(env);
1901
}
B
bellard 已提交
1902
#endif
1903

B
blueswir1 已提交
1904
static target_long monitor_get_reg(const struct MonitorDef *md, int val)
1905
{
B
bellard 已提交
1906 1907 1908 1909
    CPUState *env = mon_get_cpu();
    if (!env)
        return 0;
    return env->regwptr[val];
1910 1911 1912
}
#endif

B
blueswir1 已提交
1913
static const MonitorDef monitor_defs[] = {
1914
#ifdef TARGET_I386
B
bellard 已提交
1915 1916

#define SEG(name, seg) \
B
bellard 已提交
1917
    { name, offsetof(CPUState, segs[seg].selector), NULL, MD_I32 },\
B
bellard 已提交
1918
    { name ".base", offsetof(CPUState, segs[seg].base) },\
B
bellard 已提交
1919
    { name ".limit", offsetof(CPUState, segs[seg].limit), NULL, MD_I32 },
B
bellard 已提交
1920

1921 1922 1923 1924 1925 1926 1927
    { "eax", offsetof(CPUState, regs[0]) },
    { "ecx", offsetof(CPUState, regs[1]) },
    { "edx", offsetof(CPUState, regs[2]) },
    { "ebx", offsetof(CPUState, regs[3]) },
    { "esp|sp", offsetof(CPUState, regs[4]) },
    { "ebp|fp", offsetof(CPUState, regs[5]) },
    { "esi", offsetof(CPUState, regs[6]) },
B
bellard 已提交
1928
    { "edi", offsetof(CPUState, regs[7]) },
B
bellard 已提交
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938
#ifdef TARGET_X86_64
    { "r8", offsetof(CPUState, regs[8]) },
    { "r9", offsetof(CPUState, regs[9]) },
    { "r10", offsetof(CPUState, regs[10]) },
    { "r11", offsetof(CPUState, regs[11]) },
    { "r12", offsetof(CPUState, regs[12]) },
    { "r13", offsetof(CPUState, regs[13]) },
    { "r14", offsetof(CPUState, regs[14]) },
    { "r15", offsetof(CPUState, regs[15]) },
#endif
1939
    { "eflags", offsetof(CPUState, eflags) },
B
bellard 已提交
1940 1941 1942 1943
    { "eip", offsetof(CPUState, eip) },
    SEG("cs", R_CS)
    SEG("ds", R_DS)
    SEG("es", R_ES)
B
bellard 已提交
1944
    SEG("ss", R_SS)
B
bellard 已提交
1945 1946 1947
    SEG("fs", R_FS)
    SEG("gs", R_GS)
    { "pc", 0, monitor_get_pc, },
1948
#elif defined(TARGET_PPC)
J
j_mayer 已提交
1949
    /* General purpose registers */
1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
    { "r0", offsetof(CPUState, gpr[0]) },
    { "r1", offsetof(CPUState, gpr[1]) },
    { "r2", offsetof(CPUState, gpr[2]) },
    { "r3", offsetof(CPUState, gpr[3]) },
    { "r4", offsetof(CPUState, gpr[4]) },
    { "r5", offsetof(CPUState, gpr[5]) },
    { "r6", offsetof(CPUState, gpr[6]) },
    { "r7", offsetof(CPUState, gpr[7]) },
    { "r8", offsetof(CPUState, gpr[8]) },
    { "r9", offsetof(CPUState, gpr[9]) },
    { "r10", offsetof(CPUState, gpr[10]) },
    { "r11", offsetof(CPUState, gpr[11]) },
    { "r12", offsetof(CPUState, gpr[12]) },
    { "r13", offsetof(CPUState, gpr[13]) },
    { "r14", offsetof(CPUState, gpr[14]) },
    { "r15", offsetof(CPUState, gpr[15]) },
    { "r16", offsetof(CPUState, gpr[16]) },
    { "r17", offsetof(CPUState, gpr[17]) },
    { "r18", offsetof(CPUState, gpr[18]) },
    { "r19", offsetof(CPUState, gpr[19]) },
    { "r20", offsetof(CPUState, gpr[20]) },
    { "r21", offsetof(CPUState, gpr[21]) },
    { "r22", offsetof(CPUState, gpr[22]) },
    { "r23", offsetof(CPUState, gpr[23]) },
    { "r24", offsetof(CPUState, gpr[24]) },
    { "r25", offsetof(CPUState, gpr[25]) },
    { "r26", offsetof(CPUState, gpr[26]) },
    { "r27", offsetof(CPUState, gpr[27]) },
    { "r28", offsetof(CPUState, gpr[28]) },
    { "r29", offsetof(CPUState, gpr[29]) },
    { "r30", offsetof(CPUState, gpr[30]) },
    { "r31", offsetof(CPUState, gpr[31]) },
J
j_mayer 已提交
1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
    /* Floating point registers */
    { "f0", offsetof(CPUState, fpr[0]) },
    { "f1", offsetof(CPUState, fpr[1]) },
    { "f2", offsetof(CPUState, fpr[2]) },
    { "f3", offsetof(CPUState, fpr[3]) },
    { "f4", offsetof(CPUState, fpr[4]) },
    { "f5", offsetof(CPUState, fpr[5]) },
    { "f6", offsetof(CPUState, fpr[6]) },
    { "f7", offsetof(CPUState, fpr[7]) },
    { "f8", offsetof(CPUState, fpr[8]) },
    { "f9", offsetof(CPUState, fpr[9]) },
    { "f10", offsetof(CPUState, fpr[10]) },
    { "f11", offsetof(CPUState, fpr[11]) },
    { "f12", offsetof(CPUState, fpr[12]) },
    { "f13", offsetof(CPUState, fpr[13]) },
    { "f14", offsetof(CPUState, fpr[14]) },
    { "f15", offsetof(CPUState, fpr[15]) },
    { "f16", offsetof(CPUState, fpr[16]) },
    { "f17", offsetof(CPUState, fpr[17]) },
    { "f18", offsetof(CPUState, fpr[18]) },
    { "f19", offsetof(CPUState, fpr[19]) },
    { "f20", offsetof(CPUState, fpr[20]) },
    { "f21", offsetof(CPUState, fpr[21]) },
    { "f22", offsetof(CPUState, fpr[22]) },
    { "f23", offsetof(CPUState, fpr[23]) },
    { "f24", offsetof(CPUState, fpr[24]) },
    { "f25", offsetof(CPUState, fpr[25]) },
    { "f26", offsetof(CPUState, fpr[26]) },
    { "f27", offsetof(CPUState, fpr[27]) },
    { "f28", offsetof(CPUState, fpr[28]) },
    { "f29", offsetof(CPUState, fpr[29]) },
    { "f30", offsetof(CPUState, fpr[30]) },
    { "f31", offsetof(CPUState, fpr[31]) },
    { "fpscr", offsetof(CPUState, fpscr) },
    /* Next instruction pointer */
B
bellard 已提交
2017
    { "nip|pc", offsetof(CPUState, nip) },
2018 2019
    { "lr", offsetof(CPUState, lr) },
    { "ctr", offsetof(CPUState, ctr) },
2020
    { "decr", 0, &monitor_get_decr, },
2021
    { "ccr", 0, &monitor_get_ccr, },
J
j_mayer 已提交
2022
    /* Machine state register */
2023 2024
    { "msr", 0, &monitor_get_msr, },
    { "xer", 0, &monitor_get_xer, },
2025 2026
    { "tbu", 0, &monitor_get_tbu, },
    { "tbl", 0, &monitor_get_tbl, },
J
j_mayer 已提交
2027 2028 2029 2030 2031
#if defined(TARGET_PPC64)
    /* Address space register */
    { "asr", offsetof(CPUState, asr) },
#endif
    /* Segment registers */
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
    { "sdr1", offsetof(CPUState, sdr1) },
    { "sr0", offsetof(CPUState, sr[0]) },
    { "sr1", offsetof(CPUState, sr[1]) },
    { "sr2", offsetof(CPUState, sr[2]) },
    { "sr3", offsetof(CPUState, sr[3]) },
    { "sr4", offsetof(CPUState, sr[4]) },
    { "sr5", offsetof(CPUState, sr[5]) },
    { "sr6", offsetof(CPUState, sr[6]) },
    { "sr7", offsetof(CPUState, sr[7]) },
    { "sr8", offsetof(CPUState, sr[8]) },
    { "sr9", offsetof(CPUState, sr[9]) },
    { "sr10", offsetof(CPUState, sr[10]) },
    { "sr11", offsetof(CPUState, sr[11]) },
    { "sr12", offsetof(CPUState, sr[12]) },
    { "sr13", offsetof(CPUState, sr[13]) },
    { "sr14", offsetof(CPUState, sr[14]) },
    { "sr15", offsetof(CPUState, sr[15]) },
    /* Too lazy to put BATs and SPRs ... */
2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085
#elif defined(TARGET_SPARC)
    { "g0", offsetof(CPUState, gregs[0]) },
    { "g1", offsetof(CPUState, gregs[1]) },
    { "g2", offsetof(CPUState, gregs[2]) },
    { "g3", offsetof(CPUState, gregs[3]) },
    { "g4", offsetof(CPUState, gregs[4]) },
    { "g5", offsetof(CPUState, gregs[5]) },
    { "g6", offsetof(CPUState, gregs[6]) },
    { "g7", offsetof(CPUState, gregs[7]) },
    { "o0", 0, monitor_get_reg },
    { "o1", 1, monitor_get_reg },
    { "o2", 2, monitor_get_reg },
    { "o3", 3, monitor_get_reg },
    { "o4", 4, monitor_get_reg },
    { "o5", 5, monitor_get_reg },
    { "o6", 6, monitor_get_reg },
    { "o7", 7, monitor_get_reg },
    { "l0", 8, monitor_get_reg },
    { "l1", 9, monitor_get_reg },
    { "l2", 10, monitor_get_reg },
    { "l3", 11, monitor_get_reg },
    { "l4", 12, monitor_get_reg },
    { "l5", 13, monitor_get_reg },
    { "l6", 14, monitor_get_reg },
    { "l7", 15, monitor_get_reg },
    { "i0", 16, monitor_get_reg },
    { "i1", 17, monitor_get_reg },
    { "i2", 18, monitor_get_reg },
    { "i3", 19, monitor_get_reg },
    { "i4", 20, monitor_get_reg },
    { "i5", 21, monitor_get_reg },
    { "i6", 22, monitor_get_reg },
    { "i7", 23, monitor_get_reg },
    { "pc", offsetof(CPUState, pc) },
    { "npc", offsetof(CPUState, npc) },
    { "y", offsetof(CPUState, y) },
B
bellard 已提交
2086
#ifndef TARGET_SPARC64
2087 2088
    { "psr", 0, &monitor_get_psr, },
    { "wim", offsetof(CPUState, wim) },
B
bellard 已提交
2089
#endif
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123
    { "tbr", offsetof(CPUState, tbr) },
    { "fsr", offsetof(CPUState, fsr) },
    { "f0", offsetof(CPUState, fpr[0]) },
    { "f1", offsetof(CPUState, fpr[1]) },
    { "f2", offsetof(CPUState, fpr[2]) },
    { "f3", offsetof(CPUState, fpr[3]) },
    { "f4", offsetof(CPUState, fpr[4]) },
    { "f5", offsetof(CPUState, fpr[5]) },
    { "f6", offsetof(CPUState, fpr[6]) },
    { "f7", offsetof(CPUState, fpr[7]) },
    { "f8", offsetof(CPUState, fpr[8]) },
    { "f9", offsetof(CPUState, fpr[9]) },
    { "f10", offsetof(CPUState, fpr[10]) },
    { "f11", offsetof(CPUState, fpr[11]) },
    { "f12", offsetof(CPUState, fpr[12]) },
    { "f13", offsetof(CPUState, fpr[13]) },
    { "f14", offsetof(CPUState, fpr[14]) },
    { "f15", offsetof(CPUState, fpr[15]) },
    { "f16", offsetof(CPUState, fpr[16]) },
    { "f17", offsetof(CPUState, fpr[17]) },
    { "f18", offsetof(CPUState, fpr[18]) },
    { "f19", offsetof(CPUState, fpr[19]) },
    { "f20", offsetof(CPUState, fpr[20]) },
    { "f21", offsetof(CPUState, fpr[21]) },
    { "f22", offsetof(CPUState, fpr[22]) },
    { "f23", offsetof(CPUState, fpr[23]) },
    { "f24", offsetof(CPUState, fpr[24]) },
    { "f25", offsetof(CPUState, fpr[25]) },
    { "f26", offsetof(CPUState, fpr[26]) },
    { "f27", offsetof(CPUState, fpr[27]) },
    { "f28", offsetof(CPUState, fpr[28]) },
    { "f29", offsetof(CPUState, fpr[29]) },
    { "f30", offsetof(CPUState, fpr[30]) },
    { "f31", offsetof(CPUState, fpr[31]) },
B
bellard 已提交
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
#ifdef TARGET_SPARC64
    { "f32", offsetof(CPUState, fpr[32]) },
    { "f34", offsetof(CPUState, fpr[34]) },
    { "f36", offsetof(CPUState, fpr[36]) },
    { "f38", offsetof(CPUState, fpr[38]) },
    { "f40", offsetof(CPUState, fpr[40]) },
    { "f42", offsetof(CPUState, fpr[42]) },
    { "f44", offsetof(CPUState, fpr[44]) },
    { "f46", offsetof(CPUState, fpr[46]) },
    { "f48", offsetof(CPUState, fpr[48]) },
    { "f50", offsetof(CPUState, fpr[50]) },
    { "f52", offsetof(CPUState, fpr[52]) },
    { "f54", offsetof(CPUState, fpr[54]) },
    { "f56", offsetof(CPUState, fpr[56]) },
    { "f58", offsetof(CPUState, fpr[58]) },
    { "f60", offsetof(CPUState, fpr[60]) },
    { "f62", offsetof(CPUState, fpr[62]) },
    { "asi", offsetof(CPUState, asi) },
    { "pstate", offsetof(CPUState, pstate) },
    { "cansave", offsetof(CPUState, cansave) },
    { "canrestore", offsetof(CPUState, canrestore) },
    { "otherwin", offsetof(CPUState, otherwin) },
    { "wstate", offsetof(CPUState, wstate) },
    { "cleanwin", offsetof(CPUState, cleanwin) },
    { "fprs", offsetof(CPUState, fprs) },
#endif
2150 2151 2152 2153
#endif
    { NULL },
};

A
aliguori 已提交
2154
static void expr_error(Monitor *mon, const char *msg)
B
bellard 已提交
2155
{
A
aliguori 已提交
2156
    monitor_printf(mon, "%s\n", msg);
2157 2158 2159
    longjmp(expr_env, 1);
}

B
bellard 已提交
2160
/* return 0 if OK, -1 if not found, -2 if no CPU defined */
B
bellard 已提交
2161
static int get_monitor_def(target_long *pval, const char *name)
2162
{
B
blueswir1 已提交
2163
    const MonitorDef *md;
B
bellard 已提交
2164 2165
    void *ptr;

2166 2167 2168
    for(md = monitor_defs; md->name != NULL; md++) {
        if (compare_cmd(name, md->name)) {
            if (md->get_value) {
2169
                *pval = md->get_value(md, md->offset);
2170
            } else {
B
bellard 已提交
2171 2172 2173 2174
                CPUState *env = mon_get_cpu();
                if (!env)
                    return -2;
                ptr = (uint8_t *)env + md->offset;
B
bellard 已提交
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
                switch(md->type) {
                case MD_I32:
                    *pval = *(int32_t *)ptr;
                    break;
                case MD_TLONG:
                    *pval = *(target_long *)ptr;
                    break;
                default:
                    *pval = 0;
                    break;
                }
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196
            }
            return 0;
        }
    }
    return -1;
}

static void next(void)
{
    if (pch != '\0') {
        pch++;
2197
        while (qemu_isspace(*pch))
2198 2199 2200 2201
            pch++;
    }
}

A
aliguori 已提交
2202
static int64_t expr_sum(Monitor *mon);
2203

A
aliguori 已提交
2204
static int64_t expr_unary(Monitor *mon)
2205
{
B
blueswir1 已提交
2206
    int64_t n;
2207
    char *p;
B
bellard 已提交
2208
    int ret;
2209 2210 2211 2212

    switch(*pch) {
    case '+':
        next();
A
aliguori 已提交
2213
        n = expr_unary(mon);
2214 2215 2216
        break;
    case '-':
        next();
A
aliguori 已提交
2217
        n = -expr_unary(mon);
2218 2219 2220
        break;
    case '~':
        next();
A
aliguori 已提交
2221
        n = ~expr_unary(mon);
2222 2223 2224
        break;
    case '(':
        next();
A
aliguori 已提交
2225
        n = expr_sum(mon);
2226
        if (*pch != ')') {
A
aliguori 已提交
2227
            expr_error(mon, "')' expected");
2228 2229 2230
        }
        next();
        break;
B
bellard 已提交
2231 2232 2233
    case '\'':
        pch++;
        if (*pch == '\0')
A
aliguori 已提交
2234
            expr_error(mon, "character constant expected");
B
bellard 已提交
2235 2236 2237
        n = *pch;
        pch++;
        if (*pch != '\'')
A
aliguori 已提交
2238
            expr_error(mon, "missing terminating \' character");
B
bellard 已提交
2239 2240
        next();
        break;
2241 2242 2243
    case '$':
        {
            char buf[128], *q;
2244
            target_long reg=0;
2245

2246 2247 2248 2249 2250
            pch++;
            q = buf;
            while ((*pch >= 'a' && *pch <= 'z') ||
                   (*pch >= 'A' && *pch <= 'Z') ||
                   (*pch >= '0' && *pch <= '9') ||
B
bellard 已提交
2251
                   *pch == '_' || *pch == '.') {
2252 2253 2254 2255
                if ((q - buf) < sizeof(buf) - 1)
                    *q++ = *pch;
                pch++;
            }
2256
            while (qemu_isspace(*pch))
2257 2258
                pch++;
            *q = 0;
2259
            ret = get_monitor_def(&reg, buf);
B
bellard 已提交
2260
            if (ret == -1)
A
aliguori 已提交
2261
                expr_error(mon, "unknown register");
2262
            else if (ret == -2)
A
aliguori 已提交
2263
                expr_error(mon, "no cpu defined");
2264
            n = reg;
2265 2266 2267
        }
        break;
    case '\0':
A
aliguori 已提交
2268
        expr_error(mon, "unexpected end of expression");
2269 2270 2271
        n = 0;
        break;
    default:
2272
#if TARGET_PHYS_ADDR_BITS > 32
B
bellard 已提交
2273 2274
        n = strtoull(pch, &p, 0);
#else
2275
        n = strtoul(pch, &p, 0);
B
bellard 已提交
2276
#endif
2277
        if (pch == p) {
A
aliguori 已提交
2278
            expr_error(mon, "invalid char in expression");
2279 2280
        }
        pch = p;
2281
        while (qemu_isspace(*pch))
2282 2283 2284 2285 2286 2287 2288
            pch++;
        break;
    }
    return n;
}


A
aliguori 已提交
2289
static int64_t expr_prod(Monitor *mon)
2290
{
B
blueswir1 已提交
2291
    int64_t val, val2;
B
bellard 已提交
2292
    int op;
2293

A
aliguori 已提交
2294
    val = expr_unary(mon);
2295 2296 2297 2298 2299
    for(;;) {
        op = *pch;
        if (op != '*' && op != '/' && op != '%')
            break;
        next();
A
aliguori 已提交
2300
        val2 = expr_unary(mon);
2301 2302 2303 2304 2305 2306 2307
        switch(op) {
        default:
        case '*':
            val *= val2;
            break;
        case '/':
        case '%':
2308
            if (val2 == 0)
A
aliguori 已提交
2309
                expr_error(mon, "division by zero");
2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
            if (op == '/')
                val /= val2;
            else
                val %= val2;
            break;
        }
    }
    return val;
}

A
aliguori 已提交
2320
static int64_t expr_logic(Monitor *mon)
2321
{
B
blueswir1 已提交
2322
    int64_t val, val2;
B
bellard 已提交
2323
    int op;
2324

A
aliguori 已提交
2325
    val = expr_prod(mon);
2326 2327 2328 2329 2330
    for(;;) {
        op = *pch;
        if (op != '&' && op != '|' && op != '^')
            break;
        next();
A
aliguori 已提交
2331
        val2 = expr_prod(mon);
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
        switch(op) {
        default:
        case '&':
            val &= val2;
            break;
        case '|':
            val |= val2;
            break;
        case '^':
            val ^= val2;
            break;
        }
    }
    return val;
}

A
aliguori 已提交
2348
static int64_t expr_sum(Monitor *mon)
2349
{
B
blueswir1 已提交
2350
    int64_t val, val2;
B
bellard 已提交
2351
    int op;
2352

A
aliguori 已提交
2353
    val = expr_logic(mon);
2354 2355 2356 2357 2358
    for(;;) {
        op = *pch;
        if (op != '+' && op != '-')
            break;
        next();
A
aliguori 已提交
2359
        val2 = expr_logic(mon);
2360 2361 2362 2363 2364 2365 2366 2367
        if (op == '+')
            val += val2;
        else
            val -= val2;
    }
    return val;
}

A
aliguori 已提交
2368
static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
2369 2370 2371 2372 2373 2374
{
    pch = *pp;
    if (setjmp(expr_env)) {
        *pp = pch;
        return -1;
    }
2375
    while (qemu_isspace(*pch))
2376
        pch++;
A
aliguori 已提交
2377
    *pval = expr_sum(mon);
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
    *pp = pch;
    return 0;
}

static int get_str(char *buf, int buf_size, const char **pp)
{
    const char *p;
    char *q;
    int c;

B
bellard 已提交
2388
    q = buf;
2389
    p = *pp;
2390
    while (qemu_isspace(*p))
2391 2392 2393
        p++;
    if (*p == '\0') {
    fail:
B
bellard 已提交
2394
        *q = '\0';
2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429
        *pp = p;
        return -1;
    }
    if (*p == '\"') {
        p++;
        while (*p != '\0' && *p != '\"') {
            if (*p == '\\') {
                p++;
                c = *p++;
                switch(c) {
                case 'n':
                    c = '\n';
                    break;
                case 'r':
                    c = '\r';
                    break;
                case '\\':
                case '\'':
                case '\"':
                    break;
                default:
                    qemu_printf("unsupported escape code: '\\%c'\n", c);
                    goto fail;
                }
                if ((q - buf) < buf_size - 1) {
                    *q++ = c;
                }
            } else {
                if ((q - buf) < buf_size - 1) {
                    *q++ = *p;
                }
                p++;
            }
        }
        if (*p != '\"') {
B
bellard 已提交
2430
            qemu_printf("unterminated string\n");
2431 2432 2433 2434
            goto fail;
        }
        p++;
    } else {
2435
        while (*p != '\0' && !qemu_isspace(*p)) {
2436 2437 2438 2439 2440 2441
            if ((q - buf) < buf_size - 1) {
                *q++ = *p;
            }
            p++;
        }
    }
B
bellard 已提交
2442
    *q = '\0';
2443 2444 2445 2446 2447 2448 2449 2450 2451
    *pp = p;
    return 0;
}

static int default_fmt_format = 'x';
static int default_fmt_size = 4;

#define MAX_ARGS 16

A
aliguori 已提交
2452
static void monitor_handle_command(Monitor *mon, const char *cmdline)
2453 2454 2455 2456
{
    const char *p, *pstart, *typestr;
    char *q;
    int c, nb_args, len, i, has_arg;
A
aliguori 已提交
2457
    const mon_cmd_t *cmd;
2458 2459 2460 2461
    char cmdname[256];
    char buf[1024];
    void *str_allocated[MAX_ARGS];
    void *args[MAX_ARGS];
A
aliguori 已提交
2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473
    void (*handler_0)(Monitor *mon);
    void (*handler_1)(Monitor *mon, void *arg0);
    void (*handler_2)(Monitor *mon, void *arg0, void *arg1);
    void (*handler_3)(Monitor *mon, void *arg0, void *arg1, void *arg2);
    void (*handler_4)(Monitor *mon, void *arg0, void *arg1, void *arg2,
                      void *arg3);
    void (*handler_5)(Monitor *mon, void *arg0, void *arg1, void *arg2,
                      void *arg3, void *arg4);
    void (*handler_6)(Monitor *mon, void *arg0, void *arg1, void *arg2,
                      void *arg3, void *arg4, void *arg5);
    void (*handler_7)(Monitor *mon, void *arg0, void *arg1, void *arg2,
                      void *arg3, void *arg4, void *arg5, void *arg6);
B
bellard 已提交
2474 2475

#ifdef DEBUG
A
aliguori 已提交
2476
    monitor_printf(mon, "command='%s'\n", cmdline);
B
bellard 已提交
2477
#endif
2478

2479
    /* extract the command name */
B
bellard 已提交
2480
    p = cmdline;
2481
    q = cmdname;
2482
    while (qemu_isspace(*p))
2483 2484 2485 2486
        p++;
    if (*p == '\0')
        return;
    pstart = p;
2487
    while (*p != '\0' && *p != '/' && !qemu_isspace(*p))
2488 2489 2490 2491 2492 2493
        p++;
    len = p - pstart;
    if (len > sizeof(cmdname) - 1)
        len = sizeof(cmdname) - 1;
    memcpy(cmdname, pstart, len);
    cmdname[len] = '\0';
2494

2495
    /* find the command */
A
aliguori 已提交
2496
    for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
2497
        if (compare_cmd(cmdname, cmd->name))
2498 2499
            goto found;
    }
A
aliguori 已提交
2500
    monitor_printf(mon, "unknown command: '%s'\n", cmdname);
2501 2502 2503 2504 2505
    return;
 found:

    for(i = 0; i < MAX_ARGS; i++)
        str_allocated[i] = NULL;
2506

2507 2508 2509
    /* parse the parameters */
    typestr = cmd->args_type;
    nb_args = 0;
B
bellard 已提交
2510
    for(;;) {
2511 2512
        c = *typestr;
        if (c == '\0')
B
bellard 已提交
2513
            break;
2514 2515 2516
        typestr++;
        switch(c) {
        case 'F':
B
bellard 已提交
2517
        case 'B':
2518 2519 2520 2521
        case 's':
            {
                int ret;
                char *str;
2522

2523
                while (qemu_isspace(*p))
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
                    p++;
                if (*typestr == '?') {
                    typestr++;
                    if (*p == '\0') {
                        /* no optional string: NULL argument */
                        str = NULL;
                        goto add_str;
                    }
                }
                ret = get_str(buf, sizeof(buf), &p);
                if (ret < 0) {
B
bellard 已提交
2535 2536
                    switch(c) {
                    case 'F':
A
aliguori 已提交
2537 2538
                        monitor_printf(mon, "%s: filename expected\n",
                                       cmdname);
B
bellard 已提交
2539 2540
                        break;
                    case 'B':
A
aliguori 已提交
2541 2542
                        monitor_printf(mon, "%s: block device name expected\n",
                                       cmdname);
B
bellard 已提交
2543 2544
                        break;
                    default:
A
aliguori 已提交
2545
                        monitor_printf(mon, "%s: string expected\n", cmdname);
B
bellard 已提交
2546 2547
                        break;
                    }
2548 2549 2550
                    goto fail;
                }
                str = qemu_malloc(strlen(buf) + 1);
B
blueswir1 已提交
2551
                pstrcpy(str, sizeof(buf), buf);
2552 2553 2554 2555
                str_allocated[nb_args] = str;
            add_str:
                if (nb_args >= MAX_ARGS) {
                error_args:
A
aliguori 已提交
2556
                    monitor_printf(mon, "%s: too many arguments\n", cmdname);
2557 2558 2559 2560
                    goto fail;
                }
                args[nb_args++] = str;
            }
B
bellard 已提交
2561
            break;
2562 2563 2564
        case '/':
            {
                int count, format, size;
2565

2566
                while (qemu_isspace(*p))
2567 2568 2569 2570 2571
                    p++;
                if (*p == '/') {
                    /* format found */
                    p++;
                    count = 1;
2572
                    if (qemu_isdigit(*p)) {
2573
                        count = 0;
2574
                        while (qemu_isdigit(*p)) {
2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612
                            count = count * 10 + (*p - '0');
                            p++;
                        }
                    }
                    size = -1;
                    format = -1;
                    for(;;) {
                        switch(*p) {
                        case 'o':
                        case 'd':
                        case 'u':
                        case 'x':
                        case 'i':
                        case 'c':
                            format = *p++;
                            break;
                        case 'b':
                            size = 1;
                            p++;
                            break;
                        case 'h':
                            size = 2;
                            p++;
                            break;
                        case 'w':
                            size = 4;
                            p++;
                            break;
                        case 'g':
                        case 'L':
                            size = 8;
                            p++;
                            break;
                        default:
                            goto next;
                        }
                    }
                next:
2613
                    if (*p != '\0' && !qemu_isspace(*p)) {
A
aliguori 已提交
2614 2615
                        monitor_printf(mon, "invalid char in format: '%c'\n",
                                       *p);
2616 2617 2618 2619
                        goto fail;
                    }
                    if (format < 0)
                        format = default_fmt_format;
2620 2621 2622 2623
                    if (format != 'i') {
                        /* for 'i', not specifying a size gives -1 as size */
                        if (size < 0)
                            size = default_fmt_size;
A
aurel32 已提交
2624
                        default_fmt_size = size;
2625
                    }
2626 2627 2628 2629
                    default_fmt_format = format;
                } else {
                    count = 1;
                    format = default_fmt_format;
2630 2631 2632 2633 2634
                    if (format != 'i') {
                        size = default_fmt_size;
                    } else {
                        size = -1;
                    }
2635 2636 2637
                }
                if (nb_args + 3 > MAX_ARGS)
                    goto error_args;
J
j_mayer 已提交
2638 2639 2640
                args[nb_args++] = (void*)(long)count;
                args[nb_args++] = (void*)(long)format;
                args[nb_args++] = (void*)(long)size;
2641
            }
B
bellard 已提交
2642
            break;
2643
        case 'i':
B
bellard 已提交
2644
        case 'l':
2645
            {
B
blueswir1 已提交
2646
                int64_t val;
2647

2648
                while (qemu_isspace(*p))
2649
                    p++;
B
bellard 已提交
2650 2651 2652 2653 2654 2655 2656 2657 2658
                if (*typestr == '?' || *typestr == '.') {
                    if (*typestr == '?') {
                        if (*p == '\0')
                            has_arg = 0;
                        else
                            has_arg = 1;
                    } else {
                        if (*p == '.') {
                            p++;
2659
                            while (qemu_isspace(*p))
B
bellard 已提交
2660 2661 2662 2663 2664 2665
                                p++;
                            has_arg = 1;
                        } else {
                            has_arg = 0;
                        }
                    }
B
bellard 已提交
2666
                    typestr++;
2667 2668
                    if (nb_args >= MAX_ARGS)
                        goto error_args;
J
j_mayer 已提交
2669
                    args[nb_args++] = (void *)(long)has_arg;
2670 2671 2672 2673 2674 2675 2676
                    if (!has_arg) {
                        if (nb_args >= MAX_ARGS)
                            goto error_args;
                        val = -1;
                        goto add_num;
                    }
                }
A
aliguori 已提交
2677
                if (get_expr(mon, &val, &p))
2678 2679
                    goto fail;
            add_num:
B
bellard 已提交
2680 2681 2682
                if (c == 'i') {
                    if (nb_args >= MAX_ARGS)
                        goto error_args;
J
j_mayer 已提交
2683
                    args[nb_args++] = (void *)(long)val;
B
bellard 已提交
2684 2685 2686
                } else {
                    if ((nb_args + 1) >= MAX_ARGS)
                        goto error_args;
2687
#if TARGET_PHYS_ADDR_BITS > 32
J
j_mayer 已提交
2688
                    args[nb_args++] = (void *)(long)((val >> 32) & 0xffffffff);
B
bellard 已提交
2689 2690 2691
#else
                    args[nb_args++] = (void *)0;
#endif
J
j_mayer 已提交
2692
                    args[nb_args++] = (void *)(long)(val & 0xffffffff);
B
bellard 已提交
2693
                }
2694 2695 2696 2697 2698 2699
            }
            break;
        case '-':
            {
                int has_option;
                /* option */
2700

2701 2702 2703
                c = *typestr++;
                if (c == '\0')
                    goto bad_type;
2704
                while (qemu_isspace(*p))
2705 2706 2707 2708 2709
                    p++;
                has_option = 0;
                if (*p == '-') {
                    p++;
                    if (*p != c) {
A
aliguori 已提交
2710 2711
                        monitor_printf(mon, "%s: unsupported option -%c\n",
                                       cmdname, *p);
2712 2713 2714 2715 2716 2717 2718
                        goto fail;
                    }
                    p++;
                    has_option = 1;
                }
                if (nb_args >= MAX_ARGS)
                    goto error_args;
J
j_mayer 已提交
2719
                args[nb_args++] = (void *)(long)has_option;
2720 2721 2722 2723
            }
            break;
        default:
        bad_type:
A
aliguori 已提交
2724
            monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
2725 2726
            goto fail;
        }
B
bellard 已提交
2727
    }
2728
    /* check that all arguments were parsed */
2729
    while (qemu_isspace(*p))
2730 2731
        p++;
    if (*p != '\0') {
A
aliguori 已提交
2732 2733
        monitor_printf(mon, "%s: extraneous characters at the end of line\n",
                       cmdname);
2734
        goto fail;
B
bellard 已提交
2735
    }
2736 2737 2738

    switch(nb_args) {
    case 0:
2739
        handler_0 = cmd->handler;
A
aliguori 已提交
2740
        handler_0(mon);
2741 2742
        break;
    case 1:
2743
        handler_1 = cmd->handler;
A
aliguori 已提交
2744
        handler_1(mon, args[0]);
2745 2746
        break;
    case 2:
2747
        handler_2 = cmd->handler;
A
aliguori 已提交
2748
        handler_2(mon, args[0], args[1]);
2749 2750
        break;
    case 3:
2751
        handler_3 = cmd->handler;
A
aliguori 已提交
2752
        handler_3(mon, args[0], args[1], args[2]);
2753 2754
        break;
    case 4:
2755
        handler_4 = cmd->handler;
A
aliguori 已提交
2756
        handler_4(mon, args[0], args[1], args[2], args[3]);
2757 2758
        break;
    case 5:
2759
        handler_5 = cmd->handler;
A
aliguori 已提交
2760
        handler_5(mon, args[0], args[1], args[2], args[3], args[4]);
2761
        break;
B
bellard 已提交
2762
    case 6:
2763
        handler_6 = cmd->handler;
A
aliguori 已提交
2764
        handler_6(mon, args[0], args[1], args[2], args[3], args[4], args[5]);
B
bellard 已提交
2765
        break;
B
bellard 已提交
2766
    case 7:
2767
        handler_7 = cmd->handler;
A
aliguori 已提交
2768 2769
        handler_7(mon, args[0], args[1], args[2], args[3], args[4], args[5],
                  args[6]);
B
bellard 已提交
2770
        break;
2771
    default:
A
aliguori 已提交
2772
        monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
2773
        goto fail;
B
bellard 已提交
2774
    }
2775 2776 2777
 fail:
    for(i = 0; i < MAX_ARGS; i++)
        qemu_free(str_allocated[i]);
B
bellard 已提交
2778 2779 2780
    return;
}

B
bellard 已提交
2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
static void cmd_completion(const char *name, const char *list)
{
    const char *p, *pstart;
    char cmd[128];
    int len;

    p = list;
    for(;;) {
        pstart = p;
        p = strchr(p, '|');
        if (!p)
            p = pstart + strlen(pstart);
        len = p - pstart;
        if (len > sizeof(cmd) - 2)
            len = sizeof(cmd) - 2;
        memcpy(cmd, pstart, len);
        cmd[len] = '\0';
        if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
2799
            readline_add_completion(cur_mon->rs, cmd);
B
bellard 已提交
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815
        }
        if (*p == '\0')
            break;
        p++;
    }
}

static void file_completion(const char *input)
{
    DIR *ffs;
    struct dirent *d;
    char path[1024];
    char file[1024], file_prefix[1024];
    int input_path_len;
    const char *p;

2816
    p = strrchr(input, '/');
B
bellard 已提交
2817 2818 2819
    if (!p) {
        input_path_len = 0;
        pstrcpy(file_prefix, sizeof(file_prefix), input);
B
blueswir1 已提交
2820
        pstrcpy(path, sizeof(path), ".");
B
bellard 已提交
2821 2822 2823 2824 2825 2826 2827 2828 2829
    } else {
        input_path_len = p - input + 1;
        memcpy(path, input, input_path_len);
        if (input_path_len > sizeof(path) - 1)
            input_path_len = sizeof(path) - 1;
        path[input_path_len] = '\0';
        pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
    }
#ifdef DEBUG_COMPLETION
A
aliguori 已提交
2830 2831
    monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n",
                   input, path, file_prefix);
B
bellard 已提交
2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842
#endif
    ffs = opendir(path);
    if (!ffs)
        return;
    for(;;) {
        struct stat sb;
        d = readdir(ffs);
        if (!d)
            break;
        if (strstart(d->d_name, file_prefix, NULL)) {
            memcpy(file, input, input_path_len);
B
blueswir1 已提交
2843 2844 2845
            if (input_path_len < sizeof(file))
                pstrcpy(file + input_path_len, sizeof(file) - input_path_len,
                        d->d_name);
B
bellard 已提交
2846 2847 2848 2849 2850
            /* stat the file to find out if it's a directory.
             * In that case add a slash to speed up typing long paths
             */
            stat(file, &sb);
            if(S_ISDIR(sb.st_mode))
B
blueswir1 已提交
2851
                pstrcat(file, sizeof(file), "/");
2852
            readline_add_completion(cur_mon->rs, file);
B
bellard 已提交
2853 2854 2855 2856 2857
        }
    }
    closedir(ffs);
}

2858
static void block_completion_it(void *opaque, BlockDriverState *bs)
B
bellard 已提交
2859
{
2860
    const char *name = bdrv_get_device_name(bs);
B
bellard 已提交
2861 2862 2863 2864
    const char *input = opaque;

    if (input[0] == '\0' ||
        !strncmp(name, (char *)input, strlen(input))) {
2865
        readline_add_completion(cur_mon->rs, name);
B
bellard 已提交
2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879
    }
}

/* NOTE: this parser is an approximate form of the real command parser */
static void parse_cmdline(const char *cmdline,
                         int *pnb_args, char **args)
{
    const char *p;
    int nb_args, ret;
    char buf[1024];

    p = cmdline;
    nb_args = 0;
    for(;;) {
2880
        while (qemu_isspace(*p))
B
bellard 已提交
2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894
            p++;
        if (*p == '\0')
            break;
        if (nb_args >= MAX_ARGS)
            break;
        ret = get_str(buf, sizeof(buf), &p);
        args[nb_args] = qemu_strdup(buf);
        nb_args++;
        if (ret < 0)
            break;
    }
    *pnb_args = nb_args;
}

2895
static void monitor_find_completion(const char *cmdline)
B
bellard 已提交
2896 2897 2898 2899 2900
{
    const char *cmdname;
    char *args[MAX_ARGS];
    int nb_args, i, len;
    const char *ptype, *str;
A
aliguori 已提交
2901
    const mon_cmd_t *cmd;
2902
    const KeyDef *key;
B
bellard 已提交
2903 2904 2905 2906

    parse_cmdline(cmdline, &nb_args, args);
#ifdef DEBUG_COMPLETION
    for(i = 0; i < nb_args; i++) {
A
aliguori 已提交
2907
        monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
B
bellard 已提交
2908 2909 2910 2911 2912 2913
    }
#endif

    /* if the line ends with a space, it means we want to complete the
       next arg */
    len = strlen(cmdline);
2914
    if (len > 0 && qemu_isspace(cmdline[len - 1])) {
B
bellard 已提交
2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
        if (nb_args >= MAX_ARGS)
            return;
        args[nb_args++] = qemu_strdup("");
    }
    if (nb_args <= 1) {
        /* command completion */
        if (nb_args == 0)
            cmdname = "";
        else
            cmdname = args[0];
2925
        readline_set_completion_index(cur_mon->rs, strlen(cmdname));
A
aliguori 已提交
2926
        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
B
bellard 已提交
2927 2928 2929 2930
            cmd_completion(cmdname, cmd->name);
        }
    } else {
        /* find the command */
A
aliguori 已提交
2931
        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
B
bellard 已提交
2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948
            if (compare_cmd(args[0], cmd->name))
                goto found;
        }
        return;
    found:
        ptype = cmd->args_type;
        for(i = 0; i < nb_args - 2; i++) {
            if (*ptype != '\0') {
                ptype++;
                while (*ptype == '?')
                    ptype++;
            }
        }
        str = args[nb_args - 1];
        switch(*ptype) {
        case 'F':
            /* file completion */
2949
            readline_set_completion_index(cur_mon->rs, strlen(str));
B
bellard 已提交
2950 2951 2952 2953
            file_completion(str);
            break;
        case 'B':
            /* block device name completion */
2954
            readline_set_completion_index(cur_mon->rs, strlen(str));
B
bellard 已提交
2955 2956
            bdrv_iterate(block_completion_it, (void *)str);
            break;
B
bellard 已提交
2957 2958 2959
        case 's':
            /* XXX: more generic ? */
            if (!strcmp(cmd->name, "info")) {
2960
                readline_set_completion_index(cur_mon->rs, strlen(str));
B
bellard 已提交
2961 2962 2963
                for(cmd = info_cmds; cmd->name != NULL; cmd++) {
                    cmd_completion(str, cmd->name);
                }
2964
            } else if (!strcmp(cmd->name, "sendkey")) {
B
blueswir1 已提交
2965 2966 2967
                char *sep = strrchr(str, '-');
                if (sep)
                    str = sep + 1;
2968
                readline_set_completion_index(cur_mon->rs, strlen(str));
2969 2970 2971
                for(key = key_defs; key->name != NULL; key++) {
                    cmd_completion(str, key->name);
                }
B
bellard 已提交
2972 2973
            }
            break;
B
bellard 已提交
2974 2975 2976 2977 2978 2979 2980 2981
        default:
            break;
        }
    }
    for(i = 0; i < nb_args; i++)
        qemu_free(args[i]);
}

2982
static int monitor_can_read(void *opaque)
B
bellard 已提交
2983
{
2984 2985 2986
    Monitor *mon = opaque;

    return (mon->suspend_cnt == 0) ? 128 : 0;
B
bellard 已提交
2987 2988
}

2989
static void monitor_read(void *opaque, const uint8_t *buf, int size)
B
bellard 已提交
2990
{
2991
    Monitor *old_mon = cur_mon;
2992
    int i;
A
aliguori 已提交
2993

2994 2995
    cur_mon = opaque;

2996 2997 2998 2999 3000 3001 3002 3003 3004
    if (cur_mon->rs) {
        for (i = 0; i < size; i++)
            readline_handle_byte(cur_mon->rs, buf[i]);
    } else {
        if (size == 0 || buf[size - 1] != 0)
            monitor_printf(cur_mon, "corrupted command\n");
        else
            monitor_handle_command(cur_mon, (char *)buf);
    }
B
bellard 已提交
3005

3006 3007
    cur_mon = old_mon;
}
3008

A
aliguori 已提交
3009
static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
B
bellard 已提交
3010
{
3011
    monitor_suspend(mon);
A
aliguori 已提交
3012
    monitor_handle_command(mon, cmdline);
3013
    monitor_resume(mon);
3014 3015
}

3016
int monitor_suspend(Monitor *mon)
3017
{
3018 3019
    if (!mon->rs)
        return -ENOTTY;
3020
    mon->suspend_cnt++;
3021
    return 0;
3022 3023
}

A
aliguori 已提交
3024
void monitor_resume(Monitor *mon)
3025
{
3026 3027
    if (!mon->rs)
        return;
3028 3029
    if (--mon->suspend_cnt == 0)
        readline_show_prompt(mon->rs);
B
bellard 已提交
3030 3031
}

3032
static void monitor_event(void *opaque, int event)
3033
{
A
aliguori 已提交
3034 3035
    Monitor *mon = opaque;

3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048
    switch (event) {
    case CHR_EVENT_MUX_IN:
        readline_restart(mon->rs);
        monitor_resume(mon);
        monitor_flush(mon);
        break;

    case CHR_EVENT_MUX_OUT:
        if (mon->suspend_cnt == 0)
            monitor_printf(mon, "\n");
        monitor_flush(mon);
        monitor_suspend(mon);
        break;
3049

3050 3051 3052 3053 3054 3055 3056
    case CHR_EVENT_RESET:
        monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
                       "information\n", QEMU_VERSION);
        if (mon->chr->focus == 0)
            readline_show_prompt(mon->rs);
        break;
    }
3057 3058
}

3059 3060 3061 3062 3063 3064 3065 3066 3067

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 8
 * End:
 */

3068
void monitor_init(CharDriverState *chr, int flags)
B
bellard 已提交
3069
{
3070
    static int is_first_init = 1;
3071
    Monitor *mon;
T
ths 已提交
3072 3073

    if (is_first_init) {
3074
        key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
T
ths 已提交
3075 3076
        is_first_init = 0;
    }
3077 3078

    mon = qemu_mallocz(sizeof(*mon));
T
ths 已提交
3079

3080
    mon->chr = chr;
3081
    mon->flags = flags;
3082 3083
    if (mon->chr->focus != 0)
        mon->suspend_cnt = 1; /* mux'ed monitors start suspended */
3084 3085 3086 3087
    if (flags & MONITOR_USE_READLINE) {
        mon->rs = readline_init(mon, monitor_find_completion);
        monitor_read_command(mon, 0);
    }
3088

3089 3090
    qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
                          mon);
3091 3092

    LIST_INSERT_HEAD(&mon_list, mon, entry);
3093
    if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
3094
        cur_mon = mon;
B
bellard 已提交
3095 3096
}

A
aliguori 已提交
3097
static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
B
bellard 已提交
3098
{
3099 3100
    BlockDriverState *bs = opaque;
    int ret = 0;
B
bellard 已提交
3101

3102
    if (bdrv_set_key(bs, password) != 0) {
A
aliguori 已提交
3103
        monitor_printf(mon, "invalid password\n");
3104
        ret = -EPERM;
B
bellard 已提交
3105
    }
3106 3107
    if (mon->password_completion_cb)
        mon->password_completion_cb(mon->password_opaque, ret);
3108

3109
    monitor_read_command(mon, 1);
B
bellard 已提交
3110
}
3111

A
aliguori 已提交
3112
void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
3113 3114
                                 BlockDriverCompletionFunc *completion_cb,
                                 void *opaque)
3115
{
3116 3117
    int err;

3118 3119 3120 3121 3122
    if (!bdrv_key_required(bs)) {
        if (completion_cb)
            completion_cb(opaque, 0);
        return;
    }
3123

A
aliguori 已提交
3124 3125
    monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
                   bdrv_get_encrypted_filename(bs));
3126

3127 3128
    mon->password_completion_cb = completion_cb;
    mon->password_opaque = opaque;
3129

3130 3131 3132 3133
    err = monitor_read_password(mon, bdrv_password_cb, bs);

    if (err && completion_cb)
        completion_cb(opaque, err);
3134
}