Merge upstream QEMU 10.0.50 into the Android source tree.

This change integrates many changes from the upstream QEMU sources.
Its main purpose is to enable correct ARMv6 and ARMv7 support to the
Android emulator. Due to the nature of the upstream code base, this
unfortunately also required changes to many other parts of the source.

Note that to ensure easier integrations in the future, some source files
and directories that have heavy Android-specific customization have been
renamed with an -android suffix. The original files are still there for
easier integration tracking, but *never* compiled. For example:

  net.c        net-android.c
  qemu-char.c  qemu-char-android.c
  slirp/       slirp-android/
  etc...

Tested on linux-x86, darwin-x86 and windows host machines.
diff --git a/monitor.c b/monitor.c
index f0f38a7..6b45f6c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -21,30 +21,33 @@
  * 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 "cpu-defs.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
 
-#ifndef offsetof
-#define offsetof(type, field) ((size_t) &((type *)0)->field)
-#endif
-
 /*
  * Supported types:
  *
@@ -59,95 +62,125 @@
  *
  */
 
-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;
 
-#define MAX_MON 4
-static CharDriverState *monitor_hd[MAX_MON];
-static int hide_banner;
+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;
+};
 
-static term_cmd_t term_cmds[];
-static term_cmd_t info_cmds[];
+static LIST_HEAD(mon_list, Monitor) mon_list;
 
-static uint8_t term_outbuf[1024];
-static int term_outbuf_index;
+static const mon_cmd_t mon_cmds[];
+static const mon_cmd_t info_cmds[];
 
-static void monitor_start_input(void);
+Monitor *cur_mon = NULL;
 
-CPUState *mon_cpu = NULL;
+static void monitor_command_cb(Monitor *mon, const char *cmdline,
+                               void *opaque);
 
-void term_flush(void)
+static void monitor_read_command(Monitor *mon, int show_prompt)
 {
-    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;
+    readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
+    if (show_prompt)
+        readline_show_prompt(mon->rs);
+}
+
+static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
+                                 void *opaque)
+{
+    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;
+        }
     }
 }
 
@@ -155,7 +188,7 @@
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf((Monitor *)stream, fmt, ap);
     va_end(ap);
     return 0;
 }
@@ -180,39 +213,36 @@
     return 0;
 }
 
-static void help_cmd1(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)
 {
-    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")) {
-            CPULogItem *item;
-            term_printf("Log items (comma separated):\n");
-            term_printf("%-10s %s\n", "none", "remove all logs");
+            const CPULogItem *item;
+            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;
 
@@ -224,10 +254,10 @@
     }
 }
 
-static void do_info(const char *item)
+static void do_info(Monitor *mon, const char *item)
 {
-    term_cmd_t *cmd;
-    void (*handler)(void);
+    const mon_cmd_t *cmd;
+    void (*handler)(Monitor *);
 
     if (!item)
         goto help;
@@ -236,32 +266,39 @@
             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);
+        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 */
@@ -271,7 +308,7 @@
 
     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;
         }
     }
@@ -280,28 +317,29 @@
 
 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;
 
@@ -309,76 +347,81 @@
     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;
             }
         }
@@ -387,76 +430,90 @@
     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 do_change_vnc(const char *target)
+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(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;
 
@@ -465,64 +522,116 @@
     } 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)
 {
-    vm_start();
+    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();
 }
 
-#ifdef CONFIG_GDBSTUB
-static void do_gdbserver(const char *port)
+static void bdrv_key_cb(void *opaque, int err)
 {
-    if (!port)
-        port = DEFAULT_GDBSTUB_PORT;
-    if (gdbserver_start(port) < 0) {
-        qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
-    } else {
-        qemu_printf("Waiting gdb connection on port '%s'\n", port);
+    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);
     }
 }
-#endif
 
