]> git.proxmox.com Git - qemu.git/blobdiff - monitor.c
LAN9118 improvements
[qemu.git] / monitor.c
index d942d33edfefe8ec3444991825353ca485cb1910..c0dc48ea004fae291895ff22d5d46568e90e193a 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -140,6 +140,9 @@ static inline int monitor_ctrl_mode(const Monitor *mon)
 
 static void monitor_read_command(Monitor *mon, int show_prompt)
 {
+    if (!mon->rs)
+        return;
+
     readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
     if (show_prompt)
         readline_show_prompt(mon->rs);
@@ -174,9 +177,6 @@ static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
 
-    if (!mon)
-        return;
-
     for(;;) {
         c = *str++;
         if (c == '\0')
@@ -192,6 +192,9 @@ static void monitor_puts(Monitor *mon, const char *str)
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
+    if (!mon)
+        return;
+
     if (mon->mc && !mon->mc->print_enabled) {
         qemu_error_new(QERR_UNDEFINED_ERROR);
     } else {
@@ -257,24 +260,6 @@ static inline int monitor_has_error(const Monitor *mon)
     return mon->error != NULL;
 }
 
-static void monitor_print_qobject(Monitor *mon, const QObject *data)
-{
-    switch (qobject_type(data)) {
-        case QTYPE_QSTRING:
-            monitor_printf(mon, "%s",qstring_get_str(qobject_to_qstring(data)));
-            break;
-        case QTYPE_QINT:
-            monitor_printf(mon, "%" PRId64,qint_get_int(qobject_to_qint(data)));
-            break;
-        default:
-            monitor_printf(mon, "ERROR: unsupported type: %d",
-                                                        qobject_type(data));
-            break;
-    }
-
-    monitor_puts(mon, "\n");
-}
-
 static void monitor_json_emitter(Monitor *mon, const QObject *data)
 {
     QString *json;
@@ -298,10 +283,12 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
     if (!monitor_has_error(mon)) {
         /* success response */
         if (data) {
+            assert(qobject_type(data) == QTYPE_QDICT);
             qobject_incref(data);
             qdict_put_obj(qmp, "return", data);
         } else {
-            qdict_put(qmp, "return", qstring_from_str("OK"));
+            /* return an empty QDict by default */
+            qdict_put(qmp, "return", qdict_new());
         }
     } else {
         /* error response */
@@ -504,24 +491,91 @@ help:
     help_cmd(mon, "info");
 }
 
+static void do_info_version_print(Monitor *mon, const QObject *data)
+{
+    QDict *qdict;
+
+    qdict = qobject_to_qdict(data);
+
+    monitor_printf(mon, "%s%s\n", qdict_get_str(qdict, "qemu"),
+                                  qdict_get_str(qdict, "package"));
+}
+
 /**
  * do_info_version(): Show QEMU version
+ *
+ * Return a QDict with the following information:
+ *
+ * - "qemu": QEMU's version
+ * - "package": package's version
+ *
+ * Example:
+ *
+ * { "qemu": "0.11.50", "package": "" }
  */
 static void do_info_version(Monitor *mon, QObject **ret_data)
 {
-    *ret_data = QOBJECT(qstring_from_str(QEMU_VERSION QEMU_PKGVERSION));
+    *ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
+                                   QEMU_VERSION, QEMU_PKGVERSION);
+}
+
+static void do_info_name_print(Monitor *mon, const QObject *data)
+{
+    QDict *qdict;
+
+    qdict = qobject_to_qdict(data);
+    if (qdict_size(qdict) == 0) {
+        return;
+    }
+
+    monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
+}
+
+/**
+ * do_info_name(): Show VM name
+ *
+ * Return a QDict with the following information:
+ *
+ * - "name": VM's name (optional)
+ *
+ * Example:
+ *
+ * { "name": "qemu-name" }
+ */
+static void do_info_name(Monitor *mon, QObject **ret_data)
+{
+    *ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
+                            qobject_from_jsonf("{}");
 }
 
-static void do_info_name(Monitor *mon)
+static QObject *get_cmd_dict(const char *name)
 {
-    if (qemu_name)
-        monitor_printf(mon, "%s\n", qemu_name);
+    const char *p;
+
+    /* Remove '|' from some commands */
+    p = strchr(name, '|');
+    if (p) {
+        p++;
+    } else {
+        p = name;
+    }
+
+    return qobject_from_jsonf("{ 'name': %s }", p);
 }
 
 /**
  * do_info_commands(): List QMP available commands
  *
- * Return a QList of QStrings.
+ * Each command is represented by a QDict, the returned QObject is a QList
+ * of all commands.
+ *
+ * The QDict contains:
+ *
+ * - "name": command's name
+ *
+ * Example:
+ *
+ * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
  */
 static void do_info_commands(Monitor *mon, QObject **ret_data)
 {
@@ -532,7 +586,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
 
     for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
         if (monitor_handler_ported(cmd) && !compare_cmd(cmd->name, "info")) {
-            qlist_append(cmd_list, qstring_from_str(cmd->name));
+            qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
         }
     }
 
@@ -540,7 +594,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
         if (monitor_handler_ported(cmd)) {
             char buf[128];
             snprintf(buf, sizeof(buf), "query-%s", cmd->name);
-            qlist_append(cmd_list, qstring_from_str(buf));
+            qlist_append_obj(cmd_list, get_cmd_dict(buf));
         }
     }
 
@@ -548,20 +602,56 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
 }
 
 #if defined(TARGET_I386)
