xref: /openbmc/qemu/migration/options.c (revision 4d0c6b695bf5252402ebf967f83baebfd2f4b91e)
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"
1577608706SJuan Quintela #include "qapi/error.h"
16*4d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h"
1777608706SJuan Quintela #include "sysemu/runstate.h"
181f0776f1SJuan Quintela #include "migration.h"
1977608706SJuan Quintela #include "ram.h"
201f0776f1SJuan Quintela #include "options.h"
211f0776f1SJuan Quintela 
221f0776f1SJuan Quintela bool migrate_auto_converge(void)
231f0776f1SJuan Quintela {
241f0776f1SJuan Quintela     MigrationState *s;
251f0776f1SJuan Quintela 
261f0776f1SJuan Quintela     s = migrate_get_current();
271f0776f1SJuan Quintela 
281f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
291f0776f1SJuan Quintela }
301f0776f1SJuan Quintela 
311f0776f1SJuan Quintela bool migrate_background_snapshot(void)
321f0776f1SJuan Quintela {
331f0776f1SJuan Quintela     MigrationState *s;
341f0776f1SJuan Quintela 
351f0776f1SJuan Quintela     s = migrate_get_current();
361f0776f1SJuan Quintela 
371f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
381f0776f1SJuan Quintela }
391f0776f1SJuan Quintela 
409d4b1e5fSJuan Quintela bool migrate_block(void)
419d4b1e5fSJuan Quintela {
429d4b1e5fSJuan Quintela     MigrationState *s;
439d4b1e5fSJuan Quintela 
449d4b1e5fSJuan Quintela     s = migrate_get_current();
459d4b1e5fSJuan Quintela 
469d4b1e5fSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
479d4b1e5fSJuan Quintela }
489d4b1e5fSJuan Quintela 
495e804644SJuan Quintela bool migrate_colo(void)
505e804644SJuan Quintela {
515e804644SJuan Quintela     MigrationState *s = migrate_get_current();
525e804644SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
535e804644SJuan Quintela }
545e804644SJuan Quintela 
55a7a94d14SJuan Quintela bool migrate_compress(void)
56a7a94d14SJuan Quintela {
57a7a94d14SJuan Quintela     MigrationState *s;
58a7a94d14SJuan Quintela 
59a7a94d14SJuan Quintela     s = migrate_get_current();
60a7a94d14SJuan Quintela 
61a7a94d14SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
62a7a94d14SJuan Quintela }
63a7a94d14SJuan Quintela 
641f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void)
651f0776f1SJuan Quintela {
661f0776f1SJuan Quintela     MigrationState *s;
671f0776f1SJuan Quintela 
681f0776f1SJuan Quintela     s = migrate_get_current();
691f0776f1SJuan Quintela 
701f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
711f0776f1SJuan Quintela }
721f0776f1SJuan Quintela 
73b890902cSJuan Quintela bool migrate_events(void)
74b890902cSJuan Quintela {
75b890902cSJuan Quintela     MigrationState *s;
76b890902cSJuan Quintela 
77b890902cSJuan Quintela     s = migrate_get_current();
78b890902cSJuan Quintela 
79b890902cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
80b890902cSJuan Quintela }
81b890902cSJuan Quintela 
821f0776f1SJuan Quintela bool migrate_ignore_shared(void)
831f0776f1SJuan Quintela {
841f0776f1SJuan Quintela     MigrationState *s;
851f0776f1SJuan Quintela 
861f0776f1SJuan Quintela     s = migrate_get_current();
871f0776f1SJuan Quintela 
881f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
891f0776f1SJuan Quintela }
901f0776f1SJuan Quintela 
911f0776f1SJuan Quintela bool migrate_late_block_activate(void)
921f0776f1SJuan Quintela {
931f0776f1SJuan Quintela     MigrationState *s;
941f0776f1SJuan Quintela 
951f0776f1SJuan Quintela     s = migrate_get_current();
961f0776f1SJuan Quintela 
971f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
981f0776f1SJuan Quintela }
991f0776f1SJuan Quintela 
10051b07548SJuan Quintela bool migrate_multifd(void)
10151b07548SJuan Quintela {
10251b07548SJuan Quintela     MigrationState *s;
10351b07548SJuan Quintela 
10451b07548SJuan Quintela     s = migrate_get_current();
10551b07548SJuan Quintela 
10651b07548SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
10751b07548SJuan Quintela }
10851b07548SJuan Quintela 
1091f0776f1SJuan Quintela bool migrate_pause_before_switchover(void)
1101f0776f1SJuan Quintela {
1111f0776f1SJuan Quintela     MigrationState *s;
1121f0776f1SJuan Quintela 
1131f0776f1SJuan Quintela     s = migrate_get_current();
1141f0776f1SJuan Quintela 
1151f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
1161f0776f1SJuan Quintela }
1171f0776f1SJuan Quintela 
1181f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void)
1191f0776f1SJuan Quintela {
1201f0776f1SJuan Quintela     MigrationState *s;
1211f0776f1SJuan Quintela 
1221f0776f1SJuan Quintela     s = migrate_get_current();
1231f0776f1SJuan Quintela 
1241f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
1251f0776f1SJuan Quintela }
1261f0776f1SJuan Quintela 
1271f0776f1SJuan Quintela bool migrate_postcopy_preempt(void)
1281f0776f1SJuan Quintela {
1291f0776f1SJuan Quintela     MigrationState *s;
1301f0776f1SJuan Quintela 
1311f0776f1SJuan Quintela     s = migrate_get_current();
1321f0776f1SJuan Quintela 
1331f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
1341f0776f1SJuan Quintela }
1351f0776f1SJuan Quintela 
1361f0776f1SJuan Quintela bool migrate_postcopy_ram(void)
1371f0776f1SJuan Quintela {
1381f0776f1SJuan Quintela     MigrationState *s;
1391f0776f1SJuan Quintela 
1401f0776f1SJuan Quintela     s = migrate_get_current();
1411f0776f1SJuan Quintela 
1421f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
1431f0776f1SJuan Quintela }
1441f0776f1SJuan Quintela 
14517cba690SJuan Quintela bool migrate_rdma_pin_all(void)
14617cba690SJuan Quintela {
14717cba690SJuan Quintela     MigrationState *s = migrate_get_current();
14817cba690SJuan Quintela 
14917cba690SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
15017cba690SJuan Quintela }
15117cba690SJuan Quintela 
1521f0776f1SJuan Quintela bool migrate_release_ram(void)
1531f0776f1SJuan Quintela {
1541f0776f1SJuan Quintela     MigrationState *s;
1551f0776f1SJuan Quintela 
1561f0776f1SJuan Quintela     s = migrate_get_current();
1571f0776f1SJuan Quintela 
1581f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
1591f0776f1SJuan Quintela }
1601f0776f1SJuan Quintela 
16138ad1110SJuan Quintela bool migrate_return_path(void)
16238ad1110SJuan Quintela {
16338ad1110SJuan Quintela     MigrationState *s;
16438ad1110SJuan Quintela 
16538ad1110SJuan Quintela     s = migrate_get_current();
16638ad1110SJuan Quintela 
16738ad1110SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
16838ad1110SJuan Quintela }
16938ad1110SJuan Quintela 
1701f0776f1SJuan Quintela bool migrate_validate_uuid(void)
1711f0776f1SJuan Quintela {
1721f0776f1SJuan Quintela     MigrationState *s;
1731f0776f1SJuan Quintela 
1741f0776f1SJuan Quintela     s = migrate_get_current();
1751f0776f1SJuan Quintela 
1761f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
1771f0776f1SJuan Quintela }
1781f0776f1SJuan Quintela 
17987dca0c9SJuan Quintela bool migrate_xbzrle(void)
18087dca0c9SJuan Quintela {
18187dca0c9SJuan Quintela     MigrationState *s;
18287dca0c9SJuan Quintela 
18387dca0c9SJuan Quintela     s = migrate_get_current();
18487dca0c9SJuan Quintela 
18587dca0c9SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
18687dca0c9SJuan Quintela }
18787dca0c9SJuan Quintela 
1881f0776f1SJuan Quintela bool migrate_zero_blocks(void)
1891f0776f1SJuan Quintela {
1901f0776f1SJuan Quintela     MigrationState *s;
1911f0776f1SJuan Quintela 
1921f0776f1SJuan Quintela     s = migrate_get_current();
1931f0776f1SJuan Quintela 
1941f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
1951f0776f1SJuan Quintela }
196b4bc342cSJuan Quintela 
197b4bc342cSJuan Quintela bool migrate_zero_copy_send(void)
198b4bc342cSJuan Quintela {
199b4bc342cSJuan Quintela     MigrationState *s;
200b4bc342cSJuan Quintela 
201b4bc342cSJuan Quintela     s = migrate_get_current();
202b4bc342cSJuan Quintela 
203b4bc342cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
204b4bc342cSJuan Quintela }
20577608706SJuan Quintela typedef enum WriteTrackingSupport {
20677608706SJuan Quintela     WT_SUPPORT_UNKNOWN = 0,
20777608706SJuan Quintela     WT_SUPPORT_ABSENT,
20877608706SJuan Quintela     WT_SUPPORT_AVAILABLE,
20977608706SJuan Quintela     WT_SUPPORT_COMPATIBLE
21077608706SJuan Quintela } WriteTrackingSupport;
21177608706SJuan Quintela 
21277608706SJuan Quintela static
21377608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void)
21477608706SJuan Quintela {
21577608706SJuan Quintela     /* Check if kernel supports required UFFD features */
21677608706SJuan Quintela     if (!ram_write_tracking_available()) {
21777608706SJuan Quintela         return WT_SUPPORT_ABSENT;
21877608706SJuan Quintela     }
21977608706SJuan Quintela     /*
22077608706SJuan Quintela      * Check if current memory configuration is
22177608706SJuan Quintela      * compatible with required UFFD features.
22277608706SJuan Quintela      */
22377608706SJuan Quintela     if (!ram_write_tracking_compatible()) {
22477608706SJuan Quintela         return WT_SUPPORT_AVAILABLE;
22577608706SJuan Quintela     }
22677608706SJuan Quintela 
22777608706SJuan Quintela     return WT_SUPPORT_COMPATIBLE;
22877608706SJuan Quintela }
22977608706SJuan Quintela 
23077608706SJuan Quintela /* Migration capabilities set */
23177608706SJuan Quintela struct MigrateCapsSet {
23277608706SJuan Quintela     int size;                       /* Capability set size */
23377608706SJuan Quintela     MigrationCapability caps[];     /* Variadic array of capabilities */
23477608706SJuan Quintela };
23577608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet;
23677608706SJuan Quintela 
23777608706SJuan Quintela /* Define and initialize MigrateCapsSet */
23877608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
23977608706SJuan Quintela     MigrateCapsSet _name = {    \
24077608706SJuan Quintela         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
24177608706SJuan Quintela         .caps = { __VA_ARGS__ } \
24277608706SJuan Quintela     }
24377608706SJuan Quintela 
24477608706SJuan Quintela /* Background-snapshot compatibility check list */
24577608706SJuan Quintela static const
24677608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
24777608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_RAM,
24877608706SJuan Quintela     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
24977608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
25077608706SJuan Quintela     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
25177608706SJuan Quintela     MIGRATION_CAPABILITY_RETURN_PATH,
25277608706SJuan Quintela     MIGRATION_CAPABILITY_MULTIFD,
25377608706SJuan Quintela     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
25477608706SJuan Quintela     MIGRATION_CAPABILITY_AUTO_CONVERGE,
25577608706SJuan Quintela     MIGRATION_CAPABILITY_RELEASE_RAM,
25677608706SJuan Quintela     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
25777608706SJuan Quintela     MIGRATION_CAPABILITY_COMPRESS,
25877608706SJuan Quintela     MIGRATION_CAPABILITY_XBZRLE,
25977608706SJuan Quintela     MIGRATION_CAPABILITY_X_COLO,
26077608706SJuan Quintela     MIGRATION_CAPABILITY_VALIDATE_UUID,
26177608706SJuan Quintela     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
26277608706SJuan Quintela 
26377608706SJuan Quintela /**
26477608706SJuan Quintela  * @migration_caps_check - check capability compatibility
26577608706SJuan Quintela  *
26677608706SJuan Quintela  * @old_caps: old capability list
26777608706SJuan Quintela  * @new_caps: new capability list
26877608706SJuan Quintela  * @errp: set *errp if the check failed, with reason
26977608706SJuan Quintela  *
27077608706SJuan Quintela  * Returns true if check passed, otherwise false.
27177608706SJuan Quintela  */
27277608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
27377608706SJuan Quintela {
27477608706SJuan Quintela     MigrationIncomingState *mis = migration_incoming_get_current();
27577608706SJuan Quintela 
27677608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
27777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
27877608706SJuan Quintela         error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
27977608706SJuan Quintela                    "block migration");
28077608706SJuan Quintela         error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
28177608706SJuan Quintela         return false;
28277608706SJuan Quintela     }
28377608706SJuan Quintela #endif
28477608706SJuan Quintela 
28577608706SJuan Quintela #ifndef CONFIG_REPLICATION
28677608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
28777608706SJuan Quintela         error_setg(errp, "QEMU compiled without replication module"
28877608706SJuan Quintela                    " can't enable COLO");
28977608706SJuan Quintela         error_append_hint(errp, "Please enable replication before COLO.\n");
29077608706SJuan Quintela         return false;
29177608706SJuan Quintela     }
29277608706SJuan Quintela #endif
29377608706SJuan Quintela 
29477608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
29577608706SJuan Quintela         /* This check is reasonably expensive, so only when it's being
29677608706SJuan Quintela          * set the first time, also it's only the destination that needs
29777608706SJuan Quintela          * special support.
29877608706SJuan Quintela          */
29977608706SJuan Quintela         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
30077608706SJuan Quintela             runstate_check(RUN_STATE_INMIGRATE) &&
30177608706SJuan Quintela             !postcopy_ram_supported_by_host(mis)) {
30277608706SJuan Quintela             /* postcopy_ram_supported_by_host will have emitted a more
30377608706SJuan Quintela              * detailed message
30477608706SJuan Quintela              */
30577608706SJuan Quintela             error_setg(errp, "Postcopy is not supported");
30677608706SJuan Quintela             return false;
30777608706SJuan Quintela         }
30877608706SJuan Quintela 
30977608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
31077608706SJuan Quintela             error_setg(errp, "Postcopy is not compatible with ignore-shared");
31177608706SJuan Quintela             return false;
31277608706SJuan Quintela         }
31377608706SJuan Quintela     }
31477608706SJuan Quintela 
31577608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
31677608706SJuan Quintela         WriteTrackingSupport wt_support;
31777608706SJuan Quintela         int idx;
31877608706SJuan Quintela         /*
31977608706SJuan Quintela          * Check if 'background-snapshot' capability is supported by
32077608706SJuan Quintela          * host kernel and compatible with guest memory configuration.
32177608706SJuan Quintela          */
32277608706SJuan Quintela         wt_support = migrate_query_write_tracking();
32377608706SJuan Quintela         if (wt_support < WT_SUPPORT_AVAILABLE) {
32477608706SJuan Quintela             error_setg(errp, "Background-snapshot is not supported by host kernel");
32577608706SJuan Quintela             return false;
32677608706SJuan Quintela         }
32777608706SJuan Quintela         if (wt_support < WT_SUPPORT_COMPATIBLE) {
32877608706SJuan Quintela             error_setg(errp, "Background-snapshot is not compatible "
32977608706SJuan Quintela                     "with guest memory configuration");
33077608706SJuan Quintela             return false;
33177608706SJuan Quintela         }
33277608706SJuan Quintela 
33377608706SJuan Quintela         /*
33477608706SJuan Quintela          * Check if there are any migration capabilities
33577608706SJuan Quintela          * incompatible with 'background-snapshot'.
33677608706SJuan Quintela          */
33777608706SJuan Quintela         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
33877608706SJuan Quintela             int incomp_cap = check_caps_background_snapshot.caps[idx];
33977608706SJuan Quintela             if (new_caps[incomp_cap]) {
34077608706SJuan Quintela                 error_setg(errp,
34177608706SJuan Quintela                         "Background-snapshot is not compatible with %s",
34277608706SJuan Quintela                         MigrationCapability_str(incomp_cap));
34377608706SJuan Quintela                 return false;
34477608706SJuan Quintela             }
34577608706SJuan Quintela         }
34677608706SJuan Quintela     }
34777608706SJuan Quintela 
34877608706SJuan Quintela #ifdef CONFIG_LINUX
34977608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
35077608706SJuan Quintela         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
35177608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
35277608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
35377608706SJuan Quintela          migrate_multifd_compression() ||
35477608706SJuan Quintela          migrate_use_tls())) {
35577608706SJuan Quintela         error_setg(errp,
35677608706SJuan Quintela                    "Zero copy only available for non-compressed non-TLS multifd migration");
35777608706SJuan Quintela         return false;
35877608706SJuan Quintela     }
35977608706SJuan Quintela #else
36077608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
36177608706SJuan Quintela         error_setg(errp,
36277608706SJuan Quintela                    "Zero copy currently only available on Linux");
36377608706SJuan Quintela         return false;
36477608706SJuan Quintela     }
36577608706SJuan Quintela #endif
36677608706SJuan Quintela 
36777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
36877608706SJuan Quintela         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
36977608706SJuan Quintela             error_setg(errp, "Postcopy preempt requires postcopy-ram");
37077608706SJuan Quintela             return false;
37177608706SJuan Quintela         }
37277608706SJuan Quintela 
37377608706SJuan Quintela         /*
37477608706SJuan Quintela          * Preempt mode requires urgent pages to be sent in separate
37577608706SJuan Quintela          * channel, OTOH compression logic will disorder all pages into
37677608706SJuan Quintela          * different compression channels, which is not compatible with the
37777608706SJuan Quintela          * preempt assumptions on channel assignments.
37877608706SJuan Quintela          */
37977608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
38077608706SJuan Quintela             error_setg(errp, "Postcopy preempt not compatible with compress");
38177608706SJuan Quintela             return false;
38277608706SJuan Quintela         }
38377608706SJuan Quintela     }
38477608706SJuan Quintela 
38577608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
38677608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
38777608706SJuan Quintela             error_setg(errp, "Multifd is not compatible with compress");
38877608706SJuan Quintela             return false;
38977608706SJuan Quintela         }
39077608706SJuan Quintela     }
39177608706SJuan Quintela 
39277608706SJuan Quintela     return true;
39377608706SJuan Quintela }
394*4d0c6b69SJuan Quintela 
395*4d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
396*4d0c6b69SJuan Quintela {
397*4d0c6b69SJuan Quintela     MigrationCapabilityStatusList *head = NULL, **tail = &head;
398*4d0c6b69SJuan Quintela     MigrationCapabilityStatus *caps;
399*4d0c6b69SJuan Quintela     MigrationState *s = migrate_get_current();
400*4d0c6b69SJuan Quintela     int i;
401*4d0c6b69SJuan Quintela 
402*4d0c6b69SJuan Quintela     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
403*4d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
404*4d0c6b69SJuan Quintela         if (i == MIGRATION_CAPABILITY_BLOCK) {
405*4d0c6b69SJuan Quintela             continue;
406*4d0c6b69SJuan Quintela         }
407*4d0c6b69SJuan Quintela #endif
408*4d0c6b69SJuan Quintela         caps = g_malloc0(sizeof(*caps));
409*4d0c6b69SJuan Quintela         caps->capability = i;
410*4d0c6b69SJuan Quintela         caps->state = s->capabilities[i];
411*4d0c6b69SJuan Quintela         QAPI_LIST_APPEND(tail, caps);
412*4d0c6b69SJuan Quintela     }
413*4d0c6b69SJuan Quintela 
414*4d0c6b69SJuan Quintela     return head;
415*4d0c6b69SJuan Quintela }
416