-static void term_printc(int c)
+static void do_gdbserver(Monitor *mon, const char *device)
 {
-    term_printf("'");
+    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 {
+        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);
+    }
+}
+
+static void monitor_printc(Monitor *mon, int c)
+{
+    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;
@@ -556,7 +665,7 @@
             }
         }
 #endif
-        monitor_disas(env, addr, count, is_physical, flags);
+        monitor_disas(mon, env, addr, count, is_physical, flags);
         return;
     }
 
@@ -587,9 +696,9 @@
 
     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;
@@ -600,7 +709,7 @@
             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;
             }
         }
@@ -621,27 +730,27 @@
                 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;
     }
@@ -653,11 +762,11 @@
 #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
@@ -666,60 +775,61 @@
 #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;
@@ -734,7 +844,7 @@
 
     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) {
@@ -749,8 +859,9 @@
     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;
@@ -759,7 +870,7 @@
 
     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) {
@@ -775,7 +886,7 @@
     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];
@@ -788,7 +899,7 @@
         sum = (sum >> 1) | (sum << 15);
         sum += buf[0];
     }
-    term_printf("%05d\n", sum);
+    monitor_printf(mon, "%05d\n", sum);
 }
 
 typedef struct {
@@ -856,6 +967,9 @@
     { 0x30, "b" },
     { 0x31, "n" },
     { 0x32, "m" },
+    { 0x33, "comma" },
+    { 0x34, "dot" },
+    { 0x35, "slash" },
 
     { 0x37, "asterisk" },
 
@@ -968,7 +1082,8 @@
     }
 }
 
-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;
@@ -987,17 +1102,17 @@
         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;
@@ -1021,7 +1136,7 @@
 
 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;
@@ -1033,13 +1148,14 @@
     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;
@@ -1065,37 +1181,65 @@
         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);
 }
 