-static void do_info_hpet(Monitor *mon)
+static void do_info_hpet_print(Monitor *mon, const QObject *data)
 {
     monitor_printf(mon, "HPET is %s by QEMU\n",
-                   (no_hpet) ? "disabled" : "enabled");
+                   qdict_get_bool(qobject_to_qdict(data), "enabled") ?
+                   "enabled" : "disabled");
+}
+
+/**
+ * do_info_hpet(): Show HPET state
+ *
+ * Return a QDict with the following information:
+ *
+ * - "enabled": true if hpet if enabled, false otherwise
+ *
+ * Example:
+ *
+ * { "enabled": true }
+ */
+static void do_info_hpet(Monitor *mon, QObject **ret_data)
+{
+    *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
 }
 #endif
 
-static void do_info_uuid(Monitor *mon)
+static void do_info_uuid_print(Monitor *mon, const QObject *data)
 {
-    monitor_printf(mon, UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1],
+    monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
+}
+
+/**
+ * do_info_uuid(): Show VM UUID
+ *
+ * Return a QDict with the following information:
+ *
+ * - "UUID": Universally Unique Identifier
+ *
+ * Example:
+ *
+ * { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
+ */
+static void do_info_uuid(Monitor *mon, QObject **ret_data)
+{
+    char uuid[64];
+
+    snprintf(uuid, sizeof(uuid), UUID_FMT, 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]);
+    *ret_data = qobject_from_jsonf("{ 'UUID': %s }", uuid);
 }
 
 /* get the current CPU defined by the user */
@@ -611,8 +701,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
     assert(qobject_type(obj) == QTYPE_QDICT);
     cpu = qobject_to_qdict(obj);
 
-    if (strcmp(qdict_get_str(cpu, "current"), "yes") == 0)
+    if (qdict_get_bool(cpu, "current")) {
         active = '*';
+    }
 
     monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
 
@@ -632,8 +723,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
                    (target_long) qdict_get_int(cpu, "PC"));
 #endif
 
-    if (strcmp(qdict_get_str(cpu, "halted"), "yes") == 0)
+    if (qdict_get_bool(cpu, "halted")) {
         monitor_printf(mon, " (halted)");
+    }
 
     monitor_printf(mon, "\n");
 }
@@ -650,12 +742,21 @@ static void monitor_print_cpus(Monitor *mon, const QObject *data)
 /**
  * do_info_cpus(): Show CPU information
  *
- * Return a QList with a QDict for each CPU.
+ * Return a QList. Each CPU is represented by a QDict, which contains:
+ *
+ * - "cpu": CPU index
+ * - "current": true if this is the current CPU, false otherwise
+ * - "halted": true if the cpu is halted, false otherwise
+ * - Current program counter. The key's name depends on the architecture:
+ *      "pc": i386/x86)64
+ *      "nip": PPC
+ *      "pc" and "npc": sparc
+ *      "PC": mips
  *
- * For example:
+ * Example:
  *
- * [ { "CPU": 0, "current": "yes", "pc": 0x..., "halted": "no" },
- *   { "CPU": 1, "current": "no",  "pc": 0x..., "halted": "yes" } ]
+ * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
+ *   { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
  */
 static void do_info_cpus(Monitor *mon, QObject **ret_data)
 {
@@ -668,14 +769,17 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
     mon_get_cpu();
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
-        const char *answer;
-        QDict *cpu = qdict_new();
+        QDict *cpu;
+        QObject *obj;
 
         cpu_synchronize_state(env);
 
-        qdict_put(cpu, "CPU", qint_from_int(env->cpu_index));
-        answer = (env == mon->mon_cpu) ? "yes" : "no";
-        qdict_put(cpu, "current", qstring_from_str(answer));
+        obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
+                                 env->cpu_index, env == mon->mon_cpu,
+                                 env->halted);
+        assert(obj != NULL);
+
+        cpu = qobject_to_qdict(obj);
 
 #if defined(TARGET_I386)
         qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
