xref: /openbmc/qemu/migration/options.c (revision 10d4703be5d884bbbb6ecafe0e8bb270ad6ea937)
11f0776f1SJuan Quintela /*
21f0776f1SJuan Quintela  * QEMU migration capabilities
31f0776f1SJuan Quintela  *
41f0776f1SJuan Quintela  * Copyright (c) 2012-2023 Red Hat Inc
51f0776f1SJuan Quintela  *
61f0776f1SJuan Quintela  * Authors:
71f0776f1SJuan Quintela  *   Orit Wasserman <owasserm@redhat.com>
81f0776f1SJuan Quintela  *   Juan Quintela <quintela@redhat.com>
91f0776f1SJuan Quintela  *
101f0776f1SJuan Quintela  * This work is licensed under the terms of the GNU GPL, version 2 or later.
111f0776f1SJuan Quintela  * See the COPYING file in the top-level directory.
121f0776f1SJuan Quintela  */
131f0776f1SJuan Quintela 
141f0776f1SJuan Quintela #include "qemu/osdep.h"
159c894df3SJuan Quintela #include "qapi/clone-visitor.h"
1677608706SJuan Quintela #include "qapi/error.h"
174d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h"
189c894df3SJuan Quintela #include "qapi/qapi-visit-migration.h"
19f80196b7SJuan Quintela #include "qapi/qmp/qerror.h"
2077608706SJuan Quintela #include "sysemu/runstate.h"
212682c4eeSJuan Quintela #include "migration/misc.h"
221f0776f1SJuan Quintela #include "migration.h"
2377608706SJuan Quintela #include "ram.h"
241f0776f1SJuan Quintela #include "options.h"
251f0776f1SJuan Quintela 
261f0776f1SJuan Quintela bool migrate_auto_converge(void)
271f0776f1SJuan Quintela {
281f0776f1SJuan Quintela     MigrationState *s;
291f0776f1SJuan Quintela 
301f0776f1SJuan Quintela     s = migrate_get_current();
311f0776f1SJuan Quintela 
321f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
331f0776f1SJuan Quintela }
341f0776f1SJuan Quintela 
351f0776f1SJuan Quintela bool migrate_background_snapshot(void)
361f0776f1SJuan Quintela {
371f0776f1SJuan Quintela     MigrationState *s;
381f0776f1SJuan Quintela 
391f0776f1SJuan Quintela     s = migrate_get_current();
401f0776f1SJuan Quintela 
411f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
421f0776f1SJuan Quintela }
431f0776f1SJuan Quintela 
449d4b1e5fSJuan Quintela bool migrate_block(void)
459d4b1e5fSJuan Quintela {
469d4b1e5fSJuan Quintela     MigrationState *s;
479d4b1e5fSJuan Quintela 
489d4b1e5fSJuan Quintela     s = migrate_get_current();
499d4b1e5fSJuan Quintela 
509d4b1e5fSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
519d4b1e5fSJuan Quintela }
529d4b1e5fSJuan Quintela 
535e804644SJuan Quintela bool migrate_colo(void)
545e804644SJuan Quintela {
555e804644SJuan Quintela     MigrationState *s = migrate_get_current();
565e804644SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
575e804644SJuan Quintela }
585e804644SJuan Quintela 
59a7a94d14SJuan Quintela bool migrate_compress(void)
60a7a94d14SJuan Quintela {
61a7a94d14SJuan Quintela     MigrationState *s;
62a7a94d14SJuan Quintela 
63a7a94d14SJuan Quintela     s = migrate_get_current();
64a7a94d14SJuan Quintela 
65a7a94d14SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
66a7a94d14SJuan Quintela }
67a7a94d14SJuan Quintela 
681f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void)
691f0776f1SJuan Quintela {
701f0776f1SJuan Quintela     MigrationState *s;
711f0776f1SJuan Quintela 
721f0776f1SJuan Quintela     s = migrate_get_current();
731f0776f1SJuan Quintela 
741f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
751f0776f1SJuan Quintela }
761f0776f1SJuan Quintela 
77b890902cSJuan Quintela bool migrate_events(void)
78b890902cSJuan Quintela {
79b890902cSJuan Quintela     MigrationState *s;
80b890902cSJuan Quintela 
81b890902cSJuan Quintela     s = migrate_get_current();
82b890902cSJuan Quintela 
83b890902cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
84b890902cSJuan Quintela }
85b890902cSJuan Quintela 
861f0776f1SJuan Quintela bool migrate_ignore_shared(void)
871f0776f1SJuan Quintela {
881f0776f1SJuan Quintela     MigrationState *s;
891f0776f1SJuan Quintela 
901f0776f1SJuan Quintela     s = migrate_get_current();
911f0776f1SJuan Quintela 
921f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
931f0776f1SJuan Quintela }
941f0776f1SJuan Quintela 
951f0776f1SJuan Quintela bool migrate_late_block_activate(void)
961f0776f1SJuan Quintela {
971f0776f1SJuan Quintela     MigrationState *s;
981f0776f1SJuan Quintela 
991f0776f1SJuan Quintela     s = migrate_get_current();
1001f0776f1SJuan Quintela 
1011f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
1021f0776f1SJuan Quintela }
1031f0776f1SJuan Quintela 
10451b07548SJuan Quintela bool migrate_multifd(void)
10551b07548SJuan Quintela {
10651b07548SJuan Quintela     MigrationState *s;
10751b07548SJuan Quintela 
10851b07548SJuan Quintela     s = migrate_get_current();
10951b07548SJuan Quintela 
11051b07548SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
11151b07548SJuan Quintela }
11251b07548SJuan Quintela 
1131f0776f1SJuan Quintela bool migrate_pause_before_switchover(void)
1141f0776f1SJuan Quintela {
1151f0776f1SJuan Quintela     MigrationState *s;
1161f0776f1SJuan Quintela 
1171f0776f1SJuan Quintela     s = migrate_get_current();
1181f0776f1SJuan Quintela 
1191f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
1201f0776f1SJuan Quintela }
1211f0776f1SJuan Quintela 
1221f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void)
1231f0776f1SJuan Quintela {
1241f0776f1SJuan Quintela     MigrationState *s;
1251f0776f1SJuan Quintela 
1261f0776f1SJuan Quintela     s = migrate_get_current();
1271f0776f1SJuan Quintela 
1281f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
1291f0776f1SJuan Quintela }
1301f0776f1SJuan Quintela 
1311f0776f1SJuan Quintela bool migrate_postcopy_preempt(void)
1321f0776f1SJuan Quintela {
1331f0776f1SJuan Quintela     MigrationState *s;
1341f0776f1SJuan Quintela 
1351f0776f1SJuan Quintela     s = migrate_get_current();
1361f0776f1SJuan Quintela 
1371f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
1381f0776f1SJuan Quintela }
1391f0776f1SJuan Quintela 
1401f0776f1SJuan Quintela bool migrate_postcopy_ram(void)
1411f0776f1SJuan Quintela {
1421f0776f1SJuan Quintela     MigrationState *s;
1431f0776f1SJuan Quintela 
1441f0776f1SJuan Quintela     s = migrate_get_current();
1451f0776f1SJuan Quintela 
1461f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
1471f0776f1SJuan Quintela }
1481f0776f1SJuan Quintela 
14917cba690SJuan Quintela bool migrate_rdma_pin_all(void)
15017cba690SJuan Quintela {
15117cba690SJuan Quintela     MigrationState *s = migrate_get_current();
15217cba690SJuan Quintela 
15317cba690SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
15417cba690SJuan Quintela }
15517cba690SJuan Quintela 
1561f0776f1SJuan Quintela bool migrate_release_ram(void)
1571f0776f1SJuan Quintela {
1581f0776f1SJuan Quintela     MigrationState *s;
1591f0776f1SJuan Quintela 
1601f0776f1SJuan Quintela     s = migrate_get_current();
1611f0776f1SJuan Quintela 
1621f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
1631f0776f1SJuan Quintela }
1641f0776f1SJuan Quintela 
16538ad1110SJuan Quintela bool migrate_return_path(void)
16638ad1110SJuan Quintela {
16738ad1110SJuan Quintela     MigrationState *s;
16838ad1110SJuan Quintela 
16938ad1110SJuan Quintela     s = migrate_get_current();
17038ad1110SJuan Quintela 
17138ad1110SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
17238ad1110SJuan Quintela }
17338ad1110SJuan Quintela 
1741f0776f1SJuan Quintela bool migrate_validate_uuid(void)
1751f0776f1SJuan Quintela {
1761f0776f1SJuan Quintela     MigrationState *s;
1771f0776f1SJuan Quintela 
1781f0776f1SJuan Quintela     s = migrate_get_current();
1791f0776f1SJuan Quintela 
1801f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
1811f0776f1SJuan Quintela }
1821f0776f1SJuan Quintela 
18387dca0c9SJuan Quintela bool migrate_xbzrle(void)
18487dca0c9SJuan Quintela {
18587dca0c9SJuan Quintela     MigrationState *s;
18687dca0c9SJuan Quintela 
18787dca0c9SJuan Quintela     s = migrate_get_current();
18887dca0c9SJuan Quintela 
18987dca0c9SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
19087dca0c9SJuan Quintela }
19187dca0c9SJuan Quintela 
1921f0776f1SJuan Quintela bool migrate_zero_blocks(void)
1931f0776f1SJuan Quintela {
1941f0776f1SJuan Quintela     MigrationState *s;
1951f0776f1SJuan Quintela 
1961f0776f1SJuan Quintela     s = migrate_get_current();
1971f0776f1SJuan Quintela 
1981f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
1991f0776f1SJuan Quintela }
200b4bc342cSJuan Quintela 
201b4bc342cSJuan Quintela bool migrate_zero_copy_send(void)
202b4bc342cSJuan Quintela {
203b4bc342cSJuan Quintela     MigrationState *s;
204b4bc342cSJuan Quintela 
205b4bc342cSJuan Quintela     s = migrate_get_current();
206b4bc342cSJuan Quintela 
207b4bc342cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
208b4bc342cSJuan Quintela }
209f774fde5SJuan Quintela 
210f774fde5SJuan Quintela /* pseudo capabilities */
211f774fde5SJuan Quintela 
212f774fde5SJuan Quintela bool migrate_postcopy(void)
213f774fde5SJuan Quintela {
214f774fde5SJuan Quintela     return migrate_postcopy_ram() || migrate_dirty_bitmaps();
215f774fde5SJuan Quintela }
216f774fde5SJuan Quintela 
217*10d4703bSJuan Quintela bool migrate_tls(void)
218*10d4703bSJuan Quintela {
219*10d4703bSJuan Quintela     MigrationState *s;
220*10d4703bSJuan Quintela 
221*10d4703bSJuan Quintela     s = migrate_get_current();
222*10d4703bSJuan Quintela 
223*10d4703bSJuan Quintela     return s->parameters.tls_creds && *s->parameters.tls_creds;
224*10d4703bSJuan Quintela }
225*10d4703bSJuan Quintela 
22677608706SJuan Quintela typedef enum WriteTrackingSupport {
22777608706SJuan Quintela     WT_SUPPORT_UNKNOWN = 0,
22877608706SJuan Quintela     WT_SUPPORT_ABSENT,
22977608706SJuan Quintela     WT_SUPPORT_AVAILABLE,
23077608706SJuan Quintela     WT_SUPPORT_COMPATIBLE
23177608706SJuan Quintela } WriteTrackingSupport;
23277608706SJuan Quintela 
23377608706SJuan Quintela static
23477608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void)
23577608706SJuan Quintela {
23677608706SJuan Quintela     /* Check if kernel supports required UFFD features */
23777608706SJuan Quintela     if (!ram_write_tracking_available()) {
23877608706SJuan Quintela         return WT_SUPPORT_ABSENT;
23977608706SJuan Quintela     }
24077608706SJuan Quintela     /*
24177608706SJuan Quintela      * Check if current memory configuration is
24277608706SJuan Quintela      * compatible with required UFFD features.
24377608706SJuan Quintela      */
24477608706SJuan Quintela     if (!ram_write_tracking_compatible()) {
24577608706SJuan Quintela         return WT_SUPPORT_AVAILABLE;
24677608706SJuan Quintela     }
24777608706SJuan Quintela 
24877608706SJuan Quintela     return WT_SUPPORT_COMPATIBLE;
24977608706SJuan Quintela }
25077608706SJuan Quintela 
25177608706SJuan Quintela /* Migration capabilities set */
25277608706SJuan Quintela struct MigrateCapsSet {
25377608706SJuan Quintela     int size;                       /* Capability set size */
25477608706SJuan Quintela     MigrationCapability caps[];     /* Variadic array of capabilities */
25577608706SJuan Quintela };
25677608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet;
25777608706SJuan Quintela 
25877608706SJuan Quintela /* Define and initialize MigrateCapsSet */
25977608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
26077608706SJuan Quintela     MigrateCapsSet _name = {    \
26177608706SJuan Quintela         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
26277608706SJuan Quintela         .caps = { __VA_ARGS__ } \
26377608706SJuan Quintela     }
26477608706SJuan Quintela 
26577608706SJuan Quintela /* Background-snapshot compatibility check list */
26677608706SJuan Quintela static const
26777608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
26877608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_RAM,
26977608706SJuan Quintela     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
27077608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
27177608706SJuan Quintela     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
27277608706SJuan Quintela     MIGRATION_CAPABILITY_RETURN_PATH,
27377608706SJuan Quintela     MIGRATION_CAPABILITY_MULTIFD,
27477608706SJuan Quintela     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
27577608706SJuan Quintela     MIGRATION_CAPABILITY_AUTO_CONVERGE,
27677608706SJuan Quintela     MIGRATION_CAPABILITY_RELEASE_RAM,
27777608706SJuan Quintela     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
27877608706SJuan Quintela     MIGRATION_CAPABILITY_COMPRESS,
27977608706SJuan Quintela     MIGRATION_CAPABILITY_XBZRLE,
28077608706SJuan Quintela     MIGRATION_CAPABILITY_X_COLO,
28177608706SJuan Quintela     MIGRATION_CAPABILITY_VALIDATE_UUID,
28277608706SJuan Quintela     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
28377608706SJuan Quintela 
28477608706SJuan Quintela /**
28577608706SJuan Quintela  * @migration_caps_check - check capability compatibility
28677608706SJuan Quintela  *
28777608706SJuan Quintela  * @old_caps: old capability list
28877608706SJuan Quintela  * @new_caps: new capability list
28977608706SJuan Quintela  * @errp: set *errp if the check failed, with reason
29077608706SJuan Quintela  *
29177608706SJuan Quintela  * Returns true if check passed, otherwise false.
29277608706SJuan Quintela  */
29377608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
29477608706SJuan Quintela {
29577608706SJuan Quintela     MigrationIncomingState *mis = migration_incoming_get_current();
29677608706SJuan Quintela 
29777608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
29877608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
29977608706SJuan Quintela         error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
30077608706SJuan Quintela                    "block migration");
30177608706SJuan Quintela         error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
30277608706SJuan Quintela         return false;
30377608706SJuan Quintela     }
30477608706SJuan Quintela #endif
30577608706SJuan Quintela 
30677608706SJuan Quintela #ifndef CONFIG_REPLICATION
30777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
30877608706SJuan Quintela         error_setg(errp, "QEMU compiled without replication module"
30977608706SJuan Quintela                    " can't enable COLO");
31077608706SJuan Quintela         error_append_hint(errp, "Please enable replication before COLO.\n");
31177608706SJuan Quintela         return false;
31277608706SJuan Quintela     }
31377608706SJuan Quintela #endif
31477608706SJuan Quintela 
31577608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
31677608706SJuan Quintela         /* This check is reasonably expensive, so only when it's being
31777608706SJuan Quintela          * set the first time, also it's only the destination that needs
31877608706SJuan Quintela          * special support.
31977608706SJuan Quintela          */
32077608706SJuan Quintela         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
32177608706SJuan Quintela             runstate_check(RUN_STATE_INMIGRATE) &&
32277608706SJuan Quintela             !postcopy_ram_supported_by_host(mis)) {
32377608706SJuan Quintela             /* postcopy_ram_supported_by_host will have emitted a more
32477608706SJuan Quintela              * detailed message
32577608706SJuan Quintela              */
32677608706SJuan Quintela             error_setg(errp, "Postcopy is not supported");
32777608706SJuan Quintela             return false;
32877608706SJuan Quintela         }
32977608706SJuan Quintela 
33077608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
33177608706SJuan Quintela             error_setg(errp, "Postcopy is not compatible with ignore-shared");
33277608706SJuan Quintela             return false;
33377608706SJuan Quintela         }
334b405dfffSLeonardo Bras 
335b405dfffSLeonardo Bras         if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
336b405dfffSLeonardo Bras             error_setg(errp, "Postcopy is not yet compatible with multifd");
337b405dfffSLeonardo Bras             return false;
338b405dfffSLeonardo Bras         }
33977608706SJuan Quintela     }
34077608706SJuan Quintela 
34177608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
34277608706SJuan Quintela         WriteTrackingSupport wt_support;
34377608706SJuan Quintela         int idx;
34477608706SJuan Quintela         /*
34577608706SJuan Quintela          * Check if 'background-snapshot' capability is supported by
34677608706SJuan Quintela          * host kernel and compatible with guest memory configuration.
34777608706SJuan Quintela          */
34877608706SJuan Quintela         wt_support = migrate_query_write_tracking();
34977608706SJuan Quintela         if (wt_support < WT_SUPPORT_AVAILABLE) {
35077608706SJuan Quintela             error_setg(errp, "Background-snapshot is not supported by host kernel");
35177608706SJuan Quintela             return false;
35277608706SJuan Quintela         }
35377608706SJuan Quintela         if (wt_support < WT_SUPPORT_COMPATIBLE) {
35477608706SJuan Quintela             error_setg(errp, "Background-snapshot is not compatible "
35577608706SJuan Quintela                     "with guest memory configuration");
35677608706SJuan Quintela             return false;
35777608706SJuan Quintela         }
35877608706SJuan Quintela 
35977608706SJuan Quintela         /*
36077608706SJuan Quintela          * Check if there are any migration capabilities
36177608706SJuan Quintela          * incompatible with 'background-snapshot'.
36277608706SJuan Quintela          */
36377608706SJuan Quintela         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
36477608706SJuan Quintela             int incomp_cap = check_caps_background_snapshot.caps[idx];
36577608706SJuan Quintela             if (new_caps[incomp_cap]) {
36677608706SJuan Quintela                 error_setg(errp,
36777608706SJuan Quintela                         "Background-snapshot is not compatible with %s",
36877608706SJuan Quintela                         MigrationCapability_str(incomp_cap));
36977608706SJuan Quintela                 return false;
37077608706SJuan Quintela             }
37177608706SJuan Quintela         }
37277608706SJuan Quintela     }
37377608706SJuan Quintela 
37477608706SJuan Quintela #ifdef CONFIG_LINUX
37577608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
37677608706SJuan Quintela         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
37777608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
37877608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
37977608706SJuan Quintela          migrate_multifd_compression() ||
380*10d4703bSJuan Quintela          migrate_tls())) {
38177608706SJuan Quintela         error_setg(errp,
38277608706SJuan Quintela                    "Zero copy only available for non-compressed non-TLS multifd migration");
38377608706SJuan Quintela         return false;
38477608706SJuan Quintela     }
38577608706SJuan Quintela #else
38677608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
38777608706SJuan Quintela         error_setg(errp,
38877608706SJuan Quintela                    "Zero copy currently only available on Linux");
38977608706SJuan Quintela         return false;
39077608706SJuan Quintela     }
39177608706SJuan Quintela #endif
39277608706SJuan Quintela 
39377608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
39477608706SJuan Quintela         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
39577608706SJuan Quintela             error_setg(errp, "Postcopy preempt requires postcopy-ram");
39677608706SJuan Quintela             return false;
39777608706SJuan Quintela         }
39877608706SJuan Quintela 
39977608706SJuan Quintela         /*
40077608706SJuan Quintela          * Preempt mode requires urgent pages to be sent in separate
40177608706SJuan Quintela          * channel, OTOH compression logic will disorder all pages into
40277608706SJuan Quintela          * different compression channels, which is not compatible with the
40377608706SJuan Quintela          * preempt assumptions on channel assignments.
40477608706SJuan Quintela          */
40577608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
40677608706SJuan Quintela             error_setg(errp, "Postcopy preempt not compatible with compress");
40777608706SJuan Quintela             return false;
40877608706SJuan Quintela         }
40977608706SJuan Quintela     }
41077608706SJuan Quintela 
41177608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
41277608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
41377608706SJuan Quintela             error_setg(errp, "Multifd is not compatible with compress");
41477608706SJuan Quintela             return false;
41577608706SJuan Quintela         }
41677608706SJuan Quintela     }
41777608706SJuan Quintela 
41877608706SJuan Quintela     return true;
41977608706SJuan Quintela }
4204d0c6b69SJuan Quintela 
421f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp)
422f80196b7SJuan Quintela {
423f80196b7SJuan Quintela     MigrationState *s = migrate_get_current();
424f80196b7SJuan Quintela     bool new_caps[MIGRATION_CAPABILITY__MAX];
425f80196b7SJuan Quintela 
426f80196b7SJuan Quintela     if (migration_is_running(s->state)) {
427f80196b7SJuan Quintela         error_setg(errp, QERR_MIGRATION_ACTIVE);
428f80196b7SJuan Quintela         return false;
429f80196b7SJuan Quintela     }
430f80196b7SJuan Quintela 
431f80196b7SJuan Quintela     memcpy(new_caps, s->capabilities, sizeof(new_caps));
432f80196b7SJuan Quintela     new_caps[cap] = value;
433f80196b7SJuan Quintela 
434f80196b7SJuan Quintela     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
435f80196b7SJuan Quintela         return false;
436f80196b7SJuan Quintela     }
437f80196b7SJuan Quintela     s->capabilities[cap] = value;
438f80196b7SJuan Quintela     return true;
439f80196b7SJuan Quintela }
440f80196b7SJuan Quintela 
4414d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
4424d0c6b69SJuan Quintela {
4434d0c6b69SJuan Quintela     MigrationCapabilityStatusList *head = NULL, **tail = &head;
4444d0c6b69SJuan Quintela     MigrationCapabilityStatus *caps;
4454d0c6b69SJuan Quintela     MigrationState *s = migrate_get_current();
4464d0c6b69SJuan Quintela     int i;
4474d0c6b69SJuan Quintela 
4484d0c6b69SJuan Quintela     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
4494d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
4504d0c6b69SJuan Quintela         if (i == MIGRATION_CAPABILITY_BLOCK) {
4514d0c6b69SJuan Quintela             continue;
4524d0c6b69SJuan Quintela         }
4534d0c6b69SJuan Quintela #endif
4544d0c6b69SJuan Quintela         caps = g_malloc0(sizeof(*caps));
4554d0c6b69SJuan Quintela         caps->capability = i;
4564d0c6b69SJuan Quintela         caps->state = s->capabilities[i];
4574d0c6b69SJuan Quintela         QAPI_LIST_APPEND(tail, caps);
4584d0c6b69SJuan Quintela     }
4594d0c6b69SJuan Quintela 
4604d0c6b69SJuan Quintela     return head;
4614d0c6b69SJuan Quintela }
46245c1de13SJuan Quintela 
46345c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
46445c1de13SJuan Quintela                                   Error **errp)
46545c1de13SJuan Quintela {
46645c1de13SJuan Quintela     MigrationState *s = migrate_get_current();
46745c1de13SJuan Quintela     MigrationCapabilityStatusList *cap;
46845c1de13SJuan Quintela     bool new_caps[MIGRATION_CAPABILITY__MAX];
46945c1de13SJuan Quintela 
47045c1de13SJuan Quintela     if (migration_is_running(s->state)) {
47145c1de13SJuan Quintela         error_setg(errp, QERR_MIGRATION_ACTIVE);
47245c1de13SJuan Quintela         return;
47345c1de13SJuan Quintela     }
47445c1de13SJuan Quintela 
47545c1de13SJuan Quintela     memcpy(new_caps, s->capabilities, sizeof(new_caps));
47645c1de13SJuan Quintela     for (cap = params; cap; cap = cap->next) {
47745c1de13SJuan Quintela         new_caps[cap->value->capability] = cap->value->state;
47845c1de13SJuan Quintela     }
47945c1de13SJuan Quintela 
48045c1de13SJuan Quintela     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
48145c1de13SJuan Quintela         return;
48245c1de13SJuan Quintela     }
48345c1de13SJuan Quintela 
48445c1de13SJuan Quintela     for (cap = params; cap; cap = cap->next) {
48545c1de13SJuan Quintela         s->capabilities[cap->value->capability] = cap->value->state;
48645c1de13SJuan Quintela     }
48745c1de13SJuan Quintela }
4881dfc4b9eSJuan Quintela 
4891dfc4b9eSJuan Quintela /* parameters */
4901dfc4b9eSJuan Quintela 
4916f8be708SJuan Quintela bool migrate_block_incremental(void)
4926f8be708SJuan Quintela {
4936f8be708SJuan Quintela     MigrationState *s;
4946f8be708SJuan Quintela 
4956f8be708SJuan Quintela     s = migrate_get_current();
4966f8be708SJuan Quintela 
4976f8be708SJuan Quintela     return s->parameters.block_incremental;
4986f8be708SJuan Quintela }
4996f8be708SJuan Quintela 
500f94a858fSJuan Quintela uint32_t migrate_checkpoint_delay(void)
501f94a858fSJuan Quintela {
502f94a858fSJuan Quintela     MigrationState *s;
503f94a858fSJuan Quintela 
504f94a858fSJuan Quintela     s = migrate_get_current();
505f94a858fSJuan Quintela 
506f94a858fSJuan Quintela     return s->parameters.x_checkpoint_delay;
507f94a858fSJuan Quintela }
508f94a858fSJuan Quintela 
5091dfc4b9eSJuan Quintela int migrate_compress_level(void)
5101dfc4b9eSJuan Quintela {
5111dfc4b9eSJuan Quintela     MigrationState *s;
5121dfc4b9eSJuan Quintela 
5131dfc4b9eSJuan Quintela     s = migrate_get_current();
5141dfc4b9eSJuan Quintela 
5151dfc4b9eSJuan Quintela     return s->parameters.compress_level;
5161dfc4b9eSJuan Quintela }
5171dfc4b9eSJuan Quintela 
5181dfc4b9eSJuan Quintela int migrate_compress_threads(void)
5191dfc4b9eSJuan Quintela {
5201dfc4b9eSJuan Quintela     MigrationState *s;
5211dfc4b9eSJuan Quintela 
5221dfc4b9eSJuan Quintela     s = migrate_get_current();
5231dfc4b9eSJuan Quintela 
5241dfc4b9eSJuan Quintela     return s->parameters.compress_threads;
5251dfc4b9eSJuan Quintela }
5261dfc4b9eSJuan Quintela 
5271dfc4b9eSJuan Quintela int migrate_compress_wait_thread(void)
5281dfc4b9eSJuan Quintela {
5291dfc4b9eSJuan Quintela     MigrationState *s;
5301dfc4b9eSJuan Quintela 
5311dfc4b9eSJuan Quintela     s = migrate_get_current();
5321dfc4b9eSJuan Quintela 
5331dfc4b9eSJuan Quintela     return s->parameters.compress_wait_thread;
5341dfc4b9eSJuan Quintela }
5351dfc4b9eSJuan Quintela 
5369605c2acSJuan Quintela uint8_t migrate_cpu_throttle_increment(void)
5379605c2acSJuan Quintela {
5389605c2acSJuan Quintela     MigrationState *s;
5399605c2acSJuan Quintela 
5409605c2acSJuan Quintela     s = migrate_get_current();
5419605c2acSJuan Quintela 
5429605c2acSJuan Quintela     return s->parameters.cpu_throttle_increment;
5439605c2acSJuan Quintela }
5449605c2acSJuan Quintela 
5452a8ec380SJuan Quintela uint8_t migrate_cpu_throttle_initial(void)
5462a8ec380SJuan Quintela {
5472a8ec380SJuan Quintela     MigrationState *s;
5482a8ec380SJuan Quintela 
5492a8ec380SJuan Quintela     s = migrate_get_current();
5502a8ec380SJuan Quintela 
5512a8ec380SJuan Quintela     return s->parameters.cpu_throttle_initial;
5522a8ec380SJuan Quintela }
5532a8ec380SJuan Quintela 
554873f674cSJuan Quintela bool migrate_cpu_throttle_tailslow(void)
555873f674cSJuan Quintela {
556873f674cSJuan Quintela     MigrationState *s;
557873f674cSJuan Quintela 
558873f674cSJuan Quintela     s = migrate_get_current();
559873f674cSJuan Quintela 
560873f674cSJuan Quintela     return s->parameters.cpu_throttle_tailslow;
561873f674cSJuan Quintela }
562873f674cSJuan Quintela 
5631dfc4b9eSJuan Quintela int migrate_decompress_threads(void)
5641dfc4b9eSJuan Quintela {
5651dfc4b9eSJuan Quintela     MigrationState *s;
5661dfc4b9eSJuan Quintela 
5671dfc4b9eSJuan Quintela     s = migrate_get_current();
5681dfc4b9eSJuan Quintela 
5691dfc4b9eSJuan Quintela     return s->parameters.decompress_threads;
5701dfc4b9eSJuan Quintela }
5711dfc4b9eSJuan Quintela 
57224155bd0SJuan Quintela uint8_t migrate_max_cpu_throttle(void)
57324155bd0SJuan Quintela {
57424155bd0SJuan Quintela     MigrationState *s;
57524155bd0SJuan Quintela 
57624155bd0SJuan Quintela     s = migrate_get_current();
57724155bd0SJuan Quintela 
57824155bd0SJuan Quintela     return s->parameters.max_cpu_throttle;
57924155bd0SJuan Quintela }
58024155bd0SJuan Quintela 
5819c894df3SJuan Quintela uint64_t migrate_max_bandwidth(void)
5829c894df3SJuan Quintela {
5839c894df3SJuan Quintela     MigrationState *s;
5849c894df3SJuan Quintela 
5859c894df3SJuan Quintela     s = migrate_get_current();
5869c894df3SJuan Quintela 
5879c894df3SJuan Quintela     return s->parameters.max_bandwidth;
5889c894df3SJuan Quintela }
5899c894df3SJuan Quintela 
5901dfc4b9eSJuan Quintela int64_t migrate_max_postcopy_bandwidth(void)
5911dfc4b9eSJuan Quintela {
5921dfc4b9eSJuan Quintela     MigrationState *s;
5931dfc4b9eSJuan Quintela 
5941dfc4b9eSJuan Quintela     s = migrate_get_current();
5951dfc4b9eSJuan Quintela 
5961dfc4b9eSJuan Quintela     return s->parameters.max_postcopy_bandwidth;
5971dfc4b9eSJuan Quintela }
5981dfc4b9eSJuan Quintela 
5991dfc4b9eSJuan Quintela int migrate_multifd_channels(void)
6001dfc4b9eSJuan Quintela {
6011dfc4b9eSJuan Quintela     MigrationState *s;
6021dfc4b9eSJuan Quintela 
6031dfc4b9eSJuan Quintela     s = migrate_get_current();
6041dfc4b9eSJuan Quintela 
6051dfc4b9eSJuan Quintela     return s->parameters.multifd_channels;
6061dfc4b9eSJuan Quintela }
6071dfc4b9eSJuan Quintela 
6081dfc4b9eSJuan Quintela MultiFDCompression migrate_multifd_compression(void)
6091dfc4b9eSJuan Quintela {
6101dfc4b9eSJuan Quintela     MigrationState *s;
6111dfc4b9eSJuan Quintela 
6121dfc4b9eSJuan Quintela     s = migrate_get_current();
6131dfc4b9eSJuan Quintela 
6141dfc4b9eSJuan Quintela     assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
6151dfc4b9eSJuan Quintela     return s->parameters.multifd_compression;
6161dfc4b9eSJuan Quintela }
6171dfc4b9eSJuan Quintela 
6181dfc4b9eSJuan Quintela int migrate_multifd_zlib_level(void)
6191dfc4b9eSJuan Quintela {
6201dfc4b9eSJuan Quintela     MigrationState *s;
6211dfc4b9eSJuan Quintela 
6221dfc4b9eSJuan Quintela     s = migrate_get_current();
6231dfc4b9eSJuan Quintela 
6241dfc4b9eSJuan Quintela     return s->parameters.multifd_zlib_level;
6251dfc4b9eSJuan Quintela }
6261dfc4b9eSJuan Quintela 
6271dfc4b9eSJuan Quintela int migrate_multifd_zstd_level(void)
6281dfc4b9eSJuan Quintela {
6291dfc4b9eSJuan Quintela     MigrationState *s;
6301dfc4b9eSJuan Quintela 
6311dfc4b9eSJuan Quintela     s = migrate_get_current();
6321dfc4b9eSJuan Quintela 
6331dfc4b9eSJuan Quintela     return s->parameters.multifd_zstd_level;
6341dfc4b9eSJuan Quintela }
6351dfc4b9eSJuan Quintela 
6366499efdbSJuan Quintela uint8_t migrate_throttle_trigger_threshold(void)
6376499efdbSJuan Quintela {
6386499efdbSJuan Quintela     MigrationState *s;
6396499efdbSJuan Quintela 
6406499efdbSJuan Quintela     s = migrate_get_current();
6416499efdbSJuan Quintela 
6426499efdbSJuan Quintela     return s->parameters.throttle_trigger_threshold;
6436499efdbSJuan Quintela }
6446499efdbSJuan Quintela 
6451dfc4b9eSJuan Quintela uint64_t migrate_xbzrle_cache_size(void)
6461dfc4b9eSJuan Quintela {
6471dfc4b9eSJuan Quintela     MigrationState *s;
6481dfc4b9eSJuan Quintela 
6491dfc4b9eSJuan Quintela     s = migrate_get_current();
6501dfc4b9eSJuan Quintela 
6511dfc4b9eSJuan Quintela     return s->parameters.xbzrle_cache_size;
6521dfc4b9eSJuan Quintela }
6532682c4eeSJuan Quintela 
6542682c4eeSJuan Quintela /* parameters helpers */
6552682c4eeSJuan Quintela 
6562682c4eeSJuan Quintela AnnounceParameters *migrate_announce_params(void)
6572682c4eeSJuan Quintela {
6582682c4eeSJuan Quintela     static AnnounceParameters ap;
6592682c4eeSJuan Quintela 
6602682c4eeSJuan Quintela     MigrationState *s = migrate_get_current();
6612682c4eeSJuan Quintela 
6622682c4eeSJuan Quintela     ap.initial = s->parameters.announce_initial;
6632682c4eeSJuan Quintela     ap.max = s->parameters.announce_max;
6642682c4eeSJuan Quintela     ap.rounds = s->parameters.announce_rounds;
6652682c4eeSJuan Quintela     ap.step = s->parameters.announce_step;
6662682c4eeSJuan Quintela 
6672682c4eeSJuan Quintela     return &ap;
6682682c4eeSJuan Quintela }
6699c894df3SJuan Quintela 
6709c894df3SJuan Quintela MigrationParameters *qmp_query_migrate_parameters(Error **errp)
6719c894df3SJuan Quintela {
6729c894df3SJuan Quintela     MigrationParameters *params;
6739c894df3SJuan Quintela     MigrationState *s = migrate_get_current();
6749c894df3SJuan Quintela 
6759c894df3SJuan Quintela     /* TODO use QAPI_CLONE() instead of duplicating it inline */
6769c894df3SJuan Quintela     params = g_malloc0(sizeof(*params));
6779c894df3SJuan Quintela     params->has_compress_level = true;
6789c894df3SJuan Quintela     params->compress_level = s->parameters.compress_level;
6799c894df3SJuan Quintela     params->has_compress_threads = true;
6809c894df3SJuan Quintela     params->compress_threads = s->parameters.compress_threads;
6819c894df3SJuan Quintela     params->has_compress_wait_thread = true;
6829c894df3SJuan Quintela     params->compress_wait_thread = s->parameters.compress_wait_thread;
6839c894df3SJuan Quintela     params->has_decompress_threads = true;
6849c894df3SJuan Quintela     params->decompress_threads = s->parameters.decompress_threads;
6859c894df3SJuan Quintela     params->has_throttle_trigger_threshold = true;
6869c894df3SJuan Quintela     params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
6879c894df3SJuan Quintela     params->has_cpu_throttle_initial = true;
6889c894df3SJuan Quintela     params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
6899c894df3SJuan Quintela     params->has_cpu_throttle_increment = true;
6909c894df3SJuan Quintela     params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
6919c894df3SJuan Quintela     params->has_cpu_throttle_tailslow = true;
6929c894df3SJuan Quintela     params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
6939c894df3SJuan Quintela     params->tls_creds = g_strdup(s->parameters.tls_creds);
6949c894df3SJuan Quintela     params->tls_hostname = g_strdup(s->parameters.tls_hostname);
6959c894df3SJuan Quintela     params->tls_authz = g_strdup(s->parameters.tls_authz ?
6969c894df3SJuan Quintela                                  s->parameters.tls_authz : "");
6979c894df3SJuan Quintela     params->has_max_bandwidth = true;
6989c894df3SJuan Quintela     params->max_bandwidth = s->parameters.max_bandwidth;
6999c894df3SJuan Quintela     params->has_downtime_limit = true;
7009c894df3SJuan Quintela     params->downtime_limit = s->parameters.downtime_limit;
7019c894df3SJuan Quintela     params->has_x_checkpoint_delay = true;
7029c894df3SJuan Quintela     params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
7039c894df3SJuan Quintela     params->has_block_incremental = true;
7049c894df3SJuan Quintela     params->block_incremental = s->parameters.block_incremental;
7059c894df3SJuan Quintela     params->has_multifd_channels = true;
7069c894df3SJuan Quintela     params->multifd_channels = s->parameters.multifd_channels;
7079c894df3SJuan Quintela     params->has_multifd_compression = true;
7089c894df3SJuan Quintela     params->multifd_compression = s->parameters.multifd_compression;
7099c894df3SJuan Quintela     params->has_multifd_zlib_level = true;
7109c894df3SJuan Quintela     params->multifd_zlib_level = s->parameters.multifd_zlib_level;
7119c894df3SJuan Quintela     params->has_multifd_zstd_level = true;
7129c894df3SJuan Quintela     params->multifd_zstd_level = s->parameters.multifd_zstd_level;
7139c894df3SJuan Quintela     params->has_xbzrle_cache_size = true;
7149c894df3SJuan Quintela     params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
7159c894df3SJuan Quintela     params->has_max_postcopy_bandwidth = true;
7169c894df3SJuan Quintela     params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
7179c894df3SJuan Quintela     params->has_max_cpu_throttle = true;
7189c894df3SJuan Quintela     params->max_cpu_throttle = s->parameters.max_cpu_throttle;
7199c894df3SJuan Quintela     params->has_announce_initial = true;
7209c894df3SJuan Quintela     params->announce_initial = s->parameters.announce_initial;
7219c894df3SJuan Quintela     params->has_announce_max = true;
7229c894df3SJuan Quintela     params->announce_max = s->parameters.announce_max;
7239c894df3SJuan Quintela     params->has_announce_rounds = true;
7249c894df3SJuan Quintela     params->announce_rounds = s->parameters.announce_rounds;
7259c894df3SJuan Quintela     params->has_announce_step = true;
7269c894df3SJuan Quintela     params->announce_step = s->parameters.announce_step;
7279c894df3SJuan Quintela 
7289c894df3SJuan Quintela     if (s->parameters.has_block_bitmap_mapping) {
7299c894df3SJuan Quintela         params->has_block_bitmap_mapping = true;
7309c894df3SJuan Quintela         params->block_bitmap_mapping =
7319c894df3SJuan Quintela             QAPI_CLONE(BitmapMigrationNodeAliasList,
7329c894df3SJuan Quintela                        s->parameters.block_bitmap_mapping);
7339c894df3SJuan Quintela     }
7349c894df3SJuan Quintela 
7359c894df3SJuan Quintela     return params;
7369c894df3SJuan Quintela }
737