Merge branch 'master' of /home/nchip/public_html/qemu into garage-push
[qemu] / monitor.c
index 22360fc..7620bde 100644 (file)
--- a/monitor.c
+++ b/monitor.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include <dirent.h>
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "hw/usb.h"
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
 #include "hw/pci.h"
+#include "hw/watchdog.h"
 #include "gdbstub.h"
 #include "net.h"
 #include "qemu-char.h"
 #include "sysemu.h"
+#include "monitor.h"
+#include "readline.h"
 #include "console.h"
 #include "block.h"
 #include "audio/audio.h"
 #include "disas.h"
-#include <dirent.h>
+#include "balloon.h"
 #include "qemu-timer.h"
 #include "migration.h"
 #include "kvm.h"
+#include "acl.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
  *
  */
 
-typedef struct term_cmd_t {
+typedef struct mon_cmd_t {
     const char *name;
     const char *args_type;
     void *handler;
     const char *params;
     const char *help;
-} term_cmd_t;
+} mon_cmd_t;
+
+struct Monitor {
+    CharDriverState *chr;
+    int flags;
+    int suspend_cnt;
+    uint8_t outbuf[1024];
+    int outbuf_index;
+    ReadLineState *rs;
+    CPUState *mon_cpu;
+    BlockDriverCompletionFunc *password_completion_cb;
+    void *password_opaque;
+    LIST_ENTRY(Monitor) entry;
+};
 
-#define MAX_MON 4
-static CharDriverState *monitor_hd[MAX_MON];
-static int hide_banner;
+static LIST_HEAD(mon_list, Monitor) mon_list;
 
-static const term_cmd_t term_cmds[];
-static const term_cmd_t info_cmds[];
+static const mon_cmd_t mon_cmds[];
+static const mon_cmd_t info_cmds[];
 
-static uint8_t term_outbuf[1024];
-static int term_outbuf_index;
+Monitor *cur_mon = NULL;
 
-static void monitor_start_input(void);
+static void monitor_command_cb(Monitor *mon, const char *cmdline,
+                               void *opaque);
 
-static CPUState *mon_cpu = NULL;
+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);
+}
 
-void term_flush(void)
+static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
+                                 void *opaque)
 {
-    int i;
-    if (term_outbuf_index > 0) {
-        for (i = 0; i < MAX_MON; i++)
-            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
-                qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
-        term_outbuf_index = 0;
+    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;
+    }
+}
+
+void monitor_flush(Monitor *mon)
+{
+    if (mon && mon->outbuf_index != 0 && mon->chr->focus == 0) {
+        qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
+        mon->outbuf_index = 0;
     }
 }
 
 /* flush at every end of line or if the buffer is full */
-void term_puts(const char *str)
+static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
+
+    if (!mon)
+        return;
+
     for(;;) {
         c = *str++;
         if (c == '\0')
             break;
         if (c == '\n')
-            term_outbuf[term_outbuf_index++] = '\r';
-        term_outbuf[term_outbuf_index++] = c;
-        if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
-            c == '\n')
-            term_flush();
+            mon->outbuf[mon->outbuf_index++] = '\r';
+        mon->outbuf[mon->outbuf_index++] = c;
+        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
+            || c == '\n')
+            monitor_flush(mon);
     }
 }
 
-void term_vprintf(const char *fmt, va_list ap)
+void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
     char buf[4096];
     vsnprintf(buf, sizeof(buf), fmt, ap);
-    term_puts(buf);
+    monitor_puts(mon, buf);
 }
 
-void term_printf(const char *fmt, ...)
+void monitor_printf(Monitor *mon, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf(mon, fmt, ap);
     va_end(ap);
 }
 
-void term_print_filename(const char *filename)
+void monitor_print_filename(Monitor *mon, const char *filename)
 {
     int i;
 
     for (i = 0; filename[i]; i++) {
-       switch (filename[i]) {
-       case ' ':
-       case '"':
-       case '\\':
-           term_printf("\\%c", filename[i]);
-           break;
-       case '\t':
-           term_printf("\\t");
-           break;
-       case '\r':
-           term_printf("\\r");
-           break;
-       case '\n':
-           term_printf("\\n");
-           break;
-       default:
-           term_printf("%c", filename[i]);
-           break;
-       }
+        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;
+        }
     }
 }
 
@@ -152,7 +188,7 @@ static int monitor_fprintf(FILE *stream, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf((Monitor *)stream, fmt, ap);
     va_end(ap);
     return 0;
 }
@@ -177,39 +213,36 @@ static int compare_cmd(const char *name, const char *list)
     return 0;
 }
 
-static void help_cmd1(const term_cmd_t *cmds, const char *prefix, const char *name)
+static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
+                          const char *prefix, const char *name)
 {
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
 
     for(cmd = cmds; cmd->name != NULL; cmd++) {
         if (!name || !strcmp(name, cmd->name))
-            term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
+            monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name,
+                           cmd->params, cmd->help);
     }
 }
 
-static void help_cmd(const char *name)
+static void help_cmd(Monitor *mon, const char *name)
 {
     if (name && !strcmp(name, "info")) {
-        help_cmd1(info_cmds, "info ", NULL);
+        help_cmd_dump(mon, info_cmds, "info ", NULL);
     } else {
-        help_cmd1(term_cmds, "", name);
+        help_cmd_dump(mon, mon_cmds, "", name);
         if (name && !strcmp(name, "log")) {
             const CPULogItem *item;
-            term_printf("Log items (comma separated):\n");
-            term_printf("%-10s %s\n", "none", "remove all logs");
+            monitor_printf(mon, "Log items (comma separated):\n");
+            monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
             for(item = cpu_log_items; item->mask != 0; item++) {
-                term_printf("%-10s %s\n", item->name, item->help);
+                monitor_printf(mon, "%-10s %s\n", item->name, item->help);
             }
         }
     }
 }
 
-static void do_help(const char *name)
-{
-    help_cmd(name);
-}
-
-static void do_commit(const char *device)
+static void do_commit(Monitor *mon, const char *device)
 {
     int i, all_devices;
 
@@ -221,10 +254,10 @@ static void do_commit(const char *device)
     }
 }
 
-static void do_info(const char *item)
+static void do_info(Monitor *mon, const char *item)
 {
-    const term_cmd_t *cmd;
-    void (*handler)(void);
+    const mon_cmd_t *cmd;
+    void (*handler)(Monitor *);
 
     if (!item)
         goto help;
@@ -233,41 +266,39 @@ static void do_info(const char *item)
             goto found;
     }
  help:
-    help_cmd("info");
+    help_cmd(mon, "info");
     return;
  found:
     handler = cmd->handler;
-    handler();
+    handler(mon);
 }
 
-static void do_info_version(void)
+static void do_info_version(Monitor *mon)
 {
-  term_printf("%s\n", QEMU_VERSION);
+    monitor_printf(mon, "%s\n", QEMU_VERSION QEMU_PKGVERSION);
 }
 
-static void do_info_name(void)
+static void do_info_name(Monitor *mon)
 {
     if (qemu_name)
-        term_printf("%s\n", qemu_name);
-}
-
-static void do_info_uuid(void)
-{
-    term_printf(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]);
+        monitor_printf(mon, "%s\n", qemu_name);
 }
 
-static void do_info_block(void)
+#if defined(TARGET_I386)
+static void do_info_hpet(Monitor *mon)
 {
-    bdrv_info();
+    monitor_printf(mon, "HPET is %s by QEMU\n",
+                   (no_hpet) ? "disabled" : "enabled");
 }
+#endif
 
-static void do_info_blockstats(void)
+static void do_info_uuid(Monitor *mon)
 {
-    bdrv_info_stats();
+    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]);
 }
 
 /* get the current CPU defined by the user */
@@ -277,7 +308,7 @@ static int mon_set_cpu(int cpu_index)
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         if (env->cpu_index == cpu_index) {
-            mon_cpu = env;
+            cur_mon->mon_cpu = env;
             return 0;
         }
     }
