]> git.proxmox.com Git - qemu.git/commitdiff
Merge remote-tracking branch 'qmp/queue/qmp' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 13 Aug 2012 21:12:35 +0000 (16:12 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 13 Aug 2012 21:12:35 +0000 (16:12 -0500)
* qmp/queue/qmp: (48 commits)
  target-ppc: add implementation of query-cpu-definitions (v2)
  target-i386: add implementation of query-cpu-definitions (v2)
  qapi: add query-cpu-definitions command (v2)
  compiler: add macro for GCC weak symbols
  qapi: add query-machines command
  qapi: mark QOM commands stable
  qmp: introduce device-list-properties command
  qmp: add SUSPEND_DISK event
  qmp: qmp-events.txt: add missing doc for the SUSPEND event
  qmp: qmp-events.txt: put events in alphabetical order
  qmp: emit the WAKEUP event when the guest is put to run
  qmp: don't emit the RESET event on wakeup from S3
  scripts: qapi-commands.py: qmp-commands.h: include qdict.h
  docs: writing-qmp-commands.txt: update error section
  error, qerror: drop QDict member
  qerror: drop qerror_table and qerror_format()
  error, qerror: pass desc string to error calls
  error: drop error_get_qobject()/error_set_qobject()
  qemu-ga: switch to the new error format on the wire
  qmp: switch to the new error format on the wire
  ...

1  2 
Makefile.objs
configure
hmp.c
hmp.h
monitor.c
qapi-schema.json
qmp-commands.hx

diff --combined Makefile.objs
index e0fb69b202975270cd058cec247586e32782092f,8454b536cfe1faf0f30ef5a26fc4819b3590e68c..309d0662866a44258231c50c6e3b1672b8a3613c
@@@ -77,7 -77,6 +77,7 @@@ common-obj-y += qemu-char.o #aio.
  common-obj-y += block-migration.o iohandler.o
  common-obj-y += pflib.o
  common-obj-y += bitmap.o bitops.o
 +common-obj-y += page_cache.o
  
  common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
  common-obj-$(CONFIG_WIN32) += version.o
@@@ -212,6 -211,7 +212,7 @@@ common-obj-$(CONFIG_SMARTCARD_NSS) += $
  # qapi
  
  qapi-obj-y = qapi/
+ qapi-obj-y += qapi-types.o qapi-visit.o
  
  common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
  common-obj-y += qmp.o hmp.o
diff --combined configure
index 97b69a0d73d459e954cec4637711119f6296ec06,8a06c11a46a0b45d8b6333e7d4be45df1672563d..fea62f1d29b1d8acfd002a9eefd077cb1e1abd91
+++ b/configure
@@@ -171,7 -171,6 +171,6 @@@ vhost_net="no
  kvm="no"
  gprof="no"
  debug_tcg="no"
- debug_mon="no"
  debug="no"
  strip_opt="yes"
  tcg_interpreter="no"
@@@ -657,14 -656,9 +656,9 @@@ for opt d
    ;;
    --disable-debug-tcg) debug_tcg="no"
    ;;
-   --enable-debug-mon) debug_mon="yes"
-   ;;
-   --disable-debug-mon) debug_mon="no"
-   ;;
    --enable-debug)
        # Enable debugging options that aren't excessively noisy
        debug_tcg="yes"
-       debug_mon="yes"
        debug="yes"
        strip_opt="no"
    ;;
@@@ -3064,7 -3058,6 +3058,6 @@@ echo "host CPU          $cpu
  echo "host big endian   $bigendian"
  echo "target list       $target_list"
  echo "tcg debug enabled $debug_tcg"
- echo "Mon debug enabled $debug_mon"
  echo "gprof enabled     $gprof"
  echo "sparse enabled    $sparse"
  echo "strip binaries    $strip_opt"
@@@ -3157,9 -3150,6 +3150,6 @@@ echo "ARCH=$ARCH" >> $config_host_ma
  if test "$debug_tcg" = "yes" ; then
    echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
  fi
- if test "$debug_mon" = "yes" ; then
-   echo "CONFIG_DEBUG_MONITOR=y" >> $config_host_mak
- fi
  if test "$debug" = "yes" ; then
    echo "CONFIG_DEBUG_EXEC=y" >> $config_host_mak
  fi
@@@ -3563,23 -3553,15 +3553,23 @@@ if test "$linux" = "yes" ; the
    mkdir -p linux-headers
    case "$cpu" in
    i386|x86_64)
 -    symlink "$source_path/linux-headers/asm-x86" linux-headers/asm
 +    linux_arch=x86
      ;;
    ppcemb|ppc|ppc64)
 -    symlink "$source_path/linux-headers/asm-powerpc" linux-headers/asm
 +    linux_arch=powerpc
      ;;
    s390x)
 -    symlink "$source_path/linux-headers/asm-s390" linux-headers/asm
 +    linux_arch=s390
 +    ;;
 +  *)
 +    # For most CPUs the kernel architecture name and QEMU CPU name match.
 +    linux_arch="$cpu"
      ;;
    esac
 +    # For non-KVM architectures we will not have asm headers
 +    if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then
 +      symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm
 +    fi
  fi
  
  for target in $target_list; do
