Handle NULL bdrv.
[qemu] / monitor.c
index 3d81fbc..d64f459 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/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"
@@ -37,7 +39,6 @@
 #include "audio/audio.h"
 #include "disas.h"
 #include "balloon.h"
-#include <dirent.h>
 #include "qemu-timer.h"
 #include "migration.h"
 #include "kvm.h"
@@ -160,25 +161,25 @@ void monitor_print_filename(Monitor *mon, const char *filename)
     int i;
 
     for (i = 0; filename[i]; i++) {
-       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;
-       }
+        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;
+        }
     }
 }
 
@@ -273,7 +274,7 @@ static void do_info(Monitor *mon, const char *item)
 
 static void do_info_version(Monitor *mon)
 {
-    monitor_printf(mon, "%s\n", QEMU_VERSION);
+    monitor_printf(mon, "%s\n", QEMU_VERSION QEMU_PKGVERSION);
 }
 
 static void do_info_name(Monitor *mon)
@@ -318,6 +319,7 @@ static CPUState *mon_get_cpu(void)
     if (!cur_mon->mon_cpu) {
         mon_set_cpu(0);
     }
+    cpu_synchronize_state(cur_mon->mon_cpu, 0);
     return cur_mon->mon_cpu;
 }
 
@@ -344,6 +346,7 @@ static void do_info_cpus(Monitor *mon)
     mon_get_cpu();
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_synchronize_state(env, 0);
         monitor_printf(mon, "%c CPU #%d:",
                        (env == mon->mon_cpu) ? '*' : ' ',
                        env->cpu_index);
@@ -474,17 +477,17 @@ static void change_vnc_password_cb(Monitor *mon, const char *password,
 static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
 {
     if (strcmp(target, "passwd") == 0 ||
-       strcmp(target, "password") == 0) {
-       if (arg) {
+        strcmp(target, "password") == 0) {
+        if (arg) {
             char password[9];
-           strncpy(password, arg, sizeof(password));
-           password[sizeof(password) - 1] = '\0';
+            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)
+        if (vnc_display_open(NULL, target) < 0)
             monitor_printf(mon, "could not start VNC server on %s\n", target);
     }
 }
@@ -493,9 +496,9 @@ static void do_change(Monitor *mon, const char *device, const char *target,
                       const char *arg)
 {
     if (strcmp(device, "vnc") == 0) {
-       do_change_vnc(mon, target, arg);
+        do_change_vnc(mon, target, arg);
     } else {
-       do_change_block(mon, device, target, arg);
+        do_change_block(mon, device, target, arg);
     }
 }
 
@@ -525,6 +528,17 @@ static void do_log(Monitor *mon, const char *items)
     cpu_set_log(mask);
 }
 
+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);
@@ -568,19 +582,29 @@ static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
 }
 
 #ifdef CONFIG_GDBSTUB
-static void do_gdbserver(Monitor *mon, const char *port)
-{
-    if (!port)
-        port = DEFAULT_GDBSTUB_PORT;
-    if (gdbserver_start(port) < 0) {
-        monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n",
-                       port);
+static void do_gdbserver(Monitor *mon, const char *device)
+{
+    if (!device)
+        device = "tcp::" DEFAULT_GDBSTUB_PORT;
+    if (gdbserver_start(device) < 0) {
+        monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
+                       device);
+    } else if (strcmp(device, "none") == 0) {
+        monitor_printf(mon, "Disabled gdbserver\n");
     } else {
-        monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port);
+        monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
+                       device);
     }
 }
 #endif
 
+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, "'");
@@ -1352,7 +1376,7 @@ static void tlb_info(Monitor *mon)
 
 static void do_info_kqemu(Monitor *mon)
 {
-#ifdef USE_KQEMU
+#ifdef CONFIG_KQEMU
     CPUState *env;
     int val;
     val = 0;
@@ -1393,6 +1417,25 @@ static void do_info_kvm(Monitor *mon)
 #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;
@@ -1429,7 +1472,7 @@ static void do_info_profile(Monitor *mon)
     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
 }