@@ -687,8 +791,6 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
 #elif defined(TARGET_MIPS)
         qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
 #endif
-        answer = env->halted ? "yes" : "no";
-        qdict_put(cpu, "halted", qstring_from_str(answer));
 
         qlist_append(cpu_list, cpu);
     }
@@ -767,7 +869,7 @@ static void do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     BlockDriverState *bs;
     int force = qdict_get_int(qdict, "force");
-    const char *filename = qdict_get_str(qdict, "filename");
+    const char *filename = qdict_get_str(qdict, "device");
 
     bs = bdrv_find(filename);
     if (!bs) {
@@ -1768,16 +1870,40 @@ static void tlb_info(Monitor *mon)
 
 #endif
 
-static void do_info_kvm(Monitor *mon)
+static void do_info_kvm_print(Monitor *mon, const QObject *data)
 {
-#ifdef CONFIG_KVM
+    QDict *qdict;
+
+    qdict = qobject_to_qdict(data);
+
     monitor_printf(mon, "kvm support: ");
-    if (kvm_enabled())
-        monitor_printf(mon, "enabled\n");
-    else
-        monitor_printf(mon, "disabled\n");
+    if (qdict_get_bool(qdict, "present")) {
+        monitor_printf(mon, "%s\n", qdict_get_bool(qdict, "enabled") ?
+                                    "enabled" : "disabled");
+    } else {
+        monitor_printf(mon, "not compiled\n");
+    }
+}
+
+/**
+ * do_info_kvm(): Show KVM information
+ *
+ * Return a QDict with the following information:
+ *
+ * - "enabled": true if KVM support is enabled, false otherwise
+ * - "present": true if QEMU has KVM support, false otherwise
+ *
+ * Example:
+ *
+ * { "enabled": true, "present": true }
+ */
+static void do_info_kvm(Monitor *mon, QObject **ret_data)
+{
+#ifdef CONFIG_KVM
+    *ret_data = qobject_from_jsonf("{ 'enabled': %i, 'present': true }",
+                                   kvm_enabled());
 #else
-    monitor_printf(mon, "kvm support: not compiled\n");
+    *ret_data = qobject_from_jsonf("{ 'enabled': false, 'present': false }");
 #endif
 }
 
@@ -1895,16 +2021,59 @@ static void do_inject_nmi(Monitor *mon, const QDict *qdict)
 }
 #endif
 
-static void do_info_status(Monitor *mon)
+static void do_info_status_print(Monitor *mon, const QObject *data)
 {
-    if (vm_running) {
-        if (singlestep) {
-            monitor_printf(mon, "VM status: running (single step mode)\n");
-        } else {
-            monitor_printf(mon, "VM status: running\n");
+    QDict *qdict;
+
+    qdict = qobject_to_qdict(data);
+
+    monitor_printf(mon, "VM status: ");
+    if (qdict_get_bool(qdict, "running")) {
+        monitor_printf(mon, "running");
+        if (qdict_get_bool(qdict, "singlestep")) {
+            monitor_printf(mon, " (single step mode)");
         }
-    } else
-       monitor_printf(mon, "VM status: paused\n");
+    } else {
+        monitor_printf(mon, "paused");
+    }
+
+    monitor_printf(mon, "\n");
+}
+
+/**
+ * do_info_status(): VM status
+ *
+ * Return a QDict with the following information:
+ *
+ * - "running": true if the VM is running, or false if it is paused
+ * - "singlestep": true if the VM is in single step mode, false otherwise
+ *
+ * Example:
+ *
+ * { "running": true, "singlestep": false }
+ */
+static void do_info_status(Monitor *mon, QObject **ret_data)
+{
+    *ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
+                                    vm_running, singlestep);
+}
+
+static ram_addr_t balloon_get_value(void)
+{
+    ram_addr_t actual;
+
+    if (kvm_enabled() && !kvm_has_sync_mmu()) {
+        qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+        return 0;
+    }
+
+    actual = qemu_balloon_status();
+    if (actual == 0) {
+        qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
+        return 0;
+    }
+
+    return actual;
 }
 
 /**
@@ -1912,9 +2081,10 @@ static void do_info_status(Monitor *mon)
  */
 static void do_balloon(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    int value = qdict_get_int(qdict, "value");
-    ram_addr_t target = value;
-    qemu_balloon(target << 20);
+    if (balloon_get_value()) {
+        /* ballooning is active */
+        qemu_balloon(qdict_get_int(qdict, "value"));
+    }
 }
 
 static void monitor_print_balloon(Monitor *mon, const QObject *data)