@@ -286,28 +317,29 @@ static int mon_set_cpu(int cpu_index)
 
 static CPUState *mon_get_cpu(void)
 {
-    if (!mon_cpu) {
+    if (!cur_mon->mon_cpu) {
         mon_set_cpu(0);
     }
-    return mon_cpu;
+    cpu_synchronize_state(cur_mon->mon_cpu, 0);
+    return cur_mon->mon_cpu;
 }
 
-static void do_info_registers(void)
+static void do_info_registers(Monitor *mon)
 {
     CPUState *env;
     env = mon_get_cpu();
     if (!env)
         return;
 #ifdef TARGET_I386
-    cpu_dump_state(env, NULL, monitor_fprintf,
+    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
                    X86_DUMP_FPU);
 #else
-    cpu_dump_state(env, NULL, monitor_fprintf,
+    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
                    0);
 #endif
 }
 
-static void do_info_cpus(void)
+static void do_info_cpus(Monitor *mon)
 {
     CPUState *env;
 
@@ -315,76 +347,81 @@ static void do_info_cpus(void)
     mon_get_cpu();
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
-        term_printf("%c CPU #%d:",
-                    (env == mon_cpu) ? '*' : ' ',
-                    env->cpu_index);
+        cpu_synchronize_state(env, 0);
+        monitor_printf(mon, "%c CPU #%d:",
+                       (env == mon->mon_cpu) ? '*' : ' ',
+                       env->cpu_index);
 #if defined(TARGET_I386)
-        term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base);
+        monitor_printf(mon, " pc=0x" TARGET_FMT_lx,
+                       env->eip + env->segs[R_CS].base);
 #elif defined(TARGET_PPC)
-        term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
+        monitor_printf(mon, " nip=0x" TARGET_FMT_lx, env->nip);
 #elif defined(TARGET_SPARC)
-        term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
+        monitor_printf(mon, " pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx,
+                       env->pc, env->npc);
 #elif defined(TARGET_MIPS)
-        term_printf(" PC=0x" TARGET_FMT_lx, env->active_tc.PC);
+        monitor_printf(mon, " PC=0x" TARGET_FMT_lx, env->active_tc.PC);
 #endif
         if (env->halted)
-            term_printf(" (halted)");
-        term_printf("\n");
+            monitor_printf(mon, " (halted)");
+        monitor_printf(mon, "\n");
     }
 }
 
-static void do_cpu_set(int index)
+static void do_cpu_set(Monitor *mon, int index)
 {
     if (mon_set_cpu(index) < 0)
-        term_printf("Invalid CPU index\n");
+        monitor_printf(mon, "Invalid CPU index\n");
 }
 
-static void do_info_jit(void)
+static void do_info_jit(Monitor *mon)
 {
-    dump_exec_info(NULL, monitor_fprintf);
+    dump_exec_info((FILE *)mon, monitor_fprintf);
 }
 
-static void do_info_history (void)
+static void do_info_history(Monitor *mon)
 {
     int i;
     const char *str;
 
+    if (!mon->rs)
+        return;
     i = 0;
     for(;;) {
-        str = readline_get_history(i);
+        str = readline_get_history(mon->rs, i);
         if (!str)
             break;
-       term_printf("%d: '%s'\n", i, str);
+        monitor_printf(mon, "%d: '%s'\n", i, str);
         i++;
     }
 }
 
 #if defined(TARGET_PPC)
 /* XXX: not implemented in other targets */
-static void do_info_cpu_stats (void)
+static void do_info_cpu_stats(Monitor *mon)
 {
     CPUState *env;
 
     env = mon_get_cpu();
-    cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
+    cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
 }
 #endif
 
-static void do_quit(void)
+static void do_quit(Monitor *mon)
 {
     exit(0);
 }
 
-static int eject_device(BlockDriverState *bs, int force)
+static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
 {
     if (bdrv_is_inserted(bs)) {
         if (!force) {
             if (!bdrv_is_removable(bs)) {
-                term_printf("device is not removable\n");
+                monitor_printf(mon, "device is not removable\n");
                 return -1;
             }
             if (bdrv_is_locked(bs)) {
-                term_printf("device is locked\n");
+                monitor_printf(mon, "device is locked\n");
                 return -1;
             }
         }
@@ -393,76 +430,90 @@ static int eject_device(BlockDriverState *bs, int force)
     return 0;
 }
 
-static void do_eject(int force, const char *filename)
+static void do_eject(Monitor *mon, int force, const char *filename)
 {
     BlockDriverState *bs;
 
     bs = bdrv_find(filename);
     if (!bs) {
-        term_printf("device not found\n");
+        monitor_printf(mon, "device not found\n");
         return;
     }
-    eject_device(bs, force);
+    eject_device(mon, bs, force);
 }
 
-static void do_change_block(const char *device, const char *filename, const char *fmt)
+static void do_change_block(Monitor *mon, const char *device,
+                            const char *filename, const char *fmt)
 {
     BlockDriverState *bs;
     BlockDriver *drv = NULL;
 
     bs = bdrv_find(device);
     if (!bs) {
-        term_printf("device not found\n");
+        monitor_printf(mon, "device not found\n");
         return;
     }
     if (fmt) {
         drv = bdrv_find_format(fmt);
         if (!drv) {
-            term_printf("invalid format %s\n", fmt);
+            monitor_printf(mon, "invalid format %s\n", fmt);
             return;
         }
     }
-    if (eject_device(bs, 0) < 0)
+    if (eject_device(mon, bs, 0) < 0)
         return;
     bdrv_open2(bs, filename, 0, drv);
-    qemu_key_check(bs, filename);
+    monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+}
+
+static void change_vnc_password_cb(Monitor *mon, const char *password,
+                                   void *opaque)
+{
+    if (vnc_display_password(NULL, password) < 0)
+        monitor_printf(mon, "could not set VNC server password\n");
+
+    monitor_read_command(mon, 1);
 }
 
-static void do_change_vnc(const char *target)
+static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
 {
     if (strcmp(target, "passwd") == 0 ||
-       strcmp(target, "password") == 0) {
-       char password[9];
-       monitor_readline("Password: ", 1, password, sizeof(password)-1);
-       password[sizeof(password)-1] = '\0';
-       if (vnc_display_password(NULL, password) < 0)
-           term_printf("could not set VNC server password\n");
+        strcmp(target, "password") == 0) {
+        if (arg) {
+            char password[9];
+            strncpy(password, arg, sizeof(password));
+            password[sizeof(password) - 1] = '\0';
+            change_vnc_password_cb(mon, password, NULL);
+        } else {
+            monitor_read_password(mon, change_vnc_password_cb, NULL);
+        }
     } else {
-       if (vnc_display_open(NULL, target) < 0)
-           term_printf("could not start VNC server on %s\n", target);
+        if (vnc_display_open(NULL, target) < 0)
+            monitor_printf(mon, "could not start VNC server on %s\n", target);
     }
 }
 
-static void do_change(const char *device, const char *target, const char *fmt)
+static void do_change(Monitor *mon, const char *device, const char *target,
+                      const char *arg)
 {
     if (strcmp(device, "vnc") == 0) {
-       do_change_vnc(target);
+        do_change_vnc(mon, target, arg);
     } else {
-       do_change_block(device, target, fmt);
+        do_change_block(mon, device, target, arg);
     }
 }
 
-static void do_screen_dump(const char *filename)
+static void do_screen_dump(Monitor *mon, const char *filename)
 {
     vga_hw_screen_dump(filename);
 }
 
-static void do_logfile(const char *filename)
+static void do_logfile(Monitor *mon, const char *filename)
 {
     cpu_set_log_filename(filename);
 }
 
-static void do_log(const char *items)
+static void do_log(Monitor *mon, const char *items)
 {
     int mask;
 
@@ -471,64 +522,116 @@ static void do_log(const char *items)
     } else {
         mask = cpu_str_to_log_mask(items);
         if (!mask) {
-            help_cmd("log");
+            help_cmd(mon, "log");
             return;
         }
     }
     cpu_set_log(mask);
 }
 
-static void do_stop(void)
+static void do_singlestep(Monitor *mon, const char *option)
+{
+    if (!option || !strcmp(option, "on")) {
+        singlestep = 1;
+    } else if (!strcmp(option, "off")) {
+        singlestep = 0;
+    } else {
+        monitor_printf(mon, "unexpected option %s\n", option);
+    }
+}
+
+static void do_stop(Monitor *mon)
 {
     vm_stop(EXCP_INTERRUPT);
 }
 