-static void do_system_reset(void)
+/* 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;
+}
+
+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)
+            monitor_printf(mon, "boot device list now set to %s\n",
+                           bootdevice);
+        else
+            monitor_printf(mon, "setting boot device list failed with "
+                           "error %i\n", res);
+    } else {
+        monitor_printf(mon, "no function defined to set boot device list for "
+                       "this architecture\n");
+    }
+}
+
+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;
@@ -1106,7 +1250,7 @@
         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;
@@ -1115,14 +1259,14 @@
         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);
                     }
@@ -1132,18 +1276,18 @@
     }
 }
 
-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;
@@ -1153,7 +1297,7 @@
     }
 }
 
-static void mem_info(void)
+static void mem_info(Monitor *mon)
 {
     CPUState *env;
     int l1, l2, prot, last_prot;
@@ -1164,7 +1308,7 @@
         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;
@@ -1177,7 +1321,7 @@
         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,
@@ -1189,47 +1333,108 @@
                     } 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)
 {
-#ifdef USE_KQEMU
+    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 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(Monitor *mon)
+{
+#ifdef CONFIG_KVM
+    monitor_printf(mon, "kvm support: ");
+    if (kvm_enabled())
+        monitor_printf(mon, "enabled\n");
+    else
+        monitor_printf(mon, "disabled\n");
+#else
+    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;
@@ -1240,23 +1445,25 @@
 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;
@@ -1264,32 +1471,33 @@
     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;
@@ -1304,111 +1512,170 @@
     }
 }
 
-#ifdef HAS_AUDIO
-int wav_start_capture (CaptureState *s, const char *path, int freq,
-                       int bits, int nchannels);
-
-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);
-        return;
     }
     LIST_INSERT_HEAD (&capture_head, s, entries);
 }
 #endif
 
-static 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 media (use -f to force it)" },
-    { "change", "BF", do_change,
-      "device filename", "change a removable media" },
-    { "screendump", "F", do_screen_dump,
-      "filename", "save screen into PPM image 'filename'" },
-    { "log", "s", do_log,
-      "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
-#if 0
-    { "savevm", "F", do_savevm,
-      "filename", "save the whole virtual machine state to 'filename'" },
-    { "loadvm", "F", do_loadvm,
-      "filename", "restore the whole virtual machine state from 'filename'" },
-#endif
-    { "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" },
+#if defined(TARGET_I386)
+static void do_inject_nmi(Monitor *mon, int cpu_index)
+{
+    CPUState *env;
 
-    { "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)" },
-#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)" },
+    for (env = first_cpu; env != NULL; env = env->next_cpu)
+        if (env->cpu_index == cpu_index) {
+            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+            break;
+        }
+}
 #endif
-     { "stopcapture", "i", do_stop_capture,
-       "capture index", "stop capture" },
+
+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 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" },
-    { "block", "", do_info_block,
+    { "chardev", "", qemu_chr_info,
+      "", "show the character devices" },
+    { "block", "", bdrv_info,
       "", "show the block devices" },
+    { "blockstats", "", bdrv_info_stats,
+      "", "show block device statistics" },
     { "registers", "", do_info_registers,
       "", "show the cpu registers" },
     { "cpus", "", do_info_cpus,
@@ -1421,16 +1688,24 @@
       "", "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", },
+    { "numa", "", do_info_numa,
+      "", "show NUMA information", },
     { "usb", "", usb_info,
       "", "show guest USB devices", },
     { "usbhost", "", usb_host_info,
@@ -1438,7 +1713,34 @@
     { "profile", "", do_info_profile,
       "", "show profiling information", },
     { "capture", "", do_info_capture,
-      "show capture information" },
+      "", "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,
+      "", "show which guest mouse is receiving events" },
+    { "vnc", "", do_info_vnc,
+      "", "show the vnc server status"},
+    { "name", "", do_info_name,
+      "", "show the current VM name" },
+    { "uuid", "", do_info_uuid,
+      "", "show the current VM UUID" },
+#if defined(TARGET_PPC)
+    { "cpustats", "", do_info_cpu_stats,
+      "", "show CPU statistics", },
+#endif
+#if defined(CONFIG_SLIRP)
+    { "slirp", "", do_info_slirp,
+      "", "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, },
 };
 
@@ -1453,12 +1755,12 @@
 typedef struct MonitorDef {
     const char *name;
     int offset;
-    target_long (*get_value)(struct MonitorDef *md, int val);
+    target_long (*get_value)(const struct MonitorDef *md, int val);
     int type;
 } MonitorDef;
 
 #if defined(TARGET_I386)
-static target_long monitor_get_pc (struct MonitorDef *md, int val)
+static target_long monitor_get_pc (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1468,7 +1770,7 @@
 #endif
 
 #if defined(TARGET_PPC)
-static target_long monitor_get_ccr (struct MonitorDef *md, int val)
+static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     unsigned int u;
@@ -1479,12 +1781,12 @@
 
     u = 0;
     for (i = 0; i < 8; i++)
-	u |= env->crf[i] << (32 - (4 * i));
+        u |= env->crf[i] << (32 - (4 * i));
 
     return u;
 }
 
-static target_long monitor_get_msr (struct MonitorDef *md, int val)
+static target_long monitor_get_msr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1492,15 +1794,15 @@
     return env->msr;
 }
 
-static target_long monitor_get_xer (struct MonitorDef *md, int val)
+static target_long monitor_get_xer (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
         return 0;
-    return ppc_load_xer(env);
+    return env->xer;
 }
 
-static target_long monitor_get_decr (struct MonitorDef *md, int val)
+static target_long monitor_get_decr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1508,7 +1810,7 @@
     return cpu_ppc_load_decr(env);
 }
 
-static target_long monitor_get_tbu (struct MonitorDef *md, int val)
+static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1516,7 +1818,7 @@
     return cpu_ppc_load_tbu(env);
 }
 
-static target_long monitor_get_tbl (struct MonitorDef *md, int val)
+static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1527,7 +1829,7 @@
 
 #if defined(TARGET_SPARC)
 #ifndef TARGET_SPARC64
-static target_long monitor_get_psr (struct MonitorDef *md, int val)
+static target_long monitor_get_psr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1536,7 +1838,7 @@
 }
 #endif
 
-static target_long monitor_get_reg(struct MonitorDef *md, int val)
+static target_long monitor_get_reg(const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1545,7 +1847,7 @@
 }
 #endif
 
-static MonitorDef monitor_defs[] = {
+static const MonitorDef monitor_defs[] = {
 #ifdef TARGET_I386
 
 #define SEG(name, seg) \
@@ -1782,42 +2084,20 @@
     { "cleanwin", offsetof(CPUState, cleanwin) },
     { "fprs", offsetof(CPUState, fprs) },
 #endif
-#elif defined(TARGET_ARM)
-    { "r0", offsetof(CPUState, regs[0]) },
-    { "r1", offsetof(CPUState, regs[1]) },
-    { "r2", offsetof(CPUState, regs[2]) },
-    { "r3", offsetof(CPUState, regs[3]) },
-    { "r4", offsetof(CPUState, regs[4]) },
-    { "r5", offsetof(CPUState, regs[5]) },
-    { "r6", offsetof(CPUState, regs[6]) },
-    { "r7", offsetof(CPUState, regs[7]) },
-    { "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]) },
-    /* some interesting aliases */
-    { "sp", offsetof(CPUState, regs[13]) },
-    { "lr", offsetof(CPUState, regs[14]) },
-    { "pc", offsetof(CPUState, regs[15]) },
 #endif
     { 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);
 }
 
 /* return 0 if OK, -1 if not found, -2 if no CPU defined */
 static int get_monitor_def(target_long *pval, const char *name)
 {
-    MonitorDef *md;
+    const MonitorDef *md;
     void *ptr;
 
     for(md = monitor_defs; md->name != NULL; md++) {
@@ -1851,14 +2131,14 @@
 {
     if (pch != '\0') {
         pch++;
-        while (isspace(*pch))
+        while (qemu_isspace(*pch))
             pch++;
     }
 }
 
-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;
@@ -1867,32 +2147,32 @@
     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 '$':
@@ -1910,19 +2190,19 @@
                     *q++ = *pch;
                 pch++;
             }
-            while (isspace(*pch))
+            while (qemu_isspace(*pch))
                 pch++;
             *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:
@@ -1932,10 +2212,10 @@
         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 (isspace(*pch))
+        while (qemu_isspace(*pch))
             pch++;
         break;
     }