diff --combined hmp.c
index c13386b114fede1f82d9c618151d8c1d4126c0e0,9b44dfcf3a41b34f1aafbba1d24fd834f20664c3..a9d5675fc8d0618ccd475603c53285162c01985b
--- 1/hmp.c
--- 2/hmp.c
+++ b/hmp.c
@@@ -131,21 -131,8 +131,21 @@@ void hmp_info_mice(Monitor *mon
  void hmp_info_migrate(Monitor *mon)
  {
      MigrationInfo *info;
 +    MigrationCapabilityStatusList *caps, *cap;
  
      info = qmp_query_migrate(NULL);
 +    caps = qmp_query_migrate_capabilities(NULL);
 +
 +    /* do not display parameters during setup */
 +    if (info->has_status && caps) {
 +        monitor_printf(mon, "capabilities: ");
 +        for (cap = caps; cap; cap = cap->next) {
 +            monitor_printf(mon, "%s: %s ",
 +                           MigrationCapability_lookup[cap->value->capability],
 +                           cap->value->state ? "on" : "off");
 +        }
 +        monitor_printf(mon, "\n");
 +    }
  
      if (info->has_status) {
          monitor_printf(mon, "Migration status: %s\n", info->status);
                         info->ram->total >> 10);
          monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
                         info->ram->total_time);
 +        monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
 +                       info->ram->duplicate);
 +        monitor_printf(mon, "normal: %" PRIu64 " pages\n",
 +                       info->ram->normal);
 +        monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
 +                       info->ram->normal_bytes >> 10);
      }
  
      if (info->has_disk) {
                         info->disk->total >> 10);
      }
  
 +    if (info->has_xbzrle_cache) {
 +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
 +                       info->xbzrle_cache->cache_size);
 +        monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
 +                       info->xbzrle_cache->bytes >> 10);
 +        monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
 +                       info->xbzrle_cache->pages);
 +        monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
 +                       info->xbzrle_cache->cache_miss);
 +        monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
 +                       info->xbzrle_cache->overflow);
 +    }
 +
      qapi_free_MigrationInfo(info);
 +    qapi_free_MigrationCapabilityStatusList(caps);
 +}
 +
 +void hmp_info_migrate_capabilities(Monitor *mon)
 +{
 +    MigrationCapabilityStatusList *caps, *cap;
 +
 +    caps = qmp_query_migrate_capabilities(NULL);
 +
 +    if (caps) {
 +        monitor_printf(mon, "capabilities: ");
 +        for (cap = caps; cap; cap = cap->next) {
 +            monitor_printf(mon, "%s: %s ",
 +                           MigrationCapability_lookup[cap->value->capability],
 +                           cap->value->state ? "on" : "off");
 +        }
 +        monitor_printf(mon, "\n");
 +    }
 +
 +    qapi_free_MigrationCapabilityStatusList(caps);
 +}
 +
 +void hmp_info_migrate_cache_size(Monitor *mon)
 +{
 +    monitor_printf(mon, "xbzrel cache size: %" PRId64 " kbytes\n",
 +                   qmp_query_migrate_cache_size(NULL) >> 10);
  }
  
  void hmp_info_cpus(Monitor *mon)