-static void do_cont(void)
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
+
+struct bdrv_iterate_context {
+    Monitor *mon;
+    int err;
+};
+
+static void do_cont(Monitor *mon)
+{
+    struct bdrv_iterate_context context = { mon, 0 };
+
+    bdrv_iterate(encrypted_bdrv_it, &context);
+    /* only resume the vm if all keys are set and valid */
+    if (!context.err)
+        vm_start();
+}
+
+static void bdrv_key_cb(void *opaque, int err)
 {
-    vm_start();
+    Monitor *mon = opaque;
+
+    /* another key was set successfully, retry to continue */
+    if (!err)
+        do_cont(mon);
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    struct bdrv_iterate_context *context = opaque;
+
+    if (!context->err && bdrv_key_required(bs)) {
+        context->err = -EBUSY;
+        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
+                                    context->mon);
+    }
 }
 
-#ifdef CONFIG_GDBSTUB
-static void do_gdbserver(const char *port)
+static void do_gdbserver(Monitor *mon, const char *device)
 {
-    if (!port)
-        port = DEFAULT_GDBSTUB_PORT;
-    if (gdbserver_start(port) < 0) {
-        qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
+    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) {
+        monitor_printf(mon, "Disabled gdbserver\n");
     } else {
-        qemu_printf("Waiting gdb connection on port '%s'\n", port);
+        monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
+                       device);
+    }
+}
+
+static void do_watchdog_action(Monitor *mon, const char *action)
+{
+    if (select_watchdog_action(action) == -1) {
+        monitor_printf(mon, "Unknown watchdog action '%s'\n", action);
     }
 }
-#endif
 
-static void term_printc(int c)
+static void monitor_printc(Monitor *mon, int c)
 {
-    term_printf("'");
+    monitor_printf(mon, "'");
     switch(c) {
     case '\'':
-        term_printf("\\'");
+        monitor_printf(mon, "\\'");
         break;
     case '\\':
-        term_printf("\\\\");
+        monitor_printf(mon, "\\\\");
         break;
     case '\n':
-        term_printf("\\n");
+        monitor_printf(mon, "\\n");
         break;
     case '\r':
-        term_printf("\\r");
+        monitor_printf(mon, "\\r");
         break;
     default:
         if (c >= 32 && c <= 126) {
-            term_printf("%c", c);
+            monitor_printf(mon, "%c", c);
         } else {
-            term_printf("\\x%02x", c);
+            monitor_printf(mon, "\\x%02x", c);
         }
         break;
     }
-    term_printf("'");
+    monitor_printf(mon, "'");
 }
 
-static void memory_dump(int count, int format, int wsize,
+static void memory_dump(Monitor *mon, int count, int format, int wsize,
                         target_phys_addr_t addr, int is_physical)
 {
     CPUState *env;
@@ -562,7 +665,7 @@ static void memory_dump(int count, int format, int wsize,
             }
         }
 #endif
-        monitor_disas(env, addr, count, is_physical, flags);
+        monitor_disas(mon, env, addr, count, is_physical, flags);
         return;
     }
 
@@ -593,9 +696,9 @@ static void memory_dump(int count, int format, int wsize,
 
     while (len > 0) {
         if (is_physical)
-            term_printf(TARGET_FMT_plx ":", addr);
+            monitor_printf(mon, TARGET_FMT_plx ":", addr);
         else
-            term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
+            monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
         l = len;
         if (l > line_size)
             l = line_size;
@@ -606,7 +709,7 @@ static void memory_dump(int count, int format, int wsize,
             if (!env)
                 break;
             if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
-                term_printf(" Cannot access memory\n");
+                monitor_printf(mon, " Cannot access memory\n");
                 break;
             }
         }
@@ -627,27 +730,27 @@ static void memory_dump(int count, int format, int wsize,
                 v = ldq_raw(buf + i);
                 break;
             }
-            term_printf(" ");
+            monitor_printf(mon, " ");
             switch(format) {
             case 'o':
-                term_printf("%#*" PRIo64, max_digits, v);
+                monitor_printf(mon, "%#*" PRIo64, max_digits, v);
                 break;
             case 'x':
-                term_printf("0x%0*" PRIx64, max_digits, v);
+                monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
                 break;
             case 'u':
-                term_printf("%*" PRIu64, max_digits, v);
+                monitor_printf(mon, "%*" PRIu64, max_digits, v);
                 break;
             case 'd':
-                term_printf("%*" PRId64, max_digits, v);
+                monitor_printf(mon, "%*" PRId64, max_digits, v);
                 break;
             case 'c':
-                term_printc(v);
+                monitor_printc(mon, v);
                 break;
             }
             i += wsize;
         }
-        term_printf("\n");
+        monitor_printf(mon, "\n");
         addr += l;
         len -= l;
     }