@@ -1943,18 +2223,18 @@
 }
 
 
-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 '*':
@@ -1963,7 +2243,7 @@
         case '/':
         case '%':
             if (val2 == 0)
-                expr_error("division by zero");
+                expr_error(mon, "division by zero");
             if (op == '/')
                 val /= val2;
             else
@@ -1974,18 +2254,18 @@
     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 '&':
@@ -2002,18 +2282,18 @@
     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
@@ -2022,16 +2302,16 @@
     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)) {
         *pp = pch;
         return -1;
     }
-    while (isspace(*pch))
+    while (qemu_isspace(*pch))
         pch++;
-    *pval = expr_sum();
+    *pval = expr_sum(mon);
     *pp = pch;
     return 0;
 }
@@ -2044,7 +2324,7 @@
 
     q = buf;
     p = *pp;
-    while (isspace(*p))
+    while (qemu_isspace(*p))
         p++;
     if (*p == '\0') {
     fail:
@@ -2089,7 +2369,7 @@
         }
         p++;
     } else {
-        while (*p != '\0' && !isspace(*p)) {
+        while (*p != '\0' && !qemu_isspace(*p)) {
             if ((q - buf) < buf_size - 1) {
                 *q++ = *p;
             }
@@ -2101,61 +2381,78 @@
     return 0;
 }
 
+/*
+ * Store the command-name in cmdname, and return a pointer to
+ * the remaining of the command string.
+ */
+static const char *get_command_name(const char *cmdline,
+                                    char *cmdname, size_t nlen)
+{
+    size_t len;
+    const char *p, *pstart;
+
+    p = cmdline;
+    while (qemu_isspace(*p))
+        p++;
+    if (*p == '\0')
+        return NULL;
+    pstart = p;
+    while (*p != '\0' && *p != '/' && !qemu_isspace(*p))
+        p++;
+    len = p - pstart;
+    if (len > nlen - 1)
+        len = nlen - 1;
+    memcpy(cmdname, pstart, len);
+    cmdname[len] = '\0';
+    return p;
+}
+
 static int default_fmt_format = 'x';
 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;
-    term_cmd_t *cmd;
+    const char *p, *typestr;
+    int c, nb_args, i, has_arg;
+    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 */
-    p = cmdline;
-    q = cmdname;
-    while (isspace(*p))
-        p++;
-    if (*p == '\0')
+    p = get_command_name(cmdline, cmdname, sizeof(cmdname));
+    if (!p)
         return;
-    pstart = p;
-    while (*p != '\0' && *p != '/' && !isspace(*p))
-        p++;
-    len = p - pstart;
-    if (len > sizeof(cmdname) - 1)
-        len = sizeof(cmdname) - 1;
-    memcpy(cmdname, pstart, len);
-    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;
+            break;
     }
-    term_printf("unknown command: '%s'\n", cmdname);
-    return;
- found:
+
+    if (cmd->name == NULL) {
+        monitor_printf(mon, "unknown command: '%s'\n", cmdname);
+        return;
+    }
 
     for(i = 0; i < MAX_ARGS; i++)
         str_allocated[i] = NULL;
@@ -2176,7 +2473,7 @@
                 int ret;
                 char *str;
 
-                while (isspace(*p))
+                while (qemu_isspace(*p))
                     p++;
                 if (*typestr == '?') {
                     typestr++;
@@ -2190,13 +2487,15 @@
                 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;
@@ -2207,7 +2506,7 @@
             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;
@@ -2217,15 +2516,15 @@
             {
                 int count, format, size;
 
-                while (isspace(*p))
+                while (qemu_isspace(*p))
                     p++;
                 if (*p == '/') {
                     /* format found */
                     p++;
                     count = 1;
-                    if (isdigit(*p)) {
+                    if (qemu_isdigit(*p)) {
                         count = 0;
-                        while (isdigit(*p)) {
+                        while (qemu_isdigit(*p)) {
                             count = count * 10 + (*p - '0');
                             p++;
                         }
@@ -2264,8 +2563,9 @@
                         }
                     }
                 next:
-                    if (*p != '\0' && !isspace(*p)) {
-                        term_printf("invalid char in format: '%c'\n", *p);
+                    if (*p != '\0' && !qemu_isspace(*p)) {
+                        monitor_printf(mon, "invalid char in format: '%c'\n",
+                                       *p);
                         goto fail;
                     }
                     if (format < 0)
@@ -2274,8 +2574,8 @@
                         /* for 'i', not specifying a size gives -1 as size */
                         if (size < 0)
                             size = default_fmt_size;
+                        default_fmt_size = size;
                     }
-                    default_fmt_size = size;
                     default_fmt_format = format;
                 } else {
                     count = 1;
@@ -2298,7 +2598,7 @@
             {
                 int64_t val;
 
-                while (isspace(*p))
+                while (qemu_isspace(*p))
                     p++;
                 if (*typestr == '?' || *typestr == '.') {
                     if (*typestr == '?') {
@@ -2309,7 +2609,7 @@
                     } else {
                         if (*p == '.') {
                             p++;
-                            while (isspace(*p))
+                            while (qemu_isspace(*p))
                                 p++;
                             has_arg = 1;
                         } else {
@@ -2327,7 +2627,7 @@
                         goto add_num;
                     }
                 }
-                if (get_expr(&val, &p))
+                if (get_expr(mon, &val, &p))
                     goto fail;
             add_num:
                 if (c == 'i') {
@@ -2354,14 +2654,14 @@
                 c = *typestr++;
                 if (c == '\0')
                     goto bad_type;
-                while (isspace(*p))
+                while (qemu_isspace(*p))
                     p++;
                 has_option = 0;
                 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++;
@@ -2374,60 +2674,60 @@
             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;
         }
     }
     /* check that all arguments were parsed */
-    while (isspace(*p))
+    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:
     for(i = 0; i < MAX_ARGS; i++)
         qemu_free(str_allocated[i]);
-    return;
 }
 
 static void cmd_completion(const char *name, const char *list)
@@ -2448,7 +2748,7 @@
         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;
@@ -2479,7 +2779,8 @@
         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)
@@ -2500,19 +2801,20 @@
             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);
     }
 }
 
@@ -2527,7 +2829,7 @@
     p = cmdline;
     nb_args = 0;
     for(;;) {
-        while (isspace(*p))
+        while (qemu_isspace(*p))
             p++;
         if (*p == '\0')
             break;
@@ -2542,26 +2844,26 @@
     *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;
-    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
 
     /* if the line ends with a space, it means we want to complete the
        next arg */
     len = strlen(cmdline);
-    if (len > 0 && isspace(cmdline[len - 1])) {
+    if (len > 0 && qemu_isspace(cmdline[len - 1])) {
         if (nb_args >= MAX_ARGS)
             return;
         args[nb_args++] = qemu_strdup("");
@@ -2572,13 +2874,13 @@
             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;
         }
@@ -2596,23 +2898,26 @@
         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);
                 }
@@ -2626,111 +2931,156 @@
         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]);
