]> git.proxmox.com Git - pve-qemu.git/blobdiff - debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
update submodule and patches to QEMU 8.2.2
[pve-qemu.git] / debian / patches / pve / 0017-PVE-add-savevm-async-for-background-state-snapshots.patch
index 4b8cf7b701deb39d12b51467101b13362a447ed8..bd8837dd7524fcf4ea0fd590d6935b3ffbd11b4f 100644 (file)
@@ -21,31 +21,34 @@ still opened by QEMU.
 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
 Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
-[improve aborting]
+[SR: improve aborting
+     register yank before migration_incoming_state_destroy]
 Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
 [FE: further improve aborting
-     adapt to removal of QEMUFileOps]
+     adapt to removal of QEMUFileOps
+     improve condition for entering final stage
+     adapt to QAPI and other changes for 8.2]
 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
 ---
  hmp-commands-info.hx         |  13 +
- hmp-commands.hx              |  33 +++
+ hmp-commands.hx              |  17 ++
  include/migration/snapshot.h |   2 +
- include/monitor/hmp.h        |   5 +
+ include/monitor/hmp.h        |   3 +
  migration/meson.build        |   1 +
- migration/savevm-async.c     | 531 +++++++++++++++++++++++++++++++++++
- monitor/hmp-cmds.c           |  57 ++++
+ migration/savevm-async.c     | 534 +++++++++++++++++++++++++++++++++++
+ monitor/hmp-cmds.c           |  38 +++
  qapi/migration.json          |  34 +++
- qapi/misc.json               |  32 +++
+ qapi/misc.json               |  16 ++
  qemu-options.hx              |  12 +
- softmmu/vl.c                 |  10 +
- 11 files changed, 730 insertions(+)
+ system/vl.c                  |  10 +
+ 11 files changed, 680 insertions(+)
  create mode 100644 migration/savevm-async.c
 
 diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
-index 754b1e8408..489c524e9e 100644
+index f5b37eb74a..10fdd822e0 100644
 --- a/hmp-commands-info.hx
 +++ b/hmp-commands-info.hx
-@@ -540,6 +540,19 @@ SRST
+@@ -525,6 +525,19 @@ SRST
      Show current migration parameters.
  ERST
  
@@ -66,11 +69,11 @@ index 754b1e8408..489c524e9e 100644
          .name       = "balloon",
          .args_type  = "",
 diff --git a/hmp-commands.hx b/hmp-commands.hx
-index 673e39a697..039be0033d 100644
+index 765349ed14..893c3bd240 100644
 --- a/hmp-commands.hx
 +++ b/hmp-commands.hx
-@@ -1815,3 +1815,36 @@ SRST
-   Dump the FDT in dtb format to *filename*.
+@@ -1875,3 +1875,20 @@ SRST
+   List event channels in the guest
  ERST
  #endif
 +
@@ -83,22 +86,6 @@ index 673e39a697..039be0033d 100644
 +    },
 +
 +    {
-+        .name       = "snapshot-drive",
-+        .args_type  = "device:s,name:s",
-+        .params     = "device name",
-+        .help       = "Create internal snapshot.",
-+        .cmd = hmp_snapshot_drive,
-+    },
-+
-+    {
-+        .name       = "delete-drive-snapshot",
-+        .args_type  = "device:s,name:s",
-+        .params     = "device name",
-+        .help       = "Delete internal snapshot.",
-+        .cmd = hmp_delete_drive_snapshot,
-+    },
-+
-+    {
 +        .name       = "savevm-end",
 +        .args_type  = "",
 +        .params     = "",
@@ -118,10 +105,10 @@ index e72083b117..c846d37806 100644
 +
  #endif
 diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
-index dfbc0c9a2f..440f86aba8 100644
+index 13f9a2dedb..7a7def7530 100644
 --- a/include/monitor/hmp.h
 +++ b/include/monitor/hmp.h
-@@ -27,6 +27,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict);
+@@ -28,6 +28,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict);
  void hmp_info_uuid(Monitor *mon, const QDict *qdict);
  void hmp_info_chardev(Monitor *mon, const QDict *qdict);
  void hmp_info_mice(Monitor *mon, const QDict *qdict);