@@ -659,11 +762,11 @@ static void memory_dump(int count, int format, int wsize,
 #define GET_TLONG(h, l) (l)
 #endif
 
-static void do_memory_dump(int count, int format, int size,
+static void do_memory_dump(Monitor *mon, int count, int format, int size,
                            uint32_t addrh, uint32_t addrl)
 {
     target_long addr = GET_TLONG(addrh, addrl);
-    memory_dump(count, format, size, addr, 0);
+    memory_dump(mon, count, format, size, addr, 0);
 }
 
 #if TARGET_PHYS_ADDR_BITS > 32
@@ -672,60 +775,61 @@ static void do_memory_dump(int count, int format, int size,
 #define GET_TPHYSADDR(h, l) (l)
 #endif
 
-static void do_physical_memory_dump(int count, int format, int size,
-                                    uint32_t addrh, uint32_t addrl)
+static void do_physical_memory_dump(Monitor *mon, int count, int format,
+                                    int size, uint32_t addrh, uint32_t addrl)
 
 {
     target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
-    memory_dump(count, format, size, addr, 1);
+    memory_dump(mon, count, format, size, addr, 1);
 }
 
-static void do_print(int count, int format, int size, unsigned int valh, unsigned int vall)
+static void do_print(Monitor *mon, int count, int format, int size,
+                     unsigned int valh, unsigned int vall)
 {
     target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
 #if TARGET_PHYS_ADDR_BITS == 32
     switch(format) {
     case 'o':
-        term_printf("%#o", val);
+        monitor_printf(mon, "%#o", val);
         break;
     case 'x':
-        term_printf("%#x", val);
+        monitor_printf(mon, "%#x", val);
         break;
     case 'u':
-        term_printf("%u", val);
+        monitor_printf(mon, "%u", val);
         break;
     default:
     case 'd':
-        term_printf("%d", val);
+        monitor_printf(mon, "%d", val);
         break;
     case 'c':
-        term_printc(val);
+        monitor_printc(mon, val);
         break;
     }
 #else
     switch(format) {
     case 'o':
-        term_printf("%#" PRIo64, val);
+        monitor_printf(mon, "%#" PRIo64, val);
         break;
     case 'x':
-        term_printf("%#" PRIx64, val);
+        monitor_printf(mon, "%#" PRIx64, val);
         break;
     case 'u':
-        term_printf("%" PRIu64, val);
+        monitor_printf(mon, "%" PRIu64, val);
         break;
     default:
     case 'd':
-        term_printf("%" PRId64, val);
+        monitor_printf(mon, "%" PRId64, val);
         break;
     case 'c':
-        term_printc(val);
+        monitor_printc(mon, val);
         break;
     }
 #endif
-    term_printf("\n");
+    monitor_printf(mon, "\n");
 }
 
-static void do_memory_save(unsigned int valh, unsigned int vall,
+static void do_memory_save(Monitor *mon, unsigned int valh, unsigned int vall,
                            uint32_t size, const char *filename)
 {
     FILE *f;
@@ -740,7 +844,7 @@ static void do_memory_save(unsigned int valh, unsigned int vall,
 
     f = fopen(filename, "wb");
     if (!f) {
-        term_printf("could not open '%s'\n", filename);
+        monitor_printf(mon, "could not open '%s'\n", filename);
         return;
     }
     while (size != 0) {
@@ -755,8 +859,9 @@ static void do_memory_save(unsigned int valh, unsigned int vall,
     fclose(f);
 }
 
-static void do_physical_memory_save(unsigned int valh, unsigned int vall,
-                                    uint32_t size, const char *filename)
+static void do_physical_memory_save(Monitor *mon, unsigned int valh,
+                                    unsigned int vall, uint32_t size,
+                                    const char *filename)
 {
     FILE *f;
     uint32_t l;
@@ -765,7 +870,7 @@ static void do_physical_memory_save(unsigned int valh, unsigned int vall,
 
     f = fopen(filename, "wb");
     if (!f) {
-        term_printf("could not open '%s'\n", filename);
+        monitor_printf(mon, "could not open '%s'\n", filename);
         return;
     }
     while (size != 0) {
@@ -781,7 +886,7 @@ static void do_physical_memory_save(unsigned int valh, unsigned int vall,
     fclose(f);
 }
 
-static void do_sum(uint32_t start, uint32_t size)
+static void do_sum(Monitor *mon, uint32_t start, uint32_t size)
 {
     uint32_t addr;
     uint8_t buf[1];
@@ -794,7 +899,7 @@ static void do_sum(uint32_t start, uint32_t size)
         sum = (sum >> 1) | (sum << 15);
         sum += buf[0];
     }
-    term_printf("%05d\n", sum);
+    monitor_printf(mon, "%05d\n", sum);
 }
 
 typedef struct {
@@ -977,7 +1082,8 @@ static void release_keys(void *opaque)
     }
 }
 
-static void do_sendkey(const char *string, int has_hold_time, int hold_time)
+static void do_sendkey(Monitor *mon, const char *string, int has_hold_time,
+                       int hold_time)
 {
     char keyname_buf[16];
     char *separator;
@@ -996,17 +1102,17 @@ static void do_sendkey(const char *string, int has_hold_time, int hold_time)
         if (keyname_len > 0) {
             pstrcpy(keyname_buf, sizeof(keyname_buf), string);
             if (keyname_len > sizeof(keyname_buf) - 1) {
-                term_printf("invalid key: '%s...'\n", keyname_buf);
+                monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
                 return;
             }
             if (i == MAX_KEYCODES) {
-                term_printf("too many keys\n");
+                monitor_printf(mon, "too many keys\n");
                 return;
             }
             keyname_buf[keyname_len] = 0;
             keycode = get_keycode(keyname_buf);
             if (keycode < 0) {
-                term_printf("unknown key: '%s'\n", keyname_buf);
+                monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
                 return;
             }
             keycodes[i++] = keycode;
@@ -1030,7 +1136,7 @@ static void do_sendkey(const char *string, int has_hold_time, int hold_time)
 
 static int mouse_button_state;
 
-static void do_mouse_move(const char *dx_str, const char *dy_str,
+static void do_mouse_move(Monitor *mon, const char *dx_str, const char *dy_str,
                           const char *dz_str)
 {
     int dx, dy, dz;
@@ -1042,13 +1148,14 @@ static void do_mouse_move(const char *dx_str, const char *dy_str,
     kbd_mouse_event(dx, dy, dz, mouse_button_state);
 }
 
-static void do_mouse_button(int button_state)
+static void do_mouse_button(Monitor *mon, int button_state)
 {
     mouse_button_state = button_state;
     kbd_mouse_event(0, 0, 0, mouse_button_state);
 }
 
-static void do_ioport_read(int count, int format, int size, int addr, int has_index, int index)
+static void do_ioport_read(Monitor *mon, int count, int format, int size,
+                           int addr, int has_index, int index)
 {
     uint32_t val;
     int suffix;
@@ -1074,8 +1181,8 @@ static void do_ioport_read(int count, int format, int size, int addr, int has_in
         suffix = 'l';
         break;
     }
-    term_printf("port%c[0x%04x] = %#0*x\n",
-                suffix, addr, size * 2, val);
+    monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
+                   suffix, addr, size * 2, val);
 }
 
 /* boot_set handler */
@@ -1088,48 +1195,51 @@ void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
     boot_opaque = opaque;
 }
 
-static void do_boot_set(const char *bootdevice)
+static void do_boot_set(Monitor *mon, const char *bootdevice)
 {
     int res;
 
     if (qemu_boot_set_handler)  {
         res = qemu_boot_set_handler(boot_opaque, bootdevice);
         if (res == 0)
-            term_printf("boot device list now set to %s\n", bootdevice);
+            monitor_printf(mon, "boot device list now set to %s\n",
+                           bootdevice);
         else
-            term_printf("setting boot device list failed with error %i\n", res);
+            monitor_printf(mon, "setting boot device list failed with "
+                           "error %i\n", res);
     } else {
-        term_printf("no function defined to set boot device list for this architecture\n");
+        monitor_printf(mon, "no function defined to set boot device list for "
+                       "this architecture\n");
     }
 }
 
-static void do_system_reset(void)
+static void do_system_reset(Monitor *mon)
 {
     qemu_system_reset_request();
 }
 
-static void do_system_powerdown(void)
+static void do_system_powerdown(Monitor *mon)
 {
     qemu_system_powerdown_request();
 }
 
 #if defined(TARGET_I386)
-static void print_pte(uint32_t addr, uint32_t pte, uint32_t mask)
+static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
 {
-    term_printf("%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' : '-');
+    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' : '-');
 }
 
-static void tlb_info(void)
+static void tlb_info(Monitor *mon)
 {
     CPUState *env;
     int l1, l2;
@@ -1140,7 +1250,7 @@ static void tlb_info(void)
         return;
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
-        term_printf("PG disabled\n");
+        monitor_printf(mon, "PG disabled\n");
         return;
     }
     pgd = env->cr[3] & ~0xfff;
@@ -1149,14 +1259,14 @@ static void tlb_info(void)
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
-                print_pte((l1 << 22), pde, ~((1 << 20) - 1));
+                print_pte(mon, (l1 << 22), pde, ~((1 << 20) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
                     cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
                                              (uint8_t *)&pte, 4);
                     pte = le32_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
-                        print_pte((l1 << 22) + (l2 << 12),
+                        print_pte(mon, (l1 << 22) + (l2 << 12),
                                   pte & ~PG_PSE_MASK,
                                   ~0xfff);
                     }
@@ -1166,18 +1276,18 @@ static void tlb_info(void)
     }
 }
 
-static void mem_print(uint32_t *pstart, int *plast_prot,
+static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
                       uint32_t end, int prot)
 {
     int prot1;
     prot1 = *plast_prot;
     if (prot != prot1) {
         if (*pstart != -1) {
-            term_printf("%08x-%08x %08x %c%c%c\n",
-                        *pstart, end, end - *pstart,
-                        prot1 & PG_USER_MASK ? 'u' : '-',
-                        'r',
-                        prot1 & PG_RW_MASK ? 'w' : '-');
+            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' : '-');
         }
         if (prot != 0)
             *pstart = end;
@@ -1187,7 +1297,7 @@ static void mem_print(uint32_t *pstart, int *plast_prot,
     }
 }
 
-static void mem_info(void)
+static void mem_info(Monitor *mon)
 {
     CPUState *env;
     int l1, l2, prot, last_prot;
@@ -1198,7 +1308,7 @@ static void mem_info(void)
         return;
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
-        term_printf("PG disabled\n");
+        monitor_printf(mon, "PG disabled\n");
         return;
     }
     pgd = env->cr[3] & ~0xfff;
@@ -1211,7 +1321,7 @@ static void mem_info(void)
         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);
-                mem_print(&start, &last_prot, end, prot);
+                mem_print(mon, &start, &last_prot, end, prot);
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
                     cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
@@ -1223,60 +1333,108 @@ static void mem_info(void)
                     } else {
                         prot = 0;
                     }
-                    mem_print(&start, &last_prot, end, prot);
+                    mem_print(mon, &start, &last_prot, end, prot);
                 }
             }
         } else {
             prot = 0;
-            mem_print(&start, &last_prot, end, prot);
+            mem_print(mon, &start, &last_prot, end, prot);
         }
     }
 }
 #endif
 
-static void do_info_kqemu(void)
+#if defined(TARGET_SH4)
+
+static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
+{
+    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);
+}
+
+static void tlb_info(Monitor *mon)
+{
+    CPUState *env = mon_get_cpu();
+    int i;
+
+    monitor_printf (mon, "ITLB:\n");
+    for (i = 0 ; i < ITLB_SIZE ; i++)
+        print_tlb (mon, i, &env->itlb[i]);
+    monitor_printf (mon, "UTLB:\n");
+    for (i = 0 ; i < UTLB_SIZE ; i++)
+        print_tlb (mon, i, &env->utlb[i]);
+}
+
+#endif
+
+static void do_info_kqemu(Monitor *mon)
 {
-#ifdef USE_KQEMU
+#ifdef CONFIG_KQEMU
     CPUState *env;
     int val;
     val = 0;
     env = mon_get_cpu();
     if (!env) {
-        term_printf("No cpu initialized yet");
+        monitor_printf(mon, "No cpu initialized yet");
         return;
     }
     val = env->kqemu_enabled;
-    term_printf("kqemu support: ");
+    monitor_printf(mon, "kqemu support: ");
     switch(val) {
     default:
     case 0:
-        term_printf("disabled\n");
+        monitor_printf(mon, "disabled\n");
         break;
     case 1:
-        term_printf("enabled for user code\n");
+        monitor_printf(mon, "enabled for user code\n");
         break;
     case 2:
-        term_printf("enabled for user and kernel code\n");
+        monitor_printf(mon, "enabled for user and kernel code\n");
         break;
     }
 #else
-    term_printf("kqemu support: not compiled\n");
+    monitor_printf(mon, "kqemu support: not compiled\n");
 #endif
 }
 
-static void do_info_kvm(void)
+static void do_info_kvm(Monitor *mon)
 {
 #ifdef CONFIG_KVM
-    term_printf("kvm support: ");
+    monitor_printf(mon, "kvm support: ");
     if (kvm_enabled())
-       term_printf("enabled\n");
+        monitor_printf(mon, "enabled\n");
     else
-       term_printf("disabled\n");
+        monitor_printf(mon, "disabled\n");
 #else
-    term_printf("kvm support: not compiled\n");
+    monitor_printf(mon, "kvm support: not compiled\n");
 #endif
 }
 
+static void do_info_numa(Monitor *mon)
+{
+    int i;
+    CPUState *env;
+
+    monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
+    for (i = 0; i < nb_numa_nodes; i++) {
+        monitor_printf(mon, "node %d cpus:", i);
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            if (env->numa_node == i) {
+                monitor_printf(mon, " %d", env->cpu_index);
+            }
+        }
+        monitor_printf(mon, "\n");
+        monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
+            node_mem[i] >> 20);
+    }
+}
+
 #ifdef CONFIG_PROFILER
 
 int64_t kqemu_time;
@@ -1287,23 +1445,25 @@ int64_t kqemu_ret_int_count;
 int64_t kqemu_ret_excp_count;
 int64_t kqemu_ret_intr_count;
 
-static void do_info_profile(void)
+static void do_info_profile(Monitor *mon)
 {
     int64_t total;
     total = qemu_time;
     if (total == 0)
         total = 1;
-    term_printf("async time  %" PRId64 " (%0.3f)\n",
-                dev_time, dev_time / (double)ticks_per_sec);
-    term_printf("qemu time   %" PRId64 " (%0.3f)\n",
-                qemu_time, qemu_time / (double)ticks_per_sec);
-    term_printf("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);
+    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);
     qemu_time = 0;
     kqemu_time = 0;
     kqemu_exec_count = 0;
@@ -1311,32 +1471,33 @@ static void do_info_profile(void)
     kqemu_ret_int_count = 0;
     kqemu_ret_excp_count = 0;
     kqemu_ret_intr_count = 0;
-#ifdef USE_KQEMU
+#ifdef CONFIG_KQEMU
     kqemu_record_dump();
 #endif
 }
 #else
-static void do_info_profile(void)
+static void do_info_profile(Monitor *mon)
 {
-    term_printf("Internal profiler not compiled\n");
+    monitor_printf(mon, "Internal profiler not compiled\n");
 }
 #endif
 
 /* Capture support */
 static LIST_HEAD (capture_list_head, CaptureState) capture_head;
 
-static void do_info_capture (void)
+static void do_info_capture(Monitor *mon)
 {
     int i;
     CaptureState *s;
 
     for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
-        term_printf ("[%d]: ", i);
+        monitor_printf(mon, "[%d]: ", i);
         s->ops.info (s->opaque);
     }
 }
 