+
+    cur_mon = opaque;
+
+    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;
 }
 
-static void monitor_start_input(void);
-
-static void monitor_handle_command1(void *opaque, const char *cmdline)
+static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
 {
-    monitor_handle_command(cmdline);
-    monitor_start_input();
+    monitor_suspend(mon);
+    monitor_handle_command(mon, cmdline);
+    monitor_resume(mon);
 }
 
-static void monitor_start_input(void)
+int monitor_suspend(Monitor *mon)
 {
-    readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
+    if (!mon->rs)
+        return -ENOTTY;
+    mon->suspend_cnt++;
+    return 0;
 }
 
-static void term_event(void *opaque, int event)
+void monitor_resume(Monitor *mon)
 {
-    if (event != CHR_EVENT_RESET)
-	return;
-
-    if (!hide_banner)
-	    term_printf("QEMU %s monitor - type 'help' for more information\n",
-			QEMU_VERSION);
-    monitor_start_input();
+    if (!mon->rs)
+        return;
+    if (--mon->suspend_cnt == 0)
+        readline_show_prompt(mon->rs);
 }
 
-static int is_first_init = 1;
-
-void monitor_init(CharDriverState *hd, int show_banner)
+static void monitor_event(void *opaque, int event)
 {
-    int i;
+    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;
+
+    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;
+    }
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
+
+void monitor_init(CharDriverState *chr, int flags)
+{
+    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;
-        }
+
+    mon = qemu_mallocz(sizeof(*mon));
+
+    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);
     }
 
-    hide_banner = !show_banner;
+    qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
+                          mon);
 
-    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
-
-    readline_start("", 0, monitor_handle_command1, NULL);
+    LIST_INSERT_HEAD(&mon_list, mon, entry);
+    if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
+        cur_mon = mon;
 }
 
-/* XXX: use threads ? */
-/* modal monitor readline */
-static int monitor_readline_started;
-static char *monitor_readline_buf;
-static int monitor_readline_buf_size;
-
-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];
+    int err;
 
-    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);
-            }
-        }
+    if (!bdrv_key_required(bs)) {
+        if (completion_cb)
+            completion_cb(opaque, 0);
+        return;
     }
 
-    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];
-    }
+    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);
 }