@@ -1506,9 +1549,13 @@ static void do_inject_nmi(Monitor *mon, int cpu_index)
 
 static void do_info_status(Monitor *mon)
 {
-    if (vm_running)
-       monitor_printf(mon, "VM status: running\n");
-    else
+    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");
 }
 
@@ -1535,81 +1582,81 @@ static void do_info_balloon(Monitor *mon)
 
 static void do_acl(Monitor *mon,
                    const char *command,
-                  const char *aclname,
-                  const char *match,
-                  int has_index,
-                  int index)
+                   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;
+        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",
+        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,
+        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");
+        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);
-       }
+        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);
+               (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);
+        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);
+        monitor_printf(mon, "acl: unknown command '%s'\n", command);
     }
 }
 
@@ -1620,7 +1667,7 @@ static const mon_cmd_t mon_cmds[] = {
     { "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" },
+      "[subcommand]", "show various information about the system state" },
     { "q|quit", "", do_quit,
       "", "quit the emulator" },
     { "eject", "-fB", do_eject,
@@ -1634,18 +1681,20 @@ static const mon_cmd_t mon_cmds[] = {
     { "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" },
+      "[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" },
+    { "singlestep", "s?", do_singlestep,
+      "[on|off]", "run emulation in singlestep mode or switch to normal mode", },
     { "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)", },
+      "[device]", "start gdbserver on given device (default 'tcp::1234'), stop with 'none'", },
 #endif
     { "x", "/l", do_memory_dump,
       "/fmt addr", "virtual memory dump starting at 'addr'", },
@@ -1678,7 +1727,7 @@ static const mon_cmd_t mon_cmds[] = {
       "index", "set which mouse device receives events" },
 #ifdef HAS_AUDIO
     { "wavcapture", "si?i?i?", do_wav_capture,
-      "path [frequency bits channels]",
+      "path [frequency [bits [channels]]]",
       "capture audio to a wave file (default frequency=44100 bits=16 channels=2)" },
 #endif
     { "stopcapture", "i", do_stop_capture,
@@ -1708,16 +1757,22 @@ static const mon_cmd_t mon_cmds[] = {
                                         "add drive to PCI storage controller" },
     { "pci_add", "sss", pci_device_hot_add, "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
     { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
-    { "host_net_add", "ss", net_host_device_add,
-      "[tap,user,socket,vde] options", "add host VLAN client" },
+#endif
+    { "host_net_add", "ss?", net_host_device_add,
+      "tap|user|socket|vde|dump [options]", "add host VLAN client" },
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
+#ifdef CONFIG_SLIRP
+    { "host_net_redir", "s", net_slirp_redir,
+      "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)" },
 #endif
     { "balloon", "i", do_balloon,
       "target", "request VM to change it's memory allocation (in MB)" },
     { "set_link", "ss", do_set_link,
-      "name [up|down]", "change the link status of a network adapter" },
-    { "acl", "sss?i?", do_acl, "<command> <aclname> [<match>] [<index>]\n",
+      "name up|down", "change the link status of a network adapter" },
+    { "watchdog_action", "s", do_watchdog_action,
+      "[reset|shutdown|poweroff|pause|debug|none]", "change watchdog action" },
+    { "acl", "sss?i?", do_acl, "<command> <aclname> [<match> [<index>]]\n",
                                "acl show vnc.username\n"
                                "acl policy vnc.username deny\n"
                                "acl allow vnc.username fred\n"
@@ -1766,6 +1821,8 @@ static const mon_cmd_t info_cmds[] = {
       "", "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,
@@ -1839,7 +1896,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;
 }
@@ -2957,6 +3014,9 @@ static void monitor_find_completion(const char *cmdline)
                     cmd_completion(str, cmd->name);
                 }
             } else if (!strcmp(cmd->name, "sendkey")) {
+                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);