-static void do_stop_capture (int n)
+#ifdef HAS_AUDIO
+static void do_stop_capture(Monitor *mon, int n)
 {
     int i;
     CaptureState *s;
@@ -1351,26 +1512,21 @@ static void do_stop_capture (int n)
     }
 }
 
-#ifdef HAS_AUDIO
-static void do_wav_capture (const char *path,
-                            int has_freq, int freq,
-                            int has_bits, int bits,
-                            int has_channels, int nchannels)
+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)
 {
     CaptureState *s;
 
     s = qemu_mallocz (sizeof (*s));
-    if (!s) {
-        term_printf ("Not enough memory to add wave capture\n");
-        return;
-    }
 
     freq = has_freq ? freq : 44100;
     bits = has_bits ? bits : 16;
     nchannels = has_channels ? nchannels : 2;
 
     if (wav_start_capture (s, path, freq, bits, nchannels)) {
-        term_printf ("Faied to add wave capture\n");
+        monitor_printf(mon, "Faied to add wave capture\n");
         qemu_free (s);
     }
     LIST_INSERT_HEAD (&capture_head, s, entries);
@@ -1378,7 +1534,7 @@ static void do_wav_capture (const char *path,
 #endif
 
 #if defined(TARGET_I386)
-static void do_inject_nmi(int cpu_index)
+static void do_inject_nmi(Monitor *mon, int cpu_index)
 {
     CPUState *env;
 
@@ -1390,104 +1546,135 @@ static void do_inject_nmi(int cpu_index)
 }
 #endif
 
-static const term_cmd_t term_cmds[] = {
-    { "help|?", "s?", do_help,
-      "[cmd]", "show the help" },
-    { "commit", "s", do_commit,
-      "device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
-    { "info", "s?", do_info,
-      "subcommand", "show various information about the system state" },
-    { "q|quit", "", do_quit,
-      "", "quit the emulator" },
-    { "eject", "-fB", do_eject,
-      "[-f] device", "eject a removable medium (use -f to force it)" },
-    { "change", "BFs?", do_change,
-      "device filename [format]", "change a removable medium, optional format" },
-    { "screendump", "F", do_screen_dump,
-      "filename", "save screen into PPM image 'filename'" },
-    { "logfile", "F", do_logfile,
-      "filename", "output logs to 'filename'" },
-    { "log", "s", do_log,
-      "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
-    { "savevm", "s?", do_savevm,
-      "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" },
-    { "loadvm", "s", do_loadvm,
-      "tag|id", "restore a VM snapshot from its tag or id" },
-    { "delvm", "s", do_delvm,
-      "tag|id", "delete a VM snapshot from its tag or id" },
-    { "stop", "", do_stop,
-      "", "stop emulation", },
-    { "c|cont", "", do_cont,
-      "", "resume emulation", },
-#ifdef CONFIG_GDBSTUB
-    { "gdbserver", "s?", do_gdbserver,
-      "[port]", "start gdbserver session (default port=1234)", },
-#endif
-    { "x", "/l", do_memory_dump,
-      "/fmt addr", "virtual memory dump starting at 'addr'", },
-    { "xp", "/l", do_physical_memory_dump,
-      "/fmt addr", "physical memory dump starting at 'addr'", },
-    { "p|print", "/l", do_print,
-      "/fmt expr", "print expression value (use $reg for CPU register access)", },
-    { "i", "/ii.", do_ioport_read,
-      "/fmt addr", "I/O port read" },
-
-    { "sendkey", "si?", do_sendkey,
-      "keys [hold_ms]", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)" },
-    { "system_reset", "", do_system_reset,
-      "", "reset the system" },
-    { "system_powerdown", "", do_system_powerdown,
-      "", "send system power down event" },
-    { "sum", "ii", do_sum,
-      "addr size", "compute the checksum of a memory region" },
-    { "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'" },
-    { "cpu", "i", do_cpu_set,
-      "index", "set the default CPU" },
-    { "mouse_move", "sss?", do_mouse_move,
-      "dx dy [dz]", "send mouse move events" },
-    { "mouse_button", "i", do_mouse_button,
-      "state", "change mouse button state (1=L, 2=M, 4=R)" },
-    { "mouse_set", "i", do_mouse_set,
-      "index", "set which mouse device receives events" },
-#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
-     { "stopcapture", "i", do_stop_capture,
-       "capture index", "stop capture" },
-    { "memsave", "lis", do_memory_save,
-      "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
-    { "pmemsave", "lis", do_physical_memory_save,
-      "addr size file", "save to disk physical memory dump starting at 'addr' of size 'size'", },
-    { "boot_set", "s", do_boot_set,
-      "bootdevice", "define new values for the boot device list" },
-#if defined(TARGET_I386)
-    { "nmi", "i", do_inject_nmi,
-      "cpu", "inject an NMI on the given CPU", },
-#endif
-    { "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" },
+static void do_info_status(Monitor *mon)
+{
+    if (vm_running) {
+        if (singlestep) {
+            monitor_printf(mon, "VM status: running (single step mode)\n");
+        } else {
+            monitor_printf(mon, "VM status: running\n");
+        }
+    } else
+       monitor_printf(mon, "VM status: paused\n");
+}
+
+
+static void do_balloon(Monitor *mon, int value)
+{
+    ram_addr_t target = value;
+    qemu_balloon(target << 20);
+}
+
+static void do_info_balloon(Monitor *mon)
+{
+    ram_addr_t actual;
+
+    actual = qemu_balloon_status();
+    if (kvm_enabled() && !kvm_has_sync_mmu())
+        monitor_printf(mon, "Using KVM without synchronous MMU, "
+                       "ballooning disabled\n");
+    else if (actual == 0)
+        monitor_printf(mon, "Ballooning not activated in VM\n");
+    else
+        monitor_printf(mon, "balloon: actual=%d\n", (int)(actual >> 20));
+}
+
+static void do_acl(Monitor *mon,
+                   const char *command,
+                   const char *aclname,
+                   const char *match,
+                   int has_index,
+                   int index)
+{
+    qemu_acl *acl;
+
+    acl = qemu_acl_find(aclname);
+    if (!acl) {
+        monitor_printf(mon, "acl: unknown list '%s'\n", aclname);
+        return;
+    }
+
+    if (strcmp(command, "show") == 0) {
+        int i = 0;
+        qemu_acl_entry *entry;
+        monitor_printf(mon, "policy: %s\n",
+                       acl->defaultDeny ? "deny" : "allow");
+        TAILQ_FOREACH(entry, &acl->entries, next) {
+            i++;
+            monitor_printf(mon, "%d: %s %s\n", i,
+                           entry->deny ? "deny" : "allow",
+                           entry->match);
+        }
+    } else if (strcmp(command, "reset") == 0) {
+        qemu_acl_reset(acl);
+        monitor_printf(mon, "acl: removed all rules\n");
+    } else if (strcmp(command, "policy") == 0) {
+        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);
+        }
+    } else if ((strcmp(command, "allow") == 0) ||
+               (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);
+    } else if (strcmp(command, "remove") == 0) {
+        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);
+    } else {
+        monitor_printf(mon, "acl: unknown command '%s'\n", command);
+    }
+}
+
+static const mon_cmd_t mon_cmds[] = {
+#include "qemu-monitor.h"
     { NULL, NULL, },
 };
 
-static const term_cmd_t info_cmds[] = {
+/* Please update qemu-monitor.hx when adding or changing commands */
+static const mon_cmd_t info_cmds[] = {
     { "version", "", do_info_version,
-      "", "show the version of qemu" },
+      "", "show the version of QEMU" },
     { "network", "", do_info_network,
       "", "show the network state" },
     { "chardev", "", qemu_chr_info,
       "", "show the character devices" },
-    { "block", "", do_info_block,
+    { "block", "", bdrv_info,
       "", "show the block devices" },
-    { "blockstats", "", do_info_blockstats,
+    { "blockstats", "", bdrv_info_stats,
       "", "show block device statistics" },
     { "registers", "", do_info_registers,
       "", "show the cpu registers" },
@@ -1501,18 +1688,24 @@ static const term_cmd_t info_cmds[] = {
       "", "show i8259 (PIC) state", },
     { "pci", "", pci_info,
       "", "show PCI info", },
-#if defined(TARGET_I386)
+#if defined(TARGET_I386) || defined(TARGET_SH4)
     { "tlb", "", tlb_info,
       "", "show virtual to physical memory mappings", },
+#endif
+#if defined(TARGET_I386)
     { "mem", "", mem_info,
       "", "show the active virtual memory mappings", },
+    { "hpet", "", do_info_hpet,
+      "", "show state of HPET", },
 #endif
     { "jit", "", do_info_jit,
       "", "show dynamic compiler info", },
     { "kqemu", "", do_info_kqemu,
-      "", "show kqemu information", },
+      "", "show KQEMU information", },
     { "kvm", "", do_info_kvm,
-      "", "show kvm information", },
+      "", "show KVM information", },
+    { "numa", "", do_info_numa,
+      "", "show NUMA information", },
     { "usb", "", usb_info,
       "", "show guest USB devices", },
     { "usbhost", "", usb_host_info,
@@ -1523,6 +1716,8 @@ static const term_cmd_t info_cmds[] = {
       "", "show capture information" },
     { "snapshots", "", do_info_snapshots,
       "", "show the currently saved VM snapshots" },
+    { "status", "", do_info_status,
+      "", "show the current VM status (running|paused)" },
     { "pcmcia", "", pcmcia_info,
       "", "show guest PCMCIA status" },
     { "mice", "", do_info_mice,
@@ -1542,6 +1737,10 @@ static const term_cmd_t info_cmds[] = {
       "", "show SLIRP statistics", },
 #endif
     { "migrate", "", do_info_migrate, "", "show migration status" },
+    { "balloon", "", do_info_balloon,
+      "", "show balloon information" },
+    { "qtree", "", do_info_qtree,
+      "", "show device tree" },
     { NULL, NULL, },
 };
 
@@ -1582,7 +1781,7 @@ static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
 
     u = 0;
     for (i = 0; i < 8; i++)
-       u |= env->crf[i] << (32 - (4 * i));
+        u |= env->crf[i] << (32 - (4 * i));
 
     return u;
 }
@@ -1889,10 +2088,9 @@ static const MonitorDef monitor_defs[] = {
     { NULL },
 };
 
-static void expr_error(const char *fmt)
+static void expr_error(Monitor *mon, const char *msg)
 {
-    term_printf(fmt);
-    term_printf("\n");
+    monitor_printf(mon, "%s\n", msg);
     longjmp(expr_env, 1);
 }
 
@@ -1938,9 +2136,9 @@ static void next(void)
     }
 }
 
-static int64_t expr_sum(void);
+static int64_t expr_sum(Monitor *mon);
 
-static int64_t expr_unary(void)
+static int64_t expr_unary(Monitor *mon)
 {
     int64_t n;
     char *p;
@@ -1949,32 +2147,32 @@ static int64_t expr_unary(void)
     switch(*pch) {
     case '+':
         next();
-        n = expr_unary();
+        n = expr_unary(mon);
         break;
     case '-':
         next();
-        n = -expr_unary();
+        n = -expr_unary(mon);
         break;
     case '~':
         next();
-        n = ~expr_unary();
+        n = ~expr_unary(mon);
         break;
     case '(':
         next();
-        n = expr_sum();
+        n = expr_sum(mon);
         if (*pch != ')') {
-            expr_error("')' expected");
+            expr_error(mon, "')' expected");
         }
         next();
         break;
     case '\'':
         pch++;
         if (*pch == '\0')
-            expr_error("character constant expected");
+            expr_error(mon, "character constant expected");
         n = *pch;
         pch++;
         if (*pch != '\'')
-            expr_error("missing terminating \' character");
+            expr_error(mon, "missing terminating \' character");
         next();
         break;
     case '$':
@@ -1997,14 +2195,14 @@ static int64_t expr_unary(void)
             *q = 0;
             ret = get_monitor_def(&reg, buf);
             if (ret == -1)
-                expr_error("unknown register");
+                expr_error(mon, "unknown register");
             else if (ret == -2)
-                expr_error("no cpu defined");
+                expr_error(mon, "no cpu defined");
             n = reg;
         }
         break;
     case '\0':
-        expr_error("unexpected end of expression");
+        expr_error(mon, "unexpected end of expression");
         n = 0;
         break;
     default:
@@ -2014,7 +2212,7 @@ static int64_t expr_unary(void)
         n = strtoul(pch, &p, 0);
 #endif
         if (pch == p) {
-            expr_error("invalid char in expression");
+            expr_error(mon, "invalid char in expression");
         }
         pch = p;
         while (qemu_isspace(*pch))
@@ -2025,18 +2223,18 @@ static int64_t expr_unary(void)
 }
 
 
-static int64_t expr_prod(void)
+static int64_t expr_prod(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_unary();
+    val = expr_unary(mon);
     for(;;) {
         op = *pch;
         if (op != '*' && op != '/' && op != '%')
             break;
         next();
-        val2 = expr_unary();
+        val2 = expr_unary(mon);
         switch(op) {
         default:
         case '*':
@@ -2045,7 +2243,7 @@ static int64_t expr_prod(void)
         case '/':
         case '%':
             if (val2 == 0)
-                expr_error("division by zero");
+                expr_error(mon, "division by zero");
             if (op == '/')
                 val /= val2;
             else
@@ -2056,18 +2254,18 @@ static int64_t expr_prod(void)
     return val;
 }
 
-static int64_t expr_logic(void)
+static int64_t expr_logic(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_prod();
+    val = expr_prod(mon);
     for(;;) {
         op = *pch;
         if (op != '&' && op != '|' && op != '^')
             break;
         next();
-        val2 = expr_prod();
+        val2 = expr_prod(mon);
         switch(op) {
         default:
         case '&':
@@ -2084,18 +2282,18 @@ static int64_t expr_logic(void)
     return val;
 }
 
-static int64_t expr_sum(void)
+static int64_t expr_sum(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_logic();
+    val = expr_logic(mon);
     for(;;) {
         op = *pch;
         if (op != '+' && op != '-')
             break;
         next();
-        val2 = expr_logic();
+        val2 = expr_logic(mon);
         if (op == '+')
             val += val2;
         else
@@ -2104,7 +2302,7 @@ static int64_t expr_sum(void)
     return val;
 }
 
-static int get_expr(int64_t *pval, const char **pp)
+static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
 {
     pch = *pp;
     if (setjmp(expr_env)) {
@@ -2113,7 +2311,7 @@ static int get_expr(int64_t *pval, const char **pp)
     }
     while (qemu_isspace(*pch))
         pch++;
-    *pval = expr_sum();
+    *pval = expr_sum(mon);
     *pp = pch;
     return 0;
 }
@@ -2188,30 +2386,31 @@ static int default_fmt_size = 4;
 
 #define MAX_ARGS 16
 
-static void monitor_handle_command(const char *cmdline)
+static void monitor_handle_command(Monitor *mon, const char *cmdline)
 {
     const char *p, *pstart, *typestr;
     char *q;
     int c, nb_args, len, i, has_arg;
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
     char cmdname[256];
     char buf[1024];
     void *str_allocated[MAX_ARGS];
     void *args[MAX_ARGS];
-    void (*handler_0)(void);
-    void (*handler_1)(void *arg0);
-    void (*handler_2)(void *arg0, void *arg1);
-    void (*handler_3)(void *arg0, void *arg1, void *arg2);
-    void (*handler_4)(void *arg0, void *arg1, void *arg2, void *arg3);
-    void (*handler_5)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4);
-    void (*handler_6)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4, void *arg5);
-    void (*handler_7)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4, void *arg5, void *arg6);
+    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);
 
 #ifdef DEBUG
-    term_printf("command='%s'\n", cmdline);
+    monitor_printf(mon, "command='%s'\n", cmdline);
 #endif
 
     /* extract the command name */
@@ -2231,11 +2430,11 @@ static void monitor_handle_command(const char *cmdline)
     cmdname[len] = '\0';
 
     /* find the command */
-    for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+    for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
         if (compare_cmd(cmdname, cmd->name))
             goto found;
     }
-    term_printf("unknown command: '%s'\n", cmdname);
+    monitor_printf(mon, "unknown command: '%s'\n", cmdname);
     return;
  found:
 
@@ -2272,13 +2471,15 @@ static void monitor_handle_command(const char *cmdline)
                 if (ret < 0) {
                     switch(c) {
                     case 'F':
-                        term_printf("%s: filename expected\n", cmdname);
+                        monitor_printf(mon, "%s: filename expected\n",
+                                       cmdname);
                         break;
                     case 'B':
-                        term_printf("%s: block device name expected\n", cmdname);
+                        monitor_printf(mon, "%s: block device name expected\n",
+                                       cmdname);
                         break;
                     default:
-                        term_printf("%s: string expected\n", cmdname);
+                        monitor_printf(mon, "%s: string expected\n", cmdname);
                         break;
                     }
                     goto fail;
@@ -2289,7 +2490,7 @@ static void monitor_handle_command(const char *cmdline)
             add_str:
                 if (nb_args >= MAX_ARGS) {
                 error_args:
-                    term_printf("%s: too many arguments\n", cmdname);
+                    monitor_printf(mon, "%s: too many arguments\n", cmdname);
                     goto fail;
                 }
                 args[nb_args++] = str;
@@ -2347,7 +2548,8 @@ static void monitor_handle_command(const char *cmdline)
                     }
                 next:
                     if (*p != '\0' && !qemu_isspace(*p)) {
-                        term_printf("invalid char in format: '%c'\n", *p);
+                        monitor_printf(mon, "invalid char in format: '%c'\n",
+                                       *p);
                         goto fail;
                     }
                     if (format < 0)
@@ -2409,7 +2611,7 @@ static void monitor_handle_command(const char *cmdline)
                         goto add_num;
                     }
                 }
-                if (get_expr(&val, &p))
+                if (get_expr(mon, &val, &p))
                     goto fail;
             add_num:
                 if (c == 'i') {
@@ -2442,8 +2644,8 @@ static void monitor_handle_command(const char *cmdline)
                 if (*p == '-') {
                     p++;
                     if (*p != c) {
-                        term_printf("%s: unsupported option -%c\n",
-                                    cmdname, *p);
+                        monitor_printf(mon, "%s: unsupported option -%c\n",
+                                       cmdname, *p);
                         goto fail;
                     }
                     p++;
@@ -2456,7 +2658,7 @@ static void monitor_handle_command(const char *cmdline)
             break;
         default:
         bad_type:
-            term_printf("%s: unknown type '%c'\n", cmdname, c);
+            monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
             goto fail;
         }
     }
@@ -2464,46 +2666,47 @@ static void monitor_handle_command(const char *cmdline)
     while (qemu_isspace(*p))
         p++;
     if (*p != '\0') {
-        term_printf("%s: extraneous characters at the end of line\n",
-                    cmdname);
+        monitor_printf(mon, "%s: extraneous characters at the end of line\n",
+                       cmdname);
         goto fail;
     }
 
     switch(nb_args) {
     case 0:
         handler_0 = cmd->handler;
-        handler_0();
+        handler_0(mon);
         break;
     case 1:
         handler_1 = cmd->handler;
-        handler_1(args[0]);
+        handler_1(mon, args[0]);
         break;
     case 2:
         handler_2 = cmd->handler;
-        handler_2(args[0], args[1]);
+        handler_2(mon, args[0], args[1]);
         break;
     case 3:
         handler_3 = cmd->handler;
-        handler_3(args[0], args[1], args[2]);
+        handler_3(mon, args[0], args[1], args[2]);
         break;
     case 4:
         handler_4 = cmd->handler;
-        handler_4(args[0], args[1], args[2], args[3]);
+        handler_4(mon, args[0], args[1], args[2], args[3]);
         break;
     case 5:
         handler_5 = cmd->handler;
-        handler_5(args[0], args[1], args[2], args[3], args[4]);
+        handler_5(mon, args[0], args[1], args[2], args[3], args[4]);
         break;
     case 6:
         handler_6 = cmd->handler;
-        handler_6(args[0], args[1], args[2], args[3], args[4], args[5]);
+        handler_6(mon, args[0], args[1], args[2], args[3], args[4], args[5]);
         break;
     case 7:
         handler_7 = cmd->handler;
-        handler_7(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+        handler_7(mon, args[0], args[1], args[2], args[3], args[4], args[5],
+                  args[6]);
         break;
     default:
-        term_printf("unsupported number of arguments: %d\n", nb_args);
+        monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
         goto fail;
     }
  fail:
@@ -2530,7 +2733,7 @@ static void cmd_completion(const char *name, const char *list)
         memcpy(cmd, pstart, len);
         cmd[len] = '\0';
         if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
-            add_completion(cmd);
+            readline_add_completion(cur_mon->rs, cmd);
         }
         if (*p == '\0')
             break;
@@ -2561,7 +2764,8 @@ static void file_completion(const char *input)
         pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
     }
 #ifdef DEBUG_COMPLETION
