xref: /openbmc/qemu/migration/savevm.c (revision 97d2b66d)
1c3049a56SJuan Quintela /*
2c3049a56SJuan Quintela  * QEMU System Emulator
3c3049a56SJuan Quintela  *
4c3049a56SJuan Quintela  * Copyright (c) 2003-2008 Fabrice Bellard
576cc7b58SJuan Quintela  * Copyright (c) 2009-2015 Red Hat Inc
676cc7b58SJuan Quintela  *
776cc7b58SJuan Quintela  * Authors:
876cc7b58SJuan Quintela  *  Juan Quintela <quintela@redhat.com>
9c3049a56SJuan Quintela  *
10c3049a56SJuan Quintela  * Permission is hereby granted, free of charge, to any person obtaining a copy
11c3049a56SJuan Quintela  * of this software and associated documentation files (the "Software"), to deal
12c3049a56SJuan Quintela  * in the Software without restriction, including without limitation the rights
13c3049a56SJuan Quintela  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14c3049a56SJuan Quintela  * copies of the Software, and to permit persons to whom the Software is
15c3049a56SJuan Quintela  * furnished to do so, subject to the following conditions:
16c3049a56SJuan Quintela  *
17c3049a56SJuan Quintela  * The above copyright notice and this permission notice shall be included in
18c3049a56SJuan Quintela  * all copies or substantial portions of the Software.
19c3049a56SJuan Quintela  *
20c3049a56SJuan Quintela  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21c3049a56SJuan Quintela  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22c3049a56SJuan Quintela  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23c3049a56SJuan Quintela  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24c3049a56SJuan Quintela  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25c3049a56SJuan Quintela  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26c3049a56SJuan Quintela  * THE SOFTWARE.
27c3049a56SJuan Quintela  */
28c3049a56SJuan Quintela 
291393a485SPeter Maydell #include "qemu/osdep.h"
30c3049a56SJuan Quintela #include "hw/boards.h"
31c3049a56SJuan Quintela #include "net/net.h"
326666c96aSJuan Quintela #include "migration.h"
335e22479aSJuan Quintela #include "migration/snapshot.h"
34947701ccSJuan Quintela #include "migration-stats.h"
35d6454270SMarkus Armbruster #include "migration/vmstate.h"
36f8d806c9SJuan Quintela #include "migration/misc.h"
37f2a8f0a6SJuan Quintela #include "migration/register.h"
3884a899deSJuan Quintela #include "migration/global_state.h"
3967bdabe2SDaniel P. Berrangé #include "migration/channel-block.h"
407b1e1a22SJuan Quintela #include "ram.h"
4108a0aee1SJuan Quintela #include "qemu-file.h"
4220a519a0SJuan Quintela #include "savevm.h"
43be07b0acSJuan Quintela #include "postcopy-ram.h"
44e688df6bSMarkus Armbruster #include "qapi/error.h"
45112ed241SMarkus Armbruster #include "qapi/qapi-commands-migration.h"
46f1a9fcddSDaniel P. Berrangé #include "qapi/clone-visitor.h"
47f1a9fcddSDaniel P. Berrangé #include "qapi/qapi-builtin-visit.h"
48d49b6836SMarkus Armbruster #include "qemu/error-report.h"
49c3049a56SJuan Quintela #include "sysemu/cpus.h"
50c3049a56SJuan Quintela #include "exec/memory.h"
5151180423SJuan Quintela #include "exec/target_page.h"
52c3049a56SJuan Quintela #include "trace.h"
53c3049a56SJuan Quintela #include "qemu/iov.h"
54e2c1c34fSMarkus Armbruster #include "qemu/job.h"
55db725815SMarkus Armbruster #include "qemu/main-loop.h"
56c3049a56SJuan Quintela #include "block/snapshot.h"
57f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
5861b67d47SDaniel P. Berrange #include "io/channel-buffer.h"
598925839fSDaniel P. Berrange #include "io/channel-file.h"
60377b21ccSPavel Dovgalyuk #include "sysemu/replay.h"
6154d31236SMarkus Armbruster #include "sysemu/runstate.h"
6246517dd4SMarkus Armbruster #include "sysemu/sysemu.h"
63da278d58SPhilippe Mathieu-Daudé #include "sysemu/xen.h"
64aad555c2SZhang Chen #include "migration/colo.h"
656cafc8e4SYury Kotov #include "qemu/bitmap.h"
667659505cSDr. David Alan Gilbert #include "net/announce.h"
67b5eea99eSLukas Straub #include "qemu/yank.h"
6839675fffSPeter Xu #include "yank_functions.h"
69bb25a728SDr. David Alan Gilbert #include "sysemu/qtest.h"
701f0776f1SJuan Quintela #include "options.h"
71c3049a56SJuan Quintela 
7249324e93SBihong Yu const unsigned int postcopy_ram_discard_version;
73093e3c42SDr. David Alan Gilbert 
7420a519a0SJuan Quintela /* Subcommands for QEMU_VM_COMMAND */
7520a519a0SJuan Quintela enum qemu_vm_cmd {
7620a519a0SJuan Quintela     MIG_CMD_INVALID = 0,   /* Must be 0 */
7720a519a0SJuan Quintela     MIG_CMD_OPEN_RETURN_PATH,  /* Tell the dest to open the Return path */
7820a519a0SJuan Quintela     MIG_CMD_PING,              /* Request a PONG on the RP */
7920a519a0SJuan Quintela 
8020a519a0SJuan Quintela     MIG_CMD_POSTCOPY_ADVISE,       /* Prior to any page transfers, just
8120a519a0SJuan Quintela                                       warn we might want to do PC */
8220a519a0SJuan Quintela     MIG_CMD_POSTCOPY_LISTEN,       /* Start listening for incoming
8320a519a0SJuan Quintela                                       pages as it's running. */
8420a519a0SJuan Quintela     MIG_CMD_POSTCOPY_RUN,          /* Start execution */
8520a519a0SJuan Quintela 
8620a519a0SJuan Quintela     MIG_CMD_POSTCOPY_RAM_DISCARD,  /* A list of pages to discard that
8720a519a0SJuan Quintela                                       were previously sent during
8820a519a0SJuan Quintela                                       precopy but are dirty. */
8920a519a0SJuan Quintela     MIG_CMD_PACKAGED,          /* Send a wrapped stream within this stream */
90aad555c2SZhang Chen     MIG_CMD_ENABLE_COLO,       /* Enable COLO */
91858b6d62SPeter Xu     MIG_CMD_POSTCOPY_RESUME,   /* resume postcopy on dest */
92f25d4225SPeter Xu     MIG_CMD_RECV_BITMAP,       /* Request for recved bitmap on dst */
9320a519a0SJuan Quintela     MIG_CMD_MAX
9420a519a0SJuan Quintela };
9520a519a0SJuan Quintela 
96ee555cdfSDaniel Henrique Barboza #define MAX_VM_CMD_PACKAGED_SIZE UINT32_MAX
97c76ca188SDr. David Alan Gilbert static struct mig_cmd_args {
98c76ca188SDr. David Alan Gilbert     ssize_t     len; /* -1 = variable */
99c76ca188SDr. David Alan Gilbert     const char *name;
100c76ca188SDr. David Alan Gilbert } mig_cmd_args[] = {
101c76ca188SDr. David Alan Gilbert     [MIG_CMD_INVALID]          = { .len = -1, .name = "INVALID" },
1022e37701eSDr. David Alan Gilbert     [MIG_CMD_OPEN_RETURN_PATH] = { .len =  0, .name = "OPEN_RETURN_PATH" },
1032e37701eSDr. David Alan Gilbert     [MIG_CMD_PING]             = { .len = sizeof(uint32_t), .name = "PING" },
10458110f0aSVladimir Sementsov-Ogievskiy     [MIG_CMD_POSTCOPY_ADVISE]  = { .len = -1, .name = "POSTCOPY_ADVISE" },
105093e3c42SDr. David Alan Gilbert     [MIG_CMD_POSTCOPY_LISTEN]  = { .len =  0, .name = "POSTCOPY_LISTEN" },
106093e3c42SDr. David Alan Gilbert     [MIG_CMD_POSTCOPY_RUN]     = { .len =  0, .name = "POSTCOPY_RUN" },
107093e3c42SDr. David Alan Gilbert     [MIG_CMD_POSTCOPY_RAM_DISCARD] = {
108093e3c42SDr. David Alan Gilbert                                    .len = -1, .name = "POSTCOPY_RAM_DISCARD" },
1093f5875ecSPeter Xu     [MIG_CMD_POSTCOPY_RESUME]  = { .len =  0, .name = "POSTCOPY_RESUME" },
11011cf1d98SDr. David Alan Gilbert     [MIG_CMD_PACKAGED]         = { .len =  4, .name = "PACKAGED" },
111f25d4225SPeter Xu     [MIG_CMD_RECV_BITMAP]      = { .len = -1, .name = "RECV_BITMAP" },
112c76ca188SDr. David Alan Gilbert     [MIG_CMD_MAX]              = { .len = -1, .name = "MAX" },
113c76ca188SDr. David Alan Gilbert };
114c76ca188SDr. David Alan Gilbert 
11558110f0aSVladimir Sementsov-Ogievskiy /* Note for MIG_CMD_POSTCOPY_ADVISE:
11658110f0aSVladimir Sementsov-Ogievskiy  * The format of arguments is depending on postcopy mode:
11758110f0aSVladimir Sementsov-Ogievskiy  * - postcopy RAM only
11858110f0aSVladimir Sementsov-Ogievskiy  *   uint64_t host page size
119d8b71d96SMichael Tokarev  *   uint64_t target page size
12058110f0aSVladimir Sementsov-Ogievskiy  *
12158110f0aSVladimir Sementsov-Ogievskiy  * - postcopy RAM and postcopy dirty bitmaps
12258110f0aSVladimir Sementsov-Ogievskiy  *   format is the same as for postcopy RAM only
12358110f0aSVladimir Sementsov-Ogievskiy  *
12458110f0aSVladimir Sementsov-Ogievskiy  * - postcopy dirty bitmaps only
12558110f0aSVladimir Sementsov-Ogievskiy  *   Nothing. Command length field is 0.
12658110f0aSVladimir Sementsov-Ogievskiy  *
12758110f0aSVladimir Sementsov-Ogievskiy  * Be careful: adding a new postcopy entity with some other parameters should
12858110f0aSVladimir Sementsov-Ogievskiy  * not break format self-description ability. Good way is to introduce some
12958110f0aSVladimir Sementsov-Ogievskiy  * generic extendable format with an exception for two old entities.
13058110f0aSVladimir Sementsov-Ogievskiy  */
13158110f0aSVladimir Sementsov-Ogievskiy 
132c3049a56SJuan Quintela /***********************************************************/
133c3049a56SJuan Quintela /* savevm/loadvm support */
134c3049a56SJuan Quintela 
qemu_fopen_bdrv(BlockDriverState * bs,int is_writable)135c3049a56SJuan Quintela static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
136c3049a56SJuan Quintela {
137c3049a56SJuan Quintela     if (is_writable) {
13877ef2dc1SDaniel P. Berrangé         return qemu_file_new_output(QIO_CHANNEL(qio_channel_block_new(bs)));
13967bdabe2SDaniel P. Berrangé     } else {
14077ef2dc1SDaniel P. Berrangé         return qemu_file_new_input(QIO_CHANNEL(qio_channel_block_new(bs)));
141c3049a56SJuan Quintela     }
142c3049a56SJuan Quintela }
143c3049a56SJuan Quintela 
144c3049a56SJuan Quintela 
145c3049a56SJuan Quintela /* QEMUFile timer support.
146c3049a56SJuan Quintela  * Not in qemu-file.c to not add qemu-timer.c as dependency to qemu-file.c
147c3049a56SJuan Quintela  */
148c3049a56SJuan Quintela 
timer_put(QEMUFile * f,QEMUTimer * ts)149c3049a56SJuan Quintela void timer_put(QEMUFile *f, QEMUTimer *ts)
150c3049a56SJuan Quintela {
151c3049a56SJuan Quintela     uint64_t expire_time;
152c3049a56SJuan Quintela 
153c3049a56SJuan Quintela     expire_time = timer_expire_time_ns(ts);
154c3049a56SJuan Quintela     qemu_put_be64(f, expire_time);
155c3049a56SJuan Quintela }
156c3049a56SJuan Quintela 
timer_get(QEMUFile * f,QEMUTimer * ts)157c3049a56SJuan Quintela void timer_get(QEMUFile *f, QEMUTimer *ts)
158c3049a56SJuan Quintela {
159c3049a56SJuan Quintela     uint64_t expire_time;
160c3049a56SJuan Quintela 
161c3049a56SJuan Quintela     expire_time = qemu_get_be64(f);
162c3049a56SJuan Quintela     if (expire_time != -1) {
163c3049a56SJuan Quintela         timer_mod_ns(ts, expire_time);
164c3049a56SJuan Quintela     } else {
165c3049a56SJuan Quintela         timer_del(ts);
166c3049a56SJuan Quintela     }
167c3049a56SJuan Quintela }
168c3049a56SJuan Quintela 
169c3049a56SJuan Quintela 
170c3049a56SJuan Quintela /* VMState timer support.
171c3049a56SJuan Quintela  * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
172c3049a56SJuan Quintela  */
173c3049a56SJuan Quintela 
get_timer(QEMUFile * f,void * pv,size_t size,const VMStateField * field)17403fee66fSMarc-André Lureau static int get_timer(QEMUFile *f, void *pv, size_t size,
17503fee66fSMarc-André Lureau                      const VMStateField *field)
176c3049a56SJuan Quintela {
177c3049a56SJuan Quintela     QEMUTimer *v = pv;
178c3049a56SJuan Quintela     timer_get(f, v);
179c3049a56SJuan Quintela     return 0;
180c3049a56SJuan Quintela }
181c3049a56SJuan Quintela 
put_timer(QEMUFile * f,void * pv,size_t size,const VMStateField * field,JSONWriter * vmdesc)18203fee66fSMarc-André Lureau static int put_timer(QEMUFile *f, void *pv, size_t size,
1833ddba9a9SMarkus Armbruster                      const VMStateField *field, JSONWriter *vmdesc)
184c3049a56SJuan Quintela {
185c3049a56SJuan Quintela     QEMUTimer *v = pv;
186c3049a56SJuan Quintela     timer_put(f, v);
1872c21ee76SJianjun Duan 
1882c21ee76SJianjun Duan     return 0;
189c3049a56SJuan Quintela }
190c3049a56SJuan Quintela 
191c3049a56SJuan Quintela const VMStateInfo vmstate_info_timer = {
192c3049a56SJuan Quintela     .name = "timer",
193c3049a56SJuan Quintela     .get  = get_timer,
194c3049a56SJuan Quintela     .put  = put_timer,
195c3049a56SJuan Quintela };
196c3049a56SJuan Quintela 
197c3049a56SJuan Quintela 
198c3049a56SJuan Quintela typedef struct CompatEntry {
199c3049a56SJuan Quintela     char idstr[256];
200c3049a56SJuan Quintela     int instance_id;
201c3049a56SJuan Quintela } CompatEntry;
202c3049a56SJuan Quintela 
203c3049a56SJuan Quintela typedef struct SaveStateEntry {
204c3049a56SJuan Quintela     QTAILQ_ENTRY(SaveStateEntry) entry;
205c3049a56SJuan Quintela     char idstr[256];
20693062e23SPeter Xu     uint32_t instance_id;
207c3049a56SJuan Quintela     int alias_id;
208c3049a56SJuan Quintela     int version_id;
2090f42f657SJuan Quintela     /* version id read from the stream */
2100f42f657SJuan Quintela     int load_version_id;
211c3049a56SJuan Quintela     int section_id;
2120f42f657SJuan Quintela     /* section id read from the stream */
2130f42f657SJuan Quintela     int load_section_id;
214de22ded0SMarc-André Lureau     const SaveVMHandlers *ops;
215c3049a56SJuan Quintela     const VMStateDescription *vmsd;
216c3049a56SJuan Quintela     void *opaque;
217c3049a56SJuan Quintela     CompatEntry *compat;
218c3049a56SJuan Quintela     int is_ram;
219c3049a56SJuan Quintela } SaveStateEntry;
220c3049a56SJuan Quintela 
2210163a2e0SJuan Quintela typedef struct SaveState {
2220163a2e0SJuan Quintela     QTAILQ_HEAD(, SaveStateEntry) handlers;
223174723ffSScott Cheloha     SaveStateEntry *handler_pri_head[MIG_PRI_MAX + 1];
2240163a2e0SJuan Quintela     int global_section_id;
22561964c23SJuan Quintela     uint32_t len;
22661964c23SJuan Quintela     const char *name;
22759811a32SPeter Maydell     uint32_t target_page_bits;
2286cafc8e4SYury Kotov     uint32_t caps_count;
2296cafc8e4SYury Kotov     MigrationCapability *capabilities;
230b9d68df6SYury Kotov     QemuUUID uuid;
2310163a2e0SJuan Quintela } SaveState;
232c3049a56SJuan Quintela 
2330163a2e0SJuan Quintela static SaveState savevm_state = {
2340163a2e0SJuan Quintela     .handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers),
235174723ffSScott Cheloha     .handler_pri_head = { [MIG_PRI_DEFAULT ... MIG_PRI_MAX] = NULL },
2360163a2e0SJuan Quintela     .global_section_id = 0,
23761964c23SJuan Quintela };
23861964c23SJuan Quintela 
239caa91b3cSPeter Xu static SaveStateEntry *find_se(const char *idstr, uint32_t instance_id);
240caa91b3cSPeter Xu 
should_validate_capability(int capability)2416cafc8e4SYury Kotov static bool should_validate_capability(int capability)
2426cafc8e4SYury Kotov {
2436cafc8e4SYury Kotov     assert(capability >= 0 && capability < MIGRATION_CAPABILITY__MAX);
2446cafc8e4SYury Kotov     /* Validate only new capabilities to keep compatibility. */
2456cafc8e4SYury Kotov     switch (capability) {
2466cafc8e4SYury Kotov     case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
2474ed49febSFabiano Rosas     case MIGRATION_CAPABILITY_MAPPED_RAM:
2486cafc8e4SYury Kotov         return true;
2496cafc8e4SYury Kotov     default:
2506cafc8e4SYury Kotov         return false;
2516cafc8e4SYury Kotov     }
2526cafc8e4SYury Kotov }
2536cafc8e4SYury Kotov 
get_validatable_capabilities_count(void)2546cafc8e4SYury Kotov static uint32_t get_validatable_capabilities_count(void)
2556cafc8e4SYury Kotov {
2566cafc8e4SYury Kotov     MigrationState *s = migrate_get_current();
2576cafc8e4SYury Kotov     uint32_t result = 0;
2586cafc8e4SYury Kotov     int i;
2596cafc8e4SYury Kotov     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
2600cec2056SJuan Quintela         if (should_validate_capability(i) && s->capabilities[i]) {
2616cafc8e4SYury Kotov             result++;
2626cafc8e4SYury Kotov         }
2636cafc8e4SYury Kotov     }
2646cafc8e4SYury Kotov     return result;
2656cafc8e4SYury Kotov }
2666cafc8e4SYury Kotov 
configuration_pre_save(void * opaque)26744b1ff31SDr. David Alan Gilbert static int configuration_pre_save(void *opaque)
26861964c23SJuan Quintela {
26961964c23SJuan Quintela     SaveState *state = opaque;
27061964c23SJuan Quintela     const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
2716cafc8e4SYury Kotov     MigrationState *s = migrate_get_current();
2726cafc8e4SYury Kotov     int i, j;
27361964c23SJuan Quintela 
27461964c23SJuan Quintela     state->len = strlen(current_name);
27561964c23SJuan Quintela     state->name = current_name;
27646d702b1SJuan Quintela     state->target_page_bits = qemu_target_page_bits();
27744b1ff31SDr. David Alan Gilbert 
2786cafc8e4SYury Kotov     state->caps_count = get_validatable_capabilities_count();
2796cafc8e4SYury Kotov     state->capabilities = g_renew(MigrationCapability, state->capabilities,
2806cafc8e4SYury Kotov                                   state->caps_count);
2816cafc8e4SYury Kotov     for (i = j = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
2820cec2056SJuan Quintela         if (should_validate_capability(i) && s->capabilities[i]) {
2836cafc8e4SYury Kotov             state->capabilities[j++] = i;
2846cafc8e4SYury Kotov         }
2856cafc8e4SYury Kotov     }
286b9d68df6SYury Kotov     state->uuid = qemu_uuid;
2876cafc8e4SYury Kotov 
28844b1ff31SDr. David Alan Gilbert     return 0;
28959811a32SPeter Maydell }
29059811a32SPeter Maydell 
configuration_post_save(void * opaque)29139f633d4SJinhao Gao static int configuration_post_save(void *opaque)
29239f633d4SJinhao Gao {
29339f633d4SJinhao Gao     SaveState *state = opaque;
29439f633d4SJinhao Gao 
29539f633d4SJinhao Gao     g_free(state->capabilities);
29639f633d4SJinhao Gao     state->capabilities = NULL;
29739f633d4SJinhao Gao     state->caps_count = 0;
29839f633d4SJinhao Gao     return 0;
29939f633d4SJinhao Gao }
30039f633d4SJinhao Gao 
configuration_pre_load(void * opaque)30159811a32SPeter Maydell static int configuration_pre_load(void *opaque)
30259811a32SPeter Maydell {
30359811a32SPeter Maydell     SaveState *state = opaque;
30459811a32SPeter Maydell 
30559811a32SPeter Maydell     /* If there is no target-page-bits subsection it means the source
30659811a32SPeter Maydell      * predates the variable-target-page-bits support and is using the
30759811a32SPeter Maydell      * minimum possible value for this CPU.
30859811a32SPeter Maydell      */
30946d702b1SJuan Quintela     state->target_page_bits = qemu_target_page_bits_min();
31059811a32SPeter Maydell     return 0;
31161964c23SJuan Quintela }
31261964c23SJuan Quintela 
configuration_validate_capabilities(SaveState * state)3136cafc8e4SYury Kotov static bool configuration_validate_capabilities(SaveState *state)
3146cafc8e4SYury Kotov {
3156cafc8e4SYury Kotov     bool ret = true;
3166cafc8e4SYury Kotov     MigrationState *s = migrate_get_current();
3176cafc8e4SYury Kotov     unsigned long *source_caps_bm;
3186cafc8e4SYury Kotov     int i;
3196cafc8e4SYury Kotov 
3206cafc8e4SYury Kotov     source_caps_bm = bitmap_new(MIGRATION_CAPABILITY__MAX);
3216cafc8e4SYury Kotov     for (i = 0; i < state->caps_count; i++) {
3226cafc8e4SYury Kotov         MigrationCapability capability = state->capabilities[i];
3236cafc8e4SYury Kotov         set_bit(capability, source_caps_bm);
3246cafc8e4SYury Kotov     }
3256cafc8e4SYury Kotov 
3266cafc8e4SYury Kotov     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
3276cafc8e4SYury Kotov         bool source_state, target_state;
3286cafc8e4SYury Kotov         if (!should_validate_capability(i)) {
3296cafc8e4SYury Kotov             continue;
3306cafc8e4SYury Kotov         }
3316cafc8e4SYury Kotov         source_state = test_bit(i, source_caps_bm);
3320cec2056SJuan Quintela         target_state = s->capabilities[i];
3336cafc8e4SYury Kotov         if (source_state != target_state) {
3346cafc8e4SYury Kotov             error_report("Capability %s is %s, but received capability is %s",
3356cafc8e4SYury Kotov                          MigrationCapability_str(i),
3366cafc8e4SYury Kotov                          target_state ? "on" : "off",
3376cafc8e4SYury Kotov                          source_state ? "on" : "off");
3386cafc8e4SYury Kotov             ret = false;
3396cafc8e4SYury Kotov             /* Don't break here to report all failed capabilities */
3406cafc8e4SYury Kotov         }
3416cafc8e4SYury Kotov     }
3426cafc8e4SYury Kotov 
3436cafc8e4SYury Kotov     g_free(source_caps_bm);
3446cafc8e4SYury Kotov     return ret;
3456cafc8e4SYury Kotov }
3466cafc8e4SYury Kotov 
configuration_post_load(void * opaque,int version_id)34761964c23SJuan Quintela static int configuration_post_load(void *opaque, int version_id)
34861964c23SJuan Quintela {
34961964c23SJuan Quintela     SaveState *state = opaque;
35061964c23SJuan Quintela     const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
35139f633d4SJinhao Gao     int ret = 0;
35261964c23SJuan Quintela 
35361964c23SJuan Quintela     if (strncmp(state->name, current_name, state->len) != 0) {
35415d61692SGreg Kurz         error_report("Machine type received is '%.*s' and local is '%s'",
35515d61692SGreg Kurz                      (int) state->len, state->name, current_name);
35639f633d4SJinhao Gao         ret = -EINVAL;
35739f633d4SJinhao Gao         goto out;
35861964c23SJuan Quintela     }
35959811a32SPeter Maydell 
36046d702b1SJuan Quintela     if (state->target_page_bits != qemu_target_page_bits()) {
36159811a32SPeter Maydell         error_report("Received TARGET_PAGE_BITS is %d but local is %d",
36246d702b1SJuan Quintela                      state->target_page_bits, qemu_target_page_bits());
36339f633d4SJinhao Gao         ret = -EINVAL;
36439f633d4SJinhao Gao         goto out;
36559811a32SPeter Maydell     }
36659811a32SPeter Maydell 
3676cafc8e4SYury Kotov     if (!configuration_validate_capabilities(state)) {
36839f633d4SJinhao Gao         ret = -EINVAL;
36939f633d4SJinhao Gao         goto out;
3706cafc8e4SYury Kotov     }
3716cafc8e4SYury Kotov 
37239f633d4SJinhao Gao out:
37339f633d4SJinhao Gao     g_free((void *)state->name);
37439f633d4SJinhao Gao     state->name = NULL;
37539f633d4SJinhao Gao     state->len = 0;
37639f633d4SJinhao Gao     g_free(state->capabilities);
37739f633d4SJinhao Gao     state->capabilities = NULL;
37839f633d4SJinhao Gao     state->caps_count = 0;
37939f633d4SJinhao Gao 
38039f633d4SJinhao Gao     return ret;
38161964c23SJuan Quintela }
38261964c23SJuan Quintela 
get_capability(QEMUFile * f,void * pv,size_t size,const VMStateField * field)3836cafc8e4SYury Kotov static int get_capability(QEMUFile *f, void *pv, size_t size,
3846cafc8e4SYury Kotov                           const VMStateField *field)
3856cafc8e4SYury Kotov {
3866cafc8e4SYury Kotov     MigrationCapability *capability = pv;
3876cafc8e4SYury Kotov     char capability_str[UINT8_MAX + 1];
3886cafc8e4SYury Kotov     uint8_t len;
3896cafc8e4SYury Kotov     int i;
3906cafc8e4SYury Kotov 
3916cafc8e4SYury Kotov     len = qemu_get_byte(f);
3926cafc8e4SYury Kotov     qemu_get_buffer(f, (uint8_t *)capability_str, len);
3936cafc8e4SYury Kotov     capability_str[len] = '\0';
3946cafc8e4SYury Kotov     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
3956cafc8e4SYury Kotov         if (!strcmp(MigrationCapability_str(i), capability_str)) {
3966cafc8e4SYury Kotov             *capability = i;
3976cafc8e4SYury Kotov             return 0;
3986cafc8e4SYury Kotov         }
3996cafc8e4SYury Kotov     }
4006cafc8e4SYury Kotov     error_report("Received unknown capability %s", capability_str);
4016cafc8e4SYury Kotov     return -EINVAL;
4026cafc8e4SYury Kotov }
4036cafc8e4SYury Kotov 
put_capability(QEMUFile * f,void * pv,size_t size,const VMStateField * field,JSONWriter * vmdesc)4046cafc8e4SYury Kotov static int put_capability(QEMUFile *f, void *pv, size_t size,
4053ddba9a9SMarkus Armbruster                           const VMStateField *field, JSONWriter *vmdesc)
4066cafc8e4SYury Kotov {
4076cafc8e4SYury Kotov     MigrationCapability *capability = pv;
4086cafc8e4SYury Kotov     const char *capability_str = MigrationCapability_str(*capability);
4096cafc8e4SYury Kotov     size_t len = strlen(capability_str);
4106cafc8e4SYury Kotov     assert(len <= UINT8_MAX);
4116cafc8e4SYury Kotov 
4126cafc8e4SYury Kotov     qemu_put_byte(f, len);
4136cafc8e4SYury Kotov     qemu_put_buffer(f, (uint8_t *)capability_str, len);
4146cafc8e4SYury Kotov     return 0;
4156cafc8e4SYury Kotov }
4166cafc8e4SYury Kotov 
4176cafc8e4SYury Kotov static const VMStateInfo vmstate_info_capability = {
4186cafc8e4SYury Kotov     .name = "capability",
4196cafc8e4SYury Kotov     .get  = get_capability,
4206cafc8e4SYury Kotov     .put  = put_capability,
4216cafc8e4SYury Kotov };
4226cafc8e4SYury Kotov 
42359811a32SPeter Maydell /* The target-page-bits subsection is present only if the
42459811a32SPeter Maydell  * target page size is not the same as the default (ie the
42559811a32SPeter Maydell  * minimum page size for a variable-page-size guest CPU).
42659811a32SPeter Maydell  * If it is present then it contains the actual target page
42759811a32SPeter Maydell  * bits for the machine, and migration will fail if the
42859811a32SPeter Maydell  * two ends don't agree about it.
42959811a32SPeter Maydell  */
vmstate_target_page_bits_needed(void * opaque)43059811a32SPeter Maydell static bool vmstate_target_page_bits_needed(void *opaque)
43159811a32SPeter Maydell {
43246d702b1SJuan Quintela     return qemu_target_page_bits()
43346d702b1SJuan Quintela         > qemu_target_page_bits_min();
43459811a32SPeter Maydell }
43559811a32SPeter Maydell 
43659811a32SPeter Maydell static const VMStateDescription vmstate_target_page_bits = {
43759811a32SPeter Maydell     .name = "configuration/target-page-bits",
43859811a32SPeter Maydell     .version_id = 1,
43959811a32SPeter Maydell     .minimum_version_id = 1,
44059811a32SPeter Maydell     .needed = vmstate_target_page_bits_needed,
441a77ffe95SRichard Henderson     .fields = (const VMStateField[]) {
44259811a32SPeter Maydell         VMSTATE_UINT32(target_page_bits, SaveState),
44359811a32SPeter Maydell         VMSTATE_END_OF_LIST()
44459811a32SPeter Maydell     }
44559811a32SPeter Maydell };
44659811a32SPeter Maydell 
vmstate_capabilites_needed(void * opaque)4476cafc8e4SYury Kotov static bool vmstate_capabilites_needed(void *opaque)
4486cafc8e4SYury Kotov {
4496cafc8e4SYury Kotov     return get_validatable_capabilities_count() > 0;
4506cafc8e4SYury Kotov }
4516cafc8e4SYury Kotov 
4526cafc8e4SYury Kotov static const VMStateDescription vmstate_capabilites = {
4536cafc8e4SYury Kotov     .name = "configuration/capabilities",
4546cafc8e4SYury Kotov     .version_id = 1,
4556cafc8e4SYury Kotov     .minimum_version_id = 1,
4566cafc8e4SYury Kotov     .needed = vmstate_capabilites_needed,
457a77ffe95SRichard Henderson     .fields = (const VMStateField[]) {
4586cafc8e4SYury Kotov         VMSTATE_UINT32_V(caps_count, SaveState, 1),
4596cafc8e4SYury Kotov         VMSTATE_VARRAY_UINT32_ALLOC(capabilities, SaveState, caps_count, 1,
4606cafc8e4SYury Kotov                                     vmstate_info_capability,
4616cafc8e4SYury Kotov                                     MigrationCapability),
4626cafc8e4SYury Kotov         VMSTATE_END_OF_LIST()
4636cafc8e4SYury Kotov     }
4646cafc8e4SYury Kotov };
4656cafc8e4SYury Kotov 
vmstate_uuid_needed(void * opaque)466b9d68df6SYury Kotov static bool vmstate_uuid_needed(void *opaque)
467b9d68df6SYury Kotov {
468b9d68df6SYury Kotov     return qemu_uuid_set && migrate_validate_uuid();
469b9d68df6SYury Kotov }
470b9d68df6SYury Kotov 
vmstate_uuid_post_load(void * opaque,int version_id)471b9d68df6SYury Kotov static int vmstate_uuid_post_load(void *opaque, int version_id)
472b9d68df6SYury Kotov {
473b9d68df6SYury Kotov     SaveState *state = opaque;
474721da039SCédric Le Goater     char uuid_src[UUID_STR_LEN];
475721da039SCédric Le Goater     char uuid_dst[UUID_STR_LEN];
476b9d68df6SYury Kotov 
477b9d68df6SYury Kotov     if (!qemu_uuid_set) {
478b9d68df6SYury Kotov         /*
479b9d68df6SYury Kotov          * It's warning because user might not know UUID in some cases,
480b9d68df6SYury Kotov          * e.g. load an old snapshot
481b9d68df6SYury Kotov          */
482b9d68df6SYury Kotov         qemu_uuid_unparse(&state->uuid, uuid_src);
483b9d68df6SYury Kotov         warn_report("UUID is received %s, but local uuid isn't set",
484b9d68df6SYury Kotov                      uuid_src);
485b9d68df6SYury Kotov         return 0;
486b9d68df6SYury Kotov     }
487b9d68df6SYury Kotov     if (!qemu_uuid_is_equal(&state->uuid, &qemu_uuid)) {
488b9d68df6SYury Kotov         qemu_uuid_unparse(&state->uuid, uuid_src);
489b9d68df6SYury Kotov         qemu_uuid_unparse(&qemu_uuid, uuid_dst);
490b9d68df6SYury Kotov         error_report("UUID received is %s and local is %s", uuid_src, uuid_dst);
491b9d68df6SYury Kotov         return -EINVAL;
492b9d68df6SYury Kotov     }
493b9d68df6SYury Kotov     return 0;
494b9d68df6SYury Kotov }
495b9d68df6SYury Kotov 
496b9d68df6SYury Kotov static const VMStateDescription vmstate_uuid = {
497b9d68df6SYury Kotov     .name = "configuration/uuid",
498b9d68df6SYury Kotov     .version_id = 1,
499b9d68df6SYury Kotov     .minimum_version_id = 1,
500b9d68df6SYury Kotov     .needed = vmstate_uuid_needed,
501b9d68df6SYury Kotov     .post_load = vmstate_uuid_post_load,
502a77ffe95SRichard Henderson     .fields = (const VMStateField[]) {
503b9d68df6SYury Kotov         VMSTATE_UINT8_ARRAY_V(uuid.data, SaveState, sizeof(QemuUUID), 1),
504b9d68df6SYury Kotov         VMSTATE_END_OF_LIST()
505b9d68df6SYury Kotov     }
506b9d68df6SYury Kotov };
507b9d68df6SYury Kotov 
50861964c23SJuan Quintela static const VMStateDescription vmstate_configuration = {
50961964c23SJuan Quintela     .name = "configuration",
51061964c23SJuan Quintela     .version_id = 1,
51159811a32SPeter Maydell     .pre_load = configuration_pre_load,
51261964c23SJuan Quintela     .post_load = configuration_post_load,
51361964c23SJuan Quintela     .pre_save = configuration_pre_save,
51439f633d4SJinhao Gao     .post_save = configuration_post_save,
515a77ffe95SRichard Henderson     .fields = (const VMStateField[]) {
51661964c23SJuan Quintela         VMSTATE_UINT32(len, SaveState),
51759046ec2SHalil Pasic         VMSTATE_VBUFFER_ALLOC_UINT32(name, SaveState, 0, NULL, len),
51861964c23SJuan Quintela         VMSTATE_END_OF_LIST()
51961964c23SJuan Quintela     },
520a77ffe95SRichard Henderson     .subsections = (const VMStateDescription * const []) {
52159811a32SPeter Maydell         &vmstate_target_page_bits,
5226cafc8e4SYury Kotov         &vmstate_capabilites,
523b9d68df6SYury Kotov         &vmstate_uuid,
52459811a32SPeter Maydell         NULL
52559811a32SPeter Maydell     }
5260163a2e0SJuan Quintela };
527c3049a56SJuan Quintela 
528c3049a56SJuan Quintela static void dump_vmstate_vmsd(FILE *out_file,
529c3049a56SJuan Quintela                               const VMStateDescription *vmsd, int indent,
530c3049a56SJuan Quintela                               bool is_subsection);
531c3049a56SJuan Quintela 
dump_vmstate_vmsf(FILE * out_file,const VMStateField * field,int indent)532c3049a56SJuan Quintela static void dump_vmstate_vmsf(FILE *out_file, const VMStateField *field,
533c3049a56SJuan Quintela                               int indent)
534c3049a56SJuan Quintela {
535c3049a56SJuan Quintela     fprintf(out_file, "%*s{\n", indent, "");
536c3049a56SJuan Quintela     indent += 2;
537c3049a56SJuan Quintela     fprintf(out_file, "%*s\"field\": \"%s\",\n", indent, "", field->name);
538c3049a56SJuan Quintela     fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
539c3049a56SJuan Quintela             field->version_id);
540c3049a56SJuan Quintela     fprintf(out_file, "%*s\"field_exists\": %s,\n", indent, "",
541c3049a56SJuan Quintela             field->field_exists ? "true" : "false");
54212c81e5aSPeter Xu     if (field->flags & VMS_ARRAY) {
54312c81e5aSPeter Xu         fprintf(out_file, "%*s\"num\": %d,\n", indent, "", field->num);
54412c81e5aSPeter Xu     }
545c3049a56SJuan Quintela     fprintf(out_file, "%*s\"size\": %zu", indent, "", field->size);
546c3049a56SJuan Quintela     if (field->vmsd != NULL) {
547c3049a56SJuan Quintela         fprintf(out_file, ",\n");
548c3049a56SJuan Quintela         dump_vmstate_vmsd(out_file, field->vmsd, indent, false);
549c3049a56SJuan Quintela     }
550c3049a56SJuan Quintela     fprintf(out_file, "\n%*s}", indent - 2, "");
551c3049a56SJuan Quintela }
552c3049a56SJuan Quintela 
dump_vmstate_vmss(FILE * out_file,const VMStateDescription * subsection,int indent)553c3049a56SJuan Quintela static void dump_vmstate_vmss(FILE *out_file,
55420270019SRichard Henderson                               const VMStateDescription *subsection,
555c3049a56SJuan Quintela                               int indent)
556c3049a56SJuan Quintela {
55720270019SRichard Henderson     if (subsection != NULL) {
55820270019SRichard Henderson         dump_vmstate_vmsd(out_file, subsection, indent, true);
559c3049a56SJuan Quintela     }
560c3049a56SJuan Quintela }
561c3049a56SJuan Quintela 
dump_vmstate_vmsd(FILE * out_file,const VMStateDescription * vmsd,int indent,bool is_subsection)562c3049a56SJuan Quintela static void dump_vmstate_vmsd(FILE *out_file,
563c3049a56SJuan Quintela                               const VMStateDescription *vmsd, int indent,
564c3049a56SJuan Quintela                               bool is_subsection)
565c3049a56SJuan Quintela {
566c3049a56SJuan Quintela     if (is_subsection) {
567c3049a56SJuan Quintela         fprintf(out_file, "%*s{\n", indent, "");
568c3049a56SJuan Quintela     } else {
569c3049a56SJuan Quintela         fprintf(out_file, "%*s\"%s\": {\n", indent, "", "Description");
570c3049a56SJuan Quintela     }
571c3049a56SJuan Quintela     indent += 2;
572c3049a56SJuan Quintela     fprintf(out_file, "%*s\"name\": \"%s\",\n", indent, "", vmsd->name);
573c3049a56SJuan Quintela     fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
574c3049a56SJuan Quintela             vmsd->version_id);
575c3049a56SJuan Quintela     fprintf(out_file, "%*s\"minimum_version_id\": %d", indent, "",
576c3049a56SJuan Quintela             vmsd->minimum_version_id);
577c3049a56SJuan Quintela     if (vmsd->fields != NULL) {
578c3049a56SJuan Quintela         const VMStateField *field = vmsd->fields;
579c3049a56SJuan Quintela         bool first;
580c3049a56SJuan Quintela 
581c3049a56SJuan Quintela         fprintf(out_file, ",\n%*s\"Fields\": [\n", indent, "");
582c3049a56SJuan Quintela         first = true;
583c3049a56SJuan Quintela         while (field->name != NULL) {
584c3049a56SJuan Quintela             if (field->flags & VMS_MUST_EXIST) {
585c3049a56SJuan Quintela                 /* Ignore VMSTATE_VALIDATE bits; these don't get migrated */
586c3049a56SJuan Quintela                 field++;
587c3049a56SJuan Quintela                 continue;
588c3049a56SJuan Quintela             }
589c3049a56SJuan Quintela             if (!first) {
590c3049a56SJuan Quintela                 fprintf(out_file, ",\n");
591c3049a56SJuan Quintela             }
592c3049a56SJuan Quintela             dump_vmstate_vmsf(out_file, field, indent + 2);
593c3049a56SJuan Quintela             field++;
594c3049a56SJuan Quintela             first = false;
595c3049a56SJuan Quintela         }
59689c56848SDr. David Alan Gilbert         assert(field->flags == VMS_END);
597c3049a56SJuan Quintela         fprintf(out_file, "\n%*s]", indent, "");
598c3049a56SJuan Quintela     }
599c3049a56SJuan Quintela     if (vmsd->subsections != NULL) {
60020270019SRichard Henderson         const VMStateDescription * const *subsection = vmsd->subsections;
601c3049a56SJuan Quintela         bool first;
602c3049a56SJuan Quintela 
603c3049a56SJuan Quintela         fprintf(out_file, ",\n%*s\"Subsections\": [\n", indent, "");
604c3049a56SJuan Quintela         first = true;
6055cd8cadaSJuan Quintela         while (*subsection != NULL) {
606c3049a56SJuan Quintela             if (!first) {
607c3049a56SJuan Quintela                 fprintf(out_file, ",\n");
608c3049a56SJuan Quintela             }
60920270019SRichard Henderson             dump_vmstate_vmss(out_file, *subsection, indent + 2);
610c3049a56SJuan Quintela             subsection++;
611c3049a56SJuan Quintela             first = false;
612c3049a56SJuan Quintela         }
613c3049a56SJuan Quintela         fprintf(out_file, "\n%*s]", indent, "");
614c3049a56SJuan Quintela     }
615c3049a56SJuan Quintela     fprintf(out_file, "\n%*s}", indent - 2, "");
616c3049a56SJuan Quintela }
617c3049a56SJuan Quintela 
dump_machine_type(FILE * out_file)618c3049a56SJuan Quintela static void dump_machine_type(FILE *out_file)
619c3049a56SJuan Quintela {
620c3049a56SJuan Quintela     MachineClass *mc;
621c3049a56SJuan Quintela 
622c3049a56SJuan Quintela     mc = MACHINE_GET_CLASS(current_machine);
623c3049a56SJuan Quintela 
624c3049a56SJuan Quintela     fprintf(out_file, "  \"vmschkmachine\": {\n");
625c3049a56SJuan Quintela     fprintf(out_file, "    \"Name\": \"%s\"\n", mc->name);
626c3049a56SJuan Quintela     fprintf(out_file, "  },\n");
627c3049a56SJuan Quintela }
628c3049a56SJuan Quintela 
dump_vmstate_json_to_file(FILE * out_file)629c3049a56SJuan Quintela void dump_vmstate_json_to_file(FILE *out_file)
630c3049a56SJuan Quintela {
631c3049a56SJuan Quintela     GSList *list, *elt;
632c3049a56SJuan Quintela     bool first;
633c3049a56SJuan Quintela 
634c3049a56SJuan Quintela     fprintf(out_file, "{\n");
635c3049a56SJuan Quintela     dump_machine_type(out_file);
636c3049a56SJuan Quintela 
637c3049a56SJuan Quintela     first = true;
638c3049a56SJuan Quintela     list = object_class_get_list(TYPE_DEVICE, true);
639c3049a56SJuan Quintela     for (elt = list; elt; elt = elt->next) {
640c3049a56SJuan Quintela         DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
641c3049a56SJuan Quintela                                              TYPE_DEVICE);
642c3049a56SJuan Quintela         const char *name;
643c3049a56SJuan Quintela         int indent = 2;
644c3049a56SJuan Quintela 
645c3049a56SJuan Quintela         if (!dc->vmsd) {
646c3049a56SJuan Quintela             continue;
647c3049a56SJuan Quintela         }
648c3049a56SJuan Quintela 
649c3049a56SJuan Quintela         if (!first) {
650c3049a56SJuan Quintela             fprintf(out_file, ",\n");
651c3049a56SJuan Quintela         }
652c3049a56SJuan Quintela         name = object_class_get_name(OBJECT_CLASS(dc));
653c3049a56SJuan Quintela         fprintf(out_file, "%*s\"%s\": {\n", indent, "", name);
654c3049a56SJuan Quintela         indent += 2;
655c3049a56SJuan Quintela         fprintf(out_file, "%*s\"Name\": \"%s\",\n", indent, "", name);
656c3049a56SJuan Quintela         fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
657c3049a56SJuan Quintela                 dc->vmsd->version_id);
658c3049a56SJuan Quintela         fprintf(out_file, "%*s\"minimum_version_id\": %d,\n", indent, "",
659c3049a56SJuan Quintela                 dc->vmsd->minimum_version_id);
660c3049a56SJuan Quintela 
661c3049a56SJuan Quintela         dump_vmstate_vmsd(out_file, dc->vmsd, indent, false);
662c3049a56SJuan Quintela 
663c3049a56SJuan Quintela         fprintf(out_file, "\n%*s}", indent - 2, "");
664c3049a56SJuan Quintela         first = false;
665c3049a56SJuan Quintela     }
666c3049a56SJuan Quintela     fprintf(out_file, "\n}\n");
667c3049a56SJuan Quintela     fclose(out_file);
66826daeba4SPan Nengyuan     g_slist_free(list);
669c3049a56SJuan Quintela }
670c3049a56SJuan Quintela 
calculate_new_instance_id(const char * idstr)67193062e23SPeter Xu static uint32_t calculate_new_instance_id(const char *idstr)
672c3049a56SJuan Quintela {
673c3049a56SJuan Quintela     SaveStateEntry *se;
67493062e23SPeter Xu     uint32_t instance_id = 0;
675c3049a56SJuan Quintela 
6760163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
677c3049a56SJuan Quintela         if (strcmp(idstr, se->idstr) == 0
678c3049a56SJuan Quintela             && instance_id <= se->instance_id) {
679c3049a56SJuan Quintela             instance_id = se->instance_id + 1;
680c3049a56SJuan Quintela         }
681c3049a56SJuan Quintela     }
68293062e23SPeter Xu     /* Make sure we never loop over without being noticed */
68393062e23SPeter Xu     assert(instance_id != VMSTATE_INSTANCE_ID_ANY);
684c3049a56SJuan Quintela     return instance_id;
685c3049a56SJuan Quintela }
686c3049a56SJuan Quintela 
calculate_compat_instance_id(const char * idstr)687c3049a56SJuan Quintela static int calculate_compat_instance_id(const char *idstr)
688c3049a56SJuan Quintela {
689c3049a56SJuan Quintela     SaveStateEntry *se;
690c3049a56SJuan Quintela     int instance_id = 0;
691c3049a56SJuan Quintela 
6920163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
693c3049a56SJuan Quintela         if (!se->compat) {
694c3049a56SJuan Quintela             continue;
695c3049a56SJuan Quintela         }
696c3049a56SJuan Quintela 
697c3049a56SJuan Quintela         if (strcmp(idstr, se->compat->idstr) == 0
698c3049a56SJuan Quintela             && instance_id <= se->compat->instance_id) {
699c3049a56SJuan Quintela             instance_id = se->compat->instance_id + 1;
700c3049a56SJuan Quintela         }
701c3049a56SJuan Quintela     }
702c3049a56SJuan Quintela     return instance_id;
703c3049a56SJuan Quintela }
704c3049a56SJuan Quintela 
save_state_priority(SaveStateEntry * se)705f37bc036SPeter Xu static inline MigrationPriority save_state_priority(SaveStateEntry *se)
706f37bc036SPeter Xu {
707f37bc036SPeter Xu     if (se->vmsd) {
708f37bc036SPeter Xu         return se->vmsd->priority;
709f37bc036SPeter Xu     }
710f37bc036SPeter Xu     return MIG_PRI_DEFAULT;
711f37bc036SPeter Xu }
712f37bc036SPeter Xu 
savevm_state_handler_insert(SaveStateEntry * nse)713f37bc036SPeter Xu static void savevm_state_handler_insert(SaveStateEntry *nse)
714f37bc036SPeter Xu {
715f37bc036SPeter Xu     MigrationPriority priority = save_state_priority(nse);
716f37bc036SPeter Xu     SaveStateEntry *se;
717174723ffSScott Cheloha     int i;
718f37bc036SPeter Xu 
719f37bc036SPeter Xu     assert(priority <= MIG_PRI_MAX);
720f37bc036SPeter Xu 
721caa91b3cSPeter Xu     /*
722caa91b3cSPeter Xu      * This should never happen otherwise migration will probably fail
723caa91b3cSPeter Xu      * silently somewhere because we can be wrongly applying one
724caa91b3cSPeter Xu      * object properties upon another one.  Bail out ASAP.
725caa91b3cSPeter Xu      */
726caa91b3cSPeter Xu     if (find_se(nse->idstr, nse->instance_id)) {
727caa91b3cSPeter Xu         error_report("%s: Detected duplicate SaveStateEntry: "
728caa91b3cSPeter Xu                      "id=%s, instance_id=0x%"PRIx32, __func__,
729caa91b3cSPeter Xu                      nse->idstr, nse->instance_id);
730caa91b3cSPeter Xu         exit(EXIT_FAILURE);
731caa91b3cSPeter Xu     }
732caa91b3cSPeter Xu 
733174723ffSScott Cheloha     for (i = priority - 1; i >= 0; i--) {
734174723ffSScott Cheloha         se = savevm_state.handler_pri_head[i];
735174723ffSScott Cheloha         if (se != NULL) {
736174723ffSScott Cheloha             assert(save_state_priority(se) < priority);
737f37bc036SPeter Xu             break;
738f37bc036SPeter Xu         }
739f37bc036SPeter Xu     }
740f37bc036SPeter Xu 
741174723ffSScott Cheloha     if (i >= 0) {
742f37bc036SPeter Xu         QTAILQ_INSERT_BEFORE(se, nse, entry);
743f37bc036SPeter Xu     } else {
744f37bc036SPeter Xu         QTAILQ_INSERT_TAIL(&savevm_state.handlers, nse, entry);
745f37bc036SPeter Xu     }
746174723ffSScott Cheloha 
747174723ffSScott Cheloha     if (savevm_state.handler_pri_head[priority] == NULL) {
748174723ffSScott Cheloha         savevm_state.handler_pri_head[priority] = nse;
749174723ffSScott Cheloha     }
750f37bc036SPeter Xu }
751f37bc036SPeter Xu 
savevm_state_handler_remove(SaveStateEntry * se)752bd5de61eSScott Cheloha static void savevm_state_handler_remove(SaveStateEntry *se)
753bd5de61eSScott Cheloha {
754174723ffSScott Cheloha     SaveStateEntry *next;
755174723ffSScott Cheloha     MigrationPriority priority = save_state_priority(se);
756174723ffSScott Cheloha 
757174723ffSScott Cheloha     if (se == savevm_state.handler_pri_head[priority]) {
758174723ffSScott Cheloha         next = QTAILQ_NEXT(se, entry);
759174723ffSScott Cheloha         if (next != NULL && save_state_priority(next) == priority) {
760174723ffSScott Cheloha             savevm_state.handler_pri_head[priority] = next;
761174723ffSScott Cheloha         } else {
762174723ffSScott Cheloha             savevm_state.handler_pri_head[priority] = NULL;
763174723ffSScott Cheloha         }
764174723ffSScott Cheloha     }
765bd5de61eSScott Cheloha     QTAILQ_REMOVE(&savevm_state.handlers, se, entry);
766bd5de61eSScott Cheloha }
767bd5de61eSScott Cheloha 
768c3049a56SJuan Quintela /* TODO: Individual devices generally have very little idea about the rest
769c3049a56SJuan Quintela    of the system, so instance_id should be removed/replaced.
770c3049a56SJuan Quintela    Meanwhile pass -1 as instance_id if you do not already have a clearly
771c3049a56SJuan Quintela    distinguishing id for all instances of your device class. */
register_savevm_live(const char * idstr,uint32_t instance_id,int version_id,const SaveVMHandlers * ops,void * opaque)772ce62df53SDr. David Alan Gilbert int register_savevm_live(const char *idstr,
77393062e23SPeter Xu                          uint32_t instance_id,
774c3049a56SJuan Quintela                          int version_id,
775de22ded0SMarc-André Lureau                          const SaveVMHandlers *ops,
776c3049a56SJuan Quintela                          void *opaque)
777c3049a56SJuan Quintela {
778c3049a56SJuan Quintela     SaveStateEntry *se;
779c3049a56SJuan Quintela 
78097f3ad35SMarkus Armbruster     se = g_new0(SaveStateEntry, 1);
781c3049a56SJuan Quintela     se->version_id = version_id;
7820163a2e0SJuan Quintela     se->section_id = savevm_state.global_section_id++;
783c3049a56SJuan Quintela     se->ops = ops;
784c3049a56SJuan Quintela     se->opaque = opaque;
785c3049a56SJuan Quintela     se->vmsd = NULL;
786c3049a56SJuan Quintela     /* if this is a live_savem then set is_ram */
7879907e842SJuan Quintela     if (ops->save_setup != NULL) {
788c3049a56SJuan Quintela         se->is_ram = 1;
789c3049a56SJuan Quintela     }
790c3049a56SJuan Quintela 
791c3049a56SJuan Quintela     pstrcat(se->idstr, sizeof(se->idstr), idstr);
792c3049a56SJuan Quintela 
7931df2c9a2SPeter Xu     if (instance_id == VMSTATE_INSTANCE_ID_ANY) {
794c3049a56SJuan Quintela         se->instance_id = calculate_new_instance_id(se->idstr);
795c3049a56SJuan Quintela     } else {
796c3049a56SJuan Quintela         se->instance_id = instance_id;
797c3049a56SJuan Quintela     }
798c3049a56SJuan Quintela     assert(!se->compat || se->instance_id == 0);
799f37bc036SPeter Xu     savevm_state_handler_insert(se);
800c3049a56SJuan Quintela     return 0;
801c3049a56SJuan Quintela }
802c3049a56SJuan Quintela 
unregister_savevm(VMStateIf * obj,const char * idstr,void * opaque)8033cad405bSMarc-André Lureau void unregister_savevm(VMStateIf *obj, const char *idstr, void *opaque)
804c3049a56SJuan Quintela {
805c3049a56SJuan Quintela     SaveStateEntry *se, *new_se;
806c3049a56SJuan Quintela     char id[256] = "";
807c3049a56SJuan Quintela 
8083cad405bSMarc-André Lureau     if (obj) {
8093cad405bSMarc-André Lureau         char *oid = vmstate_if_get_id(obj);
8103cad405bSMarc-André Lureau         if (oid) {
8113cad405bSMarc-André Lureau             pstrcpy(id, sizeof(id), oid);
812c3049a56SJuan Quintela             pstrcat(id, sizeof(id), "/");
8133cad405bSMarc-André Lureau             g_free(oid);
814c3049a56SJuan Quintela         }
815c3049a56SJuan Quintela     }
816c3049a56SJuan Quintela     pstrcat(id, sizeof(id), idstr);
817c3049a56SJuan Quintela 
8180163a2e0SJuan Quintela     QTAILQ_FOREACH_SAFE(se, &savevm_state.handlers, entry, new_se) {
819c3049a56SJuan Quintela         if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
820bd5de61eSScott Cheloha             savevm_state_handler_remove(se);
821c3049a56SJuan Quintela             g_free(se->compat);
822c3049a56SJuan Quintela             g_free(se);
823c3049a56SJuan Quintela         }
824c3049a56SJuan Quintela     }
825c3049a56SJuan Quintela }
826c3049a56SJuan Quintela 
827bb25a728SDr. David Alan Gilbert /*
828bb25a728SDr. David Alan Gilbert  * Perform some basic checks on vmsd's at registration
829bb25a728SDr. David Alan Gilbert  * time.
830bb25a728SDr. David Alan Gilbert  */
vmstate_check(const VMStateDescription * vmsd)831bb25a728SDr. David Alan Gilbert static void vmstate_check(const VMStateDescription *vmsd)
832bb25a728SDr. David Alan Gilbert {
833bb25a728SDr. David Alan Gilbert     const VMStateField *field = vmsd->fields;
83420270019SRichard Henderson     const VMStateDescription * const *subsection = vmsd->subsections;
835bb25a728SDr. David Alan Gilbert 
836bb25a728SDr. David Alan Gilbert     if (field) {
837bb25a728SDr. David Alan Gilbert         while (field->name) {
838bb25a728SDr. David Alan Gilbert             if (field->flags & (VMS_STRUCT | VMS_VSTRUCT)) {
839bb25a728SDr. David Alan Gilbert                 /* Recurse to sub structures */
840bb25a728SDr. David Alan Gilbert                 vmstate_check(field->vmsd);
841bb25a728SDr. David Alan Gilbert             }
842bb25a728SDr. David Alan Gilbert             /* Carry on */
843bb25a728SDr. David Alan Gilbert             field++;
844bb25a728SDr. David Alan Gilbert         }
845bb25a728SDr. David Alan Gilbert         /* Check for the end of field list canary */
846bb25a728SDr. David Alan Gilbert         if (field->flags != VMS_END) {
847bb25a728SDr. David Alan Gilbert             error_report("VMSTATE not ending with VMS_END: %s", vmsd->name);
848bb25a728SDr. David Alan Gilbert             g_assert_not_reached();
849bb25a728SDr. David Alan Gilbert         }
850bb25a728SDr. David Alan Gilbert     }
851bb25a728SDr. David Alan Gilbert 
852bb25a728SDr. David Alan Gilbert     while (subsection && *subsection) {
853bb25a728SDr. David Alan Gilbert         /*
854bb25a728SDr. David Alan Gilbert          * The name of a subsection should start with the name of the
855bb25a728SDr. David Alan Gilbert          * current object.
856bb25a728SDr. David Alan Gilbert          */
857bb25a728SDr. David Alan Gilbert         assert(!strncmp(vmsd->name, (*subsection)->name, strlen(vmsd->name)));
858bb25a728SDr. David Alan Gilbert         vmstate_check(*subsection);
859bb25a728SDr. David Alan Gilbert         subsection++;
860bb25a728SDr. David Alan Gilbert     }
861bb25a728SDr. David Alan Gilbert }
862bb25a728SDr. David Alan Gilbert 
863485fb955SJuan Quintela /*
864485fb955SJuan Quintela  * See comment in hw/intc/xics.c:icp_realize()
865485fb955SJuan Quintela  *
866485fb955SJuan Quintela  * This function can be removed when
867485fb955SJuan Quintela  * pre_2_10_vmstate_register_dummy_icp() is removed.
868485fb955SJuan Quintela  */
vmstate_replace_hack_for_ppc(VMStateIf * obj,int instance_id,const VMStateDescription * vmsd,void * opaque)869485fb955SJuan Quintela int vmstate_replace_hack_for_ppc(VMStateIf *obj, int instance_id,
870485fb955SJuan Quintela                                  const VMStateDescription *vmsd,
871485fb955SJuan Quintela                                  void *opaque)
872485fb955SJuan Quintela {
873485fb955SJuan Quintela     SaveStateEntry *se = find_se(vmsd->name, instance_id);
874485fb955SJuan Quintela 
875485fb955SJuan Quintela     if (se) {
876485fb955SJuan Quintela         savevm_state_handler_remove(se);
877c80e2251SAkihiko Odaki         g_free(se->compat);
878c80e2251SAkihiko Odaki         g_free(se);
879485fb955SJuan Quintela     }
880485fb955SJuan Quintela     return vmstate_register(obj, instance_id, vmsd, opaque);
881485fb955SJuan Quintela }
882485fb955SJuan Quintela 
vmstate_register_with_alias_id(VMStateIf * obj,uint32_t instance_id,const VMStateDescription * vmsd,void * opaque,int alias_id,int required_for_version,Error ** errp)88393062e23SPeter Xu int vmstate_register_with_alias_id(VMStateIf *obj, uint32_t instance_id,
884c3049a56SJuan Quintela                                    const VMStateDescription *vmsd,
885c3049a56SJuan Quintela                                    void *opaque, int alias_id,
886bc5c4f21SDr. David Alan Gilbert                                    int required_for_version,
887bc5c4f21SDr. David Alan Gilbert                                    Error **errp)
888c3049a56SJuan Quintela {
889c3049a56SJuan Quintela     SaveStateEntry *se;
890c3049a56SJuan Quintela 
891c3049a56SJuan Quintela     /* If this triggers, alias support can be dropped for the vmsd. */
892c3049a56SJuan Quintela     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
893c3049a56SJuan Quintela 
89497f3ad35SMarkus Armbruster     se = g_new0(SaveStateEntry, 1);
895c3049a56SJuan Quintela     se->version_id = vmsd->version_id;
8960163a2e0SJuan Quintela     se->section_id = savevm_state.global_section_id++;
897c3049a56SJuan Quintela     se->opaque = opaque;
898c3049a56SJuan Quintela     se->vmsd = vmsd;
899c3049a56SJuan Quintela     se->alias_id = alias_id;
900c3049a56SJuan Quintela 
9013cad405bSMarc-André Lureau     if (obj) {
9023cad405bSMarc-André Lureau         char *id = vmstate_if_get_id(obj);
903c3049a56SJuan Quintela         if (id) {
904581f08baSDr. David Alan Gilbert             if (snprintf(se->idstr, sizeof(se->idstr), "%s/", id) >=
905581f08baSDr. David Alan Gilbert                 sizeof(se->idstr)) {
906581f08baSDr. David Alan Gilbert                 error_setg(errp, "Path too long for VMState (%s)", id);
907c3049a56SJuan Quintela                 g_free(id);
908581f08baSDr. David Alan Gilbert                 g_free(se);
909581f08baSDr. David Alan Gilbert 
910581f08baSDr. David Alan Gilbert                 return -1;
911581f08baSDr. David Alan Gilbert             }
912128e4e10SMarc-André Lureau             g_free(id);
913c3049a56SJuan Quintela 
91497f3ad35SMarkus Armbruster             se->compat = g_new0(CompatEntry, 1);
915c3049a56SJuan Quintela             pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
9161df2c9a2SPeter Xu             se->compat->instance_id = instance_id == VMSTATE_INSTANCE_ID_ANY ?
917c3049a56SJuan Quintela                          calculate_compat_instance_id(vmsd->name) : instance_id;
9181df2c9a2SPeter Xu             instance_id = VMSTATE_INSTANCE_ID_ANY;
919c3049a56SJuan Quintela         }
920c3049a56SJuan Quintela     }
921c3049a56SJuan Quintela     pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
922c3049a56SJuan Quintela 
9231df2c9a2SPeter Xu     if (instance_id == VMSTATE_INSTANCE_ID_ANY) {
924c3049a56SJuan Quintela         se->instance_id = calculate_new_instance_id(se->idstr);
925c3049a56SJuan Quintela     } else {
926c3049a56SJuan Quintela         se->instance_id = instance_id;
927c3049a56SJuan Quintela     }
928bb25a728SDr. David Alan Gilbert 
929bb25a728SDr. David Alan Gilbert     /* Perform a recursive sanity check during the test runs */
930bb25a728SDr. David Alan Gilbert     if (qtest_enabled()) {
931bb25a728SDr. David Alan Gilbert         vmstate_check(vmsd);
932bb25a728SDr. David Alan Gilbert     }
933c3049a56SJuan Quintela     assert(!se->compat || se->instance_id == 0);
934f37bc036SPeter Xu     savevm_state_handler_insert(se);
935c3049a56SJuan Quintela     return 0;
936c3049a56SJuan Quintela }
937c3049a56SJuan Quintela 
vmstate_unregister(VMStateIf * obj,const VMStateDescription * vmsd,void * opaque)9383cad405bSMarc-André Lureau void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
939c3049a56SJuan Quintela                         void *opaque)
940c3049a56SJuan Quintela {
941c3049a56SJuan Quintela     SaveStateEntry *se, *new_se;
942c3049a56SJuan Quintela 
9430163a2e0SJuan Quintela     QTAILQ_FOREACH_SAFE(se, &savevm_state.handlers, entry, new_se) {
944c3049a56SJuan Quintela         if (se->vmsd == vmsd && se->opaque == opaque) {
945bd5de61eSScott Cheloha             savevm_state_handler_remove(se);
946c3049a56SJuan Quintela             g_free(se->compat);
947c3049a56SJuan Quintela             g_free(se);
948c3049a56SJuan Quintela         }
949c3049a56SJuan Quintela     }
950c3049a56SJuan Quintela }
951c3049a56SJuan Quintela 
vmstate_load(QEMUFile * f,SaveStateEntry * se)9523a011c26SJuan Quintela static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
953c3049a56SJuan Quintela {
954c3049a56SJuan Quintela     trace_vmstate_load(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
955c3049a56SJuan Quintela     if (!se->vmsd) {         /* Old style */
9563a011c26SJuan Quintela         return se->ops->load_state(f, se->opaque, se->load_version_id);
957c3049a56SJuan Quintela     }
9583a011c26SJuan Quintela     return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id);
959c3049a56SJuan Quintela }
960c3049a56SJuan Quintela 
vmstate_save_old_style(QEMUFile * f,SaveStateEntry * se,JSONWriter * vmdesc)9613ddba9a9SMarkus Armbruster static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
9623ddba9a9SMarkus Armbruster                                    JSONWriter *vmdesc)
963c3049a56SJuan Quintela {
964e9c0eed7SJuan Quintela     uint64_t old_offset = qemu_file_transferred(f);
965c3049a56SJuan Quintela     se->ops->save_state(f, se->opaque);
966e9c0eed7SJuan Quintela     uint64_t size = qemu_file_transferred(f) - old_offset;
967c3049a56SJuan Quintela 
968c3049a56SJuan Quintela     if (vmdesc) {
9693ddba9a9SMarkus Armbruster         json_writer_int64(vmdesc, "size", size);
9703ddba9a9SMarkus Armbruster         json_writer_start_array(vmdesc, "fields");
9713ddba9a9SMarkus Armbruster         json_writer_start_object(vmdesc, NULL);
9723ddba9a9SMarkus Armbruster         json_writer_str(vmdesc, "name", "data");
9733ddba9a9SMarkus Armbruster         json_writer_int64(vmdesc, "size", size);
9743ddba9a9SMarkus Armbruster         json_writer_str(vmdesc, "type", "buffer");
9753ddba9a9SMarkus Armbruster         json_writer_end_object(vmdesc);
9763ddba9a9SMarkus Armbruster         json_writer_end_array(vmdesc);
977c3049a56SJuan Quintela     }
978c3049a56SJuan Quintela }
979c3049a56SJuan Quintela 
980ce39bfc9SDr. David Alan Gilbert /*
981ce39bfc9SDr. David Alan Gilbert  * Write the header for device section (QEMU_VM_SECTION START/END/PART/FULL)
982ce39bfc9SDr. David Alan Gilbert  */
save_section_header(QEMUFile * f,SaveStateEntry * se,uint8_t section_type)983ce39bfc9SDr. David Alan Gilbert static void save_section_header(QEMUFile *f, SaveStateEntry *se,
984ce39bfc9SDr. David Alan Gilbert                                 uint8_t section_type)
985ce39bfc9SDr. David Alan Gilbert {
986ce39bfc9SDr. David Alan Gilbert     qemu_put_byte(f, section_type);
987ce39bfc9SDr. David Alan Gilbert     qemu_put_be32(f, se->section_id);
988ce39bfc9SDr. David Alan Gilbert 
989ce39bfc9SDr. David Alan Gilbert     if (section_type == QEMU_VM_SECTION_FULL ||
990ce39bfc9SDr. David Alan Gilbert         section_type == QEMU_VM_SECTION_START) {
991ce39bfc9SDr. David Alan Gilbert         /* ID string */
992ce39bfc9SDr. David Alan Gilbert         size_t len = strlen(se->idstr);
993ce39bfc9SDr. David Alan Gilbert         qemu_put_byte(f, len);
994ce39bfc9SDr. David Alan Gilbert         qemu_put_buffer(f, (uint8_t *)se->idstr, len);
995ce39bfc9SDr. David Alan Gilbert 
996ce39bfc9SDr. David Alan Gilbert         qemu_put_be32(f, se->instance_id);
997ce39bfc9SDr. David Alan Gilbert         qemu_put_be32(f, se->version_id);
998ce39bfc9SDr. David Alan Gilbert     }
999ce39bfc9SDr. David Alan Gilbert }
1000ce39bfc9SDr. David Alan Gilbert 
1001f68945d4SDr. David Alan Gilbert /*
1002f68945d4SDr. David Alan Gilbert  * Write a footer onto device sections that catches cases misformatted device
1003f68945d4SDr. David Alan Gilbert  * sections.
1004f68945d4SDr. David Alan Gilbert  */
save_section_footer(QEMUFile * f,SaveStateEntry * se)1005f68945d4SDr. David Alan Gilbert static void save_section_footer(QEMUFile *f, SaveStateEntry *se)
1006f68945d4SDr. David Alan Gilbert {
100715c38503SPeter Xu     if (migrate_get_current()->send_section_footer) {
1008f68945d4SDr. David Alan Gilbert         qemu_put_byte(f, QEMU_VM_SECTION_FOOTER);
1009f68945d4SDr. David Alan Gilbert         qemu_put_be32(f, se->section_id);
1010f68945d4SDr. David Alan Gilbert     }
1011f68945d4SDr. David Alan Gilbert }
1012f68945d4SDr. David Alan Gilbert 
vmstate_save(QEMUFile * f,SaveStateEntry * se,JSONWriter * vmdesc,Error ** errp)10136138d43aSCédric Le Goater static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc,
10146138d43aSCédric Le Goater                         Error **errp)
10155e104f24SDavid Hildenbrand {
10165e104f24SDavid Hildenbrand     int ret;
10175e104f24SDavid Hildenbrand 
10185e104f24SDavid Hildenbrand     if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
10195e104f24SDavid Hildenbrand         return 0;
10205e104f24SDavid Hildenbrand     }
10214d8bdc2aSMarc-André Lureau     if (se->vmsd && !vmstate_section_needed(se->vmsd, se->opaque)) {
10225e104f24SDavid Hildenbrand         trace_savevm_section_skip(se->idstr, se->section_id);
10235e104f24SDavid Hildenbrand         return 0;
10245e104f24SDavid Hildenbrand     }
10255e104f24SDavid Hildenbrand 
10265e104f24SDavid Hildenbrand     trace_savevm_section_start(se->idstr, se->section_id);
10275e104f24SDavid Hildenbrand     save_section_header(f, se, QEMU_VM_SECTION_FULL);
10285e104f24SDavid Hildenbrand     if (vmdesc) {
10295e104f24SDavid Hildenbrand         json_writer_start_object(vmdesc, NULL);
10305e104f24SDavid Hildenbrand         json_writer_str(vmdesc, "name", se->idstr);
10315e104f24SDavid Hildenbrand         json_writer_int64(vmdesc, "instance_id", se->instance_id);
10325e104f24SDavid Hildenbrand     }
10335e104f24SDavid Hildenbrand 
10345e104f24SDavid Hildenbrand     trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
10355e104f24SDavid Hildenbrand     if (!se->vmsd) {
10365e104f24SDavid Hildenbrand         vmstate_save_old_style(f, se, vmdesc);
10375e104f24SDavid Hildenbrand     } else {
10386138d43aSCédric Le Goater         ret = vmstate_save_state_with_err(f, se->vmsd, se->opaque, vmdesc,
10396138d43aSCédric Le Goater                                           errp);
10405e104f24SDavid Hildenbrand         if (ret) {
10415e104f24SDavid Hildenbrand             return ret;
10425e104f24SDavid Hildenbrand         }
10435e104f24SDavid Hildenbrand     }
10445e104f24SDavid Hildenbrand 
10455e104f24SDavid Hildenbrand     trace_savevm_section_end(se->idstr, se->section_id, 0);
10465e104f24SDavid Hildenbrand     save_section_footer(f, se);
10475e104f24SDavid Hildenbrand     if (vmdesc) {
10485e104f24SDavid Hildenbrand         json_writer_end_object(vmdesc);
10495e104f24SDavid Hildenbrand     }
10505e104f24SDavid Hildenbrand     return 0;
10515e104f24SDavid Hildenbrand }
1052c76ca188SDr. David Alan Gilbert /**
1053c76ca188SDr. David Alan Gilbert  * qemu_savevm_command_send: Send a 'QEMU_VM_COMMAND' type element with the
1054c76ca188SDr. David Alan Gilbert  *                           command and associated data.
1055c76ca188SDr. David Alan Gilbert  *
1056c76ca188SDr. David Alan Gilbert  * @f: File to send command on
1057c76ca188SDr. David Alan Gilbert  * @command: Command type to send
1058c76ca188SDr. David Alan Gilbert  * @len: Length of associated data
1059c76ca188SDr. David Alan Gilbert  * @data: Data associated with command.
1060c76ca188SDr. David Alan Gilbert  */
qemu_savevm_command_send(QEMUFile * f,enum qemu_vm_cmd command,uint16_t len,uint8_t * data)106120a519a0SJuan Quintela static void qemu_savevm_command_send(QEMUFile *f,
1062c76ca188SDr. David Alan Gilbert                                      enum qemu_vm_cmd command,
1063c76ca188SDr. David Alan Gilbert                                      uint16_t len,
1064c76ca188SDr. David Alan Gilbert                                      uint8_t *data)
1065c76ca188SDr. David Alan Gilbert {
1066c76ca188SDr. David Alan Gilbert     trace_savevm_command_send(command, len);
1067c76ca188SDr. David Alan Gilbert     qemu_put_byte(f, QEMU_VM_COMMAND);
1068c76ca188SDr. David Alan Gilbert     qemu_put_be16(f, (uint16_t)command);
1069c76ca188SDr. David Alan Gilbert     qemu_put_be16(f, len);
1070c76ca188SDr. David Alan Gilbert     qemu_put_buffer(f, data, len);
1071c76ca188SDr. David Alan Gilbert     qemu_fflush(f);
1072c76ca188SDr. David Alan Gilbert }
1073c76ca188SDr. David Alan Gilbert 
qemu_savevm_send_colo_enable(QEMUFile * f)1074aad555c2SZhang Chen void qemu_savevm_send_colo_enable(QEMUFile *f)
1075aad555c2SZhang Chen {
1076aad555c2SZhang Chen     trace_savevm_send_colo_enable();
1077aad555c2SZhang Chen     qemu_savevm_command_send(f, MIG_CMD_ENABLE_COLO, 0, NULL);
1078aad555c2SZhang Chen }
1079aad555c2SZhang Chen 
qemu_savevm_send_ping(QEMUFile * f,uint32_t value)10802e37701eSDr. David Alan Gilbert void qemu_savevm_send_ping(QEMUFile *f, uint32_t value)
10812e37701eSDr. David Alan Gilbert {
10822e37701eSDr. David Alan Gilbert     uint32_t buf;
10832e37701eSDr. David Alan Gilbert 
10842e37701eSDr. David Alan Gilbert     trace_savevm_send_ping(value);
10852e37701eSDr. David Alan Gilbert     buf = cpu_to_be32(value);
10862e37701eSDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_PING, sizeof(value), (uint8_t *)&buf);
10872e37701eSDr. David Alan Gilbert }
10882e37701eSDr. David Alan Gilbert 
qemu_savevm_send_open_return_path(QEMUFile * f)10892e37701eSDr. David Alan Gilbert void qemu_savevm_send_open_return_path(QEMUFile *f)
10902e37701eSDr. David Alan Gilbert {
10912e37701eSDr. David Alan Gilbert     trace_savevm_send_open_return_path();
10922e37701eSDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_OPEN_RETURN_PATH, 0, NULL);
10932e37701eSDr. David Alan Gilbert }
10942e37701eSDr. David Alan Gilbert 
109511cf1d98SDr. David Alan Gilbert /* We have a buffer of data to send; we don't want that all to be loaded
109611cf1d98SDr. David Alan Gilbert  * by the command itself, so the command contains just the length of the
109711cf1d98SDr. David Alan Gilbert  * extra buffer that we then send straight after it.
109811cf1d98SDr. David Alan Gilbert  * TODO: Must be a better way to organise that
109911cf1d98SDr. David Alan Gilbert  *
110011cf1d98SDr. David Alan Gilbert  * Returns:
110111cf1d98SDr. David Alan Gilbert  *    0 on success
110211cf1d98SDr. David Alan Gilbert  *    -ve on error
110311cf1d98SDr. David Alan Gilbert  */
qemu_savevm_send_packaged(QEMUFile * f,const uint8_t * buf,size_t len)110461b67d47SDaniel P. Berrange int qemu_savevm_send_packaged(QEMUFile *f, const uint8_t *buf, size_t len)
110511cf1d98SDr. David Alan Gilbert {
110611cf1d98SDr. David Alan Gilbert     uint32_t tmp;
1107848a0503STejus GK     MigrationState *ms = migrate_get_current();
1108848a0503STejus GK     Error *local_err = NULL;
110911cf1d98SDr. David Alan Gilbert 
111011cf1d98SDr. David Alan Gilbert     if (len > MAX_VM_CMD_PACKAGED_SIZE) {
1111848a0503STejus GK         error_setg(&local_err, "%s: Unreasonably large packaged state: %zu",
111211cf1d98SDr. David Alan Gilbert                      __func__, len);
1113848a0503STejus GK         migrate_set_error(ms, local_err);
1114848a0503STejus GK         error_report_err(local_err);
111511cf1d98SDr. David Alan Gilbert         return -1;
111611cf1d98SDr. David Alan Gilbert     }
111711cf1d98SDr. David Alan Gilbert 
111811cf1d98SDr. David Alan Gilbert     tmp = cpu_to_be32(len);
111911cf1d98SDr. David Alan Gilbert 
112011cf1d98SDr. David Alan Gilbert     trace_qemu_savevm_send_packaged();
112111cf1d98SDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_PACKAGED, 4, (uint8_t *)&tmp);
112211cf1d98SDr. David Alan Gilbert 
112361b67d47SDaniel P. Berrange     qemu_put_buffer(f, buf, len);
112411cf1d98SDr. David Alan Gilbert 
112511cf1d98SDr. David Alan Gilbert     return 0;
112611cf1d98SDr. David Alan Gilbert }
112711cf1d98SDr. David Alan Gilbert 
1128093e3c42SDr. David Alan Gilbert /* Send prior to any postcopy transfer */
qemu_savevm_send_postcopy_advise(QEMUFile * f)1129093e3c42SDr. David Alan Gilbert void qemu_savevm_send_postcopy_advise(QEMUFile *f)
1130093e3c42SDr. David Alan Gilbert {
113158110f0aSVladimir Sementsov-Ogievskiy     if (migrate_postcopy_ram()) {
1132093e3c42SDr. David Alan Gilbert         uint64_t tmp[2];
1133e8ca1db2SDr. David Alan Gilbert         tmp[0] = cpu_to_be64(ram_pagesize_summary());
113420afaed9SJuan Quintela         tmp[1] = cpu_to_be64(qemu_target_page_size());
1135093e3c42SDr. David Alan Gilbert 
1136093e3c42SDr. David Alan Gilbert         trace_qemu_savevm_send_postcopy_advise();
113758110f0aSVladimir Sementsov-Ogievskiy         qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_ADVISE,
113858110f0aSVladimir Sementsov-Ogievskiy                                  16, (uint8_t *)tmp);
113958110f0aSVladimir Sementsov-Ogievskiy     } else {
114058110f0aSVladimir Sementsov-Ogievskiy         qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_ADVISE, 0, NULL);
114158110f0aSVladimir Sementsov-Ogievskiy     }
1142093e3c42SDr. David Alan Gilbert }
1143093e3c42SDr. David Alan Gilbert 
1144093e3c42SDr. David Alan Gilbert /* Sent prior to starting the destination running in postcopy, discard pages
1145093e3c42SDr. David Alan Gilbert  * that have already been sent but redirtied on the source.
1146093e3c42SDr. David Alan Gilbert  * CMD_POSTCOPY_RAM_DISCARD consist of:
1147093e3c42SDr. David Alan Gilbert  *      byte   version (0)
1148093e3c42SDr. David Alan Gilbert  *      byte   Length of name field (not including 0)
1149093e3c42SDr. David Alan Gilbert  *  n x byte   RAM block name
1150093e3c42SDr. David Alan Gilbert  *      byte   0 terminator (just for safety)
1151093e3c42SDr. David Alan Gilbert  *  n x        Byte ranges within the named RAMBlock
1152093e3c42SDr. David Alan Gilbert  *      be64   Start of the range
1153093e3c42SDr. David Alan Gilbert  *      be64   Length
1154093e3c42SDr. David Alan Gilbert  *
1155093e3c42SDr. David Alan Gilbert  *  name:  RAMBlock name that these entries are part of
1156093e3c42SDr. David Alan Gilbert  *  len: Number of page entries
1157093e3c42SDr. David Alan Gilbert  *  start_list: 'len' addresses
1158093e3c42SDr. David Alan Gilbert  *  length_list: 'len' addresses
1159093e3c42SDr. David Alan Gilbert  *
1160093e3c42SDr. David Alan Gilbert  */
qemu_savevm_send_postcopy_ram_discard(QEMUFile * f,const char * name,uint16_t len,uint64_t * start_list,uint64_t * length_list)1161093e3c42SDr. David Alan Gilbert void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name,
1162093e3c42SDr. David Alan Gilbert                                            uint16_t len,
1163093e3c42SDr. David Alan Gilbert                                            uint64_t *start_list,
1164093e3c42SDr. David Alan Gilbert                                            uint64_t *length_list)
1165093e3c42SDr. David Alan Gilbert {
1166093e3c42SDr. David Alan Gilbert     uint8_t *buf;
1167093e3c42SDr. David Alan Gilbert     uint16_t tmplen;
1168093e3c42SDr. David Alan Gilbert     uint16_t t;
1169093e3c42SDr. David Alan Gilbert     size_t name_len = strlen(name);
1170093e3c42SDr. David Alan Gilbert 
1171093e3c42SDr. David Alan Gilbert     trace_qemu_savevm_send_postcopy_ram_discard(name, len);
1172093e3c42SDr. David Alan Gilbert     assert(name_len < 256);
1173093e3c42SDr. David Alan Gilbert     buf = g_malloc0(1 + 1 + name_len + 1 + (8 + 8) * len);
1174093e3c42SDr. David Alan Gilbert     buf[0] = postcopy_ram_discard_version;
1175093e3c42SDr. David Alan Gilbert     buf[1] = name_len;
1176093e3c42SDr. David Alan Gilbert     memcpy(buf + 2, name, name_len);
1177093e3c42SDr. David Alan Gilbert     tmplen = 2 + name_len;
1178093e3c42SDr. David Alan Gilbert     buf[tmplen++] = '\0';
1179093e3c42SDr. David Alan Gilbert 
1180093e3c42SDr. David Alan Gilbert     for (t = 0; t < len; t++) {
11814d885131SPeter Maydell         stq_be_p(buf + tmplen, start_list[t]);
1182093e3c42SDr. David Alan Gilbert         tmplen += 8;
11834d885131SPeter Maydell         stq_be_p(buf + tmplen, length_list[t]);
1184093e3c42SDr. David Alan Gilbert         tmplen += 8;
1185093e3c42SDr. David Alan Gilbert     }
1186093e3c42SDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_RAM_DISCARD, tmplen, buf);
1187093e3c42SDr. David Alan Gilbert     g_free(buf);
1188093e3c42SDr. David Alan Gilbert }
1189093e3c42SDr. David Alan Gilbert 
1190093e3c42SDr. David Alan Gilbert /* Get the destination into a state where it can receive postcopy data. */
qemu_savevm_send_postcopy_listen(QEMUFile * f)1191093e3c42SDr. David Alan Gilbert void qemu_savevm_send_postcopy_listen(QEMUFile *f)
1192093e3c42SDr. David Alan Gilbert {
1193093e3c42SDr. David Alan Gilbert     trace_savevm_send_postcopy_listen();
1194093e3c42SDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_LISTEN, 0, NULL);
1195093e3c42SDr. David Alan Gilbert }
1196093e3c42SDr. David Alan Gilbert 
1197093e3c42SDr. David Alan Gilbert /* Kick the destination into running */
qemu_savevm_send_postcopy_run(QEMUFile * f)1198093e3c42SDr. David Alan Gilbert void qemu_savevm_send_postcopy_run(QEMUFile *f)
1199093e3c42SDr. David Alan Gilbert {
1200093e3c42SDr. David Alan Gilbert     trace_savevm_send_postcopy_run();
1201093e3c42SDr. David Alan Gilbert     qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_RUN, 0, NULL);
1202093e3c42SDr. David Alan Gilbert }
1203093e3c42SDr. David Alan Gilbert 
qemu_savevm_send_postcopy_resume(QEMUFile * f)12043f5875ecSPeter Xu void qemu_savevm_send_postcopy_resume(QEMUFile *f)
12053f5875ecSPeter Xu {
12063f5875ecSPeter Xu     trace_savevm_send_postcopy_resume();
12073f5875ecSPeter Xu     qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_RESUME, 0, NULL);
12083f5875ecSPeter Xu }
12093f5875ecSPeter Xu 
qemu_savevm_send_recv_bitmap(QEMUFile * f,char * block_name)1210f25d4225SPeter Xu void qemu_savevm_send_recv_bitmap(QEMUFile *f, char *block_name)
1211f25d4225SPeter Xu {
1212f25d4225SPeter Xu     size_t len;
1213f25d4225SPeter Xu     char buf[256];
1214f25d4225SPeter Xu 
1215f25d4225SPeter Xu     trace_savevm_send_recv_bitmap(block_name);
1216f25d4225SPeter Xu 
1217f25d4225SPeter Xu     buf[0] = len = strlen(block_name);
1218f25d4225SPeter Xu     memcpy(buf + 1, block_name, len);
1219f25d4225SPeter Xu 
1220f25d4225SPeter Xu     qemu_savevm_command_send(f, MIG_CMD_RECV_BITMAP, len + 1, (uint8_t *)buf);
1221f25d4225SPeter Xu }
1222f25d4225SPeter Xu 
qemu_savevm_state_blocked(Error ** errp)1223c3049a56SJuan Quintela bool qemu_savevm_state_blocked(Error **errp)
1224c3049a56SJuan Quintela {
1225c3049a56SJuan Quintela     SaveStateEntry *se;
1226c3049a56SJuan Quintela 
12270163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1228c3049a56SJuan Quintela         if (se->vmsd && se->vmsd->unmigratable) {
1229c3049a56SJuan Quintela             error_setg(errp, "State blocked by non-migratable device '%s'",
1230c3049a56SJuan Quintela                        se->idstr);
1231c3049a56SJuan Quintela             return true;
1232c3049a56SJuan Quintela         }
1233c3049a56SJuan Quintela     }
1234c3049a56SJuan Quintela     return false;
1235c3049a56SJuan Quintela }
1236c3049a56SJuan Quintela 
qemu_savevm_non_migratable_list(strList ** reasons)12373af8554bSDr. David Alan Gilbert void qemu_savevm_non_migratable_list(strList **reasons)
12383af8554bSDr. David Alan Gilbert {
12393af8554bSDr. David Alan Gilbert     SaveStateEntry *se;
12403af8554bSDr. David Alan Gilbert 
12413af8554bSDr. David Alan Gilbert     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
12423af8554bSDr. David Alan Gilbert         if (se->vmsd && se->vmsd->unmigratable) {
12433af8554bSDr. David Alan Gilbert             QAPI_LIST_PREPEND(*reasons,
12443af8554bSDr. David Alan Gilbert                               g_strdup_printf("non-migratable device: %s",
12453af8554bSDr. David Alan Gilbert                                               se->idstr));
12463af8554bSDr. David Alan Gilbert         }
12473af8554bSDr. David Alan Gilbert     }
12483af8554bSDr. David Alan Gilbert }
12493af8554bSDr. David Alan Gilbert 
qemu_savevm_state_header(QEMUFile * f)1250f796baa1SDr. David Alan Gilbert void qemu_savevm_state_header(QEMUFile *f)
1251f796baa1SDr. David Alan Gilbert {
12522aae1eb8SNikolay Borisov     MigrationState *s = migrate_get_current();
12532aae1eb8SNikolay Borisov 
12542aae1eb8SNikolay Borisov     s->vmdesc = json_writer_new(false);
12552aae1eb8SNikolay Borisov 
1256f796baa1SDr. David Alan Gilbert     trace_savevm_state_header();
1257f796baa1SDr. David Alan Gilbert     qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1258f796baa1SDr. David Alan Gilbert     qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1259172dfd4fSDr. David Alan Gilbert 
12602aae1eb8SNikolay Borisov     if (s->send_configuration) {
1261172dfd4fSDr. David Alan Gilbert         qemu_put_byte(f, QEMU_VM_CONFIGURATION);
12622aae1eb8SNikolay Borisov 
12632aae1eb8SNikolay Borisov         /*
12642aae1eb8SNikolay Borisov          * This starts the main json object and is paired with the
12652aae1eb8SNikolay Borisov          * json_writer_end_object in
12662aae1eb8SNikolay Borisov          * qemu_savevm_state_complete_precopy_non_iterable
12672aae1eb8SNikolay Borisov          */
12682aae1eb8SNikolay Borisov         json_writer_start_object(s->vmdesc, NULL);
12692aae1eb8SNikolay Borisov 
12702aae1eb8SNikolay Borisov         json_writer_start_object(s->vmdesc, "configuration");
12712aae1eb8SNikolay Borisov         vmstate_save_state(f, &vmstate_configuration, &savevm_state, s->vmdesc);
12722aae1eb8SNikolay Borisov         json_writer_end_object(s->vmdesc);
1273172dfd4fSDr. David Alan Gilbert     }
1274f796baa1SDr. David Alan Gilbert }
1275f796baa1SDr. David Alan Gilbert 
qemu_savevm_state_guest_unplug_pending(void)1276d05de9e3SKeqian Zhu bool qemu_savevm_state_guest_unplug_pending(void)
1277c7e0acd5SJens Freimann {
1278c7e0acd5SJens Freimann     SaveStateEntry *se;
1279c7e0acd5SJens Freimann 
1280c7e0acd5SJens Freimann     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1281284f42a5SJens Freimann         if (se->vmsd && se->vmsd->dev_unplug_pending &&
1282284f42a5SJens Freimann             se->vmsd->dev_unplug_pending(se->opaque)) {
1283d05de9e3SKeqian Zhu             return true;
1284c7e0acd5SJens Freimann         }
1285c7e0acd5SJens Freimann     }
1286c7e0acd5SJens Freimann 
1287d05de9e3SKeqian Zhu     return false;
1288c7e0acd5SJens Freimann }
1289c7e0acd5SJens Freimann 
qemu_savevm_state_prepare(Error ** errp)129008fc4cb5SAvihai Horon int qemu_savevm_state_prepare(Error **errp)
129108fc4cb5SAvihai Horon {
129208fc4cb5SAvihai Horon     SaveStateEntry *se;
129308fc4cb5SAvihai Horon     int ret;
129408fc4cb5SAvihai Horon 
129508fc4cb5SAvihai Horon     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
129608fc4cb5SAvihai Horon         if (!se->ops || !se->ops->save_prepare) {
129708fc4cb5SAvihai Horon             continue;
129808fc4cb5SAvihai Horon         }
129908fc4cb5SAvihai Horon         if (se->ops->is_active) {
130008fc4cb5SAvihai Horon             if (!se->ops->is_active(se->opaque)) {
130108fc4cb5SAvihai Horon                 continue;
130208fc4cb5SAvihai Horon             }
130308fc4cb5SAvihai Horon         }
130408fc4cb5SAvihai Horon 
130508fc4cb5SAvihai Horon         ret = se->ops->save_prepare(se->opaque, errp);
130608fc4cb5SAvihai Horon         if (ret < 0) {
130708fc4cb5SAvihai Horon             return ret;
130808fc4cb5SAvihai Horon         }
130908fc4cb5SAvihai Horon     }
131008fc4cb5SAvihai Horon 
131108fc4cb5SAvihai Horon     return 0;
131208fc4cb5SAvihai Horon }
131308fc4cb5SAvihai Horon 
qemu_savevm_state_setup(QEMUFile * f,Error ** errp)1314057a2009SCédric Le Goater int qemu_savevm_state_setup(QEMUFile *f, Error **errp)
1315c3049a56SJuan Quintela {
1316057a2009SCédric Le Goater     ERRP_GUARD();
1317e3bf5e68SDavid Hildenbrand     MigrationState *ms = migrate_get_current();
1318c3049a56SJuan Quintela     SaveStateEntry *se;
1319e6e08e83SCédric Le Goater     int ret = 0;
1320c3049a56SJuan Quintela 
1321e3bf5e68SDavid Hildenbrand     json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size());
1322e3bf5e68SDavid Hildenbrand     json_writer_start_array(ms->vmdesc, "devices");
1323e3bf5e68SDavid Hildenbrand 
13249907e842SJuan Quintela     trace_savevm_state_setup();
13250163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
132662f42625SDavid Hildenbrand         if (se->vmsd && se->vmsd->early_setup) {
1327057a2009SCédric Le Goater             ret = vmstate_save(f, se, ms->vmdesc, errp);
132862f42625SDavid Hildenbrand             if (ret) {
1329057a2009SCédric Le Goater                 migrate_set_error(ms, *errp);
133062f42625SDavid Hildenbrand                 qemu_file_set_error(f, ret);
133162f42625SDavid Hildenbrand                 break;
133262f42625SDavid Hildenbrand             }
133362f42625SDavid Hildenbrand             continue;
133462f42625SDavid Hildenbrand         }
133562f42625SDavid Hildenbrand 
13369907e842SJuan Quintela         if (!se->ops || !se->ops->save_setup) {
1337c3049a56SJuan Quintela             continue;
1338c3049a56SJuan Quintela         }
1339cea3b4c0SWei Yang         if (se->ops->is_active) {
1340c3049a56SJuan Quintela             if (!se->ops->is_active(se->opaque)) {
1341c3049a56SJuan Quintela                 continue;
1342c3049a56SJuan Quintela             }
1343c3049a56SJuan Quintela         }
1344ce39bfc9SDr. David Alan Gilbert         save_section_header(f, se, QEMU_VM_SECTION_START);
1345c3049a56SJuan Quintela 
134601c3ac68SCédric Le Goater         ret = se->ops->save_setup(f, se->opaque, errp);
1347f68945d4SDr. David Alan Gilbert         save_section_footer(f, se);
1348c3049a56SJuan Quintela         if (ret < 0) {
1349c3049a56SJuan Quintela             qemu_file_set_error(f, ret);
1350c3049a56SJuan Quintela             break;
1351c3049a56SJuan Quintela         }
1352c3049a56SJuan Quintela     }
1353bd227060SWei Wang 
1354e6e08e83SCédric Le Goater     if (ret) {
1355057a2009SCédric Le Goater         return ret;
1356e6e08e83SCédric Le Goater     }
1357e6e08e83SCédric Le Goater 
1358057a2009SCédric Le Goater     /* TODO: Should we check that errp is set in case of failure ? */
1359057a2009SCédric Le Goater     return precopy_notify(PRECOPY_NOTIFY_SETUP, errp);
1360c3049a56SJuan Quintela }
1361c3049a56SJuan Quintela 
qemu_savevm_state_resume_prepare(MigrationState * s)1362d1b8eadbSPeter Xu int qemu_savevm_state_resume_prepare(MigrationState *s)
1363d1b8eadbSPeter Xu {
1364d1b8eadbSPeter Xu     SaveStateEntry *se;
1365d1b8eadbSPeter Xu     int ret;
1366d1b8eadbSPeter Xu 
1367d1b8eadbSPeter Xu     trace_savevm_state_resume_prepare();
1368d1b8eadbSPeter Xu 
1369d1b8eadbSPeter Xu     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1370d1b8eadbSPeter Xu         if (!se->ops || !se->ops->resume_prepare) {
1371d1b8eadbSPeter Xu             continue;
1372d1b8eadbSPeter Xu         }
1373cea3b4c0SWei Yang         if (se->ops->is_active) {
1374d1b8eadbSPeter Xu             if (!se->ops->is_active(se->opaque)) {
1375d1b8eadbSPeter Xu                 continue;
1376d1b8eadbSPeter Xu             }
1377d1b8eadbSPeter Xu         }
1378d1b8eadbSPeter Xu         ret = se->ops->resume_prepare(s, se->opaque);
1379d1b8eadbSPeter Xu         if (ret < 0) {
1380d1b8eadbSPeter Xu             return ret;
1381d1b8eadbSPeter Xu         }
1382d1b8eadbSPeter Xu     }
1383d1b8eadbSPeter Xu 
1384d1b8eadbSPeter Xu     return 0;
1385d1b8eadbSPeter Xu }
1386d1b8eadbSPeter Xu 
1387c3049a56SJuan Quintela /*
1388c3049a56SJuan Quintela  * this function has three return values:
1389c3049a56SJuan Quintela  *   negative: there was one error, and we have -errno.
1390c3049a56SJuan Quintela  *   0 : We haven't finished, caller have to go again
1391c3049a56SJuan Quintela  *   1 : We have finished, we can go to complete phase
1392c3049a56SJuan Quintela  */
qemu_savevm_state_iterate(QEMUFile * f,bool postcopy)139335ecd943SDr. David Alan Gilbert int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy)
1394c3049a56SJuan Quintela {
1395c3049a56SJuan Quintela     SaveStateEntry *se;
13964e1871c4SAvihai Horon     bool all_finished = true;
13974e1871c4SAvihai Horon     int ret;
1398c3049a56SJuan Quintela 
1399c3049a56SJuan Quintela     trace_savevm_state_iterate();
14000163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1401c3049a56SJuan Quintela         if (!se->ops || !se->ops->save_live_iterate) {
1402c3049a56SJuan Quintela             continue;
1403c3049a56SJuan Quintela         }
1404a94cd7b8SWei Yang         if (se->ops->is_active &&
1405a94cd7b8SWei Yang             !se->ops->is_active(se->opaque)) {
1406c3049a56SJuan Quintela             continue;
1407c3049a56SJuan Quintela         }
1408a94cd7b8SWei Yang         if (se->ops->is_active_iterate &&
1409a94cd7b8SWei Yang             !se->ops->is_active_iterate(se->opaque)) {
1410c865d848SVladimir Sementsov-Ogievskiy             continue;
1411c865d848SVladimir Sementsov-Ogievskiy         }
141235ecd943SDr. David Alan Gilbert         /*
141335ecd943SDr. David Alan Gilbert          * In the postcopy phase, any device that doesn't know how to
141435ecd943SDr. David Alan Gilbert          * do postcopy should have saved it's state in the _complete
141535ecd943SDr. David Alan Gilbert          * call that's already run, it might get confused if we call
141635ecd943SDr. David Alan Gilbert          * iterate afterwards.
141735ecd943SDr. David Alan Gilbert          */
1418c6467627SVladimir Sementsov-Ogievskiy         if (postcopy &&
1419c6467627SVladimir Sementsov-Ogievskiy             !(se->ops->has_postcopy && se->ops->has_postcopy(se->opaque))) {
142035ecd943SDr. David Alan Gilbert             continue;
142135ecd943SDr. David Alan Gilbert         }
1422e1fde0e0SJuan Quintela         if (migration_rate_exceeded(f)) {
1423c3049a56SJuan Quintela             return 0;
1424c3049a56SJuan Quintela         }
1425c3049a56SJuan Quintela         trace_savevm_section_start(se->idstr, se->section_id);
1426ce39bfc9SDr. David Alan Gilbert 
1427ce39bfc9SDr. David Alan Gilbert         save_section_header(f, se, QEMU_VM_SECTION_PART);
1428c3049a56SJuan Quintela 
1429c3049a56SJuan Quintela         ret = se->ops->save_live_iterate(f, se->opaque);
1430c3049a56SJuan Quintela         trace_savevm_section_end(se->idstr, se->section_id, ret);
1431f68945d4SDr. David Alan Gilbert         save_section_footer(f, se);
1432c3049a56SJuan Quintela 
1433c3049a56SJuan Quintela         if (ret < 0) {
143492002658SDavid Edmondson             error_report("failed to save SaveStateEntry with id(name): "
143592002658SDavid Edmondson                          "%d(%s): %d",
143692002658SDavid Edmondson                          se->section_id, se->idstr, ret);
1437c3049a56SJuan Quintela             qemu_file_set_error(f, ret);
1438c3049a56SJuan Quintela             return ret;
14394e1871c4SAvihai Horon         } else if (!ret) {
14404e1871c4SAvihai Horon             all_finished = false;
14414e1871c4SAvihai Horon         }
14424e1871c4SAvihai Horon     }
14434e1871c4SAvihai Horon     return all_finished;
1444c3049a56SJuan Quintela }
1445c3049a56SJuan Quintela 
should_send_vmdesc(void)1446c3049a56SJuan Quintela static bool should_send_vmdesc(void)
1447c3049a56SJuan Quintela {
1448c3049a56SJuan Quintela     MachineState *machine = MACHINE(qdev_get_machine());
14495727309dSJuan Quintela     bool in_postcopy = migration_in_postcopy();
14508421b205SDr. David Alan Gilbert     return !machine->suppress_vmdesc && !in_postcopy;
1451c3049a56SJuan Quintela }
1452c3049a56SJuan Quintela 
1453763c906bSDr. David Alan Gilbert /*
1454763c906bSDr. David Alan Gilbert  * Calls the save_live_complete_postcopy methods
1455763c906bSDr. David Alan Gilbert  * causing the last few pages to be sent immediately and doing any associated
1456763c906bSDr. David Alan Gilbert  * cleanup.
1457763c906bSDr. David Alan Gilbert  * Note postcopy also calls qemu_savevm_state_complete_precopy to complete
1458763c906bSDr. David Alan Gilbert  * all the other devices, but that happens at the point we switch to postcopy.
1459763c906bSDr. David Alan Gilbert  */
qemu_savevm_state_complete_postcopy(QEMUFile * f)1460763c906bSDr. David Alan Gilbert void qemu_savevm_state_complete_postcopy(QEMUFile *f)
1461763c906bSDr. David Alan Gilbert {
1462763c906bSDr. David Alan Gilbert     SaveStateEntry *se;
1463763c906bSDr. David Alan Gilbert     int ret;
1464763c906bSDr. David Alan Gilbert 
1465763c906bSDr. David Alan Gilbert     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1466763c906bSDr. David Alan Gilbert         if (!se->ops || !se->ops->save_live_complete_postcopy) {
1467763c906bSDr. David Alan Gilbert             continue;
1468763c906bSDr. David Alan Gilbert         }
1469cea3b4c0SWei Yang         if (se->ops->is_active) {
1470763c906bSDr. David Alan Gilbert             if (!se->ops->is_active(se->opaque)) {
1471763c906bSDr. David Alan Gilbert                 continue;
1472763c906bSDr. David Alan Gilbert             }
1473763c906bSDr. David Alan Gilbert         }
1474763c906bSDr. David Alan Gilbert         trace_savevm_section_start(se->idstr, se->section_id);
1475763c906bSDr. David Alan Gilbert         /* Section type */
1476763c906bSDr. David Alan Gilbert         qemu_put_byte(f, QEMU_VM_SECTION_END);
1477763c906bSDr. David Alan Gilbert         qemu_put_be32(f, se->section_id);
1478763c906bSDr. David Alan Gilbert 
1479763c906bSDr. David Alan Gilbert         ret = se->ops->save_live_complete_postcopy(f, se->opaque);
1480763c906bSDr. David Alan Gilbert         trace_savevm_section_end(se->idstr, se->section_id, ret);
1481763c906bSDr. David Alan Gilbert         save_section_footer(f, se);
1482763c906bSDr. David Alan Gilbert         if (ret < 0) {
1483763c906bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
1484763c906bSDr. David Alan Gilbert             return;
1485763c906bSDr. David Alan Gilbert         }
1486763c906bSDr. David Alan Gilbert     }
1487763c906bSDr. David Alan Gilbert 
1488763c906bSDr. David Alan Gilbert     qemu_put_byte(f, QEMU_VM_EOF);
1489763c906bSDr. David Alan Gilbert     qemu_fflush(f);
1490763c906bSDr. David Alan Gilbert }
1491763c906bSDr. David Alan Gilbert 
1492622a80c9SWei Yang static
qemu_savevm_state_complete_precopy_iterable(QEMUFile * f,bool in_postcopy)1493e326767bSWei Yang int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
1494c3049a56SJuan Quintela {
14953c80f142SPeter Xu     int64_t start_ts_each, end_ts_each;
1496c3049a56SJuan Quintela     SaveStateEntry *se;
1497c3049a56SJuan Quintela     int ret;
1498c3049a56SJuan Quintela 
14990163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1500763c906bSDr. David Alan Gilbert         if (!se->ops ||
1501c6467627SVladimir Sementsov-Ogievskiy             (in_postcopy && se->ops->has_postcopy &&
1502c6467627SVladimir Sementsov-Ogievskiy              se->ops->has_postcopy(se->opaque)) ||
1503763c906bSDr. David Alan Gilbert             !se->ops->save_live_complete_precopy) {
1504c3049a56SJuan Quintela             continue;
1505c3049a56SJuan Quintela         }
15061c0d249dSDr. David Alan Gilbert 
1507cea3b4c0SWei Yang         if (se->ops->is_active) {
1508c3049a56SJuan Quintela             if (!se->ops->is_active(se->opaque)) {
1509c3049a56SJuan Quintela                 continue;
1510c3049a56SJuan Quintela             }
1511c3049a56SJuan Quintela         }
15123c80f142SPeter Xu 
15133c80f142SPeter Xu         start_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
1514c3049a56SJuan Quintela         trace_savevm_section_start(se->idstr, se->section_id);
1515ce39bfc9SDr. David Alan Gilbert 
1516ce39bfc9SDr. David Alan Gilbert         save_section_header(f, se, QEMU_VM_SECTION_END);
1517c3049a56SJuan Quintela 
1518a3e06c3dSDr. David Alan Gilbert         ret = se->ops->save_live_complete_precopy(f, se->opaque);
1519c3049a56SJuan Quintela         trace_savevm_section_end(se->idstr, se->section_id, ret);
1520f68945d4SDr. David Alan Gilbert         save_section_footer(f, se);
1521c3049a56SJuan Quintela         if (ret < 0) {
1522c3049a56SJuan Quintela             qemu_file_set_error(f, ret);
1523a1fbe750SFam Zheng             return -1;
1524c3049a56SJuan Quintela         }
15253c80f142SPeter Xu         end_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
15263c80f142SPeter Xu         trace_vmstate_downtime_save("iterable", se->idstr, se->instance_id,
15273c80f142SPeter Xu                                     end_ts_each - start_ts_each);
1528c3049a56SJuan Quintela     }
1529c3049a56SJuan Quintela 
15303e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("src-iterable-saved");
15313e5f3bcdSPeter Xu 
1532622a80c9SWei Yang     return 0;
15331c0d249dSDr. David Alan Gilbert }
15341c0d249dSDr. David Alan Gilbert 
qemu_savevm_state_complete_precopy_non_iterable(QEMUFile * f,bool in_postcopy,bool inactivate_disks)1535622a80c9SWei Yang int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
1536622a80c9SWei Yang                                                     bool in_postcopy,
1537622a80c9SWei Yang                                                     bool inactivate_disks)
1538622a80c9SWei Yang {
1539e3bf5e68SDavid Hildenbrand     MigrationState *ms = migrate_get_current();
15403c80f142SPeter Xu     int64_t start_ts_each, end_ts_each;
1541e3bf5e68SDavid Hildenbrand     JSONWriter *vmdesc = ms->vmdesc;
1542622a80c9SWei Yang     int vmdesc_len;
1543622a80c9SWei Yang     SaveStateEntry *se;
15446138d43aSCédric Le Goater     Error *local_err = NULL;
1545622a80c9SWei Yang     int ret;
1546622a80c9SWei Yang 
15470163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
154862f42625SDavid Hildenbrand         if (se->vmsd && se->vmsd->early_setup) {
154962f42625SDavid Hildenbrand             /* Already saved during qemu_savevm_state_setup(). */
155062f42625SDavid Hildenbrand             continue;
155162f42625SDavid Hildenbrand         }
155262f42625SDavid Hildenbrand 
15533c80f142SPeter Xu         start_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
15543c80f142SPeter Xu 
15556138d43aSCédric Le Goater         ret = vmstate_save(f, se, vmdesc, &local_err);
1556687433f6SDr. David Alan Gilbert         if (ret) {
15576138d43aSCédric Le Goater             migrate_set_error(ms, local_err);
15586138d43aSCédric Le Goater             error_report_err(local_err);
1559687433f6SDr. David Alan Gilbert             qemu_file_set_error(f, ret);
1560687433f6SDr. David Alan Gilbert             return ret;
1561687433f6SDr. David Alan Gilbert         }
15623c80f142SPeter Xu 
15633c80f142SPeter Xu         end_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
15643c80f142SPeter Xu         trace_vmstate_downtime_save("non-iterable", se->idstr, se->instance_id,
15653c80f142SPeter Xu                                     end_ts_each - start_ts_each);
1566c3049a56SJuan Quintela     }
1567c3049a56SJuan Quintela 
1568a1fbe750SFam Zheng     if (inactivate_disks) {
1569a1fbe750SFam Zheng         /* Inactivate before sending QEMU_VM_EOF so that the
15703b717194SEmanuele Giuseppe Esposito          * bdrv_activate_all() on the other end won't fail. */
1571a1fbe750SFam Zheng         ret = bdrv_inactivate_all();
1572a1fbe750SFam Zheng         if (ret) {
1573848a0503STejus GK             error_setg(&local_err, "%s: bdrv_inactivate_all() failed (%d)",
1574c232bf58SDr. David Alan Gilbert                        __func__, ret);
1575848a0503STejus GK             migrate_set_error(ms, local_err);
1576848a0503STejus GK             error_report_err(local_err);
1577a1fbe750SFam Zheng             qemu_file_set_error(f, ret);
1578a1fbe750SFam Zheng             return ret;
1579a1fbe750SFam Zheng         }
1580a1fbe750SFam Zheng     }
1581763c906bSDr. David Alan Gilbert     if (!in_postcopy) {
1582763c906bSDr. David Alan Gilbert         /* Postcopy stream will still be going */
1583c3049a56SJuan Quintela         qemu_put_byte(f, QEMU_VM_EOF);
1584763c906bSDr. David Alan Gilbert     }
1585c3049a56SJuan Quintela 
15863ddba9a9SMarkus Armbruster     json_writer_end_array(vmdesc);
15873ddba9a9SMarkus Armbruster     json_writer_end_object(vmdesc);
15883ddba9a9SMarkus Armbruster     vmdesc_len = strlen(json_writer_get(vmdesc));
1589c3049a56SJuan Quintela 
1590c3049a56SJuan Quintela     if (should_send_vmdesc()) {
1591c3049a56SJuan Quintela         qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
1592c3049a56SJuan Quintela         qemu_put_be32(f, vmdesc_len);
15933ddba9a9SMarkus Armbruster         qemu_put_buffer(f, (uint8_t *)json_writer_get(vmdesc), vmdesc_len);
1594c3049a56SJuan Quintela     }
1595c3049a56SJuan Quintela 
1596e3bf5e68SDavid Hildenbrand     /* Free it now to detect any inconsistencies. */
1597e3bf5e68SDavid Hildenbrand     json_writer_free(vmdesc);
1598e3bf5e68SDavid Hildenbrand     ms->vmdesc = NULL;
1599e3bf5e68SDavid Hildenbrand 
16003e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("src-non-iterable-saved");
16013e5f3bcdSPeter Xu 
1602622a80c9SWei Yang     return 0;
1603622a80c9SWei Yang }
1604622a80c9SWei Yang 
qemu_savevm_state_complete_precopy(QEMUFile * f,bool iterable_only,bool inactivate_disks)1605622a80c9SWei Yang int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
1606622a80c9SWei Yang                                        bool inactivate_disks)
1607622a80c9SWei Yang {
1608622a80c9SWei Yang     int ret;
1609622a80c9SWei Yang     Error *local_err = NULL;
1610622a80c9SWei Yang     bool in_postcopy = migration_in_postcopy();
1611622a80c9SWei Yang 
1612622a80c9SWei Yang     if (precopy_notify(PRECOPY_NOTIFY_COMPLETE, &local_err)) {
1613622a80c9SWei Yang         error_report_err(local_err);
1614622a80c9SWei Yang     }
1615622a80c9SWei Yang 
1616622a80c9SWei Yang     trace_savevm_state_complete_precopy();
1617622a80c9SWei Yang 
1618622a80c9SWei Yang     cpu_synchronize_all_states();
1619622a80c9SWei Yang 
1620e326767bSWei Yang     if (!in_postcopy || iterable_only) {
1621e326767bSWei Yang         ret = qemu_savevm_state_complete_precopy_iterable(f, in_postcopy);
1622622a80c9SWei Yang         if (ret) {
1623622a80c9SWei Yang             return ret;
1624622a80c9SWei Yang         }
1625e326767bSWei Yang     }
1626622a80c9SWei Yang 
1627622a80c9SWei Yang     if (iterable_only) {
1628622a80c9SWei Yang         goto flush;
1629622a80c9SWei Yang     }
1630622a80c9SWei Yang 
1631622a80c9SWei Yang     ret = qemu_savevm_state_complete_precopy_non_iterable(f, in_postcopy,
1632622a80c9SWei Yang                                                           inactivate_disks);
1633622a80c9SWei Yang     if (ret) {
1634622a80c9SWei Yang         return ret;
1635622a80c9SWei Yang     }
1636622a80c9SWei Yang 
16374e455d51SWei Yang flush:
1638be07a0edSJuan Quintela     return qemu_fflush(f);
1639c3049a56SJuan Quintela }
1640c3049a56SJuan Quintela 
1641c31b098fSDr. David Alan Gilbert /* Give an estimate of the amount left to be transferred,
1642c31b098fSDr. David Alan Gilbert  * the result is split into the amount for units that can and
1643c31b098fSDr. David Alan Gilbert  * for units that can't do postcopy.
1644c31b098fSDr. David Alan Gilbert  */
qemu_savevm_state_pending_estimate(uint64_t * must_precopy,uint64_t * can_postcopy)164524beea4eSJuan Quintela void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,
164624beea4eSJuan Quintela                                         uint64_t *can_postcopy)
1647c3049a56SJuan Quintela {
1648c3049a56SJuan Quintela     SaveStateEntry *se;
1649c31b098fSDr. David Alan Gilbert 
165024beea4eSJuan Quintela     *must_precopy = 0;
165124beea4eSJuan Quintela     *can_postcopy = 0;
1652c31b098fSDr. David Alan Gilbert 
16530163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1654e2647050SJuan Quintela         if (!se->ops || !se->ops->state_pending_estimate) {
1655c3049a56SJuan Quintela             continue;
1656c3049a56SJuan Quintela         }
1657cea3b4c0SWei Yang         if (se->ops->is_active) {
1658c3049a56SJuan Quintela             if (!se->ops->is_active(se->opaque)) {
1659c3049a56SJuan Quintela                 continue;
1660c3049a56SJuan Quintela             }
1661c3049a56SJuan Quintela         }
166224beea4eSJuan Quintela         se->ops->state_pending_estimate(se->opaque, must_precopy, can_postcopy);
1663c8df4a7aSJuan Quintela     }
1664c8df4a7aSJuan Quintela }
1665c8df4a7aSJuan Quintela 
qemu_savevm_state_pending_exact(uint64_t * must_precopy,uint64_t * can_postcopy)166624beea4eSJuan Quintela void qemu_savevm_state_pending_exact(uint64_t *must_precopy,
166724beea4eSJuan Quintela                                      uint64_t *can_postcopy)
1668c8df4a7aSJuan Quintela {
1669c8df4a7aSJuan Quintela     SaveStateEntry *se;
1670c8df4a7aSJuan Quintela 
167124beea4eSJuan Quintela     *must_precopy = 0;
167224beea4eSJuan Quintela     *can_postcopy = 0;
1673c8df4a7aSJuan Quintela 
1674c8df4a7aSJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1675e2647050SJuan Quintela         if (!se->ops || !se->ops->state_pending_exact) {
1676c8df4a7aSJuan Quintela             continue;
1677c8df4a7aSJuan Quintela         }
1678c8df4a7aSJuan Quintela         if (se->ops->is_active) {
1679c8df4a7aSJuan Quintela             if (!se->ops->is_active(se->opaque)) {
1680c8df4a7aSJuan Quintela                 continue;
1681c8df4a7aSJuan Quintela             }
1682c8df4a7aSJuan Quintela         }
168324beea4eSJuan Quintela         se->ops->state_pending_exact(se->opaque, must_precopy, can_postcopy);
1684c3049a56SJuan Quintela     }
1685c3049a56SJuan Quintela }
1686c3049a56SJuan Quintela 
qemu_savevm_state_cleanup(void)1687ea7415faSLiang Li void qemu_savevm_state_cleanup(void)
1688c3049a56SJuan Quintela {
1689c3049a56SJuan Quintela     SaveStateEntry *se;
1690bd227060SWei Wang     Error *local_err = NULL;
1691bd227060SWei Wang 
1692bd227060SWei Wang     if (precopy_notify(PRECOPY_NOTIFY_CLEANUP, &local_err)) {
1693bd227060SWei Wang         error_report_err(local_err);
1694bd227060SWei Wang     }
1695c3049a56SJuan Quintela 
1696ea7415faSLiang Li     trace_savevm_state_cleanup();
16970163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
169870f794fcSJuan Quintela         if (se->ops && se->ops->save_cleanup) {
169970f794fcSJuan Quintela             se->ops->save_cleanup(se->opaque);
1700c3049a56SJuan Quintela         }
1701c3049a56SJuan Quintela     }
1702c3049a56SJuan Quintela }
1703c3049a56SJuan Quintela 
qemu_savevm_state(QEMUFile * f,Error ** errp)1704c3049a56SJuan Quintela static int qemu_savevm_state(QEMUFile *f, Error **errp)
1705c3049a56SJuan Quintela {
1706c3049a56SJuan Quintela     int ret;
17073e0c8050SPeter Xu     MigrationState *ms = migrate_get_current();
17086dcf6668SDenis V. Lunev     MigrationStatus status;
17093e0c8050SPeter Xu 
1710aeaafb1eSSteve Sistare     if (migration_is_running()) {
171100580786SPhilippe Mathieu-Daudé         error_setg(errp, "There's a migration process in progress");
17123d63da16SJia Lina         return -EINVAL;
17133d63da16SJia Lina     }
1714c3049a56SJuan Quintela 
171508fc4cb5SAvihai Horon     ret = migrate_init(ms, errp);
171608fc4cb5SAvihai Horon     if (ret) {
171708fc4cb5SAvihai Horon         return ret;
171808fc4cb5SAvihai Horon     }
17193d63da16SJia Lina     ms->to_dst_file = f;
17203d63da16SJia Lina 
1721f796baa1SDr. David Alan Gilbert     qemu_savevm_state_header(f);
1722057a2009SCédric Le Goater     ret = qemu_savevm_state_setup(f, errp);
1723057a2009SCédric Le Goater     if (ret) {
1724057a2009SCédric Le Goater         goto cleanup;
1725057a2009SCédric Le Goater     }
1726c3049a56SJuan Quintela 
1727c3049a56SJuan Quintela     while (qemu_file_get_error(f) == 0) {
172835ecd943SDr. David Alan Gilbert         if (qemu_savevm_state_iterate(f, false) > 0) {
1729c3049a56SJuan Quintela             break;
1730c3049a56SJuan Quintela         }
1731c3049a56SJuan Quintela     }
1732c3049a56SJuan Quintela 
1733c3049a56SJuan Quintela     ret = qemu_file_get_error(f);
1734c3049a56SJuan Quintela     if (ret == 0) {
1735a1fbe750SFam Zheng         qemu_savevm_state_complete_precopy(f, false, false);
1736c3049a56SJuan Quintela         ret = qemu_file_get_error(f);
1737c3049a56SJuan Quintela     }
173815b3b8eaSDenis V. Lunev     if (ret != 0) {
1739c3049a56SJuan Quintela         error_setg_errno(errp, -ret, "Error while writing VM state");
1740c3049a56SJuan Quintela     }
1741057a2009SCédric Le Goater cleanup:
1742057a2009SCédric Le Goater     qemu_savevm_state_cleanup();
17436dcf6668SDenis V. Lunev 
17446dcf6668SDenis V. Lunev     if (ret != 0) {
17456dcf6668SDenis V. Lunev         status = MIGRATION_STATUS_FAILED;
17466dcf6668SDenis V. Lunev     } else {
17476dcf6668SDenis V. Lunev         status = MIGRATION_STATUS_COMPLETED;
17486dcf6668SDenis V. Lunev     }
17496dcf6668SDenis V. Lunev     migrate_set_state(&ms->state, MIGRATION_STATUS_SETUP, status);
1750f9c8caa0SVladimir Sementsov-Ogievskiy 
1751f9c8caa0SVladimir Sementsov-Ogievskiy     /* f is outer parameter, it should not stay in global migration state after
1752f9c8caa0SVladimir Sementsov-Ogievskiy      * this function finished */
1753f9c8caa0SVladimir Sementsov-Ogievskiy     ms->to_dst_file = NULL;
1754f9c8caa0SVladimir Sementsov-Ogievskiy 
1755c3049a56SJuan Quintela     return ret;
1756c3049a56SJuan Quintela }
1757c3049a56SJuan Quintela 
qemu_savevm_live_state(QEMUFile * f)17583f6df99dSZhang Chen void qemu_savevm_live_state(QEMUFile *f)
17593f6df99dSZhang Chen {
17603f6df99dSZhang Chen     /* save QEMU_VM_SECTION_END section */
17613f6df99dSZhang Chen     qemu_savevm_state_complete_precopy(f, true, false);
17623f6df99dSZhang Chen     qemu_put_byte(f, QEMU_VM_EOF);
17633f6df99dSZhang Chen }
17643f6df99dSZhang Chen 
qemu_save_device_state(QEMUFile * f)17653f6df99dSZhang Chen int qemu_save_device_state(QEMUFile *f)
1766c3049a56SJuan Quintela {
17676138d43aSCédric Le Goater     MigrationState *ms = migrate_get_current();
17686138d43aSCédric Le Goater     Error *local_err = NULL;
1769c3049a56SJuan Quintela     SaveStateEntry *se;
1770c3049a56SJuan Quintela 
17713f6df99dSZhang Chen     if (!migration_in_colo_state()) {
1772c3049a56SJuan Quintela         qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1773c3049a56SJuan Quintela         qemu_put_be32(f, QEMU_VM_FILE_VERSION);
17743f6df99dSZhang Chen     }
1775c3049a56SJuan Quintela     cpu_synchronize_all_states();
1776c3049a56SJuan Quintela 
17770163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1778687433f6SDr. David Alan Gilbert         int ret;
1779687433f6SDr. David Alan Gilbert 
1780c3049a56SJuan Quintela         if (se->is_ram) {
1781c3049a56SJuan Quintela             continue;
1782c3049a56SJuan Quintela         }
17836138d43aSCédric Le Goater         ret = vmstate_save(f, se, NULL, &local_err);
1784687433f6SDr. David Alan Gilbert         if (ret) {
17856138d43aSCédric Le Goater             migrate_set_error(ms, local_err);
17866138d43aSCédric Le Goater             error_report_err(local_err);
1787687433f6SDr. David Alan Gilbert             return ret;
1788687433f6SDr. David Alan Gilbert         }
1789c3049a56SJuan Quintela     }
1790c3049a56SJuan Quintela 
1791c3049a56SJuan Quintela     qemu_put_byte(f, QEMU_VM_EOF);
1792c3049a56SJuan Quintela 
1793c3049a56SJuan Quintela     return qemu_file_get_error(f);
1794c3049a56SJuan Quintela }
1795c3049a56SJuan Quintela 
find_se(const char * idstr,uint32_t instance_id)179693062e23SPeter Xu static SaveStateEntry *find_se(const char *idstr, uint32_t instance_id)
1797c3049a56SJuan Quintela {
1798c3049a56SJuan Quintela     SaveStateEntry *se;
1799c3049a56SJuan Quintela 
18000163a2e0SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1801c3049a56SJuan Quintela         if (!strcmp(se->idstr, idstr) &&
1802c3049a56SJuan Quintela             (instance_id == se->instance_id ||
1803c3049a56SJuan Quintela              instance_id == se->alias_id))
1804c3049a56SJuan Quintela             return se;
1805c3049a56SJuan Quintela         /* Migrating from an older version? */
1806c3049a56SJuan Quintela         if (strstr(se->idstr, idstr) && se->compat) {
1807c3049a56SJuan Quintela             if (!strcmp(se->compat->idstr, idstr) &&
1808c3049a56SJuan Quintela                 (instance_id == se->compat->instance_id ||
1809c3049a56SJuan Quintela                  instance_id == se->alias_id))
1810c3049a56SJuan Quintela                 return se;
1811c3049a56SJuan Quintela         }
1812c3049a56SJuan Quintela     }
1813c3049a56SJuan Quintela     return NULL;
1814c3049a56SJuan Quintela }
1815c3049a56SJuan Quintela 
18167b89bf27SDr. David Alan Gilbert enum LoadVMExitCodes {
18177b89bf27SDr. David Alan Gilbert     /* Allow a command to quit all layers of nested loadvm loops */
18187b89bf27SDr. David Alan Gilbert     LOADVM_QUIT     =  1,
18197b89bf27SDr. David Alan Gilbert };
18207b89bf27SDr. David Alan Gilbert 
1821093e3c42SDr. David Alan Gilbert /* ------ incoming postcopy messages ------ */
1822093e3c42SDr. David Alan Gilbert /* 'advise' arrives before any transfers just to tell us that a postcopy
1823093e3c42SDr. David Alan Gilbert  * *might* happen - it might be skipped if precopy transferred everything
1824093e3c42SDr. David Alan Gilbert  * quickly.
1825093e3c42SDr. David Alan Gilbert  */
loadvm_postcopy_handle_advise(MigrationIncomingState * mis,uint16_t len)1826875fcd01SGreg Kurz static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
1827875fcd01SGreg Kurz                                          uint16_t len)
1828093e3c42SDr. David Alan Gilbert {
1829093e3c42SDr. David Alan Gilbert     PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE);
1830e8ca1db2SDr. David Alan Gilbert     uint64_t remote_pagesize_summary, local_pagesize_summary, remote_tps;
1831144fa06bSJuan Quintela     size_t page_size = qemu_target_page_size();
1832d3dff7a5SDr. David Alan Gilbert     Error *local_err = NULL;
1833093e3c42SDr. David Alan Gilbert 
1834093e3c42SDr. David Alan Gilbert     trace_loadvm_postcopy_handle_advise();
1835093e3c42SDr. David Alan Gilbert     if (ps != POSTCOPY_INCOMING_NONE) {
1836093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_ADVISE in wrong postcopy state (%d)", ps);
1837093e3c42SDr. David Alan Gilbert         return -1;
1838093e3c42SDr. David Alan Gilbert     }
1839093e3c42SDr. David Alan Gilbert 
1840875fcd01SGreg Kurz     switch (len) {
1841875fcd01SGreg Kurz     case 0:
1842875fcd01SGreg Kurz         if (migrate_postcopy_ram()) {
1843875fcd01SGreg Kurz             error_report("RAM postcopy is enabled but have 0 byte advise");
1844875fcd01SGreg Kurz             return -EINVAL;
1845875fcd01SGreg Kurz         }
184658110f0aSVladimir Sementsov-Ogievskiy         return 0;
1847875fcd01SGreg Kurz     case 8 + 8:
1848875fcd01SGreg Kurz         if (!migrate_postcopy_ram()) {
1849875fcd01SGreg Kurz             error_report("RAM postcopy is disabled but have 16 byte advise");
1850875fcd01SGreg Kurz             return -EINVAL;
1851875fcd01SGreg Kurz         }
1852875fcd01SGreg Kurz         break;
1853875fcd01SGreg Kurz     default:
1854875fcd01SGreg Kurz         error_report("CMD_POSTCOPY_ADVISE invalid length (%d)", len);
1855875fcd01SGreg Kurz         return -EINVAL;
185658110f0aSVladimir Sementsov-Ogievskiy     }
185758110f0aSVladimir Sementsov-Ogievskiy 
185874c38cf7SPeter Xu     if (!postcopy_ram_supported_by_host(mis, &local_err)) {
185974c38cf7SPeter Xu         error_report_err(local_err);
1860328d4d85SDr. David Alan Gilbert         postcopy_state_set(POSTCOPY_INCOMING_NONE);
1861eb59db53SDr. David Alan Gilbert         return -1;
1862eb59db53SDr. David Alan Gilbert     }
1863eb59db53SDr. David Alan Gilbert 
1864e8ca1db2SDr. David Alan Gilbert     remote_pagesize_summary = qemu_get_be64(mis->from_src_file);
1865e8ca1db2SDr. David Alan Gilbert     local_pagesize_summary = ram_pagesize_summary();
1866e8ca1db2SDr. David Alan Gilbert 
1867e8ca1db2SDr. David Alan Gilbert     if (remote_pagesize_summary != local_pagesize_summary)  {
1868093e3c42SDr. David Alan Gilbert         /*
1869e8ca1db2SDr. David Alan Gilbert          * This detects two potential causes of mismatch:
1870e8ca1db2SDr. David Alan Gilbert          *   a) A mismatch in host page sizes
1871093e3c42SDr. David Alan Gilbert          *      Some combinations of mismatch are probably possible but it gets
1872093e3c42SDr. David Alan Gilbert          *      a bit more complicated.  In particular we need to place whole
1873093e3c42SDr. David Alan Gilbert          *      host pages on the dest at once, and we need to ensure that we
1874093e3c42SDr. David Alan Gilbert          *      handle dirtying to make sure we never end up sending part of
1875093e3c42SDr. David Alan Gilbert          *      a hostpage on it's own.
1876e8ca1db2SDr. David Alan Gilbert          *   b) The use of different huge page sizes on source/destination
1877e8ca1db2SDr. David Alan Gilbert          *      a more fine grain test is performed during RAM block migration
1878e8ca1db2SDr. David Alan Gilbert          *      but this test here causes a nice early clear failure, and
1879e8ca1db2SDr. David Alan Gilbert          *      also fails when passed to an older qemu that doesn't
1880e8ca1db2SDr. David Alan Gilbert          *      do huge pages.
1881093e3c42SDr. David Alan Gilbert          */
1882e8ca1db2SDr. David Alan Gilbert         error_report("Postcopy needs matching RAM page sizes (s=%" PRIx64
1883e8ca1db2SDr. David Alan Gilbert                                                              " d=%" PRIx64 ")",
1884e8ca1db2SDr. David Alan Gilbert                      remote_pagesize_summary, local_pagesize_summary);
1885093e3c42SDr. David Alan Gilbert         return -1;
1886093e3c42SDr. David Alan Gilbert     }
1887093e3c42SDr. David Alan Gilbert 
1888093e3c42SDr. David Alan Gilbert     remote_tps = qemu_get_be64(mis->from_src_file);
1889144fa06bSJuan Quintela     if (remote_tps != page_size) {
1890093e3c42SDr. David Alan Gilbert         /*
1891093e3c42SDr. David Alan Gilbert          * Again, some differences could be dealt with, but for now keep it
1892093e3c42SDr. David Alan Gilbert          * simple.
1893093e3c42SDr. David Alan Gilbert          */
189420afaed9SJuan Quintela         error_report("Postcopy needs matching target page sizes (s=%d d=%zd)",
1895144fa06bSJuan Quintela                      (int)remote_tps, page_size);
1896093e3c42SDr. David Alan Gilbert         return -1;
1897093e3c42SDr. David Alan Gilbert     }
1898093e3c42SDr. David Alan Gilbert 
1899d3dff7a5SDr. David Alan Gilbert     if (postcopy_notify(POSTCOPY_NOTIFY_INBOUND_ADVISE, &local_err)) {
1900d3dff7a5SDr. David Alan Gilbert         error_report_err(local_err);
1901d3dff7a5SDr. David Alan Gilbert         return -1;
1902d3dff7a5SDr. David Alan Gilbert     }
1903d3dff7a5SDr. David Alan Gilbert 
19041caddf8aSDr. David Alan Gilbert     if (ram_postcopy_incoming_init(mis)) {
19051caddf8aSDr. David Alan Gilbert         return -1;
19061caddf8aSDr. David Alan Gilbert     }
19071caddf8aSDr. David Alan Gilbert 
1908093e3c42SDr. David Alan Gilbert     return 0;
1909093e3c42SDr. David Alan Gilbert }
1910093e3c42SDr. David Alan Gilbert 
1911093e3c42SDr. David Alan Gilbert /* After postcopy we will be told to throw some pages away since they're
1912093e3c42SDr. David Alan Gilbert  * dirty and will have to be demand fetched.  Must happen before CPU is
1913093e3c42SDr. David Alan Gilbert  * started.
1914093e3c42SDr. David Alan Gilbert  * There can be 0..many of these messages, each encoding multiple pages.
1915093e3c42SDr. David Alan Gilbert  */
loadvm_postcopy_ram_handle_discard(MigrationIncomingState * mis,uint16_t len)1916093e3c42SDr. David Alan Gilbert static int loadvm_postcopy_ram_handle_discard(MigrationIncomingState *mis,
1917093e3c42SDr. David Alan Gilbert                                               uint16_t len)
1918093e3c42SDr. David Alan Gilbert {
1919093e3c42SDr. David Alan Gilbert     int tmp;
1920093e3c42SDr. David Alan Gilbert     char ramid[256];
1921093e3c42SDr. David Alan Gilbert     PostcopyState ps = postcopy_state_get();
1922093e3c42SDr. David Alan Gilbert 
1923093e3c42SDr. David Alan Gilbert     trace_loadvm_postcopy_ram_handle_discard();
1924093e3c42SDr. David Alan Gilbert 
1925093e3c42SDr. David Alan Gilbert     switch (ps) {
1926093e3c42SDr. David Alan Gilbert     case POSTCOPY_INCOMING_ADVISE:
1927093e3c42SDr. David Alan Gilbert         /* 1st discard */
1928f9527107SDr. David Alan Gilbert         tmp = postcopy_ram_prepare_discard(mis);
1929093e3c42SDr. David Alan Gilbert         if (tmp) {
1930093e3c42SDr. David Alan Gilbert             return tmp;
1931093e3c42SDr. David Alan Gilbert         }
1932093e3c42SDr. David Alan Gilbert         break;
1933093e3c42SDr. David Alan Gilbert 
1934093e3c42SDr. David Alan Gilbert     case POSTCOPY_INCOMING_DISCARD:
1935093e3c42SDr. David Alan Gilbert         /* Expected state */
1936093e3c42SDr. David Alan Gilbert         break;
1937093e3c42SDr. David Alan Gilbert 
1938093e3c42SDr. David Alan Gilbert     default:
1939093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD in wrong postcopy state (%d)",
1940093e3c42SDr. David Alan Gilbert                      ps);
1941093e3c42SDr. David Alan Gilbert         return -1;
1942093e3c42SDr. David Alan Gilbert     }
1943093e3c42SDr. David Alan Gilbert     /* We're expecting a
1944093e3c42SDr. David Alan Gilbert      *    Version (0)
1945093e3c42SDr. David Alan Gilbert      *    a RAM ID string (length byte, name, 0 term)
1946093e3c42SDr. David Alan Gilbert      *    then at least 1 16 byte chunk
1947093e3c42SDr. David Alan Gilbert     */
1948093e3c42SDr. David Alan Gilbert     if (len < (1 + 1 + 1 + 1 + 2 * 8)) {
1949093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD invalid length (%d)", len);
1950093e3c42SDr. David Alan Gilbert         return -1;
1951093e3c42SDr. David Alan Gilbert     }
1952093e3c42SDr. David Alan Gilbert 
1953093e3c42SDr. David Alan Gilbert     tmp = qemu_get_byte(mis->from_src_file);
1954093e3c42SDr. David Alan Gilbert     if (tmp != postcopy_ram_discard_version) {
1955093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD invalid version (%d)", tmp);
1956093e3c42SDr. David Alan Gilbert         return -1;
1957093e3c42SDr. David Alan Gilbert     }
1958093e3c42SDr. David Alan Gilbert 
1959093e3c42SDr. David Alan Gilbert     if (!qemu_get_counted_string(mis->from_src_file, ramid)) {
1960093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD Failed to read RAMBlock ID");
1961093e3c42SDr. David Alan Gilbert         return -1;
1962093e3c42SDr. David Alan Gilbert     }
1963093e3c42SDr. David Alan Gilbert     tmp = qemu_get_byte(mis->from_src_file);
1964093e3c42SDr. David Alan Gilbert     if (tmp != 0) {
1965093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD missing nil (%d)", tmp);
1966093e3c42SDr. David Alan Gilbert         return -1;
1967093e3c42SDr. David Alan Gilbert     }
1968093e3c42SDr. David Alan Gilbert 
1969093e3c42SDr. David Alan Gilbert     len -= 3 + strlen(ramid);
1970093e3c42SDr. David Alan Gilbert     if (len % 16) {
1971093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_RAM_DISCARD invalid length (%d)", len);
1972093e3c42SDr. David Alan Gilbert         return -1;
1973093e3c42SDr. David Alan Gilbert     }
1974093e3c42SDr. David Alan Gilbert     trace_loadvm_postcopy_ram_handle_discard_header(ramid, len);
1975093e3c42SDr. David Alan Gilbert     while (len) {
1976093e3c42SDr. David Alan Gilbert         uint64_t start_addr, block_length;
1977093e3c42SDr. David Alan Gilbert         start_addr = qemu_get_be64(mis->from_src_file);
1978093e3c42SDr. David Alan Gilbert         block_length = qemu_get_be64(mis->from_src_file);
1979093e3c42SDr. David Alan Gilbert 
1980093e3c42SDr. David Alan Gilbert         len -= 16;
1981aaa2064cSJuan Quintela         int ret = ram_discard_range(ramid, start_addr, block_length);
1982093e3c42SDr. David Alan Gilbert         if (ret) {
1983093e3c42SDr. David Alan Gilbert             return ret;
1984093e3c42SDr. David Alan Gilbert         }
1985093e3c42SDr. David Alan Gilbert     }
1986093e3c42SDr. David Alan Gilbert     trace_loadvm_postcopy_ram_handle_discard_end();
1987093e3c42SDr. David Alan Gilbert 
1988093e3c42SDr. David Alan Gilbert     return 0;
1989093e3c42SDr. David Alan Gilbert }
1990093e3c42SDr. David Alan Gilbert 
1991c76201abSDr. David Alan Gilbert /*
1992c76201abSDr. David Alan Gilbert  * Triggered by a postcopy_listen command; this thread takes over reading
1993c76201abSDr. David Alan Gilbert  * the input stream, leaving the main thread free to carry on loading the rest
1994c76201abSDr. David Alan Gilbert  * of the device state (from RAM).
1995c76201abSDr. David Alan Gilbert  * (TODO:This could do with being in a postcopy file - but there again it's
1996c76201abSDr. David Alan Gilbert  * just another input loop, not that postcopy specific)
1997c76201abSDr. David Alan Gilbert  */
postcopy_ram_listen_thread(void * opaque)1998c76201abSDr. David Alan Gilbert static void *postcopy_ram_listen_thread(void *opaque)
1999c76201abSDr. David Alan Gilbert {
2000c76201abSDr. David Alan Gilbert     MigrationIncomingState *mis = migration_incoming_get_current();
2001b411b844SPeter Xu     QEMUFile *f = mis->from_src_file;
2002c76201abSDr. David Alan Gilbert     int load_res;
2003ee647225SVladimir Sementsov-Ogievskiy     MigrationState *migr = migrate_get_current();
2004ee647225SVladimir Sementsov-Ogievskiy 
2005ee647225SVladimir Sementsov-Ogievskiy     object_ref(OBJECT(migr));
2006c76201abSDr. David Alan Gilbert 
20076ba996bbSDr. David Alan Gilbert     migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
20086ba996bbSDr. David Alan Gilbert                                    MIGRATION_STATUS_POSTCOPY_ACTIVE);
2009095c12a4SPeter Xu     qemu_sem_post(&mis->thread_sync_sem);
2010c76201abSDr. David Alan Gilbert     trace_postcopy_ram_listen_thread_start();
2011c76201abSDr. David Alan Gilbert 
201274637e6fSLidong Chen     rcu_register_thread();
2013c76201abSDr. David Alan Gilbert     /*
2014c76201abSDr. David Alan Gilbert      * Because we're a thread and not a coroutine we can't yield
2015c76201abSDr. David Alan Gilbert      * in qemu_file, and thus we must be blocking now.
2016c76201abSDr. David Alan Gilbert      */
2017c76201abSDr. David Alan Gilbert     qemu_file_set_blocking(f, true);
2018c76201abSDr. David Alan Gilbert     load_res = qemu_loadvm_state_main(f, mis);
2019b411b844SPeter Xu 
2020b411b844SPeter Xu     /*
2021b411b844SPeter Xu      * This is tricky, but, mis->from_src_file can change after it
2022b411b844SPeter Xu      * returns, when postcopy recovery happened. In the future, we may
2023b411b844SPeter Xu      * want a wrapper for the QEMUFile handle.
2024b411b844SPeter Xu      */
2025b411b844SPeter Xu     f = mis->from_src_file;
2026b411b844SPeter Xu 
2027c76201abSDr. David Alan Gilbert     /* And non-blocking again so we don't block in any cleanup */
2028c76201abSDr. David Alan Gilbert     qemu_file_set_blocking(f, false);
2029c76201abSDr. David Alan Gilbert 
2030c76201abSDr. David Alan Gilbert     trace_postcopy_ram_listen_thread_exit();
2031c76201abSDr. David Alan Gilbert     if (load_res < 0) {
2032c76201abSDr. David Alan Gilbert         qemu_file_set_error(f, load_res);
2033ee647225SVladimir Sementsov-Ogievskiy         dirty_bitmap_mig_cancel_incoming();
2034ee647225SVladimir Sementsov-Ogievskiy         if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING &&
2035ee647225SVladimir Sementsov-Ogievskiy             !migrate_postcopy_ram() && migrate_dirty_bitmaps())
2036ee647225SVladimir Sementsov-Ogievskiy         {
2037ee647225SVladimir Sementsov-Ogievskiy             error_report("%s: loadvm failed during postcopy: %d. All states "
2038ee647225SVladimir Sementsov-Ogievskiy                          "are migrated except dirty bitmaps. Some dirty "
2039ee647225SVladimir Sementsov-Ogievskiy                          "bitmaps may be lost, and present migrated dirty "
2040ee647225SVladimir Sementsov-Ogievskiy                          "bitmaps are correctly migrated and valid.",
2041ee647225SVladimir Sementsov-Ogievskiy                          __func__, load_res);
2042ee647225SVladimir Sementsov-Ogievskiy             load_res = 0; /* prevent further exit() */
2043ee647225SVladimir Sementsov-Ogievskiy         } else {
2044ee647225SVladimir Sementsov-Ogievskiy             error_report("%s: loadvm failed: %d", __func__, load_res);
20456ba996bbSDr. David Alan Gilbert             migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE,
20466ba996bbSDr. David Alan Gilbert                                            MIGRATION_STATUS_FAILED);
2047ee647225SVladimir Sementsov-Ogievskiy         }
2048ee647225SVladimir Sementsov-Ogievskiy     }
2049ee647225SVladimir Sementsov-Ogievskiy     if (load_res >= 0) {
2050c76201abSDr. David Alan Gilbert         /*
2051c76201abSDr. David Alan Gilbert          * This looks good, but it's possible that the device loading in the
2052c76201abSDr. David Alan Gilbert          * main thread hasn't finished yet, and so we might not be in 'RUN'
2053c76201abSDr. David Alan Gilbert          * state yet; wait for the end of the main thread.
2054c76201abSDr. David Alan Gilbert          */
2055c76201abSDr. David Alan Gilbert         qemu_event_wait(&mis->main_thread_load_event);
2056c76201abSDr. David Alan Gilbert     }
2057c76201abSDr. David Alan Gilbert     postcopy_ram_incoming_cleanup(mis);
2058c76201abSDr. David Alan Gilbert 
2059c76201abSDr. David Alan Gilbert     if (load_res < 0) {
2060c76201abSDr. David Alan Gilbert         /*
2061c76201abSDr. David Alan Gilbert          * If something went wrong then we have a bad state so exit;
2062c76201abSDr. David Alan Gilbert          * depending how far we got it might be possible at this point
2063c76201abSDr. David Alan Gilbert          * to leave the guest running and fire MCEs for pages that never
2064c76201abSDr. David Alan Gilbert          * arrived as a desperate recovery step.
2065c76201abSDr. David Alan Gilbert          */
206674637e6fSLidong Chen         rcu_unregister_thread();
2067c76201abSDr. David Alan Gilbert         exit(EXIT_FAILURE);
2068c76201abSDr. David Alan Gilbert     }
2069c76201abSDr. David Alan Gilbert 
20706ba996bbSDr. David Alan Gilbert     migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE,
20716ba996bbSDr. David Alan Gilbert                                    MIGRATION_STATUS_COMPLETED);
20726ba996bbSDr. David Alan Gilbert     /*
20736ba996bbSDr. David Alan Gilbert      * If everything has worked fine, then the main thread has waited
20746ba996bbSDr. David Alan Gilbert      * for us to start, and we're the last use of the mis.
20756ba996bbSDr. David Alan Gilbert      * (If something broke then qemu will have to exit anyway since it's
20766ba996bbSDr. David Alan Gilbert      * got a bad migration state).
20776ba996bbSDr. David Alan Gilbert      */
20786ba996bbSDr. David Alan Gilbert     migration_incoming_state_destroy();
2079acb5ea86SJuan Quintela     qemu_loadvm_state_cleanup();
20806ba996bbSDr. David Alan Gilbert 
208174637e6fSLidong Chen     rcu_unregister_thread();
20829cf4bb87SDr. David Alan Gilbert     mis->have_listen_thread = false;
20832d49bacdSWei Yang     postcopy_state_set(POSTCOPY_INCOMING_END);
20842d49bacdSWei Yang 
2085ee647225SVladimir Sementsov-Ogievskiy     object_unref(OBJECT(migr));
2086ee647225SVladimir Sementsov-Ogievskiy 
2087c76201abSDr. David Alan Gilbert     return NULL;
2088c76201abSDr. David Alan Gilbert }
2089c76201abSDr. David Alan Gilbert 
2090093e3c42SDr. David Alan Gilbert /* After this message we must be able to immediately receive postcopy data */
loadvm_postcopy_handle_listen(MigrationIncomingState * mis)2091093e3c42SDr. David Alan Gilbert static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
2092093e3c42SDr. David Alan Gilbert {
2093093e3c42SDr. David Alan Gilbert     PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_LISTENING);
20946864a7b5SDr. David Alan Gilbert     Error *local_err = NULL;
20956864a7b5SDr. David Alan Gilbert 
2096c84f976eSPeter Xu     trace_loadvm_postcopy_handle_listen("enter");
2097c84f976eSPeter Xu 
2098093e3c42SDr. David Alan Gilbert     if (ps != POSTCOPY_INCOMING_ADVISE && ps != POSTCOPY_INCOMING_DISCARD) {
2099093e3c42SDr. David Alan Gilbert         error_report("CMD_POSTCOPY_LISTEN in wrong postcopy state (%d)", ps);
2100093e3c42SDr. David Alan Gilbert         return -1;
2101093e3c42SDr. David Alan Gilbert     }
2102f9527107SDr. David Alan Gilbert     if (ps == POSTCOPY_INCOMING_ADVISE) {
2103f9527107SDr. David Alan Gilbert         /*
2104f9527107SDr. David Alan Gilbert          * A rare case, we entered listen without having to do any discards,
2105f9527107SDr. David Alan Gilbert          * so do the setup that's normally done at the time of the 1st discard.
2106f9527107SDr. David Alan Gilbert          */
210758110f0aSVladimir Sementsov-Ogievskiy         if (migrate_postcopy_ram()) {
2108f9527107SDr. David Alan Gilbert             postcopy_ram_prepare_discard(mis);
2109f9527107SDr. David Alan Gilbert         }
211058110f0aSVladimir Sementsov-Ogievskiy     }
2111093e3c42SDr. David Alan Gilbert 
2112c84f976eSPeter Xu     trace_loadvm_postcopy_handle_listen("after discard");
2113c84f976eSPeter Xu 
2114f0a227adSDr. David Alan Gilbert     /*
2115f0a227adSDr. David Alan Gilbert      * Sensitise RAM - can now generate requests for blocks that don't exist
2116f0a227adSDr. David Alan Gilbert      * However, at this point the CPU shouldn't be running, and the IO
2117f0a227adSDr. David Alan Gilbert      * shouldn't be doing anything yet so don't actually expect requests
2118f0a227adSDr. David Alan Gilbert      */
211958110f0aSVladimir Sementsov-Ogievskiy     if (migrate_postcopy_ram()) {
21202a7eb148SWei Yang         if (postcopy_ram_incoming_setup(mis)) {
212191b02dc7SFei Li             postcopy_ram_incoming_cleanup(mis);
2122f0a227adSDr. David Alan Gilbert             return -1;
2123f0a227adSDr. David Alan Gilbert         }
212458110f0aSVladimir Sementsov-Ogievskiy     }
2125f0a227adSDr. David Alan Gilbert 
2126c84f976eSPeter Xu     trace_loadvm_postcopy_handle_listen("after uffd");
2127c84f976eSPeter Xu 
21286864a7b5SDr. David Alan Gilbert     if (postcopy_notify(POSTCOPY_NOTIFY_INBOUND_LISTEN, &local_err)) {
21296864a7b5SDr. David Alan Gilbert         error_report_err(local_err);
21306864a7b5SDr. David Alan Gilbert         return -1;
21316864a7b5SDr. David Alan Gilbert     }
21326864a7b5SDr. David Alan Gilbert 
2133c76201abSDr. David Alan Gilbert     mis->have_listen_thread = true;
213460ce4767SPeter Xu     postcopy_thread_create(mis, &mis->listen_thread, "mig/dst/listen",
2135095c12a4SPeter Xu                            postcopy_ram_listen_thread, QEMU_THREAD_DETACHED);
2136c84f976eSPeter Xu     trace_loadvm_postcopy_handle_listen("return");
2137c84f976eSPeter Xu 
2138093e3c42SDr. David Alan Gilbert     return 0;
2139093e3c42SDr. David Alan Gilbert }
2140093e3c42SDr. David Alan Gilbert 
loadvm_postcopy_handle_run_bh(void * opaque)2141ea6a55bcSDenis V. Lunev static void loadvm_postcopy_handle_run_bh(void *opaque)
2142093e3c42SDr. David Alan Gilbert {
214327c6825bSDr. David Alan Gilbert     Error *local_err = NULL;
21441ce54262SWei Yang     MigrationIncomingState *mis = opaque;
2145093e3c42SDr. David Alan Gilbert 
21463e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("dst-postcopy-bh-enter");
2147b9a040b9SPeter Xu 
214827c6825bSDr. David Alan Gilbert     /* TODO we should move all of this lot into postcopy_ram.c or a shared code
214927c6825bSDr. David Alan Gilbert      * in migration.c
215027c6825bSDr. David Alan Gilbert      */
215127c6825bSDr. David Alan Gilbert     cpu_synchronize_all_post_init();
215227c6825bSDr. David Alan Gilbert 
21533e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("dst-postcopy-bh-cpu-synced");
2154b9a040b9SPeter Xu 
21557659505cSDr. David Alan Gilbert     qemu_announce_self(&mis->announce_timer, migrate_announce_params());
215627c6825bSDr. David Alan Gilbert 
21573e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("dst-postcopy-bh-announced");
2158b9a040b9SPeter Xu 
21593b717194SEmanuele Giuseppe Esposito     /* Make sure all file formats throw away their mutable metadata.
2160ace21a58SKevin Wolf      * If we get an error here, just don't restart the VM yet. */
21613b717194SEmanuele Giuseppe Esposito     bdrv_activate_all(&local_err);
216227c6825bSDr. David Alan Gilbert     if (local_err) {
216327c6825bSDr. David Alan Gilbert         error_report_err(local_err);
21640042fd36SKevin Wolf         local_err = NULL;
21650042fd36SKevin Wolf         autostart = false;
21660042fd36SKevin Wolf     }
21670042fd36SKevin Wolf 
21683e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("dst-postcopy-bh-cache-invalidated");
216927c6825bSDr. David Alan Gilbert 
2170b35ebdf0SVladimir Sementsov-Ogievskiy     dirty_bitmap_mig_before_vm_start();
2171b35ebdf0SVladimir Sementsov-Ogievskiy 
2172093e3c42SDr. David Alan Gilbert     if (autostart) {
2173093e3c42SDr. David Alan Gilbert         /* Hold onto your hats, starting the CPU */
2174093e3c42SDr. David Alan Gilbert         vm_start();
2175093e3c42SDr. David Alan Gilbert     } else {
2176093e3c42SDr. David Alan Gilbert         /* leave it paused and let management decide when to start the CPU */
2177093e3c42SDr. David Alan Gilbert         runstate_set(RUN_STATE_PAUSED);
2178093e3c42SDr. David Alan Gilbert     }
2179093e3c42SDr. David Alan Gilbert 
21803e5f3bcdSPeter Xu     trace_vmstate_downtime_checkpoint("dst-postcopy-bh-vm-started");
2181ea6a55bcSDenis V. Lunev }
2182ea6a55bcSDenis V. Lunev 
2183ea6a55bcSDenis V. Lunev /* After all discards we can start running and asking for pages */
loadvm_postcopy_handle_run(MigrationIncomingState * mis)2184ea6a55bcSDenis V. Lunev static int loadvm_postcopy_handle_run(MigrationIncomingState *mis)
2185ea6a55bcSDenis V. Lunev {
21860197d890SWei Yang     PostcopyState ps = postcopy_state_get();
2187ea6a55bcSDenis V. Lunev 
2188ea6a55bcSDenis V. Lunev     trace_loadvm_postcopy_handle_run();
2189ea6a55bcSDenis V. Lunev     if (ps != POSTCOPY_INCOMING_LISTENING) {
2190ea6a55bcSDenis V. Lunev         error_report("CMD_POSTCOPY_RUN in wrong postcopy state (%d)", ps);
2191ea6a55bcSDenis V. Lunev         return -1;
2192ea6a55bcSDenis V. Lunev     }
2193ea6a55bcSDenis V. Lunev 
21940197d890SWei Yang     postcopy_state_set(POSTCOPY_INCOMING_RUNNING);
219544d0d456SFabiano Rosas     migration_bh_schedule(loadvm_postcopy_handle_run_bh, mis);
2196ea6a55bcSDenis V. Lunev 
219727c6825bSDr. David Alan Gilbert     /* We need to finish reading the stream from the package
219827c6825bSDr. David Alan Gilbert      * and also stop reading anything more from the stream that loaded the
219927c6825bSDr. David Alan Gilbert      * package (since it's now being read by the listener thread).
220027c6825bSDr. David Alan Gilbert      * LOADVM_QUIT will quit all the layers of nested loadvm loops.
220127c6825bSDr. David Alan Gilbert      */
220227c6825bSDr. David Alan Gilbert     return LOADVM_QUIT;
2203093e3c42SDr. David Alan Gilbert }
2204093e3c42SDr. David Alan Gilbert 
22050c26781cSPeter Xu /* We must be with page_request_mutex held */
postcopy_sync_page_req(gpointer key,gpointer value,gpointer data)22060c26781cSPeter Xu static gboolean postcopy_sync_page_req(gpointer key, gpointer value,
22070c26781cSPeter Xu                                        gpointer data)
22080c26781cSPeter Xu {
22090c26781cSPeter Xu     MigrationIncomingState *mis = data;
22100c26781cSPeter Xu     void *host_addr = (void *) key;
22110c26781cSPeter Xu     ram_addr_t rb_offset;
22120c26781cSPeter Xu     RAMBlock *rb;
22130c26781cSPeter Xu     int ret;
22140c26781cSPeter Xu 
22150c26781cSPeter Xu     rb = qemu_ram_block_from_host(host_addr, true, &rb_offset);
22160c26781cSPeter Xu     if (!rb) {
22170c26781cSPeter Xu         /*
22180c26781cSPeter Xu          * This should _never_ happen.  However be nice for a migrating VM to
22190c26781cSPeter Xu          * not crash/assert.  Post an error (note: intended to not use *_once
22200c26781cSPeter Xu          * because we do want to see all the illegal addresses; and this can
22210c26781cSPeter Xu          * never be triggered by the guest so we're safe) and move on next.
22220c26781cSPeter Xu          */
22230c26781cSPeter Xu         error_report("%s: illegal host addr %p", __func__, host_addr);
22240c26781cSPeter Xu         /* Try the next entry */
22250c26781cSPeter Xu         return FALSE;
22260c26781cSPeter Xu     }
22270c26781cSPeter Xu 
22280c26781cSPeter Xu     ret = migrate_send_rp_message_req_pages(mis, rb, rb_offset);
22290c26781cSPeter Xu     if (ret) {
22300c26781cSPeter Xu         /* Please refer to above comment. */
22310c26781cSPeter Xu         error_report("%s: send rp message failed for addr %p",
22320c26781cSPeter Xu                      __func__, host_addr);
22330c26781cSPeter Xu         return FALSE;
22340c26781cSPeter Xu     }
22350c26781cSPeter Xu 
22360c26781cSPeter Xu     trace_postcopy_page_req_sync(host_addr);
22370c26781cSPeter Xu 
22380c26781cSPeter Xu     return FALSE;
22390c26781cSPeter Xu }
22400c26781cSPeter Xu 
migrate_send_rp_req_pages_pending(MigrationIncomingState * mis)22410c26781cSPeter Xu static void migrate_send_rp_req_pages_pending(MigrationIncomingState *mis)
22420c26781cSPeter Xu {
22430c26781cSPeter Xu     WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) {
22440c26781cSPeter Xu         g_tree_foreach(mis->page_requested, postcopy_sync_page_req, mis);
22450c26781cSPeter Xu     }
22460c26781cSPeter Xu }
22470c26781cSPeter Xu 
loadvm_postcopy_handle_resume(MigrationIncomingState * mis)22483f5875ecSPeter Xu static int loadvm_postcopy_handle_resume(MigrationIncomingState *mis)
22493f5875ecSPeter Xu {
22503f5875ecSPeter Xu     if (mis->state != MIGRATION_STATUS_POSTCOPY_RECOVER) {
22513f5875ecSPeter Xu         error_report("%s: illegal resume received", __func__);
22523f5875ecSPeter Xu         /* Don't fail the load, only for this. */
22533f5875ecSPeter Xu         return 0;
22543f5875ecSPeter Xu     }
22553f5875ecSPeter Xu 
22563f5875ecSPeter Xu     /*
2257cc5ab872SPeter Xu      * Reset the last_rb before we resend any page req to source again, since
2258cc5ab872SPeter Xu      * the source should have it reset already.
2259cc5ab872SPeter Xu      */
2260cc5ab872SPeter Xu     mis->last_rb = NULL;
2261cc5ab872SPeter Xu 
2262cc5ab872SPeter Xu     /*
22633f5875ecSPeter Xu      * This means source VM is ready to resume the postcopy migration.
22643f5875ecSPeter Xu      */
22653f5875ecSPeter Xu     migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_RECOVER,
22663f5875ecSPeter Xu                       MIGRATION_STATUS_POSTCOPY_ACTIVE);
22673f5875ecSPeter Xu 
22683f5875ecSPeter Xu     trace_loadvm_postcopy_handle_resume();
22693f5875ecSPeter Xu 
227013955b89SPeter Xu     /* Tell source that "we are ready" */
227113955b89SPeter Xu     migrate_send_rp_resume_ack(mis, MIGRATION_RESUME_ACK_VALUE);
22723f5875ecSPeter Xu 
22730c26781cSPeter Xu     /*
22740c26781cSPeter Xu      * After a postcopy recovery, the source should have lost the postcopy
22750c26781cSPeter Xu      * queue, or potentially the requested pages could have been lost during
22760c26781cSPeter Xu      * the network down phase.  Let's re-sync with the source VM by re-sending
22770c26781cSPeter Xu      * all the pending pages that we eagerly need, so these threads won't get
22780c26781cSPeter Xu      * blocked too long due to the recovery.
22790c26781cSPeter Xu      *
22800c26781cSPeter Xu      * Without this procedure, the faulted destination VM threads (waiting for
22810c26781cSPeter Xu      * page requests right before the postcopy is interrupted) can keep hanging
22820c26781cSPeter Xu      * until the pages are sent by the source during the background copying of
22830c26781cSPeter Xu      * pages, or another thread faulted on the same address accidentally.
22840c26781cSPeter Xu      */
22850c26781cSPeter Xu     migrate_send_rp_req_pages_pending(mis);
22860c26781cSPeter Xu 
22875e773431SPeter Xu     /*
22885e773431SPeter Xu      * It's time to switch state and release the fault thread to continue
22895e773431SPeter Xu      * service page faults.  Note that this should be explicitly after the
22905e773431SPeter Xu      * above call to migrate_send_rp_req_pages_pending().  In short:
22915e773431SPeter Xu      * migrate_send_rp_message_req_pages() is not thread safe, yet.
22925e773431SPeter Xu      */
22935e773431SPeter Xu     qemu_sem_post(&mis->postcopy_pause_sem_fault);
22945e773431SPeter Xu 
229560bb3c58SPeter Xu     if (migrate_postcopy_preempt()) {
22965655aab0SPeter Xu         /*
22975655aab0SPeter Xu          * The preempt channel will be created in async manner, now let's
22985655aab0SPeter Xu          * wait for it and make sure it's created.
22995655aab0SPeter Xu          */
23005655aab0SPeter Xu         qemu_sem_wait(&mis->postcopy_qemufile_dst_done);
230160bb3c58SPeter Xu         assert(mis->postcopy_qemufile_dst);
230260bb3c58SPeter Xu         /* Kick the fast ram load thread too */
230360bb3c58SPeter Xu         qemu_sem_post(&mis->postcopy_pause_sem_fast_load);
230460bb3c58SPeter Xu     }
230560bb3c58SPeter Xu 
23063f5875ecSPeter Xu     return 0;
23073f5875ecSPeter Xu }
23083f5875ecSPeter Xu 
2309c76ca188SDr. David Alan Gilbert /**
231011cf1d98SDr. David Alan Gilbert  * Immediately following this command is a blob of data containing an embedded
231111cf1d98SDr. David Alan Gilbert  * chunk of migration stream; read it and load it.
2312c76ca188SDr. David Alan Gilbert  *
231311cf1d98SDr. David Alan Gilbert  * @mis: Incoming state
231411cf1d98SDr. David Alan Gilbert  * @length: Length of packaged data to read
231511cf1d98SDr. David Alan Gilbert  *
231611cf1d98SDr. David Alan Gilbert  * Returns: Negative values on error
231711cf1d98SDr. David Alan Gilbert  *
231811cf1d98SDr. David Alan Gilbert  */
loadvm_handle_cmd_packaged(MigrationIncomingState * mis)231911cf1d98SDr. David Alan Gilbert static int loadvm_handle_cmd_packaged(MigrationIncomingState *mis)
232011cf1d98SDr. David Alan Gilbert {
232111cf1d98SDr. David Alan Gilbert     int ret;
232261b67d47SDaniel P. Berrange     size_t length;
232361b67d47SDaniel P. Berrange     QIOChannelBuffer *bioc;
232411cf1d98SDr. David Alan Gilbert 
232511cf1d98SDr. David Alan Gilbert     length = qemu_get_be32(mis->from_src_file);
232611cf1d98SDr. David Alan Gilbert     trace_loadvm_handle_cmd_packaged(length);
232711cf1d98SDr. David Alan Gilbert 
232811cf1d98SDr. David Alan Gilbert     if (length > MAX_VM_CMD_PACKAGED_SIZE) {
232961b67d47SDaniel P. Berrange         error_report("Unreasonably large packaged state: %zu", length);
233011cf1d98SDr. David Alan Gilbert         return -1;
233111cf1d98SDr. David Alan Gilbert     }
233261b67d47SDaniel P. Berrange 
233361b67d47SDaniel P. Berrange     bioc = qio_channel_buffer_new(length);
23346f01f136SDaniel P. Berrange     qio_channel_set_name(QIO_CHANNEL(bioc), "migration-loadvm-buffer");
233561b67d47SDaniel P. Berrange     ret = qemu_get_buffer(mis->from_src_file,
233661b67d47SDaniel P. Berrange                           bioc->data,
233761b67d47SDaniel P. Berrange                           length);
233811cf1d98SDr. David Alan Gilbert     if (ret != length) {
233961b67d47SDaniel P. Berrange         object_unref(OBJECT(bioc));
234061b67d47SDaniel P. Berrange         error_report("CMD_PACKAGED: Buffer receive fail ret=%d length=%zu",
234111cf1d98SDr. David Alan Gilbert                      ret, length);
234211cf1d98SDr. David Alan Gilbert         return (ret < 0) ? ret : -EAGAIN;
234311cf1d98SDr. David Alan Gilbert     }
234461b67d47SDaniel P. Berrange     bioc->usage += length;
234511cf1d98SDr. David Alan Gilbert     trace_loadvm_handle_cmd_packaged_received(ret);
234611cf1d98SDr. David Alan Gilbert 
234777ef2dc1SDaniel P. Berrangé     QEMUFile *packf = qemu_file_new_input(QIO_CHANNEL(bioc));
234811cf1d98SDr. David Alan Gilbert 
23497afbdadaSWei Wang     /*
23507afbdadaSWei Wang      * Before loading the guest states, ensure that the preempt channel has
23517afbdadaSWei Wang      * been ready to use, as some of the states (e.g. via virtio_load) might
23527afbdadaSWei Wang      * trigger page faults that will be handled through the preempt channel.
23537afbdadaSWei Wang      * So yield to the main thread in the case that the channel create event
23547afbdadaSWei Wang      * hasn't been dispatched.
23557afbdadaSWei Wang      *
23567afbdadaSWei Wang      * TODO: if we can move migration loadvm out of main thread, then we
23577afbdadaSWei Wang      * won't block main thread from polling the accept() fds.  We can drop
23587afbdadaSWei Wang      * this as a whole when that is done.
23597afbdadaSWei Wang      */
23607afbdadaSWei Wang     do {
23617afbdadaSWei Wang         if (!migrate_postcopy_preempt() || !qemu_in_coroutine() ||
23627afbdadaSWei Wang             mis->postcopy_qemufile_dst) {
23637afbdadaSWei Wang             break;
23647afbdadaSWei Wang         }
23657afbdadaSWei Wang 
23667afbdadaSWei Wang         aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self());
23677afbdadaSWei Wang         qemu_coroutine_yield();
23687afbdadaSWei Wang     } while (1);
23697afbdadaSWei Wang 
237011cf1d98SDr. David Alan Gilbert     ret = qemu_loadvm_state_main(packf, mis);
237111cf1d98SDr. David Alan Gilbert     trace_loadvm_handle_cmd_packaged_main(ret);
237211cf1d98SDr. David Alan Gilbert     qemu_fclose(packf);
237361b67d47SDaniel P. Berrange     object_unref(OBJECT(bioc));
237411cf1d98SDr. David Alan Gilbert 
237511cf1d98SDr. David Alan Gilbert     return ret;
237611cf1d98SDr. David Alan Gilbert }
237711cf1d98SDr. David Alan Gilbert 
237811cf1d98SDr. David Alan Gilbert /*
2379f25d4225SPeter Xu  * Handle request that source requests for recved_bitmap on
2380f25d4225SPeter Xu  * destination. Payload format:
2381f25d4225SPeter Xu  *
2382f25d4225SPeter Xu  * len (1 byte) + ramblock_name (<255 bytes)
2383f25d4225SPeter Xu  */
loadvm_handle_recv_bitmap(MigrationIncomingState * mis,uint16_t len)2384f25d4225SPeter Xu static int loadvm_handle_recv_bitmap(MigrationIncomingState *mis,
2385f25d4225SPeter Xu                                      uint16_t len)
2386f25d4225SPeter Xu {
2387f25d4225SPeter Xu     QEMUFile *file = mis->from_src_file;
2388f25d4225SPeter Xu     RAMBlock *rb;
2389f25d4225SPeter Xu     char block_name[256];
2390f25d4225SPeter Xu     size_t cnt;
2391f25d4225SPeter Xu 
2392f25d4225SPeter Xu     cnt = qemu_get_counted_string(file, block_name);
2393f25d4225SPeter Xu     if (!cnt) {
2394f25d4225SPeter Xu         error_report("%s: failed to read block name", __func__);
2395f25d4225SPeter Xu         return -EINVAL;
2396f25d4225SPeter Xu     }
2397f25d4225SPeter Xu 
2398f25d4225SPeter Xu     /* Validate before using the data */
2399f25d4225SPeter Xu     if (qemu_file_get_error(file)) {
2400f25d4225SPeter Xu         return qemu_file_get_error(file);
2401f25d4225SPeter Xu     }
2402f25d4225SPeter Xu 
2403f25d4225SPeter Xu     if (len != cnt + 1) {
2404f25d4225SPeter Xu         error_report("%s: invalid payload length (%d)", __func__, len);
2405f25d4225SPeter Xu         return -EINVAL;
2406f25d4225SPeter Xu     }
2407f25d4225SPeter Xu 
2408f25d4225SPeter Xu     rb = qemu_ram_block_by_name(block_name);
2409f25d4225SPeter Xu     if (!rb) {
2410f25d4225SPeter Xu         error_report("%s: block '%s' not found", __func__, block_name);
2411f25d4225SPeter Xu         return -EINVAL;
2412f25d4225SPeter Xu     }
2413f25d4225SPeter Xu 
2414a335debbSPeter Xu     migrate_send_rp_recv_bitmap(mis, block_name);
2415f25d4225SPeter Xu 
2416f25d4225SPeter Xu     trace_loadvm_handle_recv_bitmap(block_name);
2417f25d4225SPeter Xu 
2418f25d4225SPeter Xu     return 0;
2419f25d4225SPeter Xu }
2420f25d4225SPeter Xu 
loadvm_process_enable_colo(MigrationIncomingState * mis)2421aad555c2SZhang Chen static int loadvm_process_enable_colo(MigrationIncomingState *mis)
2422aad555c2SZhang Chen {
242318b1d3c9SDavid Hildenbrand     int ret = migration_incoming_enable_colo();
242418b1d3c9SDavid Hildenbrand 
242518b1d3c9SDavid Hildenbrand     if (!ret) {
242618b1d3c9SDavid Hildenbrand         ret = colo_init_ram_cache();
242718b1d3c9SDavid Hildenbrand         if (ret) {
242818b1d3c9SDavid Hildenbrand             migration_incoming_disable_colo();
242918b1d3c9SDavid Hildenbrand         }
243018b1d3c9SDavid Hildenbrand     }
243118b1d3c9SDavid Hildenbrand     return ret;
2432aad555c2SZhang Chen }
2433aad555c2SZhang Chen 
2434f25d4225SPeter Xu /*
243511cf1d98SDr. David Alan Gilbert  * Process an incoming 'QEMU_VM_COMMAND'
243611cf1d98SDr. David Alan Gilbert  * 0           just a normal return
24377b89bf27SDr. David Alan Gilbert  * LOADVM_QUIT All good, but exit the loop
243811cf1d98SDr. David Alan Gilbert  * <0          Error
2439c76ca188SDr. David Alan Gilbert  */
loadvm_process_command(QEMUFile * f)2440c76ca188SDr. David Alan Gilbert static int loadvm_process_command(QEMUFile *f)
2441c76ca188SDr. David Alan Gilbert {
24422e37701eSDr. David Alan Gilbert     MigrationIncomingState *mis = migration_incoming_get_current();
2443c76ca188SDr. David Alan Gilbert     uint16_t cmd;
2444c76ca188SDr. David Alan Gilbert     uint16_t len;
24452e37701eSDr. David Alan Gilbert     uint32_t tmp32;
2446c76ca188SDr. David Alan Gilbert 
2447c76ca188SDr. David Alan Gilbert     cmd = qemu_get_be16(f);
2448c76ca188SDr. David Alan Gilbert     len = qemu_get_be16(f);
2449c76ca188SDr. David Alan Gilbert 
24507a9ddfbfSPeter Xu     /* Check validity before continue processing of cmds */
24517a9ddfbfSPeter Xu     if (qemu_file_get_error(f)) {
24527a9ddfbfSPeter Xu         return qemu_file_get_error(f);
24537a9ddfbfSPeter Xu     }
24547a9ddfbfSPeter Xu 
2455c76ca188SDr. David Alan Gilbert     if (cmd >= MIG_CMD_MAX || cmd == MIG_CMD_INVALID) {
2456c76ca188SDr. David Alan Gilbert         error_report("MIG_CMD 0x%x unknown (len 0x%x)", cmd, len);
2457c76ca188SDr. David Alan Gilbert         return -EINVAL;
2458c76ca188SDr. David Alan Gilbert     }
2459c76ca188SDr. David Alan Gilbert 
2460a7060ba3SPeter Xu     trace_loadvm_process_command(mig_cmd_args[cmd].name, len);
2461a7060ba3SPeter Xu 
2462c76ca188SDr. David Alan Gilbert     if (mig_cmd_args[cmd].len != -1 && mig_cmd_args[cmd].len != len) {
2463c76ca188SDr. David Alan Gilbert         error_report("%s received with bad length - expecting %zu, got %d",
2464c76ca188SDr. David Alan Gilbert                      mig_cmd_args[cmd].name,
2465c76ca188SDr. David Alan Gilbert                      (size_t)mig_cmd_args[cmd].len, len);
2466c76ca188SDr. David Alan Gilbert         return -ERANGE;
2467c76ca188SDr. David Alan Gilbert     }
2468c76ca188SDr. David Alan Gilbert 
2469c76ca188SDr. David Alan Gilbert     switch (cmd) {
24702e37701eSDr. David Alan Gilbert     case MIG_CMD_OPEN_RETURN_PATH:
24712e37701eSDr. David Alan Gilbert         if (mis->to_src_file) {
24722e37701eSDr. David Alan Gilbert             error_report("CMD_OPEN_RETURN_PATH called when RP already open");
24732e37701eSDr. David Alan Gilbert             /* Not really a problem, so don't give up */
24742e37701eSDr. David Alan Gilbert             return 0;
24752e37701eSDr. David Alan Gilbert         }
24762e37701eSDr. David Alan Gilbert         mis->to_src_file = qemu_file_get_return_path(f);
24772e37701eSDr. David Alan Gilbert         if (!mis->to_src_file) {
24782e37701eSDr. David Alan Gilbert             error_report("CMD_OPEN_RETURN_PATH failed");
24792e37701eSDr. David Alan Gilbert             return -1;
24802e37701eSDr. David Alan Gilbert         }
24811b4adb10SAvihai Horon 
24821b4adb10SAvihai Horon         /*
24831b4adb10SAvihai Horon          * Switchover ack is enabled but no device uses it, so send an ACK to
24841b4adb10SAvihai Horon          * source that it's OK to switchover. Do it here, after return path has
24851b4adb10SAvihai Horon          * been created.
24861b4adb10SAvihai Horon          */
24871b4adb10SAvihai Horon         if (migrate_switchover_ack() && !mis->switchover_ack_pending_num) {
24881b4adb10SAvihai Horon             int ret = migrate_send_rp_switchover_ack(mis);
24891b4adb10SAvihai Horon             if (ret) {
24901b4adb10SAvihai Horon                 error_report(
24911b4adb10SAvihai Horon                     "Could not send switchover ack RP MSG, err %d (%s)", ret,
24921b4adb10SAvihai Horon                     strerror(-ret));
24931b4adb10SAvihai Horon                 return ret;
24941b4adb10SAvihai Horon             }
24951b4adb10SAvihai Horon         }
24962e37701eSDr. David Alan Gilbert         break;
24972e37701eSDr. David Alan Gilbert 
24982e37701eSDr. David Alan Gilbert     case MIG_CMD_PING:
24992e37701eSDr. David Alan Gilbert         tmp32 = qemu_get_be32(f);
25002e37701eSDr. David Alan Gilbert         trace_loadvm_process_command_ping(tmp32);
25012e37701eSDr. David Alan Gilbert         if (!mis->to_src_file) {
25022e37701eSDr. David Alan Gilbert             error_report("CMD_PING (0x%x) received with no return path",
25032e37701eSDr. David Alan Gilbert                          tmp32);
25042e37701eSDr. David Alan Gilbert             return -1;
25052e37701eSDr. David Alan Gilbert         }
25066decec93SDr. David Alan Gilbert         migrate_send_rp_pong(mis, tmp32);
25072e37701eSDr. David Alan Gilbert         break;
2508093e3c42SDr. David Alan Gilbert 
250911cf1d98SDr. David Alan Gilbert     case MIG_CMD_PACKAGED:
251011cf1d98SDr. David Alan Gilbert         return loadvm_handle_cmd_packaged(mis);
251111cf1d98SDr. David Alan Gilbert 
2512093e3c42SDr. David Alan Gilbert     case MIG_CMD_POSTCOPY_ADVISE:
2513875fcd01SGreg Kurz         return loadvm_postcopy_handle_advise(mis, len);
2514093e3c42SDr. David Alan Gilbert 
2515093e3c42SDr. David Alan Gilbert     case MIG_CMD_POSTCOPY_LISTEN:
2516093e3c42SDr. David Alan Gilbert         return loadvm_postcopy_handle_listen(mis);
2517093e3c42SDr. David Alan Gilbert 
2518093e3c42SDr. David Alan Gilbert     case MIG_CMD_POSTCOPY_RUN:
2519093e3c42SDr. David Alan Gilbert         return loadvm_postcopy_handle_run(mis);
2520093e3c42SDr. David Alan Gilbert 
2521093e3c42SDr. David Alan Gilbert     case MIG_CMD_POSTCOPY_RAM_DISCARD:
2522093e3c42SDr. David Alan Gilbert         return loadvm_postcopy_ram_handle_discard(mis, len);
2523f25d4225SPeter Xu 
25243f5875ecSPeter Xu     case MIG_CMD_POSTCOPY_RESUME:
25253f5875ecSPeter Xu         return loadvm_postcopy_handle_resume(mis);
25263f5875ecSPeter Xu 
2527f25d4225SPeter Xu     case MIG_CMD_RECV_BITMAP:
2528f25d4225SPeter Xu         return loadvm_handle_recv_bitmap(mis, len);
2529aad555c2SZhang Chen 
2530aad555c2SZhang Chen     case MIG_CMD_ENABLE_COLO:
2531aad555c2SZhang Chen         return loadvm_process_enable_colo(mis);
2532c76ca188SDr. David Alan Gilbert     }
2533c76ca188SDr. David Alan Gilbert 
2534c76ca188SDr. David Alan Gilbert     return 0;
2535c76ca188SDr. David Alan Gilbert }
2536c76ca188SDr. David Alan Gilbert 
253759f39a47SDr. David Alan Gilbert /*
253859f39a47SDr. David Alan Gilbert  * Read a footer off the wire and check that it matches the expected section
253959f39a47SDr. David Alan Gilbert  *
254059f39a47SDr. David Alan Gilbert  * Returns: true if the footer was good
254159f39a47SDr. David Alan Gilbert  *          false if there is a problem (and calls error_report to say why)
254259f39a47SDr. David Alan Gilbert  */
check_section_footer(QEMUFile * f,SaveStateEntry * se)25430f42f657SJuan Quintela static bool check_section_footer(QEMUFile *f, SaveStateEntry *se)
254459f39a47SDr. David Alan Gilbert {
25457a9ddfbfSPeter Xu     int ret;
254659f39a47SDr. David Alan Gilbert     uint8_t read_mark;
254759f39a47SDr. David Alan Gilbert     uint32_t read_section_id;
254859f39a47SDr. David Alan Gilbert 
254915c38503SPeter Xu     if (!migrate_get_current()->send_section_footer) {
255059f39a47SDr. David Alan Gilbert         /* No footer to check */
255159f39a47SDr. David Alan Gilbert         return true;
255259f39a47SDr. David Alan Gilbert     }
255359f39a47SDr. David Alan Gilbert 
255459f39a47SDr. David Alan Gilbert     read_mark = qemu_get_byte(f);
255559f39a47SDr. David Alan Gilbert 
25567a9ddfbfSPeter Xu     ret = qemu_file_get_error(f);
25577a9ddfbfSPeter Xu     if (ret) {
25587a9ddfbfSPeter Xu         error_report("%s: Read section footer failed: %d",
25597a9ddfbfSPeter Xu                      __func__, ret);
25607a9ddfbfSPeter Xu         return false;
25617a9ddfbfSPeter Xu     }
25627a9ddfbfSPeter Xu 
256359f39a47SDr. David Alan Gilbert     if (read_mark != QEMU_VM_SECTION_FOOTER) {
25640f42f657SJuan Quintela         error_report("Missing section footer for %s", se->idstr);
256559f39a47SDr. David Alan Gilbert         return false;
256659f39a47SDr. David Alan Gilbert     }
256759f39a47SDr. David Alan Gilbert 
256859f39a47SDr. David Alan Gilbert     read_section_id = qemu_get_be32(f);
25690f42f657SJuan Quintela     if (read_section_id != se->load_section_id) {
257059f39a47SDr. David Alan Gilbert         error_report("Mismatched section id in footer for %s -"
257159f39a47SDr. David Alan Gilbert                      " read 0x%x expected 0x%x",
25720f42f657SJuan Quintela                      se->idstr, read_section_id, se->load_section_id);
257359f39a47SDr. David Alan Gilbert         return false;
257459f39a47SDr. David Alan Gilbert     }
257559f39a47SDr. David Alan Gilbert 
257659f39a47SDr. David Alan Gilbert     /* All good */
257759f39a47SDr. David Alan Gilbert     return true;
257859f39a47SDr. David Alan Gilbert }
257959f39a47SDr. David Alan Gilbert 
2580fb3520a8Szhanghailiang static int
qemu_loadvm_section_start_full(QEMUFile * f,MigrationIncomingState * mis,uint8_t type)25813c80f142SPeter Xu qemu_loadvm_section_start_full(QEMUFile *f, MigrationIncomingState *mis,
25823c80f142SPeter Xu                                uint8_t type)
25837b89bf27SDr. David Alan Gilbert {
25843c80f142SPeter Xu     bool trace_downtime = (type == QEMU_VM_SECTION_FULL);
25857b89bf27SDr. David Alan Gilbert     uint32_t instance_id, version_id, section_id;
25863c80f142SPeter Xu     int64_t start_ts, end_ts;
25877b89bf27SDr. David Alan Gilbert     SaveStateEntry *se;
25887b89bf27SDr. David Alan Gilbert     char idstr[256];
2589fb3520a8Szhanghailiang     int ret;
25907b89bf27SDr. David Alan Gilbert 
25917b89bf27SDr. David Alan Gilbert     /* Read section start */
25927b89bf27SDr. David Alan Gilbert     section_id = qemu_get_be32(f);
25937b89bf27SDr. David Alan Gilbert     if (!qemu_get_counted_string(f, idstr)) {
25947b89bf27SDr. David Alan Gilbert         error_report("Unable to read ID string for section %u",
25957b89bf27SDr. David Alan Gilbert                      section_id);
25967b89bf27SDr. David Alan Gilbert         return -EINVAL;
25977b89bf27SDr. David Alan Gilbert     }
25987b89bf27SDr. David Alan Gilbert     instance_id = qemu_get_be32(f);
25997b89bf27SDr. David Alan Gilbert     version_id = qemu_get_be32(f);
26007b89bf27SDr. David Alan Gilbert 
26017a9ddfbfSPeter Xu     ret = qemu_file_get_error(f);
26027a9ddfbfSPeter Xu     if (ret) {
26037a9ddfbfSPeter Xu         error_report("%s: Failed to read instance/version ID: %d",
26047a9ddfbfSPeter Xu                      __func__, ret);
26057a9ddfbfSPeter Xu         return ret;
26067a9ddfbfSPeter Xu     }
26077a9ddfbfSPeter Xu 
26087b89bf27SDr. David Alan Gilbert     trace_qemu_loadvm_state_section_startfull(section_id, idstr,
26097b89bf27SDr. David Alan Gilbert             instance_id, version_id);
26107b89bf27SDr. David Alan Gilbert     /* Find savevm section */
26117b89bf27SDr. David Alan Gilbert     se = find_se(idstr, instance_id);
26127b89bf27SDr. David Alan Gilbert     if (se == NULL) {
261393062e23SPeter Xu         error_report("Unknown savevm section or instance '%s' %"PRIu32". "
2614827beacbSJose Ricardo Ziviani                      "Make sure that your current VM setup matches your "
2615827beacbSJose Ricardo Ziviani                      "saved VM setup, including any hotplugged devices",
26167b89bf27SDr. David Alan Gilbert                      idstr, instance_id);
26177b89bf27SDr. David Alan Gilbert         return -EINVAL;
26187b89bf27SDr. David Alan Gilbert     }
26197b89bf27SDr. David Alan Gilbert 
26207b89bf27SDr. David Alan Gilbert     /* Validate version */
26217b89bf27SDr. David Alan Gilbert     if (version_id > se->version_id) {
26227b89bf27SDr. David Alan Gilbert         error_report("savevm: unsupported version %d for '%s' v%d",
26237b89bf27SDr. David Alan Gilbert                      version_id, idstr, se->version_id);
26247b89bf27SDr. David Alan Gilbert         return -EINVAL;
26257b89bf27SDr. David Alan Gilbert     }
26260f42f657SJuan Quintela     se->load_version_id = version_id;
26270f42f657SJuan Quintela     se->load_section_id = section_id;
26287b89bf27SDr. David Alan Gilbert 
262988c16567SWen Congyang     /* Validate if it is a device's state */
263088c16567SWen Congyang     if (xen_enabled() && se->is_ram) {
263188c16567SWen Congyang         error_report("loadvm: %s RAM loading not allowed on Xen", idstr);
263288c16567SWen Congyang         return -EINVAL;
263388c16567SWen Congyang     }
263488c16567SWen Congyang 
26353c80f142SPeter Xu     if (trace_downtime) {
26363c80f142SPeter Xu         start_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
26373c80f142SPeter Xu     }
26383c80f142SPeter Xu 
26393a011c26SJuan Quintela     ret = vmstate_load(f, se);
26407b89bf27SDr. David Alan Gilbert     if (ret < 0) {
264193062e23SPeter Xu         error_report("error while loading state for instance 0x%"PRIx32" of"
26427b89bf27SDr. David Alan Gilbert                      " device '%s'", instance_id, idstr);
26437b89bf27SDr. David Alan Gilbert         return ret;
26447b89bf27SDr. David Alan Gilbert     }
26453c80f142SPeter Xu 
26463c80f142SPeter Xu     if (trace_downtime) {
26473c80f142SPeter Xu         end_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
26483c80f142SPeter Xu         trace_vmstate_downtime_load("non-iterable", se->idstr,
26493c80f142SPeter Xu                                     se->instance_id, end_ts - start_ts);
26503c80f142SPeter Xu     }
26513c80f142SPeter Xu 
26520f42f657SJuan Quintela     if (!check_section_footer(f, se)) {
26537b89bf27SDr. David Alan Gilbert         return -EINVAL;
26547b89bf27SDr. David Alan Gilbert     }
2655fb3520a8Szhanghailiang 
2656fb3520a8Szhanghailiang     return 0;
2657fb3520a8Szhanghailiang }
2658fb3520a8Szhanghailiang 
2659fb3520a8Szhanghailiang static int
qemu_loadvm_section_part_end(QEMUFile * f,MigrationIncomingState * mis,uint8_t type)26603c80f142SPeter Xu qemu_loadvm_section_part_end(QEMUFile *f, MigrationIncomingState *mis,
26613c80f142SPeter Xu                              uint8_t type)
2662fb3520a8Szhanghailiang {
26633c80f142SPeter Xu     bool trace_downtime = (type == QEMU_VM_SECTION_END);
26643c80f142SPeter Xu     int64_t start_ts, end_ts;
2665fb3520a8Szhanghailiang     uint32_t section_id;
26660f42f657SJuan Quintela     SaveStateEntry *se;
2667fb3520a8Szhanghailiang     int ret;
2668fb3520a8Szhanghailiang 
26697b89bf27SDr. David Alan Gilbert     section_id = qemu_get_be32(f);
26707b89bf27SDr. David Alan Gilbert 
26717a9ddfbfSPeter Xu     ret = qemu_file_get_error(f);
26727a9ddfbfSPeter Xu     if (ret) {
26737a9ddfbfSPeter Xu         error_report("%s: Failed to read section ID: %d",
26747a9ddfbfSPeter Xu                      __func__, ret);
26757a9ddfbfSPeter Xu         return ret;
26767a9ddfbfSPeter Xu     }
26777a9ddfbfSPeter Xu 
26787b89bf27SDr. David Alan Gilbert     trace_qemu_loadvm_state_section_partend(section_id);
26790f42f657SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
26800f42f657SJuan Quintela         if (se->load_section_id == section_id) {
26817b89bf27SDr. David Alan Gilbert             break;
26827b89bf27SDr. David Alan Gilbert         }
26837b89bf27SDr. David Alan Gilbert     }
26840f42f657SJuan Quintela     if (se == NULL) {
26857b89bf27SDr. David Alan Gilbert         error_report("Unknown savevm section %d", section_id);
26867b89bf27SDr. David Alan Gilbert         return -EINVAL;
26877b89bf27SDr. David Alan Gilbert     }
26887b89bf27SDr. David Alan Gilbert 
26893c80f142SPeter Xu     if (trace_downtime) {
26903c80f142SPeter Xu         start_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
26913c80f142SPeter Xu     }
26923c80f142SPeter Xu 
26933a011c26SJuan Quintela     ret = vmstate_load(f, se);
26947b89bf27SDr. David Alan Gilbert     if (ret < 0) {
26957b89bf27SDr. David Alan Gilbert         error_report("error while loading state section id %d(%s)",
26960f42f657SJuan Quintela                      section_id, se->idstr);
26977b89bf27SDr. David Alan Gilbert         return ret;
26987b89bf27SDr. David Alan Gilbert     }
26993c80f142SPeter Xu 
27003c80f142SPeter Xu     if (trace_downtime) {
27013c80f142SPeter Xu         end_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
27023c80f142SPeter Xu         trace_vmstate_downtime_load("iterable", se->idstr,
27033c80f142SPeter Xu                                     se->instance_id, end_ts - start_ts);
27043c80f142SPeter Xu     }
27053c80f142SPeter Xu 
27060f42f657SJuan Quintela     if (!check_section_footer(f, se)) {
27077b89bf27SDr. David Alan Gilbert         return -EINVAL;
27087b89bf27SDr. David Alan Gilbert     }
2709fb3520a8Szhanghailiang 
2710fb3520a8Szhanghailiang     return 0;
2711fb3520a8Szhanghailiang }
2712fb3520a8Szhanghailiang 
qemu_loadvm_state_header(QEMUFile * f)271316015d32SWei Yang static int qemu_loadvm_state_header(QEMUFile *f)
271416015d32SWei Yang {
271516015d32SWei Yang     unsigned int v;
271616015d32SWei Yang     int ret;
271716015d32SWei Yang 
271816015d32SWei Yang     v = qemu_get_be32(f);
271916015d32SWei Yang     if (v != QEMU_VM_FILE_MAGIC) {
272016015d32SWei Yang         error_report("Not a migration stream");
272116015d32SWei Yang         return -EINVAL;
272216015d32SWei Yang     }
272316015d32SWei Yang 
272416015d32SWei Yang     v = qemu_get_be32(f);
272516015d32SWei Yang     if (v == QEMU_VM_FILE_VERSION_COMPAT) {
272616015d32SWei Yang         error_report("SaveVM v2 format is obsolete and don't work anymore");
272716015d32SWei Yang         return -ENOTSUP;
272816015d32SWei Yang     }
272916015d32SWei Yang     if (v != QEMU_VM_FILE_VERSION) {
273016015d32SWei Yang         error_report("Unsupported migration stream version");
273116015d32SWei Yang         return -ENOTSUP;
273216015d32SWei Yang     }
273316015d32SWei Yang 
273416015d32SWei Yang     if (migrate_get_current()->send_configuration) {
273516015d32SWei Yang         if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
273616015d32SWei Yang             error_report("Configuration section missing");
273716015d32SWei Yang             qemu_loadvm_state_cleanup();
273816015d32SWei Yang             return -EINVAL;
273916015d32SWei Yang         }
274016015d32SWei Yang         ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0);
274116015d32SWei Yang 
274216015d32SWei Yang         if (ret) {
274316015d32SWei Yang             qemu_loadvm_state_cleanup();
274416015d32SWei Yang             return ret;
274516015d32SWei Yang         }
274616015d32SWei Yang     }
274716015d32SWei Yang     return 0;
274816015d32SWei Yang }
274916015d32SWei Yang 
qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState * mis)27501b4adb10SAvihai Horon static void qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState *mis)
27511b4adb10SAvihai Horon {
27521b4adb10SAvihai Horon     SaveStateEntry *se;
27531b4adb10SAvihai Horon 
27541b4adb10SAvihai Horon     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
27551b4adb10SAvihai Horon         if (!se->ops || !se->ops->switchover_ack_needed) {
27561b4adb10SAvihai Horon             continue;
27571b4adb10SAvihai Horon         }
27581b4adb10SAvihai Horon 
27591b4adb10SAvihai Horon         if (se->ops->switchover_ack_needed(se->opaque)) {
27601b4adb10SAvihai Horon             mis->switchover_ack_pending_num++;
27611b4adb10SAvihai Horon         }
27621b4adb10SAvihai Horon     }
27631b4adb10SAvihai Horon 
27641b4adb10SAvihai Horon     trace_loadvm_state_switchover_ack_needed(mis->switchover_ack_pending_num);
27651b4adb10SAvihai Horon }
27661b4adb10SAvihai Horon 
qemu_loadvm_state_setup(QEMUFile * f,Error ** errp)2767e4fa064dSCédric Le Goater static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp)
2768acb5ea86SJuan Quintela {
2769e4fa064dSCédric Le Goater     ERRP_GUARD();
2770acb5ea86SJuan Quintela     SaveStateEntry *se;
2771acb5ea86SJuan Quintela     int ret;
2772acb5ea86SJuan Quintela 
2773acb5ea86SJuan Quintela     trace_loadvm_state_setup();
2774acb5ea86SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
2775acb5ea86SJuan Quintela         if (!se->ops || !se->ops->load_setup) {
2776acb5ea86SJuan Quintela             continue;
2777acb5ea86SJuan Quintela         }
2778cea3b4c0SWei Yang         if (se->ops->is_active) {
2779acb5ea86SJuan Quintela             if (!se->ops->is_active(se->opaque)) {
2780acb5ea86SJuan Quintela                 continue;
2781acb5ea86SJuan Quintela             }
2782acb5ea86SJuan Quintela         }
2783acb5ea86SJuan Quintela 
2784e4fa064dSCédric Le Goater         ret = se->ops->load_setup(f, se->opaque, errp);
2785acb5ea86SJuan Quintela         if (ret < 0) {
2786e4fa064dSCédric Le Goater             error_prepend(errp, "Load state of device %s failed: ",
2787e4fa064dSCédric Le Goater                           se->idstr);
2788acb5ea86SJuan Quintela             qemu_file_set_error(f, ret);
2789acb5ea86SJuan Quintela             return ret;
2790acb5ea86SJuan Quintela         }
2791acb5ea86SJuan Quintela     }
2792acb5ea86SJuan Quintela     return 0;
2793acb5ea86SJuan Quintela }
2794acb5ea86SJuan Quintela 
qemu_loadvm_state_cleanup(void)2795acb5ea86SJuan Quintela void qemu_loadvm_state_cleanup(void)
2796acb5ea86SJuan Quintela {
2797acb5ea86SJuan Quintela     SaveStateEntry *se;
2798acb5ea86SJuan Quintela 
2799acb5ea86SJuan Quintela     trace_loadvm_state_cleanup();
2800acb5ea86SJuan Quintela     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
2801acb5ea86SJuan Quintela         if (se->ops && se->ops->load_cleanup) {
2802acb5ea86SJuan Quintela             se->ops->load_cleanup(se->opaque);
2803acb5ea86SJuan Quintela         }
2804acb5ea86SJuan Quintela     }
2805acb5ea86SJuan Quintela }
2806acb5ea86SJuan Quintela 
2807b411b844SPeter Xu /* Return true if we should continue the migration, or false. */
postcopy_pause_incoming(MigrationIncomingState * mis)2808b411b844SPeter Xu static bool postcopy_pause_incoming(MigrationIncomingState *mis)
2809b411b844SPeter Xu {
281077dadc3fSPeter Xu     int i;
281177dadc3fSPeter Xu 
2812b411b844SPeter Xu     trace_postcopy_pause_incoming();
2813b411b844SPeter Xu 
2814ee647225SVladimir Sementsov-Ogievskiy     assert(migrate_postcopy_ram());
2815ee647225SVladimir Sementsov-Ogievskiy 
281639675fffSPeter Xu     /*
281739675fffSPeter Xu      * Unregister yank with either from/to src would work, since ioc behind it
281839675fffSPeter Xu      * is the same
281939675fffSPeter Xu      */
282039675fffSPeter Xu     migration_ioc_unregister_yank_from_file(mis->from_src_file);
282139675fffSPeter Xu 
2822b411b844SPeter Xu     assert(mis->from_src_file);
2823b411b844SPeter Xu     qemu_file_shutdown(mis->from_src_file);
2824b411b844SPeter Xu     qemu_fclose(mis->from_src_file);
2825b411b844SPeter Xu     mis->from_src_file = NULL;
2826b411b844SPeter Xu 
2827b411b844SPeter Xu     assert(mis->to_src_file);
2828b411b844SPeter Xu     qemu_file_shutdown(mis->to_src_file);
2829b411b844SPeter Xu     qemu_mutex_lock(&mis->rp_mutex);
2830b411b844SPeter Xu     qemu_fclose(mis->to_src_file);
2831b411b844SPeter Xu     mis->to_src_file = NULL;
2832b411b844SPeter Xu     qemu_mutex_unlock(&mis->rp_mutex);
2833b411b844SPeter Xu 
283460bb3c58SPeter Xu     /*
283560bb3c58SPeter Xu      * NOTE: this must happen before reset the PostcopyTmpPages below,
283660bb3c58SPeter Xu      * otherwise it's racy to reset those fields when the fast load thread
283760bb3c58SPeter Xu      * can be accessing it in parallel.
283860bb3c58SPeter Xu      */
283960bb3c58SPeter Xu     if (mis->postcopy_qemufile_dst) {
284060bb3c58SPeter Xu         qemu_file_shutdown(mis->postcopy_qemufile_dst);
284160bb3c58SPeter Xu         /* Take the mutex to make sure the fast ram load thread halted */
284260bb3c58SPeter Xu         qemu_mutex_lock(&mis->postcopy_prio_thread_mutex);
284360bb3c58SPeter Xu         migration_ioc_unregister_yank_from_file(mis->postcopy_qemufile_dst);
284460bb3c58SPeter Xu         qemu_fclose(mis->postcopy_qemufile_dst);
284560bb3c58SPeter Xu         mis->postcopy_qemufile_dst = NULL;
284660bb3c58SPeter Xu         qemu_mutex_unlock(&mis->postcopy_prio_thread_mutex);
284760bb3c58SPeter Xu     }
284860bb3c58SPeter Xu 
28490e99bb8fSPeter Xu     /* Current state can be either ACTIVE or RECOVER */
28500e99bb8fSPeter Xu     migrate_set_state(&mis->state, mis->state,
2851eed1cc78SPeter Xu                       MIGRATION_STATUS_POSTCOPY_PAUSED);
2852eed1cc78SPeter Xu 
28533a7804c3SPeter Xu     /* Notify the fault thread for the invalidated file handle */
28543a7804c3SPeter Xu     postcopy_fault_thread_notify(mis);
28553a7804c3SPeter Xu 
285636f62f11SPeter Xu     /*
285736f62f11SPeter Xu      * If network is interrupted, any temp page we received will be useless
285836f62f11SPeter Xu      * because we didn't mark them as "received" in receivedmap.  After a
285936f62f11SPeter Xu      * proper recovery later (which will sync src dirty bitmap with receivedmap
286036f62f11SPeter Xu      * on dest) these cached small pages will be resent again.
286136f62f11SPeter Xu      */
286236f62f11SPeter Xu     for (i = 0; i < mis->postcopy_channels; i++) {
286336f62f11SPeter Xu         postcopy_temp_page_reset(&mis->postcopy_tmp_pages[i]);
286436f62f11SPeter Xu     }
286536f62f11SPeter Xu 
2866b411b844SPeter Xu     error_report("Detected IO failure for postcopy. "
2867b411b844SPeter Xu                  "Migration paused.");
2868b411b844SPeter Xu 
28694146b77eSPeter Xu     do {
2870b411b844SPeter Xu         qemu_sem_wait(&mis->postcopy_pause_sem_dst);
28714146b77eSPeter Xu     } while (postcopy_is_paused(mis->state));
2872b411b844SPeter Xu 
2873b411b844SPeter Xu     trace_postcopy_pause_incoming_continued();
2874b411b844SPeter Xu 
2875b411b844SPeter Xu     return true;
2876b411b844SPeter Xu }
2877b411b844SPeter Xu 
qemu_loadvm_state_main(QEMUFile * f,MigrationIncomingState * mis)28783f6df99dSZhang Chen int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis)
2879fb3520a8Szhanghailiang {
2880fb3520a8Szhanghailiang     uint8_t section_type;
2881ccb783c3SDr. David Alan Gilbert     int ret = 0;
2882fb3520a8Szhanghailiang 
2883b411b844SPeter Xu retry:
28847a9ddfbfSPeter Xu     while (true) {
28857a9ddfbfSPeter Xu         section_type = qemu_get_byte(f);
28867a9ddfbfSPeter Xu 
288760bb3c58SPeter Xu         ret = qemu_file_get_error_obj_any(f, mis->postcopy_qemufile_dst, NULL);
288860bb3c58SPeter Xu         if (ret) {
28897a9ddfbfSPeter Xu             break;
28907a9ddfbfSPeter Xu         }
28917a9ddfbfSPeter Xu 
2892fb3520a8Szhanghailiang         trace_qemu_loadvm_state_section(section_type);
2893fb3520a8Szhanghailiang         switch (section_type) {
2894fb3520a8Szhanghailiang         case QEMU_VM_SECTION_START:
2895fb3520a8Szhanghailiang         case QEMU_VM_SECTION_FULL:
28963c80f142SPeter Xu             ret = qemu_loadvm_section_start_full(f, mis, section_type);
2897fb3520a8Szhanghailiang             if (ret < 0) {
2898ccb783c3SDr. David Alan Gilbert                 goto out;
2899fb3520a8Szhanghailiang             }
2900fb3520a8Szhanghailiang             break;
2901fb3520a8Szhanghailiang         case QEMU_VM_SECTION_PART:
2902fb3520a8Szhanghailiang         case QEMU_VM_SECTION_END:
29033c80f142SPeter Xu             ret = qemu_loadvm_section_part_end(f, mis, section_type);
2904fb3520a8Szhanghailiang             if (ret < 0) {
2905ccb783c3SDr. David Alan Gilbert                 goto out;
2906fb3520a8Szhanghailiang             }
29077b89bf27SDr. David Alan Gilbert             break;
29087b89bf27SDr. David Alan Gilbert         case QEMU_VM_COMMAND:
29097b89bf27SDr. David Alan Gilbert             ret = loadvm_process_command(f);
29107b89bf27SDr. David Alan Gilbert             trace_qemu_loadvm_state_section_command(ret);
29114695ce3fSWei Yang             if ((ret < 0) || (ret == LOADVM_QUIT)) {
2912ccb783c3SDr. David Alan Gilbert                 goto out;
29137b89bf27SDr. David Alan Gilbert             }
29147b89bf27SDr. David Alan Gilbert             break;
29157a9ddfbfSPeter Xu         case QEMU_VM_EOF:
29167a9ddfbfSPeter Xu             /* This is the end of migration */
29177a9ddfbfSPeter Xu             goto out;
29187b89bf27SDr. David Alan Gilbert         default:
29197b89bf27SDr. David Alan Gilbert             error_report("Unknown savevm section type %d", section_type);
2920ccb783c3SDr. David Alan Gilbert             ret = -EINVAL;
2921ccb783c3SDr. David Alan Gilbert             goto out;
29227b89bf27SDr. David Alan Gilbert         }
29237b89bf27SDr. David Alan Gilbert     }
29247b89bf27SDr. David Alan Gilbert 
2925ccb783c3SDr. David Alan Gilbert out:
2926ccb783c3SDr. David Alan Gilbert     if (ret < 0) {
2927ccb783c3SDr. David Alan Gilbert         qemu_file_set_error(f, ret);
2928b411b844SPeter Xu 
2929ee647225SVladimir Sementsov-Ogievskiy         /* Cancel bitmaps incoming regardless of recovery */
2930ee647225SVladimir Sementsov-Ogievskiy         dirty_bitmap_mig_cancel_incoming();
2931ee647225SVladimir Sementsov-Ogievskiy 
2932b411b844SPeter Xu         /*
2933fd037a65SPeter Xu          * If we are during an active postcopy, then we pause instead
2934fd037a65SPeter Xu          * of bail out to at least keep the VM's dirty data.  Note
2935fd037a65SPeter Xu          * that POSTCOPY_INCOMING_LISTENING stage is still not enough,
2936fd037a65SPeter Xu          * during which we're still receiving device states and we
2937fd037a65SPeter Xu          * still haven't yet started the VM on destination.
2938ee647225SVladimir Sementsov-Ogievskiy          *
2939ee647225SVladimir Sementsov-Ogievskiy          * Only RAM postcopy supports recovery. Still, if RAM postcopy is
2940ee647225SVladimir Sementsov-Ogievskiy          * enabled, canceled bitmaps postcopy will not affect RAM postcopy
2941ee647225SVladimir Sementsov-Ogievskiy          * recovering.
2942b411b844SPeter Xu          */
2943b411b844SPeter Xu         if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING &&
2944ee647225SVladimir Sementsov-Ogievskiy             migrate_postcopy_ram() && postcopy_pause_incoming(mis)) {
2945b411b844SPeter Xu             /* Reset f to point to the newly created channel */
2946b411b844SPeter Xu             f = mis->from_src_file;
2947b411b844SPeter Xu             goto retry;
2948b411b844SPeter Xu         }
2949ccb783c3SDr. David Alan Gilbert     }
2950ccb783c3SDr. David Alan Gilbert     return ret;
29517b89bf27SDr. David Alan Gilbert }
29527b89bf27SDr. David Alan Gilbert 
qemu_loadvm_state(QEMUFile * f)2953c3049a56SJuan Quintela int qemu_loadvm_state(QEMUFile *f)
2954c3049a56SJuan Quintela {
29551a8f46f8SDr. David Alan Gilbert     MigrationIncomingState *mis = migration_incoming_get_current();
2956c3049a56SJuan Quintela     Error *local_err = NULL;
2957c3049a56SJuan Quintela     int ret;
2958c3049a56SJuan Quintela 
2959c3049a56SJuan Quintela     if (qemu_savevm_state_blocked(&local_err)) {
2960c3049a56SJuan Quintela         error_report_err(local_err);
2961c3049a56SJuan Quintela         return -EINVAL;
2962c3049a56SJuan Quintela     }
2963c3049a56SJuan Quintela 
296416015d32SWei Yang     ret = qemu_loadvm_state_header(f);
296561964c23SJuan Quintela     if (ret) {
296661964c23SJuan Quintela         return ret;
296761964c23SJuan Quintela     }
296861964c23SJuan Quintela 
2969e4fa064dSCédric Le Goater     if (qemu_loadvm_state_setup(f, &local_err) != 0) {
2970e4fa064dSCédric Le Goater         error_report_err(local_err);
29719e14b849SWei Yang         return -EINVAL;
29729e14b849SWei Yang     }
29739e14b849SWei Yang 
29741b4adb10SAvihai Horon     if (migrate_switchover_ack()) {
29751b4adb10SAvihai Horon         qemu_loadvm_state_switchover_ack_needed(mis);
29761b4adb10SAvihai Horon     }
29771b4adb10SAvihai Horon 
297875e972daSDavid Gibson     cpu_synchronize_all_pre_loadvm();
297975e972daSDavid Gibson 
29807b89bf27SDr. David Alan Gilbert     ret = qemu_loadvm_state_main(f, mis);
29817b89bf27SDr. David Alan Gilbert     qemu_event_set(&mis->main_thread_load_event);
2982c3049a56SJuan Quintela 
29837b89bf27SDr. David Alan Gilbert     trace_qemu_loadvm_state_post_main(ret);
2984c3049a56SJuan Quintela 
2985c76201abSDr. David Alan Gilbert     if (mis->have_listen_thread) {
2986c76201abSDr. David Alan Gilbert         /* Listen thread still going, can't clean up yet */
2987c76201abSDr. David Alan Gilbert         return ret;
2988c76201abSDr. David Alan Gilbert     }
2989c76201abSDr. David Alan Gilbert 
29907b89bf27SDr. David Alan Gilbert     if (ret == 0) {
29917b89bf27SDr. David Alan Gilbert         ret = qemu_file_get_error(f);
2992c3049a56SJuan Quintela     }
2993c3049a56SJuan Quintela 
2994c3049a56SJuan Quintela     /*
2995c3049a56SJuan Quintela      * Try to read in the VMDESC section as well, so that dumping tools that
2996c3049a56SJuan Quintela      * intercept our migration stream have the chance to see it.
2997c3049a56SJuan Quintela      */
29981aca9a5fSDr. David Alan Gilbert 
29991aca9a5fSDr. David Alan Gilbert     /* We've got to be careful; if we don't read the data and just shut the fd
30001aca9a5fSDr. David Alan Gilbert      * then the sender can error if we close while it's still sending.
30011aca9a5fSDr. David Alan Gilbert      * We also mustn't read data that isn't there; some transports (RDMA)
30021aca9a5fSDr. David Alan Gilbert      * will stall waiting for that data when the source has already closed.
30031aca9a5fSDr. David Alan Gilbert      */
30047b89bf27SDr. David Alan Gilbert     if (ret == 0 && should_send_vmdesc()) {
30051aca9a5fSDr. David Alan Gilbert         uint8_t *buf;
30061aca9a5fSDr. David Alan Gilbert         uint32_t size;
30077b89bf27SDr. David Alan Gilbert         uint8_t  section_type = qemu_get_byte(f);
30081aca9a5fSDr. David Alan Gilbert 
30091aca9a5fSDr. David Alan Gilbert         if (section_type != QEMU_VM_VMDESCRIPTION) {
30101aca9a5fSDr. David Alan Gilbert             error_report("Expected vmdescription section, but got %d",
30111aca9a5fSDr. David Alan Gilbert                          section_type);
30121aca9a5fSDr. David Alan Gilbert             /*
30131aca9a5fSDr. David Alan Gilbert              * It doesn't seem worth failing at this point since
30141aca9a5fSDr. David Alan Gilbert              * we apparently have an otherwise valid VM state
30151aca9a5fSDr. David Alan Gilbert              */
30161aca9a5fSDr. David Alan Gilbert         } else {
30171aca9a5fSDr. David Alan Gilbert             buf = g_malloc(0x1000);
30181aca9a5fSDr. David Alan Gilbert             size = qemu_get_be32(f);
3019c3049a56SJuan Quintela 
3020c3049a56SJuan Quintela             while (size > 0) {
3021c3049a56SJuan Quintela                 uint32_t read_chunk = MIN(size, 0x1000);
3022c3049a56SJuan Quintela                 qemu_get_buffer(f, buf, read_chunk);
3023c3049a56SJuan Quintela                 size -= read_chunk;
3024c3049a56SJuan Quintela             }
3025c3049a56SJuan Quintela             g_free(buf);
3026c3049a56SJuan Quintela         }
30271aca9a5fSDr. David Alan Gilbert     }
3028c3049a56SJuan Quintela 
3029acb5ea86SJuan Quintela     qemu_loadvm_state_cleanup();
3030c3049a56SJuan Quintela     cpu_synchronize_all_post_init();
3031c3049a56SJuan Quintela 
3032c3049a56SJuan Quintela     return ret;
3033c3049a56SJuan Quintela }
3034c3049a56SJuan Quintela 
qemu_load_device_state(QEMUFile * f)30353f6df99dSZhang Chen int qemu_load_device_state(QEMUFile *f)
30363f6df99dSZhang Chen {
30373f6df99dSZhang Chen     MigrationIncomingState *mis = migration_incoming_get_current();
30383f6df99dSZhang Chen     int ret;
30393f6df99dSZhang Chen 
30403f6df99dSZhang Chen     /* Load QEMU_VM_SECTION_FULL section */
30413f6df99dSZhang Chen     ret = qemu_loadvm_state_main(f, mis);
30423f6df99dSZhang Chen     if (ret < 0) {
30433f6df99dSZhang Chen         error_report("Failed to load device state: %d", ret);
30443f6df99dSZhang Chen         return ret;
30453f6df99dSZhang Chen     }
30463f6df99dSZhang Chen 
30473f6df99dSZhang Chen     cpu_synchronize_all_post_init();
30483f6df99dSZhang Chen     return 0;
30493f6df99dSZhang Chen }
30503f6df99dSZhang Chen 
qemu_loadvm_approve_switchover(void)30511b4adb10SAvihai Horon int qemu_loadvm_approve_switchover(void)
30521b4adb10SAvihai Horon {
30531b4adb10SAvihai Horon     MigrationIncomingState *mis = migration_incoming_get_current();
30541b4adb10SAvihai Horon 
30551b4adb10SAvihai Horon     if (!mis->switchover_ack_pending_num) {
30561b4adb10SAvihai Horon         return -EINVAL;
30571b4adb10SAvihai Horon     }
30581b4adb10SAvihai Horon 
30591b4adb10SAvihai Horon     mis->switchover_ack_pending_num--;
30601b4adb10SAvihai Horon     trace_loadvm_approve_switchover(mis->switchover_ack_pending_num);
30611b4adb10SAvihai Horon 
30621b4adb10SAvihai Horon     if (mis->switchover_ack_pending_num) {
30631b4adb10SAvihai Horon         return 0;
30641b4adb10SAvihai Horon     }
30651b4adb10SAvihai Horon 
30661b4adb10SAvihai Horon     return migrate_send_rp_switchover_ack(mis);
30671b4adb10SAvihai Horon }
30681b4adb10SAvihai Horon 
save_snapshot(const char * name,bool overwrite,const char * vmstate,bool has_devices,strList * devices,Error ** errp)3069f1a9fcddSDaniel P. Berrangé bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
3070f1a9fcddSDaniel P. Berrangé                   bool has_devices, strList *devices, Error **errp)
3071c3049a56SJuan Quintela {
3072e26f98e2SDaniel P. Berrangé     BlockDriverState *bs;
307380ef0586STuguoyi     QEMUSnapshotInfo sn1, *sn = &sn1;
307466270a47SDenis V. Lunev     int ret = -1, ret2;
3075c3049a56SJuan Quintela     QEMUFile *f;
307658b10570SSteve Sistare     RunState saved_state = runstate_get();
3077c3049a56SJuan Quintela     uint64_t vm_state_size;
307885cd1cc6SDaniel P. Berrangé     g_autoptr(GDateTime) now = g_date_time_new_now_local();
3079c3049a56SJuan Quintela 
30806b573efeSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
30816b573efeSEmanuele Giuseppe Esposito 
30825aaac467SPaolo Bonzini     if (migration_is_blocked(errp)) {
30837ea14df2SPhilippe Mathieu-Daudé         return false;
30845aaac467SPaolo Bonzini     }
30855aaac467SPaolo Bonzini 
3086377b21ccSPavel Dovgalyuk     if (!replay_can_snapshot()) {
30874dd32b3dSMarkus Armbruster         error_setg(errp, "Record/replay does not allow making snapshot "
3088377b21ccSPavel Dovgalyuk                    "right now. Try once more later.");
30897ea14df2SPhilippe Mathieu-Daudé         return false;
3090377b21ccSPavel Dovgalyuk     }
3091377b21ccSPavel Dovgalyuk 
3092f1a9fcddSDaniel P. Berrangé     if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
30937ea14df2SPhilippe Mathieu-Daudé         return false;
3094c3049a56SJuan Quintela     }
3095c3049a56SJuan Quintela 
30960b461605SDenis V. Lunev     /* Delete old snapshots of the same name */
3097ac8c19baSPavel Dovgalyuk     if (name) {
3098f781f841SDaniel P. Berrangé         if (overwrite) {
3099f1a9fcddSDaniel P. Berrangé             if (bdrv_all_delete_snapshot(name, has_devices,
3100f1a9fcddSDaniel P. Berrangé                                          devices, errp) < 0) {
31017ea14df2SPhilippe Mathieu-Daudé                 return false;
3102ac8c19baSPavel Dovgalyuk             }
3103f781f841SDaniel P. Berrangé         } else {
3104f1a9fcddSDaniel P. Berrangé             ret2 = bdrv_all_has_snapshot(name, has_devices, devices, errp);
3105f781f841SDaniel P. Berrangé             if (ret2 < 0) {
3106f781f841SDaniel P. Berrangé                 return false;
3107f781f841SDaniel P. Berrangé             }
3108f781f841SDaniel P. Berrangé             if (ret2 == 1) {
3109f781f841SDaniel P. Berrangé                 error_setg(errp,
3110f781f841SDaniel P. Berrangé                            "Snapshot '%s' already exists in one or more devices",
3111f781f841SDaniel P. Berrangé                            name);
3112f781f841SDaniel P. Berrangé                 return false;
3113f781f841SDaniel P. Berrangé             }
3114f781f841SDaniel P. Berrangé         }
31150b461605SDenis V. Lunev     }
31160b461605SDenis V. Lunev 
3117f1a9fcddSDaniel P. Berrangé     bs = bdrv_all_find_vmstate_bs(vmstate, has_devices, devices, errp);
31187cb14481SDenis V. Lunev     if (bs == NULL) {
31197ea14df2SPhilippe Mathieu-Daudé         return false;
3120c3049a56SJuan Quintela     }
3121c3049a56SJuan Quintela 
3122c33f1829SVladimir Sementsov-Ogievskiy     global_state_store();
3123c3049a56SJuan Quintela     vm_stop(RUN_STATE_SAVE_VM);
3124c3049a56SJuan Quintela 
31258649f2f9SStefan Hajnoczi     bdrv_drain_all_begin();
31268649f2f9SStefan Hajnoczi 
3127c3049a56SJuan Quintela     memset(sn, 0, sizeof(*sn));
3128c3049a56SJuan Quintela 
3129c3049a56SJuan Quintela     /* fill auxiliary fields */
313085cd1cc6SDaniel P. Berrangé     sn->date_sec = g_date_time_to_unix(now);
313185cd1cc6SDaniel P. Berrangé     sn->date_nsec = g_date_time_get_microsecond(now) * 1000;
3132c3049a56SJuan Quintela     sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
3133b39847a5SPavel Dovgalyuk     if (replay_mode != REPLAY_MODE_NONE) {
3134b39847a5SPavel Dovgalyuk         sn->icount = replay_get_current_icount();
3135b39847a5SPavel Dovgalyuk     } else {
3136b39847a5SPavel Dovgalyuk         sn->icount = -1ULL;
3137b39847a5SPavel Dovgalyuk     }
3138c3049a56SJuan Quintela 
3139c3049a56SJuan Quintela     if (name) {
3140c3049a56SJuan Quintela         pstrcpy(sn->name, sizeof(sn->name), name);
3141c3049a56SJuan Quintela     } else {
314285cd1cc6SDaniel P. Berrangé         g_autofree char *autoname = g_date_time_format(now,  "vm-%Y%m%d%H%M%S");
314385cd1cc6SDaniel P. Berrangé         pstrcpy(sn->name, sizeof(sn->name), autoname);
3144c3049a56SJuan Quintela     }
3145c3049a56SJuan Quintela 
3146c3049a56SJuan Quintela     /* save the VM state */
3147c3049a56SJuan Quintela     f = qemu_fopen_bdrv(bs, 1);
3148c3049a56SJuan Quintela     if (!f) {
3149927d6638SJuan Quintela         error_setg(errp, "Could not open VM state file");
3150c3049a56SJuan Quintela         goto the_end;
3151c3049a56SJuan Quintela     }
3152927d6638SJuan Quintela     ret = qemu_savevm_state(f, errp);
3153e9c0eed7SJuan Quintela     vm_state_size = qemu_file_transferred(f);
315466270a47SDenis V. Lunev     ret2 = qemu_fclose(f);
3155c3049a56SJuan Quintela     if (ret < 0) {
3156c3049a56SJuan Quintela         goto the_end;
3157c3049a56SJuan Quintela     }
315866270a47SDenis V. Lunev     if (ret2 < 0) {
315966270a47SDenis V. Lunev         ret = ret2;
316066270a47SDenis V. Lunev         goto the_end;
316166270a47SDenis V. Lunev     }
3162c3049a56SJuan Quintela 
3163f1a9fcddSDaniel P. Berrangé     ret = bdrv_all_create_snapshot(sn, bs, vm_state_size,
3164f1a9fcddSDaniel P. Berrangé                                    has_devices, devices, errp);
3165c3049a56SJuan Quintela     if (ret < 0) {
3166f1a9fcddSDaniel P. Berrangé         bdrv_all_delete_snapshot(sn->name, has_devices, devices, NULL);
3167ac8c19baSPavel Dovgalyuk         goto the_end;
3168c3049a56SJuan Quintela     }
3169c3049a56SJuan Quintela 
3170ac8c19baSPavel Dovgalyuk     ret = 0;
3171ac8c19baSPavel Dovgalyuk 
3172c3049a56SJuan Quintela  the_end:
31738649f2f9SStefan Hajnoczi     bdrv_drain_all_end();
31748649f2f9SStefan Hajnoczi 
317558b10570SSteve Sistare     vm_resume(saved_state);
31767ea14df2SPhilippe Mathieu-Daudé     return ret == 0;
3177ac8c19baSPavel Dovgalyuk }
3178ac8c19baSPavel Dovgalyuk 
qmp_xen_save_devices_state(const char * filename,bool has_live,bool live,Error ** errp)31795d6c599fSAnthony PERARD void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live,
31805d6c599fSAnthony PERARD                                 Error **errp)
3181c3049a56SJuan Quintela {
3182c3049a56SJuan Quintela     QEMUFile *f;
31838925839fSDaniel P. Berrange     QIOChannelFile *ioc;
3184c3049a56SJuan Quintela     int saved_vm_running;
3185c3049a56SJuan Quintela     int ret;
3186c3049a56SJuan Quintela 
31875d6c599fSAnthony PERARD     if (!has_live) {
31885d6c599fSAnthony PERARD         /* live default to true so old version of Xen tool stack can have a
31893a4452d8Szhaolichang          * successful live migration */
31905d6c599fSAnthony PERARD         live = true;
31915d6c599fSAnthony PERARD     }
31925d6c599fSAnthony PERARD 
3193c3049a56SJuan Quintela     saved_vm_running = runstate_is_running();
3194c3049a56SJuan Quintela     vm_stop(RUN_STATE_SAVE_VM);
3195c69adea4SAnthony PERARD     global_state_store_running();
3196c3049a56SJuan Quintela 
3197b4deb9bfSDov Murik     ioc = qio_channel_file_new_path(filename, O_WRONLY | O_CREAT | O_TRUNC,
3198b4deb9bfSDov Murik                                     0660, errp);
31998925839fSDaniel P. Berrange     if (!ioc) {
3200c3049a56SJuan Quintela         goto the_end;
3201c3049a56SJuan Quintela     }
32026f01f136SDaniel P. Berrange     qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-save-state");
320377ef2dc1SDaniel P. Berrangé     f = qemu_file_new_output(QIO_CHANNEL(ioc));
3204032b79f7SRoss Lagerwall     object_unref(OBJECT(ioc));
3205c3049a56SJuan Quintela     ret = qemu_save_device_state(f);
320696994fd1SRoss Lagerwall     if (ret < 0 || qemu_fclose(f) < 0) {
3207fdac62dbSMarkus Armbruster         error_setg(errp, "saving Xen device state failed");
32085d6c599fSAnthony PERARD     } else {
32095d6c599fSAnthony PERARD         /* libxl calls the QMP command "stop" before calling
32105d6c599fSAnthony PERARD          * "xen-save-devices-state" and in case of migration failure, libxl
32115d6c599fSAnthony PERARD          * would call "cont".
32125d6c599fSAnthony PERARD          * So call bdrv_inactivate_all (release locks) here to let the other
32133a4452d8Szhaolichang          * side of the migration take control of the images.
32145d6c599fSAnthony PERARD          */
32155d6c599fSAnthony PERARD         if (live && !saved_vm_running) {
32165d6c599fSAnthony PERARD             ret = bdrv_inactivate_all();
32175d6c599fSAnthony PERARD             if (ret) {
32185d6c599fSAnthony PERARD                 error_setg(errp, "%s: bdrv_inactivate_all() failed (%d)",
32195d6c599fSAnthony PERARD                            __func__, ret);
32205d6c599fSAnthony PERARD             }
32215d6c599fSAnthony PERARD         }
3222c3049a56SJuan Quintela     }
3223c3049a56SJuan Quintela 
3224c3049a56SJuan Quintela  the_end:
3225c3049a56SJuan Quintela     if (saved_vm_running) {
3226c3049a56SJuan Quintela         vm_start();
3227c3049a56SJuan Quintela     }
3228c3049a56SJuan Quintela }
3229c3049a56SJuan Quintela 
qmp_xen_load_devices_state(const char * filename,Error ** errp)323088c16567SWen Congyang void qmp_xen_load_devices_state(const char *filename, Error **errp)
323188c16567SWen Congyang {
323288c16567SWen Congyang     QEMUFile *f;
323388c16567SWen Congyang     QIOChannelFile *ioc;
323488c16567SWen Congyang     int ret;
323588c16567SWen Congyang 
323688c16567SWen Congyang     /* Guest must be paused before loading the device state; the RAM state
323788c16567SWen Congyang      * will already have been loaded by xc
323888c16567SWen Congyang      */
323988c16567SWen Congyang     if (runstate_is_running()) {
324088c16567SWen Congyang         error_setg(errp, "Cannot update device state while vm is running");
324188c16567SWen Congyang         return;
324288c16567SWen Congyang     }
324388c16567SWen Congyang     vm_stop(RUN_STATE_RESTORE_VM);
324488c16567SWen Congyang 
324588c16567SWen Congyang     ioc = qio_channel_file_new_path(filename, O_RDONLY | O_BINARY, 0, errp);
324688c16567SWen Congyang     if (!ioc) {
324788c16567SWen Congyang         return;
324888c16567SWen Congyang     }
32496f01f136SDaniel P. Berrange     qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-load-state");
325077ef2dc1SDaniel P. Berrangé     f = qemu_file_new_input(QIO_CHANNEL(ioc));
3251032b79f7SRoss Lagerwall     object_unref(OBJECT(ioc));
325288c16567SWen Congyang 
325388c16567SWen Congyang     ret = qemu_loadvm_state(f);
325488c16567SWen Congyang     qemu_fclose(f);
325588c16567SWen Congyang     if (ret < 0) {
3256fdac62dbSMarkus Armbruster         error_setg(errp, "loading Xen device state failed");
325788c16567SWen Congyang     }
325888c16567SWen Congyang     migration_incoming_state_destroy();
325988c16567SWen Congyang }
326088c16567SWen Congyang 
load_snapshot(const char * name,const char * vmstate,bool has_devices,strList * devices,Error ** errp)3261f1a9fcddSDaniel P. Berrangé bool load_snapshot(const char *name, const char *vmstate,
3262f1a9fcddSDaniel P. Berrangé                    bool has_devices, strList *devices, Error **errp)
3263c3049a56SJuan Quintela {
3264e26f98e2SDaniel P. Berrangé     BlockDriverState *bs_vm_state;
3265c3049a56SJuan Quintela     QEMUSnapshotInfo sn;
3266c3049a56SJuan Quintela     QEMUFile *f;
3267c3049a56SJuan Quintela     int ret;
3268b4b076daSJuan Quintela     MigrationIncomingState *mis = migration_incoming_get_current();
3269c3049a56SJuan Quintela 
3270f1a9fcddSDaniel P. Berrangé     if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
3271f61fe11aSDaniel P. Berrangé         return false;
3272849f96e2SDenis V. Lunev     }
3273f1a9fcddSDaniel P. Berrangé     ret = bdrv_all_has_snapshot(name, has_devices, devices, errp);
3274723ccda1SDenis V. Lunev     if (ret < 0) {
3275f61fe11aSDaniel P. Berrangé         return false;
3276723ccda1SDenis V. Lunev     }
32773d3e9b1fSDaniel P. Berrangé     if (ret == 0) {
32783d3e9b1fSDaniel P. Berrangé         error_setg(errp, "Snapshot '%s' does not exist in one or more devices",
32793d3e9b1fSDaniel P. Berrangé                    name);
32803d3e9b1fSDaniel P. Berrangé         return false;
32813d3e9b1fSDaniel P. Berrangé     }
3282849f96e2SDenis V. Lunev 
3283f1a9fcddSDaniel P. Berrangé     bs_vm_state = bdrv_all_find_vmstate_bs(vmstate, has_devices, devices, errp);
3284c3049a56SJuan Quintela     if (!bs_vm_state) {
3285f61fe11aSDaniel P. Berrangé         return false;
3286c3049a56SJuan Quintela     }
3287c3049a56SJuan Quintela 
3288c3049a56SJuan Quintela     /* Don't even try to load empty VM states */
3289c3049a56SJuan Quintela     ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
3290c3049a56SJuan Quintela     if (ret < 0) {
3291*97d2b66dSNicholas Piggin         error_setg(errp, "Snapshot can not be found");
3292f61fe11aSDaniel P. Berrangé         return false;
3293c3049a56SJuan Quintela     } else if (sn.vm_state_size == 0) {
3294927d6638SJuan Quintela         error_setg(errp, "This is a disk-only snapshot. Revert to it "
3295927d6638SJuan Quintela                    " offline using qemu-img");
3296f61fe11aSDaniel P. Berrangé         return false;
3297c3049a56SJuan Quintela     }
3298c3049a56SJuan Quintela 
3299f9a9fb65SPavel Dovgalyuk     /*
3300f9a9fb65SPavel Dovgalyuk      * Flush the record/replay queue. Now the VM state is going
3301f9a9fb65SPavel Dovgalyuk      * to change. Therefore we don't need to preserve its consistency
3302f9a9fb65SPavel Dovgalyuk      */
3303f9a9fb65SPavel Dovgalyuk     replay_flush_events();
3304f9a9fb65SPavel Dovgalyuk 
3305c3049a56SJuan Quintela     /* Flush all IO requests so they don't interfere with the new state.  */
33068649f2f9SStefan Hajnoczi     bdrv_drain_all_begin();
3307c3049a56SJuan Quintela 
3308f1a9fcddSDaniel P. Berrangé     ret = bdrv_all_goto_snapshot(name, has_devices, devices, errp);
3309c3049a56SJuan Quintela     if (ret < 0) {
33108649f2f9SStefan Hajnoczi         goto err_drain;
3311c3049a56SJuan Quintela     }
3312c3049a56SJuan Quintela 
3313c3049a56SJuan Quintela     /* restore the VM state */
3314c3049a56SJuan Quintela     f = qemu_fopen_bdrv(bs_vm_state, 0);
3315c3049a56SJuan Quintela     if (!f) {
3316927d6638SJuan Quintela         error_setg(errp, "Could not open VM state file");
33178649f2f9SStefan Hajnoczi         goto err_drain;
3318c3049a56SJuan Quintela     }
3319c3049a56SJuan Quintela 
33207966d70fSJason A. Donenfeld     qemu_system_reset(SHUTDOWN_CAUSE_SNAPSHOT_LOAD);
3321b4b076daSJuan Quintela     mis->from_src_file = f;
3322c3049a56SJuan Quintela 
3323b5eea99eSLukas Straub     if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) {
3324b5eea99eSLukas Straub         ret = -EINVAL;
3325b5eea99eSLukas Straub         goto err_drain;
3326b5eea99eSLukas Straub     }
332779b3c12aSDenis V. Lunev     ret = qemu_loadvm_state(f);
33281575829dSStefan Hajnoczi     migration_incoming_state_destroy();
332979b3c12aSDenis V. Lunev 
33308649f2f9SStefan Hajnoczi     bdrv_drain_all_end();
33318649f2f9SStefan Hajnoczi 
3332c3049a56SJuan Quintela     if (ret < 0) {
3333927d6638SJuan Quintela         error_setg(errp, "Error %d while loading VM state", ret);
3334f61fe11aSDaniel P. Berrangé         return false;
3335c3049a56SJuan Quintela     }
3336c3049a56SJuan Quintela 
3337f61fe11aSDaniel P. Berrangé     return true;
33388649f2f9SStefan Hajnoczi 
33398649f2f9SStefan Hajnoczi err_drain:
33408649f2f9SStefan Hajnoczi     bdrv_drain_all_end();
3341f61fe11aSDaniel P. Berrangé     return false;
3342c3049a56SJuan Quintela }
3343c3049a56SJuan Quintela 
load_snapshot_resume(RunState state)334458b10570SSteve Sistare void load_snapshot_resume(RunState state)
334558b10570SSteve Sistare {
334658b10570SSteve Sistare     vm_resume(state);
334758b10570SSteve Sistare     if (state == RUN_STATE_RUNNING && runstate_get() == RUN_STATE_SUSPENDED) {
334858b10570SSteve Sistare         qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, &error_abort);
334958b10570SSteve Sistare     }
335058b10570SSteve Sistare }
335158b10570SSteve Sistare 
delete_snapshot(const char * name,bool has_devices,strList * devices,Error ** errp)3352bef7e9e2SDaniel P. Berrangé bool delete_snapshot(const char *name, bool has_devices,
3353bef7e9e2SDaniel P. Berrangé                      strList *devices, Error **errp)
3354bef7e9e2SDaniel P. Berrangé {
3355bef7e9e2SDaniel P. Berrangé     if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
3356bef7e9e2SDaniel P. Berrangé         return false;
3357bef7e9e2SDaniel P. Berrangé     }
3358bef7e9e2SDaniel P. Berrangé 
3359bef7e9e2SDaniel P. Berrangé     if (bdrv_all_delete_snapshot(name, has_devices, devices, errp) < 0) {
3360bef7e9e2SDaniel P. Berrangé         return false;
3361bef7e9e2SDaniel P. Berrangé     }
3362bef7e9e2SDaniel P. Berrangé 
3363bef7e9e2SDaniel P. Berrangé     return true;
3364bef7e9e2SDaniel P. Berrangé }
3365bef7e9e2SDaniel P. Berrangé 
vmstate_register_ram(MemoryRegion * mr,DeviceState * dev)3366c3049a56SJuan Quintela void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
3367c3049a56SJuan Quintela {
3368fa53a0e5SGonglei     qemu_ram_set_idstr(mr->ram_block,
3369c3049a56SJuan Quintela                        memory_region_name(mr), dev);
3370b895de50SCédric Le Goater     qemu_ram_set_migratable(mr->ram_block);
3371c3049a56SJuan Quintela }
3372c3049a56SJuan Quintela 
vmstate_unregister_ram(MemoryRegion * mr,DeviceState * dev)3373c3049a56SJuan Quintela void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
3374c3049a56SJuan Quintela {
3375fa53a0e5SGonglei     qemu_ram_unset_idstr(mr->ram_block);
3376b895de50SCédric Le Goater     qemu_ram_unset_migratable(mr->ram_block);
3377c3049a56SJuan Quintela }
3378c3049a56SJuan Quintela 
vmstate_register_ram_global(MemoryRegion * mr)3379c3049a56SJuan Quintela void vmstate_register_ram_global(MemoryRegion *mr)
3380c3049a56SJuan Quintela {
3381c3049a56SJuan Quintela     vmstate_register_ram(mr, NULL);
3382c3049a56SJuan Quintela }
33831bfe5f05SJuan Quintela 
vmstate_check_only_migratable(const VMStateDescription * vmsd)33841bfe5f05SJuan Quintela bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
33851bfe5f05SJuan Quintela {
33861bfe5f05SJuan Quintela     /* check needed if --only-migratable is specified */
3387811f8652SMarkus Armbruster     if (!only_migratable) {
33881bfe5f05SJuan Quintela         return true;
33891bfe5f05SJuan Quintela     }
33901bfe5f05SJuan Quintela 
33911bfe5f05SJuan Quintela     return !(vmsd && vmsd->unmigratable);
33921bfe5f05SJuan Quintela }
33930f0d83a4SDaniel P. Berrangé 
33940f0d83a4SDaniel P. Berrangé typedef struct SnapshotJob {
33950f0d83a4SDaniel P. Berrangé     Job common;
33960f0d83a4SDaniel P. Berrangé     char *tag;
33970f0d83a4SDaniel P. Berrangé     char *vmstate;
33980f0d83a4SDaniel P. Berrangé     strList *devices;
33990f0d83a4SDaniel P. Berrangé     Coroutine *co;
34000f0d83a4SDaniel P. Berrangé     Error **errp;
34010f0d83a4SDaniel P. Berrangé     bool ret;
34020f0d83a4SDaniel P. Berrangé } SnapshotJob;
34030f0d83a4SDaniel P. Berrangé 
qmp_snapshot_job_free(SnapshotJob * s)34040f0d83a4SDaniel P. Berrangé static void qmp_snapshot_job_free(SnapshotJob *s)
34050f0d83a4SDaniel P. Berrangé {
34060f0d83a4SDaniel P. Berrangé     g_free(s->tag);
34070f0d83a4SDaniel P. Berrangé     g_free(s->vmstate);
34080f0d83a4SDaniel P. Berrangé     qapi_free_strList(s->devices);
34090f0d83a4SDaniel P. Berrangé }
34100f0d83a4SDaniel P. Berrangé 
34110f0d83a4SDaniel P. Berrangé 
snapshot_load_job_bh(void * opaque)34120f0d83a4SDaniel P. Berrangé static void snapshot_load_job_bh(void *opaque)
34130f0d83a4SDaniel P. Berrangé {
34140f0d83a4SDaniel P. Berrangé     Job *job = opaque;
34150f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
341658b10570SSteve Sistare     RunState orig_state = runstate_get();
34170f0d83a4SDaniel P. Berrangé 
34180f0d83a4SDaniel P. Berrangé     job_progress_set_remaining(&s->common, 1);
34190f0d83a4SDaniel P. Berrangé 
34200f0d83a4SDaniel P. Berrangé     vm_stop(RUN_STATE_RESTORE_VM);
34210f0d83a4SDaniel P. Berrangé 
34220f0d83a4SDaniel P. Berrangé     s->ret = load_snapshot(s->tag, s->vmstate, true, s->devices, s->errp);
342358b10570SSteve Sistare     if (s->ret) {
342458b10570SSteve Sistare         load_snapshot_resume(orig_state);
34250f0d83a4SDaniel P. Berrangé     }
34260f0d83a4SDaniel P. Berrangé 
34270f0d83a4SDaniel P. Berrangé     job_progress_update(&s->common, 1);
34280f0d83a4SDaniel P. Berrangé 
34290f0d83a4SDaniel P. Berrangé     qmp_snapshot_job_free(s);
34300f0d83a4SDaniel P. Berrangé     aio_co_wake(s->co);
34310f0d83a4SDaniel P. Berrangé }
34320f0d83a4SDaniel P. Berrangé 
snapshot_save_job_bh(void * opaque)34330f0d83a4SDaniel P. Berrangé static void snapshot_save_job_bh(void *opaque)
34340f0d83a4SDaniel P. Berrangé {
34350f0d83a4SDaniel P. Berrangé     Job *job = opaque;
34360f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
34370f0d83a4SDaniel P. Berrangé 
34380f0d83a4SDaniel P. Berrangé     job_progress_set_remaining(&s->common, 1);
34390f0d83a4SDaniel P. Berrangé     s->ret = save_snapshot(s->tag, false, s->vmstate,
34400f0d83a4SDaniel P. Berrangé                            true, s->devices, s->errp);
34410f0d83a4SDaniel P. Berrangé     job_progress_update(&s->common, 1);
34420f0d83a4SDaniel P. Berrangé 
34430f0d83a4SDaniel P. Berrangé     qmp_snapshot_job_free(s);
34440f0d83a4SDaniel P. Berrangé     aio_co_wake(s->co);
34450f0d83a4SDaniel P. Berrangé }
34460f0d83a4SDaniel P. Berrangé 
snapshot_delete_job_bh(void * opaque)34470f0d83a4SDaniel P. Berrangé static void snapshot_delete_job_bh(void *opaque)
34480f0d83a4SDaniel P. Berrangé {
34490f0d83a4SDaniel P. Berrangé     Job *job = opaque;
34500f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
34510f0d83a4SDaniel P. Berrangé 
34520f0d83a4SDaniel P. Berrangé     job_progress_set_remaining(&s->common, 1);
34530f0d83a4SDaniel P. Berrangé     s->ret = delete_snapshot(s->tag, true, s->devices, s->errp);
34540f0d83a4SDaniel P. Berrangé     job_progress_update(&s->common, 1);
34550f0d83a4SDaniel P. Berrangé 
34560f0d83a4SDaniel P. Berrangé     qmp_snapshot_job_free(s);
34570f0d83a4SDaniel P. Berrangé     aio_co_wake(s->co);
34580f0d83a4SDaniel P. Berrangé }
34590f0d83a4SDaniel P. Berrangé 
snapshot_save_job_run(Job * job,Error ** errp)34600f0d83a4SDaniel P. Berrangé static int coroutine_fn snapshot_save_job_run(Job *job, Error **errp)
34610f0d83a4SDaniel P. Berrangé {
34620f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
34630f0d83a4SDaniel P. Berrangé     s->errp = errp;
34640f0d83a4SDaniel P. Berrangé     s->co = qemu_coroutine_self();
34650f0d83a4SDaniel P. Berrangé     aio_bh_schedule_oneshot(qemu_get_aio_context(),
34660f0d83a4SDaniel P. Berrangé                             snapshot_save_job_bh, job);
34670f0d83a4SDaniel P. Berrangé     qemu_coroutine_yield();
34680f0d83a4SDaniel P. Berrangé     return s->ret ? 0 : -1;
34690f0d83a4SDaniel P. Berrangé }
34700f0d83a4SDaniel P. Berrangé 
snapshot_load_job_run(Job * job,Error ** errp)34710f0d83a4SDaniel P. Berrangé static int coroutine_fn snapshot_load_job_run(Job *job, Error **errp)
34720f0d83a4SDaniel P. Berrangé {
34730f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
34740f0d83a4SDaniel P. Berrangé     s->errp = errp;
34750f0d83a4SDaniel P. Berrangé     s->co = qemu_coroutine_self();
34760f0d83a4SDaniel P. Berrangé     aio_bh_schedule_oneshot(qemu_get_aio_context(),
34770f0d83a4SDaniel P. Berrangé                             snapshot_load_job_bh, job);
34780f0d83a4SDaniel P. Berrangé     qemu_coroutine_yield();
34790f0d83a4SDaniel P. Berrangé     return s->ret ? 0 : -1;
34800f0d83a4SDaniel P. Berrangé }
34810f0d83a4SDaniel P. Berrangé 
snapshot_delete_job_run(Job * job,Error ** errp)34820f0d83a4SDaniel P. Berrangé static int coroutine_fn snapshot_delete_job_run(Job *job, Error **errp)
34830f0d83a4SDaniel P. Berrangé {
34840f0d83a4SDaniel P. Berrangé     SnapshotJob *s = container_of(job, SnapshotJob, common);
34850f0d83a4SDaniel P. Berrangé     s->errp = errp;
34860f0d83a4SDaniel P. Berrangé     s->co = qemu_coroutine_self();
34870f0d83a4SDaniel P. Berrangé     aio_bh_schedule_oneshot(qemu_get_aio_context(),
34880f0d83a4SDaniel P. Berrangé                             snapshot_delete_job_bh, job);
34890f0d83a4SDaniel P. Berrangé     qemu_coroutine_yield();
34900f0d83a4SDaniel P. Berrangé     return s->ret ? 0 : -1;
34910f0d83a4SDaniel P. Berrangé }
34920f0d83a4SDaniel P. Berrangé 
34930f0d83a4SDaniel P. Berrangé 
34940f0d83a4SDaniel P. Berrangé static const JobDriver snapshot_load_job_driver = {
34950f0d83a4SDaniel P. Berrangé     .instance_size = sizeof(SnapshotJob),
34960f0d83a4SDaniel P. Berrangé     .job_type      = JOB_TYPE_SNAPSHOT_LOAD,
34970f0d83a4SDaniel P. Berrangé     .run           = snapshot_load_job_run,
34980f0d83a4SDaniel P. Berrangé };
34990f0d83a4SDaniel P. Berrangé 
35000f0d83a4SDaniel P. Berrangé static const JobDriver snapshot_save_job_driver = {
35010f0d83a4SDaniel P. Berrangé     .instance_size = sizeof(SnapshotJob),
35020f0d83a4SDaniel P. Berrangé     .job_type      = JOB_TYPE_SNAPSHOT_SAVE,
35030f0d83a4SDaniel P. Berrangé     .run           = snapshot_save_job_run,
35040f0d83a4SDaniel P. Berrangé };
35050f0d83a4SDaniel P. Berrangé 
35060f0d83a4SDaniel P. Berrangé static const JobDriver snapshot_delete_job_driver = {
35070f0d83a4SDaniel P. Berrangé     .instance_size = sizeof(SnapshotJob),
35080f0d83a4SDaniel P. Berrangé     .job_type      = JOB_TYPE_SNAPSHOT_DELETE,
35090f0d83a4SDaniel P. Berrangé     .run           = snapshot_delete_job_run,
35100f0d83a4SDaniel P. Berrangé };
35110f0d83a4SDaniel P. Berrangé 
35120f0d83a4SDaniel P. Berrangé 
qmp_snapshot_save(const char * job_id,const char * tag,const char * vmstate,strList * devices,Error ** errp)35130f0d83a4SDaniel P. Berrangé void qmp_snapshot_save(const char *job_id,
35140f0d83a4SDaniel P. Berrangé                        const char *tag,
35150f0d83a4SDaniel P. Berrangé                        const char *vmstate,
35160f0d83a4SDaniel P. Berrangé                        strList *devices,
35170f0d83a4SDaniel P. Berrangé                        Error **errp)
35180f0d83a4SDaniel P. Berrangé {
35190f0d83a4SDaniel P. Berrangé     SnapshotJob *s;
35200f0d83a4SDaniel P. Berrangé 
35210f0d83a4SDaniel P. Berrangé     s = job_create(job_id, &snapshot_save_job_driver, NULL,
35220f0d83a4SDaniel P. Berrangé                    qemu_get_aio_context(), JOB_MANUAL_DISMISS,
35230f0d83a4SDaniel P. Berrangé                    NULL, NULL, errp);
35240f0d83a4SDaniel P. Berrangé     if (!s) {
35250f0d83a4SDaniel P. Berrangé         return;
35260f0d83a4SDaniel P. Berrangé     }
35270f0d83a4SDaniel P. Berrangé 
35280f0d83a4SDaniel P. Berrangé     s->tag = g_strdup(tag);
35290f0d83a4SDaniel P. Berrangé     s->vmstate = g_strdup(vmstate);
35300f0d83a4SDaniel P. Berrangé     s->devices = QAPI_CLONE(strList, devices);
35310f0d83a4SDaniel P. Berrangé 
35320f0d83a4SDaniel P. Berrangé     job_start(&s->common);
35330f0d83a4SDaniel P. Berrangé }
35340f0d83a4SDaniel P. Berrangé 
qmp_snapshot_load(const char * job_id,const char * tag,const char * vmstate,strList * devices,Error ** errp)35350f0d83a4SDaniel P. Berrangé void qmp_snapshot_load(const char *job_id,
35360f0d83a4SDaniel P. Berrangé                        const char *tag,
35370f0d83a4SDaniel P. Berrangé                        const char *vmstate,
35380f0d83a4SDaniel P. Berrangé                        strList *devices,
35390f0d83a4SDaniel P. Berrangé                        Error **errp)
35400f0d83a4SDaniel P. Berrangé {
35410f0d83a4SDaniel P. Berrangé     SnapshotJob *s;
35420f0d83a4SDaniel P. Berrangé 
35430f0d83a4SDaniel P. Berrangé     s = job_create(job_id, &snapshot_load_job_driver, NULL,
35440f0d83a4SDaniel P. Berrangé                    qemu_get_aio_context(), JOB_MANUAL_DISMISS,
35450f0d83a4SDaniel P. Berrangé                    NULL, NULL, errp);
35460f0d83a4SDaniel P. Berrangé     if (!s) {
35470f0d83a4SDaniel P. Berrangé         return;
35480f0d83a4SDaniel P. Berrangé     }
35490f0d83a4SDaniel P. Berrangé 
35500f0d83a4SDaniel P. Berrangé     s->tag = g_strdup(tag);
35510f0d83a4SDaniel P. Berrangé     s->vmstate = g_strdup(vmstate);
35520f0d83a4SDaniel P. Berrangé     s->devices = QAPI_CLONE(strList, devices);
35530f0d83a4SDaniel P. Berrangé 
35540f0d83a4SDaniel P. Berrangé     job_start(&s->common);
35550f0d83a4SDaniel P. Berrangé }
35560f0d83a4SDaniel P. Berrangé 
qmp_snapshot_delete(const char * job_id,const char * tag,strList * devices,Error ** errp)35570f0d83a4SDaniel P. Berrangé void qmp_snapshot_delete(const char *job_id,
35580f0d83a4SDaniel P. Berrangé                          const char *tag,
35590f0d83a4SDaniel P. Berrangé                          strList *devices,
35600f0d83a4SDaniel P. Berrangé                          Error **errp)
35610f0d83a4SDaniel P. Berrangé {
35620f0d83a4SDaniel P. Berrangé     SnapshotJob *s;
35630f0d83a4SDaniel P. Berrangé 
35640f0d83a4SDaniel P. Berrangé     s = job_create(job_id, &snapshot_delete_job_driver, NULL,
35650f0d83a4SDaniel P. Berrangé                    qemu_get_aio_context(), JOB_MANUAL_DISMISS,
35660f0d83a4SDaniel P. Berrangé                    NULL, NULL, errp);
35670f0d83a4SDaniel P. Berrangé     if (!s) {
35680f0d83a4SDaniel P. Berrangé         return;
35690f0d83a4SDaniel P. Berrangé     }
35700f0d83a4SDaniel P. Berrangé 
35710f0d83a4SDaniel P. Berrangé     s->tag = g_strdup(tag);
35720f0d83a4SDaniel P. Berrangé     s->devices = QAPI_CLONE(strList, devices);
35730f0d83a4SDaniel P. Berrangé 
35740f0d83a4SDaniel P. Berrangé     job_start(&s->common);
35750f0d83a4SDaniel P. Berrangé }
3576