@@ -1942,14 +2112,11 @@ static void do_info_balloon(Monitor *mon, QObject **ret_data)
 {
     ram_addr_t actual;
 
-    actual = qemu_balloon_status();
-    if (kvm_enabled() && !kvm_has_sync_mmu())
-        qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
-    else if (actual == 0)
-        qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
-    else
+    actual = balloon_get_value();
+    if (actual != 0) {
         *ret_data = qobject_from_jsonf("{ 'balloon': %" PRId64 "}",
                                        (int64_t) actual);
+    }
 }
 
 static qemu_acl *find_acl(Monitor *mon, const char *name)
@@ -2187,7 +2354,7 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the version of QEMU",
-        .user_print = monitor_print_qobject,
+        .user_print = do_info_version_print,
         .mhandler.info_new = do_info_version,
     },
     {
@@ -2210,21 +2377,24 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the character devices",
-        .mhandler.info = qemu_chr_info,
+        .user_print = qemu_chr_info_print,
+        .mhandler.info_new = qemu_chr_info,
     },
     {
         .name       = "block",
         .args_type  = "",
         .params     = "",
         .help       = "show the block devices",
-        .mhandler.info = bdrv_info,
+        .user_print = bdrv_info_print,
+        .mhandler.info_new = bdrv_info,
     },
     {
         .name       = "blockstats",
         .args_type  = "",
         .params     = "",
         .help       = "show block device statistics",
-        .mhandler.info = bdrv_info_stats,
+        .user_print = bdrv_stats_print,
+        .mhandler.info_new = bdrv_info_stats,
     },
     {
         .name       = "registers",
@@ -2291,7 +2461,8 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show state of HPET",
-        .mhandler.info = do_info_hpet,
+        .user_print = do_info_hpet_print,
+        .mhandler.info_new = do_info_hpet,
     },
 #endif
     {
@@ -2306,7 +2477,8 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show KVM information",
-        .mhandler.info = do_info_kvm,
+        .user_print = do_info_kvm_print,
+        .mhandler.info_new = do_info_kvm,
     },
     {
         .name       = "numa",
@@ -2355,7 +2527,8 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM status (running|paused)",
-        .mhandler.info = do_info_status,
+        .user_print = do_info_status_print,
+        .mhandler.info_new = do_info_status,
     },
     {
         .name       = "pcmcia",
@@ -2369,28 +2542,32 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show which guest mouse is receiving events",
-        .mhandler.info = do_info_mice,
+        .user_print = do_info_mice_print,
+        .mhandler.info_new = do_info_mice,
     },
     {
         .name       = "vnc",
         .args_type  = "",
         .params     = "",
         .help       = "show the vnc server status",
-        .mhandler.info = do_info_vnc,
+        .user_print = do_info_vnc_print,
+        .mhandler.info_new = do_info_vnc,
     },
     {
         .name       = "name",
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM name",
-        .mhandler.info = do_info_name,
+        .user_print = do_info_name_print,
+        .mhandler.info_new = do_info_name,
     },
     {
         .name       = "uuid",
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM UUID",
-        .mhandler.info = do_info_uuid,
+        .user_print = do_info_uuid_print,
+        .mhandler.info_new = do_info_uuid,
     },
 #if defined(TARGET_PPC)
     {
@@ -2415,7 +2592,8 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show migration status",
-        .mhandler.info = do_info_migrate,
+        .user_print = do_info_migrate_print,
+        .mhandler.info_new = do_info_migrate,
     },
     {
         .name       = "balloon",
@@ -3322,6 +3500,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
             break;
         case 'i':
         case 'l':
+        case 'M':
             {
                 int64_t val;
 
@@ -3352,6 +3531,8 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
                     monitor_printf(mon, "\'%s\' has failed: ", cmdname);
                     monitor_printf(mon, "integer is for 32-bit values\n");
                     goto fail;
+                } else if (c == 'M') {
+                    val <<= 20;
                 }
                 qdict_put(qdict, key, qint_from_int(val));
             }
@@ -3687,7 +3868,7 @@ static int monitor_can_read(void *opaque)
 {
     Monitor *mon = opaque;
 
-    return (mon->suspend_cnt == 0) ? 128 : 0;
+    return (mon->suspend_cnt == 0) ? 1 : 0;
 }
 
 typedef struct CmdArgs {
@@ -3756,6 +3937,7 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
         }
         case 'i':
         case 'l':
+        case 'M':
             if (qobject_type(value) != QTYPE_QINT) {
                 qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
                 return -1;
@@ -3893,7 +4075,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
                       qobject_from_jsonf("{ 'item': %s }", info_item));
     } else {
         cmd = monitor_find_command(cmd_name);
-        if (!cmd) {
+        if (!cmd || !monitor_handler_ported(cmd)) {
             qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
             goto err_input;
         }