-    term_printf("input='%s' path='%s' prefix='%s'\n", input, path, file_prefix);
+    monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n",
+                   input, path, file_prefix);
 #endif
     ffs = opendir(path);
     if (!ffs)
@@ -2582,19 +2786,20 @@ static void file_completion(const char *input)
             stat(file, &sb);
             if(S_ISDIR(sb.st_mode))
                 pstrcat(file, sizeof(file), "/");
-            add_completion(file);
+            readline_add_completion(cur_mon->rs, file);
         }
     }
     closedir(ffs);
 }
 
-static void block_completion_it(void *opaque, const char *name)
+static void block_completion_it(void *opaque, BlockDriverState *bs)
 {
+    const char *name = bdrv_get_device_name(bs);
     const char *input = opaque;
 
     if (input[0] == '\0' ||
         !strncmp(name, (char *)input, strlen(input))) {
-        add_completion(name);
+        readline_add_completion(cur_mon->rs, name);
     }
 }
 
@@ -2624,19 +2829,19 @@ static void parse_cmdline(const char *cmdline,
     *pnb_args = nb_args;
 }
 
-void readline_find_completion(const char *cmdline)
+static void monitor_find_completion(const char *cmdline)
 {
     const char *cmdname;
     char *args[MAX_ARGS];
     int nb_args, i, len;
     const char *ptype, *str;
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
     const KeyDef *key;
 
     parse_cmdline(cmdline, &nb_args, args);
 #ifdef DEBUG_COMPLETION
     for(i = 0; i < nb_args; i++) {
-        term_printf("arg%d = '%s'\n", i, (char *)args[i]);
+        monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
     }
 #endif
 
@@ -2654,13 +2859,13 @@ void readline_find_completion(const char *cmdline)
             cmdname = "";
         else
             cmdname = args[0];
-        completion_index = strlen(cmdname);
-        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+        readline_set_completion_index(cur_mon->rs, strlen(cmdname));
+        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             cmd_completion(cmdname, cmd->name);
         }
     } else {
         /* find the command */
-        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             if (compare_cmd(args[0], cmd->name))
                 goto found;
         }