@@ -129,38 +116,38 @@ index dfbc0c9a2f..440f86aba8 100644
  void hmp_info_migrate(Monitor *mon, const QDict *qdict);
  void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict);
  void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
-@@ -81,6 +82,10 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
- void hmp_netdev_del(Monitor *mon, const QDict *qdict);
- void hmp_getfd(Monitor *mon, const QDict *qdict);
- void hmp_closefd(Monitor *mon, const QDict *qdict);
+@@ -94,6 +95,8 @@ void hmp_closefd(Monitor *mon, const QDict *qdict);
+ void hmp_mouse_move(Monitor *mon, const QDict *qdict);
+ void hmp_mouse_button(Monitor *mon, const QDict *qdict);
+ void hmp_mouse_set(Monitor *mon, const QDict *qdict);
 +void hmp_savevm_start(Monitor *mon, const QDict *qdict);
-+void hmp_snapshot_drive(Monitor *mon, const QDict *qdict);
-+void hmp_delete_drive_snapshot(Monitor *mon, const QDict *qdict);
 +void hmp_savevm_end(Monitor *mon, const QDict *qdict);
  void hmp_sendkey(Monitor *mon, const QDict *qdict);
  void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
  void hmp_chardev_add(Monitor *mon, const QDict *qdict);
 diff --git a/migration/meson.build b/migration/meson.build
-index 8cac83c06c..0842d00cd2 100644
+index 0e689eac09..8f9d122187 100644
 --- a/migration/meson.build
 +++ b/migration/meson.build