@@@ -670,34 -612,35 +670,35 @@@ void hmp_pmemsave(Monitor *mon, const Q
  
  static void hmp_cont_cb(void *opaque, int err)
  {
-     Monitor *mon = opaque;
      if (!err) {
-         hmp_cont(mon, NULL);
+         qmp_cont(NULL);
      }
  }
  
+ static bool key_is_missing(const BlockInfo *bdev)
+ {
+     return (bdev->inserted && bdev->inserted->encryption_key_missing);
+ }
  void hmp_cont(Monitor *mon, const QDict *qdict)
  {
+     BlockInfoList *bdev_list, *bdev;
      Error *errp = NULL;
  
-     qmp_cont(&errp);
-     if (error_is_set(&errp)) {
-         if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
-             const char *device;
-             /* The device is encrypted. Ask the user for the password
-                and retry */
-             device = error_get_field(errp, "device");
-             assert(device != NULL);
-             monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
-             error_free(errp);
-             return;
+     bdev_list = qmp_query_block(NULL);
+     for (bdev = bdev_list; bdev; bdev = bdev->next) {
+         if (key_is_missing(bdev->value)) {
+             monitor_read_block_device_key(mon, bdev->value->device,
+                                           hmp_cont_cb, NULL);
+             goto out;
          }
-         hmp_handle_error(mon, &errp);
      }
+     qmp_cont(&errp);
+     hmp_handle_error(mon, &errp);
+ out:
+     qapi_free_BlockInfoList(bdev_list);
  }
  
  void hmp_system_wakeup(Monitor *mon, const QDict *qdict)
@@@ -789,57 -732,12 +790,57 @@@ void hmp_migrate_set_downtime(Monitor *
      qmp_migrate_set_downtime(value, NULL);
  }
  
 +void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict)
 +{
 +    int64_t value = qdict_get_int(qdict, "value");
 +    Error *err = NULL;
 +
 +    qmp_migrate_set_cache_size(value, &err);
 +    if (err) {
 +        monitor_printf(mon, "%s\n", error_get_pretty(err));
 +        error_free(err);
 +        return;
 +    }
 +}
 +
  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
  {
      int64_t value = qdict_get_int(qdict, "value");
      qmp_migrate_set_speed(value, NULL);
  }
  
 +void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
 +{
 +    const char *cap = qdict_get_str(qdict, "capability");
 +    bool state = qdict_get_bool(qdict, "state");
 +    Error *err = NULL;
 +    MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
 +    int i;
 +
 +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
 +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
 +            caps->value = g_malloc0(sizeof(*caps->value));
 +            caps->value->capability = i;
 +            caps->value->state = state;
 +            caps->next = NULL;
 +            qmp_migrate_set_capabilities(caps, &err);
 +            break;
 +        }
 +    }
 +
 +    if (i == MIGRATION_CAPABILITY_MAX) {
 +        error_set(&err, QERR_INVALID_PARAMETER, cap);
 +    }
 +
 +    qapi_free_MigrationCapabilityStatusList(caps);
 +
 +    if (err) {
 +        monitor_printf(mon, "migrate_set_parameter: %s\n",
 +                       error_get_pretty(err));
 +        error_free(err);
 +    }
 +}
 +
  void hmp_set_password(Monitor *mon, const QDict *qdict)
  {
      const char *protocol  = qdict_get_str(qdict, "protocol");
@@@ -878,22 -776,6 +879,6 @@@ static void hmp_change_read_arg(Monito
      monitor_read_command(mon, 1);
  }
  
- static void cb_hmp_change_bdrv_pwd(Monitor *mon, const char *password,
-                                    void *opaque)
- {
-     Error *encryption_err = opaque;
-     Error *err = NULL;
-     const char *device;
-     device = error_get_field(encryption_err, "device");
-     qmp_block_passwd(device, password, &err);
-     hmp_handle_error(mon, &err);
-     error_free(encryption_err);
-     monitor_read_command(mon, 1);
- }
  void hmp_change(Monitor *mon, const QDict *qdict)
  {
      const char *device = qdict_get_str(qdict, "device");
      }
  
      qmp_change(device, target, !!arg, arg, &err);
-     if (error_is_type(err, QERR_DEVICE_ENCRYPTED)) {
-         monitor_printf(mon, "%s (%s) is encrypted.\n",
-                        error_get_field(err, "device"),
-                        error_get_field(err, "filename"));
-         if (!monitor_get_rs(mon)) {
-             monitor_printf(mon,
-                     "terminal does not support password prompting\n");
-             error_free(err);
-             return;
-         }
-         readline_start(monitor_get_rs(mon), "Password: ", 1,
-                        cb_hmp_change_bdrv_pwd, err);
+     if (error_is_set(&err) &&
+         error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
+         error_free(err);
+         monitor_read_block_device_key(mon, device, NULL, NULL);
          return;
      }
      hmp_handle_error(mon, &err);
diff --combined hmp.h
index 6d6e53bd6e4d17e5647f689c5d1e301deb6df364,3275522bdccf7035ec39fd1a748be5131f32bfa0..7dd93bf0f454f590822e4617981b7b978673ba2a
--- 1/hmp.h
--- 2/hmp.h
+++ b/hmp.h
@@@ -16,6 -16,7 +16,7 @@@
  
  #include "qemu-common.h"
  #include "qapi-types.h"
+ #include "qdict.h"
  
  void hmp_info_name(Monitor *mon);
  void hmp_info_version(Monitor *mon);
@@@ -25,8 -26,6 +26,8 @@@ void hmp_info_uuid(Monitor *mon)
  void hmp_info_chardev(Monitor *mon);
  void hmp_info_mice(Monitor *mon);
  void hmp_info_migrate(Monitor *mon);
 +void hmp_info_migrate_capabilities(Monitor *mon);
 +void hmp_info_migrate_cache_size(Monitor *mon);
  void hmp_info_cpus(Monitor *mon);
  void hmp_info_block(Monitor *mon);
  void hmp_info_blockstats(Monitor *mon);
@@@ -53,8 -52,6 +54,8 @@@ void hmp_snapshot_blkdev(Monitor *mon, 
  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 +void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
 +void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
  void hmp_set_password(Monitor *mon, const QDict *qdict);
  void hmp_expire_password(Monitor *mon, const QDict *qdict);
  void hmp_eject(Monitor *mon, const QDict *qdict);
diff --combined monitor.c
index 5227cf15e39cfb80ce457e1fbb889a3e2c9ee2fc,586abae178235dbc29823864da8844b16df00b20..dd63f1d640c3fa385a87555b9cbb54371349880b
+++ b/monitor.c
@@@ -172,41 -172,11 +172,11 @@@ struct Monitor 
      CPUArchState *mon_cpu;
      BlockDriverCompletionFunc *password_completion_cb;
      void *password_opaque;
- #ifdef CONFIG_DEBUG_MONITOR
-     int print_calls_nr;
- #endif
      QError *error;
      QLIST_HEAD(,mon_fd_t) fds;
      QLIST_ENTRY(Monitor) entry;
  };
  
- #ifdef CONFIG_DEBUG_MONITOR
- #define MON_DEBUG(fmt, ...) do {    \
-     fprintf(stderr, "Monitor: ");       \
-     fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
- static inline void mon_print_count_inc(Monitor *mon)
- {
-     mon->print_calls_nr++;
- }
- static inline void mon_print_count_init(Monitor *mon)
- {
-     mon->print_calls_nr = 0;
- }
- static inline int mon_print_count_get(const Monitor *mon)
- {
-     return mon->print_calls_nr;
- }
- #else /* !CONFIG_DEBUG_MONITOR */
- #define MON_DEBUG(fmt, ...) do { } while (0)
- static inline void mon_print_count_inc(Monitor *mon) { }
- static inline void mon_print_count_init(Monitor *mon) { }
- static inline int mon_print_count_get(const Monitor *mon) { return 0; }
- #endif /* CONFIG_DEBUG_MONITOR */
  /* QMP checker flags */
  #define QMP_ACCEPT_UNKNOWNS 1
  
@@@ -299,8 -269,6 +269,6 @@@ void monitor_vprintf(Monitor *mon, cons
      if (!mon)
          return;
  
-     mon_print_count_inc(mon);
      if (monitor_ctrl_mode(mon)) {
          return;
      }
@@@ -385,16 -353,26 +353,26 @@@ static void monitor_json_emitter(Monito
      QDECREF(json);
  }
  
+ static QDict *build_qmp_error_dict(const QError *err)
+ {
+     QObject *obj;
+     obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }",
+                              ErrorClass_lookup[err->err_class],
+                              qerror_human(err));
+     return qobject_to_qdict(obj);
+ }
  static void monitor_protocol_emitter(Monitor *mon, QObject *data)
  {
      QDict *qmp;
  
      trace_monitor_protocol_emitter(mon);
  
-     qmp = qdict_new();
      if (!monitor_has_error(mon)) {
          /* success response */
+         qmp = qdict_new();
          if (data) {
              qobject_incref(data);
              qdict_put_obj(qmp, "return", data);
          }
      } else {
          /* error response */
-         qdict_put(mon->error->error, "desc", qerror_human(mon->error));
-         qdict_put(qmp, "error", mon->error->error);
-         QINCREF(mon->error->error);
+         qmp = build_qmp_error_dict(mon->error);
          QDECREF(mon->error);
          mon->error = NULL;
      }
@@@ -456,6 -432,7 +432,7 @@@ static const char *monitor_event_names[
      [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
      [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
      [QEVENT_SUSPEND] = "SUSPEND",
+     [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
      [QEVENT_WAKEUP] = "WAKEUP",
      [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
  };
@@@ -2654,20 -2631,6 +2631,20 @@@ static mon_cmd_t info_cmds[] = 
          .help       = "show migration status",
          .mhandler.info = hmp_info_migrate,
      },
 +    {
 +        .name       = "migrate_capabilities",
 +        .args_type  = "",
 +        .params     = "",
 +        .help       = "show current migration capabilities",
 +        .mhandler.info = hmp_info_migrate_capabilities,
 +    },
 +    {
 +        .name       = "migrate_cache_size",
 +        .args_type  = "",
 +        .params     = "",
 +        .help       = "show current migration xbzrle cache size",
 +        .mhandler.info = hmp_info_migrate_cache_size,
 +    },
      {
          .name       = "balloon",
          .args_type  = "",
@@@ -3874,8 -3837,6 +3851,6 @@@ void monitor_set_error(Monitor *mon, QE
      if (!mon->error) {
          mon->error = qerror;
      } else {
-         MON_DEBUG("Additional error report at %s:%d\n",
-                   qerror->file, qerror->linenr);
          QDECREF(qerror);
      }
  }
@@@ -3889,36 -3850,7 +3864,7 @@@ static void handler_audit(Monitor *mon
           * Action: Report an internal error to the client if in QMP.
           */
          qerror_report(QERR_UNDEFINED_ERROR);
-         MON_DEBUG("command '%s' returned failure but did not pass an error\n",
-                   cmd->name);
-     }
- #ifdef CONFIG_DEBUG_MONITOR
-     if (!ret && monitor_has_error(mon)) {
-         /*
-          * If it returns success, it must not have passed an error.
-          *
-          * Action: Report the passed error to the client.
-          */
-         MON_DEBUG("command '%s' returned success but passed an error\n",
-                   cmd->name);
      }
-     if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
-         /*
-          * Handlers should not call Monitor print functions.
-          *
-          * Action: Ignore them in QMP.
-          *
-          * (XXX: we don't check any 'info' or 'query' command here
-          * because the user print function _is_ called by do_info(), hence
-          * we will trigger this check. This problem will go away when we
-          * make 'query' commands real and kill do_info())
-          */
-         MON_DEBUG("command '%s' called print functions %d time(s)\n",
-                   cmd->name, mon_print_count_get(mon));
-     }
- #endif
  }
  
  static void handle_user_command(Monitor *mon, const char *cmdline)
@@@ -4447,8 -4379,6 +4393,6 @@@ static void qmp_call_cmd(Monitor *mon, 
      int ret;
      QObject *data = NULL;
  
-     mon_print_count_init(mon);
      ret = cmd->mhandler.cmd_new(mon, params, &data);
      handler_audit(mon, cmd, ret);
      monitor_protocol_emitter(mon, data);
diff --combined qapi-schema.json
index 56d9d7b0e2f91c98f5a600a0e2a9dd7dd648a63d,9347b6a49935767e459fdfe9ac7e54d379af04c0..53bbe46e4dd090a98776b328bc9e2f6e37d6e0ff
@@@ -2,6 -2,36 +2,36 @@@
  #
  # QAPI Schema
  
+ ##
+ # @ErrorClass
+ #
+ # QEMU error classes
+ #
+ # @GenericError: this is used for errors that don't require a specific error
+ #                class. This should be the default case for most errors
+ #
+ # @CommandNotFound: the requested command has not been found
+ #
+ # @DeviceEncrypted: the requested operation can't be fulfilled because the
+ #                   selected device is encrypted
+ #
+ # @DeviceNotActive: a device has failed to be become active
+ #
+ # @DeviceNotFound: the requested device has not been found
+ #
+ # @KVMMissingCap: the requested operation can't be fulfilled because a
+ #                 required KVM capability is missing
+ #
+ # @MigrationExpected: the requested operation can't be fulfilled because a
+ #                     migration process is expected
+ #
+ # Since: 1.2
+ ##
+ { 'enum': 'ErrorClass',
+   'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
+             'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap',
+             'MigrationExpected' ] }
  ##
  # @NameInfo:
  #
  #
  # @total: total amount of bytes involved in the migration process
  #
 -# @total_time: tota0l amount of ms since migration started.  If
 +# @total-time: total amount of ms since migration started.  If
  #        migration has ended, it returns the total migration
  #        time. (since 1.2)
  #
 -# Since: 0.14.0.
 +# @duplicate: number of duplicate pages (since 1.2)
 +#
 +# @normal : number of normal pages (since 1.2)
 +#
 +# @normal-bytes : number of normal bytes sent (since 1.2)
 +#
 +# Since: 0.14.0
  ##
  { 'type': 'MigrationStats',
    'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
 -           'total_time': 'int' } }
 +           'total-time': 'int', 'duplicate': 'int', 'normal': 'int',
 +           'normal-bytes': 'int' } }
 +
 +##
 +# @XBZRLECacheStats
 +#
 +# Detailed XBZRLE migration cache statistics
 +#
 +# @cache-size: XBZRLE cache size
 +#
 +# @bytes: amount of bytes already transferred to the target VM
 +#
 +# @pages: amount of pages transferred to the target VM
 +#
 +# @cache-miss: number of cache miss
 +#
 +# @overflow: number of overflows
 +#
 +# Since: 1.2
 +##
 +{ 'type': 'XBZRLECacheStats',
 +  'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int',
 +           'cache-miss': 'int', 'overflow': 'int' } }
  
  ##
  # @MigrationInfo
  #        status, only returned if status is 'active' and it is a block
  #        migration
  #
 +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
 +#                migration statistics, only returned if XBZRLE feature is on and
 +#                status is 'active' or 'completed' (since 1.2)
 +#
  # Since: 0.14.0
  ##
  { 'type': 'MigrationInfo',
    'data': {'*status': 'str', '*ram': 'MigrationStats',
 -           '*disk': 'MigrationStats'} }
 +           '*disk': 'MigrationStats',
 +           '*xbzrle-cache': 'XBZRLECacheStats'} }
  
  ##
  # @query-migrate
  ##
  { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
  
 +##
 +# @MigrationCapability
 +#
 +# Migration capabilities enumeration
 +#
 +# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
 +#          This feature allows us to minimize migration traffic for certain work
 +#          loads, by sending compressed difference of the pages
 +#
 +# Since: 1.2
 +##
 +{ 'enum': 'MigrationCapability',
 +  'data': ['xbzrle'] }
 +
 +##
 +# @MigrationCapabilityStatus
 +#
 +# Migration capability information
 +#
 +# @capability: capability enum
 +#
 +# @state: capability state bool
 +#
 +# Since: 1.2
 +##
 +{ 'type': 'MigrationCapabilityStatus',
 +  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
 +
 +##
 +# @migrate-set-capabilities
 +#
 +# Enable/Disable the following migration capabilities (like xbzrle)
 +#
 +# @capabilities: json array of capability modifications to make
 +#
 +# Since: 1.2
 +##
 +{ 'command': 'migrate-set-capabilities',
 +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
 +
 +##
 +# @query-migrate-capabilities
 +#
 +# Returns information about the current migration capabilities status
 +#
 +# Returns: @MigrationCapabilitiesStatus
 +#
 +# Since: 1.2
 +##
 +{ 'command': 'query-migrate-capabilities', 'returns':   ['MigrationCapabilityStatus']}
 +
  ##
  # @MouseInfo:
  #
  #
  # @encrypted: true if the backing device is encrypted
  #
+ # @encryption_key_missing: true if the backing device is encrypted but an
+ #                          valid encryption key is missing
+ #
  # @bps: total throughput limit in bytes per second is specified
  #
  # @bps_rd: read throughput limit in bytes per second is specified
  { 'type': 'BlockDeviceInfo',
    'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',
              '*backing_file': 'str', 'backing_file_depth': 'int',
-             'encrypted': 'bool', 'bps': 'int', 'bps_rd': 'int',
-             'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int',
-             'iops_wr': 'int'} }
+             'encrypted': 'bool', 'encryption_key_missing': 'bool',
+             'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
+             'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
  
  ##
  # @BlockDeviceIoStatus:
  # Returns information about the current VNC server
  #
  # Returns: @VncInfo
- #          If VNC support is not compiled in, FeatureDisabled
  #
  # Since: 0.14.0
  ##
  #                       virtual address (defaults to CPU 0)
  #
  # Returns: Nothing on success
- #          If @cpu is not a valid VCPU, InvalidParameterValue
- #          If @filename cannot be opened, OpenFileFailed
- #          If an I/O error occurs while writing the file, IOError
  #
  # Since: 0.14.0
  #
  # @filename: the file to save the memory to as binary data
  #
  # Returns: Nothing on success
- #          If @filename cannot be opened, OpenFileFailed
- #          If an I/O error occurs while writing the file, IOError
  #
  # Since: 0.14.0
  #
  # Injects an Non-Maskable Interrupt into all guest's VCPUs.
  #
  # Returns:  If successful, nothing
- #           If the Virtual Machine doesn't support NMI injection, Unsupported
  #
  # Since:  0.14.0
  #
  # Returns: nothing on success
  #          If @device is not a valid block device, DeviceNotFound
  #          If @device is not encrypted, DeviceNotEncrypted
- #          If @password is not valid for this device, InvalidPassword
  #
  # Notes:  Not all block formats support encryption and some that do are not
  #         able to validate that a password is correct.  Disk corruption may
  #
  # Returns: nothing on success
  #          If @device is not a valid block device, DeviceNotFound
- #          If @size is negative, InvalidParameterValue
- #          If the block device has no medium inserted, DeviceHasNoMedium
- #          If the block device does not support resize, Unsupported
- #          If the block device is read-only, DeviceIsReadOnly
- #          If a long-running operation is using the device, DeviceInUse
  #
  # Since: 0.14.0
  ##
  #
  # Returns: nothing on success
  #          If @device is not a valid block device, DeviceNotFound
- #          If @device is busy, DeviceInUse will be returned
- #          If @snapshot-file can't be created, OpenFileFailed
- #          If @snapshot-file can't be opened, OpenFileFailed
- #          If @format is invalid, InvalidBlockFormat
  #
  # Note: The transaction aborts on the first failure.  Therefore, there will
  # be only one device or snapshot file returned in an error condition, and
  #
  # Returns: nothing on success
  #          If @device is not a valid block device, DeviceNotFound
- #          If @snapshot-file can't be opened, OpenFileFailed
- #          If @format is invalid, InvalidBlockFormat
  #
  # Since 0.14.0
  ##
  ##
  { 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
  
 +##
 +# @migrate-set-cache-size
 +#
 +# Set XBZRLE cache size
 +#
 +# @value: cache size in bytes
 +#
 +# The size will be rounded down to the nearest power of 2.
 +# The cache size can be modified before and during ongoing migration
 +#
 +# Returns: nothing on success
 +#
 +# Since: 1.2
 +##
 +{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }
 +
 +##
 +# @query-migrate-cache-size
 +#
 +# query XBZRLE cache size
 +#
 +# Returns: XBZRLE cache size in bytes
 +#
 +# Since: 1.2
 +##
 +{ 'command': 'query-migrate-cache-size', 'returns': 'int' }
 +
  ##
  # @ObjectPropertyInfo:
  #
  #        4) A link type in the form 'link<subtype>' where subtype is a qdev
  #           device type name.  Link properties form the device model graph.
  #
- # Since: 1.1
- #
- # Notes: This type is experimental.  Its syntax may change in future releases.
+ # Since: 1.2
  ##
  { 'type': 'ObjectPropertyInfo',
    'data': { 'name': 'str', 'type': 'str' } }
  # Returns: a list of @ObjectPropertyInfo that describe the properties of the
  #          object.
  #
- # Since: 1.1
- #
- # Notes: This command is experimental.  It's syntax may change in future
- #        releases.
+ # Since: 1.2
  ##
  { 'command': 'qom-list',
    'data': { 'path': 'str' },
  #          returns as #str pathnames.  All integer property types (u8, u16, etc)
  #          are returned as #int.
  #
- # Since: 1.1
- #
- # Notes: This command is experimental and may change syntax in future releases.
+ # Since: 1.2
  ##
  { 'command': 'qom-get',
    'data': { 'path': 'str', 'property': 'str' },
  # @value: a value who's type is appropriate for the property type.  See @qom-get
  #         for a description of type mapping.
  #
- # Since: 1.1
- #
- # Notes: This command is experimental and may change syntax in future releases.
+ # Since: 1.2
  ##
  { 'command': 'qom-set',
    'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' },
  #
  # Returns: Nothing on success
  #          If Spice is not enabled, DeviceNotFound
- #          If @protocol does not support connected, InvalidParameter
- #          If @protocol is invalid, InvalidParameter
- #          If any other error occurs, SetPasswdFailed
- #
- # Notes: If VNC is not enabled, SetPasswdFailed is returned.
  #
  # Since: 0.14.0
  ##
  #
  # Returns: Nothing on success
  #          If @protocol is `spice' and Spice is not active, DeviceNotFound
- #          If an error occurs setting password expiration, SetPasswdFailed
- #          If @protocol is not `spice' or 'vnc', InvalidParameter
  #
  # Since: 0.14.0
  #
  #
  # Returns:  Nothing on success
  #           If @device is not a valid block device, DeviceNotFound
- #           If @device is not removable and @force is false, DeviceNotRemovable
- #           If @force is false and @device is locked, DeviceLocked
  #
  # Notes:    Ejecting a device will no media results in success
  #
  #
  # Returns: Nothing on success.
  #          If @device is not a valid block device, DeviceNotFound
- #          If @format is not a valid block format, InvalidBlockFormat
  #          If the new block device is encrypted, DeviceEncrypted.  Note that
  #          if this error is returned, the device has been opened successfully
  #          and an additional call to @block_passwd is required to set the
  #
  # Returns: Nothing on success
  #          If @device is not a valid block device, DeviceNotFound
- #          If the argument combination is invalid, InvalidParameterCombination
  #
  # Since: 1.1
  ##
  # @speed:  #optional the maximum speed, in bytes per second
  #
  # Returns: Nothing on success
- #          If streaming is already active on this device, DeviceInUse
  #          If @device does not exist, DeviceNotFound
- #          If image streaming is not supported by this device, NotSupported
- #          If @base does not exist, BaseNotFound
- #          If @speed is invalid, InvalidParameter
  #
  # Since: 1.1
  ##
  #          Defaults to 0.
  #
  # Returns: Nothing on success
- #          If the job type does not support throttling, NotSupported
- #          If the speed value is invalid, InvalidParameter
  #          If no background operation is active on this device, DeviceNotActive
  #
  # Since: 1.1
  #
  # Returns: Nothing on success
  #          If no background operation is active on this device, DeviceNotActive
- #          If cancellation already in progress, DeviceInUse
  #
  # Since: 1.1
  ##
  # Returns: a list of @ObjectTypeInfo or an empty list if no results are found
  #
  # Since: 1.1
- #
- # Notes: This command is experimental and may change syntax in future releases.
  ##
  { 'command': 'qom-list-types',
    'data': { '*implements': 'str', '*abstract': 'bool' },
    'returns': [ 'ObjectTypeInfo' ] }
  
+ ##
+ # @DevicePropertyInfo:
+ #
+ # Information about device properties.
+ #
+ # @name: the name of the property
+ # @type: the typename of the property
+ #
+ # Since: 1.2
+ ##
+ { 'type': 'DevicePropertyInfo',
+   'data': { 'name': 'str', 'type': 'str' } }
+ ##
+ # @device-list-properties:
+ #
+ # List properties associated with a device.
+ #
+ # @typename: the type name of a device
+ #
+ # Returns: a list of DevicePropertyInfo describing a devices properties
+ #
+ # Since: 1.2
+ ##
+ { 'command': 'device-list-properties',
+   'data': { 'typename': 'str'},
+   'returns': [ 'DevicePropertyInfo' ] }
  ##
  # @migrate
  #
  # format.
  #
  # Returns: Nothing on success
- #          If @filename cannot be opened, OpenFileFailed
- #          If an I/O error occurs while writing the file, IOError
  #
  # Since: 1.1
  ##
  #
  # Returns: Nothing on success
  #          If @id is not a valid device, DeviceNotFound
- #          If the device does not support unplug, BusNoHotplug
  #
  # Notes: When this command completes, the device may not be removed from the
  #        guest.  Hot removal is an operation that requires guest cooperation.
  # want to dump all guest's memory, please specify the start @begin and @length
  #
  # Returns: nothing on success
- #          If @begin contains an invalid address, InvalidParameter
- #          If only one of @begin and @length is specified, MissingParameter
- #          If @protocol stats with "fd:", and the fd cannot be found, FdNotFound
- #          If @protocol starts with "file:", and the file cannot be
- #             opened, OpenFileFailed
- #          If @protocol does not start with "fd:" or "file:", InvalidParameter
- #          If an I/O error occurs while writing the file, IOError
- #          If the target does not support this command, Unsupported
  #
  # Since: 1.2
  ##
  #
  # Returns: Nothing on success
  #          If @type is not a valid network backend, DeviceNotFound
- #          If @id is not a valid identifier, InvalidParameterValue
- #          if @id already exists, DuplicateId
- #          If @props contains an invalid parameter for this backend,
- #            InvalidParameter
  ##
  { 'command': 'netdev_add',
    'data': {'type': 'str', 'id': 'str', '*props': '**'},
  # @fdname: file descriptor name
  #
  # Returns: Nothing on success
- #          If file descriptor was not received, FdNotSupplied
- #          If @fdname is not valid, InvalidParameterType
  #
  # Since: 0.14.0
  #
  # @fdname: file descriptor name
  #
  # Returns: Nothing on success
- #          If @fdname is not found, FdNotFound
  #
  # Since: 0.14.0
  ##
  { 'command': 'closefd', 'data': {'fdname': 'str'} }
+ ##
+ # @MachineInfo:
+ #
+ # Information describing a machine.
+ #
+ # @name: the name of the machine
+ #
+ # @alias: #optional an alias for the machine name
+ #
+ # @default: #optional whether the machine is default
+ #
+ # Since: 1.2.0
+ ##
+ { 'type': 'MachineInfo',
+   'data': { 'name': 'str', '*alias': 'str',
+             '*is-default': 'bool' } }
+ ##
+ # @query-machines:
+ #
+ # Return a list of supported machines
+ #
+ # Returns: a list of MachineInfo
+ #
+ # Since: 1.2.0
+ ##
+ { 'command': 'query-machines', 'returns': ['MachineInfo'] }
+ ##
+ # @CpuDefinitionInfo:
+ #
+ # Virtual CPU definition.
+ #
+ # @name: the name of the CPU definition
+ #
+ # Since: 1.2.0
+ ##
+ { 'type': 'CpuDefinitionInfo',
+   'data': { 'name': 'str' } }
+ ##
+ # @query-cpu-definitions:
+ #
+ # Return a list of supported virtual CPU definitions
+ #
+ # Returns: a list of CpuDefInfo
+ #
+ # Since: 1.2.0
+ ##
+ { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
diff --combined qmp-commands.hx
index 0363d7cca997da3343288abddfbfc39a5d328ac0,521da1055ffda8fab6682e4d768a0396b8c6bd13..527b9f7c2499feb213c562c1373d772202e83b36
@@@ -435,8 -435,8 +435,8 @@@ Example
  -> { "execute": "inject-nmi" }
  <- { "return": {} }
  
- Note: inject-nmi is only supported for x86 guest currently, it will
-       returns "Unsupported" error for non-x86 guest.
+ Note: inject-nmi fails when the guest doesn't support injecting.
+       Currently, only x86 guests do.
  
  EQMP
  
@@@ -519,50 -519,6 +519,50 @@@ Example
  -> { "execute": "migrate_cancel" }
  <- { "return": {} }
  
 +EQMP
 +{
 +        .name       = "migrate-set-cache-size",
 +        .args_type  = "value:o",
 +        .mhandler.cmd_new = qmp_marshal_input_migrate_set_cache_size,
 +    },
 +
 +SQMP
 +migrate-set-cache-size
 +---------------------
 +
 +Set cache size to be used by XBZRLE migration, the cache size will be rounded
 +down to the nearest power of 2
 +
 +Arguments:
 +
 +- "value": cache size in bytes (json-int)
 +
 +Example:
 +
 +-> { "execute": "migrate-set-cache-size", "arguments": { "value": 536870912 } }
 +<- { "return": {} }
 +
 +EQMP
 +    {
 +        .name       = "query-migrate-cache-size",
 +        .args_type  = "",
 +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_cache_size,
 +    },
 +
 +SQMP
 +query-migrate-cache-size
 +---------------------
 +
 +Show cache size to be used by XBZRLE migration
 +
 +returns a json-object with the following information:
 +- "size" : json-int
 +
 +Example:
 +
 +-> { "execute": "query-migrate-cache-size" }
 +<- { "return": 67108864 }
 +
  EQMP
  
      {
@@@ -2122,24 -2078,12 +2122,24 @@@ The main json-object contains the follo
           - "transferred": amount transferred (json-int)
           - "remaining": amount remaining (json-int)
           - "total": total (json-int)
 +         - "total-time": total amount of ms since migration started.  If
 +                         migration has ended, it returns the total migration time
 +                         (json-int)
 +         - "duplicate": number of duplicated pages (json-int)
 +         - "normal" : number of normal pages transferred (json-int)
 +         - "normal-bytes" : number of normal bytes transferred (json-int)
  - "disk": only present if "status" is "active" and it is a block migration,
    it is a json-object with the following disk information (in bytes):
           - "transferred": amount transferred (json-int)
           - "remaining": amount remaining (json-int)
           - "total": total (json-int)
 -
 +- "xbzrle-cache": only present if XBZRLE is active.
 +  It is a json-object with the following XBZRLE information:
 +         - "cache-size": XBZRLE cache size
 +         - "bytes": total XBZRLE bytes transferred
 +         - "pages": number of XBZRLE compressed pages
 +         - "cache-miss": number of cache misses
 +         - "overflow": number of XBZRLE overflows
  Examples:
  
  1. Before the first migration
  2. Migration is done and has succeeded
  
  -> { "execute": "query-migrate" }
 -<- { "return": { "status": "completed" } }
 +<- { "return": {
 +        "status": "completed",
 +        "ram":{
 +          "transferred":123,
 +          "remaining":123,
 +          "total":246,
 +          "total-time":12345,
 +          "duplicate":123,
 +          "normal":123,
 +          "normal-bytes":123456
 +        }
 +     }
 +   }
  
  3. Migration is done and has failed
  
           "ram":{
              "transferred":123,
              "remaining":123,
 -            "total":246
 +            "total":246,
 +            "total-time":12345,
 +            "duplicate":123,
 +            "normal":123,
 +            "normal-bytes":123456
           }
        }
     }
           "ram":{
              "total":1057024,
              "remaining":1053304,
 -            "transferred":3720
 +            "transferred":3720,
 +            "total-time":12345,
 +            "duplicate":123,
 +            "normal":123,
 +            "normal-bytes":123456
           },
           "disk":{
              "total":20971520,
        }
     }
  
 +6. Migration is being performed and XBZRLE is active:
 +
 +-> { "execute": "query-migrate" }
 +<- {
 +      "return":{
 +         "status":"active",
 +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
 +         "ram":{
 +            "total":1057024,
 +            "remaining":1053304,
 +            "transferred":3720,
 +            "total-time":12345,
 +            "duplicate":10,
 +            "normal":3333,
 +            "normal-bytes":3412992
 +         },
 +         "xbzrle-cache":{
 +            "cache-size":67108864,
 +            "bytes":20971520,
 +            "pages":2444343,
 +            "cache-miss":2244,
 +            "overflow":34434
 +         }
 +      }
 +   }
 +
  EQMP
  
      {
          .mhandler.cmd_new = qmp_marshal_input_query_migrate,
      },
  
 +SQMP
 +migrate-set-capabilities
 +-------
 +
 +Enable/Disable migration capabilities
 +
 +- "xbzrle": xbzrle support
 +
 +Arguments:
 +
 +Example:
 +
 +-> { "execute": "migrate-set-capabilities" , "arguments":
 +     { "capabilities": [ { "capability": "xbzrle", "state": true } ] } }
 +
 +EQMP
 +
 +    {
 +        .name       = "migrate-set-capabilities",
 +        .args_type  = "capabilities:O",
 +        .params     = "capability:s,state:b",
 +      .mhandler.cmd_new = qmp_marshal_input_migrate_set_capabilities,
 +    },
 +SQMP
 +query-migrate-capabilities
 +-------
 +
 +Query current migration capabilities
 +
 +- "capabilities": migration capabilities state
 +         - "xbzrle" : XBZRLE state (json-bool)
 +
 +Arguments:
 +
 +Example:
 +
 +-> { "execute": "query-migrate-capabilities" }
 +<- { "return": {
 +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
 +     }
 +   }
 +EQMP
 +
 +    {
 +        .name       = "query-migrate-capabilities",
 +        .args_type  = "",
 +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_capabilities,
 +    },
 +
  SQMP
  query-balloon
  -------------
          .args_type  = "implements:s?,abstract:b?",
          .mhandler.cmd_new = qmp_marshal_input_qom_list_types,
      },
+     {
+         .name       = "device-list-properties",
+         .args_type  = "typename:s",
+         .mhandler.cmd_new = qmp_marshal_input_device_list_properties,
+     },
+     {
+         .name       = "query-machines",
+         .args_type  = "",
+         .mhandler.cmd_new = qmp_marshal_input_query_machines,
+     },
+     {
+         .name       = "query-cpu-definitions",
+         .args_type  = "",
+         .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions,
+     },