@@ -2678,23 +2883,26 @@ void readline_find_completion(const char *cmdline)
         switch(*ptype) {
         case 'F':
             /* file completion */
-            completion_index = strlen(str);
+            readline_set_completion_index(cur_mon->rs, strlen(str));
             file_completion(str);
             break;
         case 'B':
             /* block device name completion */
-            completion_index = strlen(str);
+            readline_set_completion_index(cur_mon->rs, strlen(str));
             bdrv_iterate(block_completion_it, (void *)str);
             break;
         case 's':
             /* XXX: more generic ? */
             if (!strcmp(cmd->name, "info")) {
-                completion_index = strlen(str);
+                readline_set_completion_index(cur_mon->rs, strlen(str));
                 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
                     cmd_completion(str, cmd->name);
                 }
             } else if (!strcmp(cmd->name, "sendkey")) {
-                completion_index = strlen(str);
+                char *sep = strrchr(str, '-');
+                if (sep)
+                    str = sep + 1;
+                readline_set_completion_index(cur_mon->rs, strlen(str));
                 for(key = key_defs; key->name != NULL; key++) {
                     cmd_completion(str, key->name);
                 }
@@ -2708,126 +2916,156 @@ void readline_find_completion(const char *cmdline)
         qemu_free(args[i]);
 }
 