-@@ -24,6 +24,7 @@ softmmu_ss.add(files(
-   'multifd-zlib.c',
+@@ -27,6 +27,7 @@ system_ss.add(files(
+   'options.c',
    'postcopy-ram.c',
    'savevm.c',
 +  'savevm-async.c',
    'socket.c',
    'tls.c',
- ), gnutls)
+   'threadinfo.c',
 diff --git a/migration/savevm-async.c b/migration/savevm-async.c
 new file mode 100644
-index 0000000000..05d394c0e2
+index 0000000000..8f63c4c637
 --- /dev/null
 +++ b/migration/savevm-async.c
-@@ -0,0 +1,531 @@
+@@ -0,0 +1,534 @@
 +#include "qemu/osdep.h"
 +#include "migration/channel-savevm-async.h"
 +#include "migration/migration.h"
++#include "migration/migration-stats.h"
++#include "migration/options.h"
 +#include "migration/savevm.h"
 +#include "migration/snapshot.h"
 +#include "migration/global_state.h"
@@ -180,6 +167,7 @@ index 0000000000..05d394c0e2
 +#include "qemu/timer.h"
 +#include "qemu/main-loop.h"
 +#include "qemu/rcu.h"
++#include "qemu/yank.h"
 +
 +/* #define DEBUG_SAVEVM_STATE */
 +
@@ -230,24 +218,20 @@ index 0000000000..05d394c0e2
 +        info->bytes = s->bs_pos;
 +        switch (s->state) {
 +        case SAVE_STATE_ERROR:
-+            info->has_status = true;
 +            info->status = g_strdup("failed");
 +            info->has_total_time = true;
 +            info->total_time = s->total_time;
 +            if (s->error) {
-+                info->has_error = true;
 +                info->error = g_strdup(error_get_pretty(s->error));
 +            }
 +            break;
 +        case SAVE_STATE_ACTIVE:
-+            info->has_status = true;
 +            info->status = g_strdup("active");
 +            info->has_total_time = true;
 +            info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
 +                - s->total_time;
 +            break;
 +        case SAVE_STATE_COMPLETED:
-+            info->has_status = true;
 +            info->status = g_strdup("completed");
 +            info->has_total_time = true;
 +            info->total_time = s->total_time;
@@ -293,7 +277,7 @@ index 0000000000..05d394c0e2
 +    return ret;
 +}
 +
-+static void save_snapshot_error(const char *fmt, ...)
++static void G_GNUC_PRINTF(1, 2) save_snapshot_error(const char *fmt, ...)
 +{
 +    va_list ap;
 +    char *msg;
@@ -347,7 +331,7 @@ index 0000000000..05d394c0e2
 +        (void)qemu_savevm_state_complete_precopy(snap_state.file, false, false);
 +        ret = qemu_file_get_error(snap_state.file);
 +        if (ret < 0) {
-+                save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
++            save_snapshot_error("qemu_savevm_state_complete_precopy error %d", ret);
 +        }
 +    }
 +
@@ -404,18 +388,32 @@ index 0000000000..05d394c0e2
 +    }
 +
 +    while (snap_state.state == SAVE_STATE_ACTIVE) {
-+        uint64_t pending_size, pend_precopy, pend_compatible, pend_postcopy;
++        uint64_t pending_size, pend_precopy, pend_postcopy;
++        uint64_t threshold = 400 * 1000;
 +
-+        /* pending is expected to be called without iothread lock */
++        /*
++         * pending_{estimate,exact} are expected to be called without iothread
++         * lock. Similar to what is done in migration.c, call the exact variant
++         * only once pend_precopy in the estimate is below the threshold.
++         */
 +        qemu_mutex_unlock_iothread();
-+        qemu_savevm_state_pending(snap_state.file, 0, &pend_precopy, &pend_compatible, &pend_postcopy);
++        qemu_savevm_state_pending_estimate(&pend_precopy, &pend_postcopy);
++        if (pend_precopy <= threshold) {
++            qemu_savevm_state_pending_exact(&pend_precopy, &pend_postcopy);
++        }
 +        qemu_mutex_lock_iothread();
++        pending_size = pend_precopy + pend_postcopy;
 +
-+        pending_size = pend_precopy + pend_compatible + pend_postcopy;
-+
-+        maxlen = blk_getlength(snap_state.target) - 30*1024*1024;
++        /*
++         * A guest reaching this cutoff is dirtying lots of RAM. It should be
++         * large enough so that the guest can't dirty this much between the
++         * check and the guest actually being stopped, but it should be small
++         * enough to avoid long downtimes for non-hibernation snapshots.
++         */
++        maxlen = blk_getlength(snap_state.target) - 100*1024*1024;
 +
-+        if (pending_size > 400000 && snap_state.bs_pos + pending_size < maxlen) {
++        /* Note that there is no progress for pend_postcopy when iterating */
++        if (pend_precopy > threshold && snap_state.bs_pos + pending_size < maxlen) {
 +            ret = qemu_savevm_state_iterate(snap_state.file, false);
 +            if (ret < 0) {
 +                save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
@@ -424,11 +422,7 @@ index 0000000000..05d394c0e2
 +            DPRINTF("savevm iterate pending size %lu ret %d\n", pending_size, ret);
 +        } else {
 +            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
-+            ret = global_state_store();
-+            if (ret) {
-+                save_snapshot_error("global_state_store error %d", ret);
-+                break;
-+            }
++            global_state_store();
 +
 +            DPRINTF("savevm iterate complete\n");
 +            break;
@@ -447,19 +441,25 @@ index 0000000000..05d394c0e2
 +     * so move there now and after every flush.
 +     */
 +    aio_co_reschedule_self(qemu_get_aio_context());
-+    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
++    bdrv_graph_co_rdlock();
++    bs = bdrv_first(&it);
++    bdrv_graph_co_rdunlock();
++    while (bs) {
 +        /* target has BDRV_O_NO_FLUSH, no sense calling bdrv_flush on it */
-+        if (bs == blk_bs(snap_state.target)) {
-+            continue;
-+        }
-+
-+        AioContext *bs_ctx = bdrv_get_aio_context(bs);
-+        if (bs_ctx != qemu_get_aio_context()) {
-+            DPRINTF("savevm: async flushing drive %s\n", bs->filename);
-+            aio_co_reschedule_self(bs_ctx);
-+            bdrv_flush(bs);
-+            aio_co_reschedule_self(qemu_get_aio_context());
++        if (bs != blk_bs(snap_state.target)) {
++            AioContext *bs_ctx = bdrv_get_aio_context(bs);
++            if (bs_ctx != qemu_get_aio_context()) {
++                DPRINTF("savevm: async flushing drive %s\n", bs->filename);
++                aio_co_reschedule_self(bs_ctx);
++                bdrv_graph_co_rdlock();
++                bdrv_flush(bs);
++                bdrv_graph_co_rdunlock();
++                aio_co_reschedule_self(qemu_get_aio_context());
++            }
 +        }
++        bdrv_graph_co_rdlock();
++        bs = bdrv_next(&it);
++        bdrv_graph_co_rdunlock();
 +    }
 +
 +    DPRINTF("timing: async flushing took %ld ms\n",
@@ -468,7 +468,7 @@ index 0000000000..05d394c0e2
 +    qemu_bh_schedule(snap_state.finalize_bh);
 +}
 +
-+void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
++void qmp_savevm_start(const char *statefile, Error **errp)
 +{
 +    Error *local_err = NULL;
 +    MigrationState *ms = migrate_get_current();
@@ -487,7 +487,7 @@ index 0000000000..05d394c0e2
 +        return;
 +    }
 +
-+    if (migrate_use_block()) {
++    if (migrate_block()) {
 +        error_set(errp, ERROR_CLASS_GENERIC_ERROR,
 +                  "Block migration and snapshots are incompatible");
 +        return;
@@ -505,7 +505,7 @@ index 0000000000..05d394c0e2
 +        snap_state.error = NULL;
 +    }
 +
-+    if (!has_statefile) {
++    if (!statefile) {
 +        vm_stop(RUN_STATE_SAVE_VM);
 +        snap_state.state = SAVE_STATE_COMPLETED;
 +        return;
@@ -539,8 +539,10 @@ index 0000000000..05d394c0e2
 +     * State is cleared in process_savevm_co, but has to be initialized
 +     * here (blocking main thread, from QMP) to avoid race conditions.
 +     */
-+    migrate_init(ms);
-+    memset(&ram_counters, 0, sizeof(ram_counters));
++    if (migrate_init(ms, errp)) {
++        return;
++    }
++    memset(&mig_stats, 0, sizeof(mig_stats));
 +    ms->to_dst_file = snap_state.file;
 +
 +    error_setg(&snap_state.blocker, "block device is in use by savevm");
@@ -549,10 +551,8 @@ index 0000000000..05d394c0e2
 +    snap_state.state = SAVE_STATE_ACTIVE;
 +    snap_state.finalize_bh = qemu_bh_new(process_savevm_finalize, &snap_state);
 +    snap_state.co = qemu_coroutine_create(&process_savevm_co, NULL);
-+    qemu_mutex_unlock_iothread();
 +    qemu_savevm_state_header(snap_state.file);
 +    qemu_savevm_state_setup(snap_state.file);
-+    qemu_mutex_lock_iothread();
 +
 +    /* Async processing from here on out happens in iohandler context, so let
 +     * the target bdrv have its home there.
@@ -623,22 +623,6 @@ index 0000000000..05d394c0e2
 +    DPRINTF("savevm-end: cleanup done\n");
 +}
 +
-+// FIXME: Deprecated
-+void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
-+{
-+    // Compatibility to older qemu-server.
-+    qmp_blockdev_snapshot_internal_sync(device, name, errp);
-+}
-+
-+// FIXME: Deprecated
-+void qmp_delete_drive_snapshot(const char *device, const char *name,
-+                               Error **errp)
-+{
-+    // Compatibility to older qemu-server.
-+    (void)qmp_blockdev_snapshot_delete_internal_sync(device, false, NULL,
-+                                                     true, name, errp);
-+}
-+
 +int load_snapshot_from_blockdev(const char *filename, Error **errp)
 +{
 +    BlockBackend *be;
@@ -673,6 +657,10 @@ index 0000000000..05d394c0e2
 +    dirty_bitmap_mig_before_vm_start();
 +
 +    qemu_fclose(f);
++
++    /* state_destroy assumes a real migration which would have added a yank */
++    yank_register_instance(MIGRATION_YANK_INSTANCE, &error_abort);
++
 +    migration_incoming_state_destroy();
 +    if (ret < 0) {
 +        error_setg_errno(errp, -ret, "Error while loading VM state");
@@ -690,39 +678,28 @@ index 0000000000..05d394c0e2
 +    return ret;
 +}
 diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
-index 480b798963..cfebfd1db5 100644
+index 871898ac46..ef4634e5c1 100644
 --- a/monitor/hmp-cmds.c
 +++ b/monitor/hmp-cmds.c
-@@ -1906,6 +1906,63 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
-     hmp_handle_error(mon, err);
- }
+@@ -22,6 +22,7 @@
+ #include "monitor/monitor-internal.h"
+ #include "qapi/error.h"
+ #include "qapi/qapi-commands-control.h"
++#include "qapi/qapi-commands-migration.h"
+ #include "qapi/qapi-commands-misc.h"
+ #include "qapi/qmp/qdict.h"
+ #include "qemu/cutils.h"
+@@ -443,3 +444,40 @@ void hmp_info_mtree(Monitor *mon, const QDict *qdict)
  
+     mtree_info(flatview, dispatch_tree, owner, disabled);
+ }
++
 +void hmp_savevm_start(Monitor *mon, const QDict *qdict)
 +{
 +    Error *errp = NULL;
 +    const char *statefile = qdict_get_try_str(qdict, "statefile");
 +
-+    qmp_savevm_start(statefile != NULL, statefile, &errp);
-+    hmp_handle_error(mon, errp);
-+}
-+
-+void hmp_snapshot_drive(Monitor *mon, const QDict *qdict)
-+{
-+    Error *errp = NULL;
-+    const char *name = qdict_get_str(qdict, "name");
-+    const char *device = qdict_get_str(qdict, "device");
-+
-+    qmp_snapshot_drive(device, name, &errp);
-+    hmp_handle_error(mon, errp);
-+}
-+
-+void hmp_delete_drive_snapshot(Monitor *mon, const QDict *qdict)
-+{
-+    Error *errp = NULL;
-+    const char *name = qdict_get_str(qdict, "name");
-+    const char *device = qdict_get_str(qdict, "device");
-+
-+    qmp_delete_drive_snapshot(device, name, &errp);
++    qmp_savevm_start(statefile, &errp);
 +    hmp_handle_error(mon, errp);
 +}
 +
@@ -739,7 +716,7 @@ index 480b798963..cfebfd1db5 100644
 +    SaveVMInfo *info;
 +    info = qmp_query_savevm(NULL);
 +
-+    if (info->has_status) {
++    if (info->status) {
 +        monitor_printf(mon, "savevm status: %s\n", info->status);
 +        monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
 +                       info->total_time);
@@ -749,21 +726,17 @@ index 480b798963..cfebfd1db5 100644
 +    if (info->has_bytes) {
 +        monitor_printf(mon, "Bytes saved: %"PRIu64"\n", info->bytes);
 +    }
-+    if (info->has_error) {
++    if (info->error) {
 +        monitor_printf(mon, "Error: %s\n", info->error);
 +    }
 +}
-+
- void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
- {
-     IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
 diff --git a/qapi/migration.json b/qapi/migration.json
-index 88ecf86ac8..4435866379 100644
+index 197d3faa43..b41465fbe9 100644
 --- a/qapi/migration.json
 +++ b/qapi/migration.json
-@@ -261,6 +261,40 @@
-            '*compression': 'CompressionStats',
-            '*socket-address': ['SocketAddress'] } }
+@@ -298,6 +298,40 @@
+            '*dirty-limit-throttle-time-per-round': 'uint64',
+            '*dirty-limit-ring-full-time': 'uint64'} }
  
 +##
 +# @SaveVMInfo:
@@ -803,10 +776,10 @@ index 88ecf86ac8..4435866379 100644
  # @query-migrate:
  #
 diff --git a/qapi/misc.json b/qapi/misc.json
-index 27ef5a2b20..b3ce75dcae 100644
+index cda2effa81..94a58bb0bf 100644
 --- a/qapi/misc.json
 +++ b/qapi/misc.json
-@@ -435,6 +435,38 @@
+@@ -456,6 +456,22 @@
  ##
  { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
  
@@ -819,22 +792,6 @@ index 27ef5a2b20..b3ce75dcae 100644
 +{ 'command': 'savevm-start', 'data': { '*statefile': 'str' } }
 +
 +##
-+# @snapshot-drive:
-+#
-+# Create an internal drive snapshot.
-+#
-+##
-+{ 'command': 'snapshot-drive', 'data': { 'device': 'str', 'name': 'str' } }
-+
-+##
-+# @delete-drive-snapshot:
-+#
-+# Delete a drive snapshot.
-+#
-+##
-+{ 'command': 'delete-drive-snapshot', 'data': { 'device': 'str', 'name': 'str' } }
-+
-+##
 +# @savevm-end:
 +#
 +# Resume VM after a snapshot.
@@ -846,10 +803,10 @@ index 27ef5a2b20..b3ce75dcae 100644
  # @CommandLineParameterType:
  #
 diff --git a/qemu-options.hx b/qemu-options.hx
-index 7f99d15b23..54efb127c4 100644
+index b6b4ad9e67..881b0b3c43 100644
 --- a/qemu-options.hx
 +++ b/qemu-options.hx
-@@ -4391,6 +4391,18 @@ SRST
+@@ -4590,6 +4590,18 @@ SRST
      Start right away with a saved state (``loadvm`` in monitor)
  ERST
  
@@ -868,11 +825,11 @@ index 7f99d15b23..54efb127c4 100644
  #ifndef _WIN32
  DEF("daemonize", 0, QEMU_OPTION_daemonize, \
      "-daemonize      daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
-diff --git a/softmmu/vl.c b/softmmu/vl.c
-index 5f7f6ca981..21f067d115 100644
---- a/softmmu/vl.c
-+++ b/softmmu/vl.c
-@@ -164,6 +164,7 @@ static const char *accelerators;
+diff --git a/system/vl.c b/system/vl.c
+index d2a3b3f457..57f7ba0525 100644
+--- a/system/vl.c
++++ b/system/vl.c
+@@ -163,6 +163,7 @@ static const char *accelerators;
  static bool have_custom_ram_size;
  static const char *ram_memdev_id;
  static QDict *machine_opts_dict;
@@ -880,7 +837,7 @@ index 5f7f6ca981..21f067d115 100644
  static QTAILQ_HEAD(, ObjectOption) object_opts = QTAILQ_HEAD_INITIALIZER(object_opts);
  static QTAILQ_HEAD(, DeviceOption) device_opts = QTAILQ_HEAD_INITIALIZER(device_opts);
  static int display_remote;
-@@ -2607,6 +2608,12 @@ void qmp_x_exit_preconfig(Error **errp)
+@@ -2715,6 +2716,12 @@ void qmp_x_exit_preconfig(Error **errp)
  
      if (loadvm) {
          load_snapshot(loadvm, NULL, false, NULL, &error_fatal);
@@ -893,7 +850,7 @@ index 5f7f6ca981..21f067d115 100644
      }
      if (replay_mode != REPLAY_MODE_NONE) {
          replay_vmstate_init();
-@@ -3151,6 +3158,9 @@ void qemu_init(int argc, char **argv)
+@@ -3265,6 +3272,9 @@ void qemu_init(int argc, char **argv)
              case QEMU_OPTION_loadvm:
                  loadvm = optarg;
                  break;