-static int term_can_read(void *opaque)
+static int monitor_can_read(void *opaque)
 {
-    return 128;
+    Monitor *mon = opaque;
+
+    return (mon->suspend_cnt == 0) ? 128 : 0;
 }
 
-static void term_read(void *opaque, const uint8_t *buf, int size)
+static void monitor_read(void *opaque, const uint8_t *buf, int size)
 {
+    Monitor *old_mon = cur_mon;
     int i;
-    for(i = 0; i < size; i++)
-        readline_handle_byte(buf[i]);
-}
 
-static int monitor_suspended;
+    cur_mon = opaque;
 
-static void monitor_handle_command1(void *opaque, const char *cmdline)
-{
-    monitor_handle_command(cmdline);
-    if (!monitor_suspended)
-        monitor_start_input();
-    else
-        monitor_suspended = 2;
+    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);
+    }
+
+    cur_mon = old_mon;
 }
 
-void monitor_suspend(void)
+static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
 {
-    monitor_suspended = 1;
+    monitor_suspend(mon);
+    monitor_handle_command(mon, cmdline);
+    monitor_resume(mon);
 }
 
-void monitor_resume(void)
+int monitor_suspend(Monitor *mon)
 {
-    if (monitor_suspended == 2)
-        monitor_start_input();
-    monitor_suspended = 0;
+    if (!mon->rs)
+        return -ENOTTY;
+    mon->suspend_cnt++;
+    return 0;
 }
 
-static void monitor_start_input(void)
+void monitor_resume(Monitor *mon)
 {
-    readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
+    if (!mon->rs)
+        return;
+    if (--mon->suspend_cnt == 0)
+        readline_show_prompt(mon->rs);
 }
 
-static void term_event(void *opaque, int event)
+static void monitor_event(void *opaque, int event)
 {
-    if (event != CHR_EVENT_RESET)
-       return;
+    Monitor *mon = opaque;
+
+    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;
 
-    if (!hide_banner)
-           term_printf("QEMU %s monitor - type 'help' for more information\n",
-                       QEMU_VERSION);
-    monitor_start_input();
+    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;
+    }
 }
 
-static int is_first_init = 1;
 
-void monitor_init(CharDriverState *hd, int show_banner)
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
+
+void monitor_init(CharDriverState *chr, int flags)
 {
-    int i;
+    static int is_first_init = 1;
+    Monitor *mon;
 
     if (is_first_init) {
         key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
-        if (!key_timer)
-            return;
-        for (i = 0; i < MAX_MON; i++) {
-            monitor_hd[i] = NULL;
-        }
         is_first_init = 0;
     }
-    for (i = 0; i < MAX_MON; i++) {
-        if (monitor_hd[i] == NULL) {
-            monitor_hd[i] = hd;
-            break;
-        }
-    }
 
-    hide_banner = !show_banner;
+    mon = qemu_mallocz(sizeof(*mon));
 
-    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
+    mon->chr = chr;
+    mon->flags = flags;
+    if (mon->chr->focus != 0)
+        mon->suspend_cnt = 1; /* mux'ed monitors start suspended */
+    if (flags & MONITOR_USE_READLINE) {
+        mon->rs = readline_init(mon, monitor_find_completion);
+        monitor_read_command(mon, 0);
+    }
 
-    readline_start("", 0, monitor_handle_command1, NULL);
-}
+    qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
+                          mon);
 
-/* XXX: use threads ? */
-/* modal monitor readline */
-static int monitor_readline_started;
-static char *monitor_readline_buf;
-static int monitor_readline_buf_size;
+    LIST_INSERT_HEAD(&mon_list, mon, entry);
+    if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
+        cur_mon = mon;
+}
 
-static void monitor_readline_cb(void *opaque, const char *input)
+static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
 {
-    pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input);
-    monitor_readline_started = 0;
+    BlockDriverState *bs = opaque;
+    int ret = 0;
+
+    if (bdrv_set_key(bs, password) != 0) {
+        monitor_printf(mon, "invalid password\n");
+        ret = -EPERM;
+    }
+    if (mon->password_completion_cb)
+        mon->password_completion_cb(mon->password_opaque, ret);
+
+    monitor_read_command(mon, 1);
 }
 
-void monitor_readline(const char *prompt, int is_password,
-                      char *buf, int buf_size)
+void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
+                                 BlockDriverCompletionFunc *completion_cb,
+                                 void *opaque)
 {
-    int i;
-    int old_focus[MAX_MON];
-
-    if (is_password) {
-        for (i = 0; i < MAX_MON; i++) {
-            old_focus[i] = 0;
-            if (monitor_hd[i]) {
-                old_focus[i] = monitor_hd[i]->focus;
-                monitor_hd[i]->focus = 0;
-                qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
-            }
-        }
-    }
+    int err;
 
-    readline_start(prompt, is_password, monitor_readline_cb, NULL);
-    monitor_readline_buf = buf;
-    monitor_readline_buf_size = buf_size;
-    monitor_readline_started = 1;
-    while (monitor_readline_started) {
-        main_loop_wait(10);
-    }
-    /* restore original focus */
-    if (is_password) {
-        for (i = 0; i < MAX_MON; i++)
-            if (old_focus[i])
-                monitor_hd[i]->focus = old_focus[i];
+    if (!bdrv_key_required(bs)) {
+        if (completion_cb)
+            completion_cb(opaque, 0);
+        return;
     }
+
+    monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
+                   bdrv_get_encrypted_filename(bs));
+
+    mon->password_completion_cb = completion_cb;
+    mon->password_opaque = opaque;
+
+    err = monitor_read_password(mon, bdrv_password_cb, bs);
+
+    if (err && completion_cb)
+        completion_cb(opaque, err);
 }