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" 164d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h" 17f80196b7SJuan Quintela #include "qapi/qmp/qerror.h" 1877608706SJuan Quintela #include "sysemu/runstate.h" 192682c4eeSJuan Quintela #include "migration/misc.h" 201f0776f1SJuan Quintela #include "migration.h" 2177608706SJuan Quintela #include "ram.h" 221f0776f1SJuan Quintela #include "options.h" 231f0776f1SJuan Quintela 241f0776f1SJuan Quintela bool migrate_auto_converge(void) 251f0776f1SJuan Quintela { 261f0776f1SJuan Quintela MigrationState *s; 271f0776f1SJuan Quintela 281f0776f1SJuan Quintela s = migrate_get_current(); 291f0776f1SJuan Quintela 301f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 311f0776f1SJuan Quintela } 321f0776f1SJuan Quintela 331f0776f1SJuan Quintela bool migrate_background_snapshot(void) 341f0776f1SJuan Quintela { 351f0776f1SJuan Quintela MigrationState *s; 361f0776f1SJuan Quintela 371f0776f1SJuan Quintela s = migrate_get_current(); 381f0776f1SJuan Quintela 391f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 401f0776f1SJuan Quintela } 411f0776f1SJuan Quintela 429d4b1e5fSJuan Quintela bool migrate_block(void) 439d4b1e5fSJuan Quintela { 449d4b1e5fSJuan Quintela MigrationState *s; 459d4b1e5fSJuan Quintela 469d4b1e5fSJuan Quintela s = migrate_get_current(); 479d4b1e5fSJuan Quintela 489d4b1e5fSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 499d4b1e5fSJuan Quintela } 509d4b1e5fSJuan Quintela 515e804644SJuan Quintela bool migrate_colo(void) 525e804644SJuan Quintela { 535e804644SJuan Quintela MigrationState *s = migrate_get_current(); 545e804644SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 555e804644SJuan Quintela } 565e804644SJuan Quintela 57a7a94d14SJuan Quintela bool migrate_compress(void) 58a7a94d14SJuan Quintela { 59a7a94d14SJuan Quintela MigrationState *s; 60a7a94d14SJuan Quintela 61a7a94d14SJuan Quintela s = migrate_get_current(); 62a7a94d14SJuan Quintela 63a7a94d14SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 64a7a94d14SJuan Quintela } 65a7a94d14SJuan Quintela 661f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void) 671f0776f1SJuan Quintela { 681f0776f1SJuan Quintela MigrationState *s; 691f0776f1SJuan Quintela 701f0776f1SJuan Quintela s = migrate_get_current(); 711f0776f1SJuan Quintela 721f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 731f0776f1SJuan Quintela } 741f0776f1SJuan Quintela 75b890902cSJuan Quintela bool migrate_events(void) 76b890902cSJuan Quintela { 77b890902cSJuan Quintela MigrationState *s; 78b890902cSJuan Quintela 79b890902cSJuan Quintela s = migrate_get_current(); 80b890902cSJuan Quintela 81b890902cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 82b890902cSJuan Quintela } 83b890902cSJuan Quintela 841f0776f1SJuan Quintela bool migrate_ignore_shared(void) 851f0776f1SJuan Quintela { 861f0776f1SJuan Quintela MigrationState *s; 871f0776f1SJuan Quintela 881f0776f1SJuan Quintela s = migrate_get_current(); 891f0776f1SJuan Quintela 901f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 911f0776f1SJuan Quintela } 921f0776f1SJuan Quintela 931f0776f1SJuan Quintela bool migrate_late_block_activate(void) 941f0776f1SJuan Quintela { 951f0776f1SJuan Quintela MigrationState *s; 961f0776f1SJuan Quintela 971f0776f1SJuan Quintela s = migrate_get_current(); 981f0776f1SJuan Quintela 991f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 1001f0776f1SJuan Quintela } 1011f0776f1SJuan Quintela 10251b07548SJuan Quintela bool migrate_multifd(void) 10351b07548SJuan Quintela { 10451b07548SJuan Quintela MigrationState *s; 10551b07548SJuan Quintela 10651b07548SJuan Quintela s = migrate_get_current(); 10751b07548SJuan Quintela 10851b07548SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 10951b07548SJuan Quintela } 11051b07548SJuan Quintela 1111f0776f1SJuan Quintela bool migrate_pause_before_switchover(void) 1121f0776f1SJuan Quintela { 1131f0776f1SJuan Quintela MigrationState *s; 1141f0776f1SJuan Quintela 1151f0776f1SJuan Quintela s = migrate_get_current(); 1161f0776f1SJuan Quintela 1171f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 1181f0776f1SJuan Quintela } 1191f0776f1SJuan Quintela 1201f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void) 1211f0776f1SJuan Quintela { 1221f0776f1SJuan Quintela MigrationState *s; 1231f0776f1SJuan Quintela 1241f0776f1SJuan Quintela s = migrate_get_current(); 1251f0776f1SJuan Quintela 1261f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 1271f0776f1SJuan Quintela } 1281f0776f1SJuan Quintela 1291f0776f1SJuan Quintela bool migrate_postcopy_preempt(void) 1301f0776f1SJuan Quintela { 1311f0776f1SJuan Quintela MigrationState *s; 1321f0776f1SJuan Quintela 1331f0776f1SJuan Quintela s = migrate_get_current(); 1341f0776f1SJuan Quintela 1351f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 1361f0776f1SJuan Quintela } 1371f0776f1SJuan Quintela 1381f0776f1SJuan Quintela bool migrate_postcopy_ram(void) 1391f0776f1SJuan Quintela { 1401f0776f1SJuan Quintela MigrationState *s; 1411f0776f1SJuan Quintela 1421f0776f1SJuan Quintela s = migrate_get_current(); 1431f0776f1SJuan Quintela 1441f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 1451f0776f1SJuan Quintela } 1461f0776f1SJuan Quintela 14717cba690SJuan Quintela bool migrate_rdma_pin_all(void) 14817cba690SJuan Quintela { 14917cba690SJuan Quintela MigrationState *s = migrate_get_current(); 15017cba690SJuan Quintela 15117cba690SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 15217cba690SJuan Quintela } 15317cba690SJuan Quintela 1541f0776f1SJuan Quintela bool migrate_release_ram(void) 1551f0776f1SJuan Quintela { 1561f0776f1SJuan Quintela MigrationState *s; 1571f0776f1SJuan Quintela 1581f0776f1SJuan Quintela s = migrate_get_current(); 1591f0776f1SJuan Quintela 1601f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 1611f0776f1SJuan Quintela } 1621f0776f1SJuan Quintela 16338ad1110SJuan Quintela bool migrate_return_path(void) 16438ad1110SJuan Quintela { 16538ad1110SJuan Quintela MigrationState *s; 16638ad1110SJuan Quintela 16738ad1110SJuan Quintela s = migrate_get_current(); 16838ad1110SJuan Quintela 16938ad1110SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 17038ad1110SJuan Quintela } 17138ad1110SJuan Quintela 1721f0776f1SJuan Quintela bool migrate_validate_uuid(void) 1731f0776f1SJuan Quintela { 1741f0776f1SJuan Quintela MigrationState *s; 1751f0776f1SJuan Quintela 1761f0776f1SJuan Quintela s = migrate_get_current(); 1771f0776f1SJuan Quintela 1781f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 1791f0776f1SJuan Quintela } 1801f0776f1SJuan Quintela 18187dca0c9SJuan Quintela bool migrate_xbzrle(void) 18287dca0c9SJuan Quintela { 18387dca0c9SJuan Quintela MigrationState *s; 18487dca0c9SJuan Quintela 18587dca0c9SJuan Quintela s = migrate_get_current(); 18687dca0c9SJuan Quintela 18787dca0c9SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 18887dca0c9SJuan Quintela } 18987dca0c9SJuan Quintela 1901f0776f1SJuan Quintela bool migrate_zero_blocks(void) 1911f0776f1SJuan Quintela { 1921f0776f1SJuan Quintela MigrationState *s; 1931f0776f1SJuan Quintela 1941f0776f1SJuan Quintela s = migrate_get_current(); 1951f0776f1SJuan Quintela 1961f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 1971f0776f1SJuan Quintela } 198b4bc342cSJuan Quintela 199b4bc342cSJuan Quintela bool migrate_zero_copy_send(void) 200b4bc342cSJuan Quintela { 201b4bc342cSJuan Quintela MigrationState *s; 202b4bc342cSJuan Quintela 203b4bc342cSJuan Quintela s = migrate_get_current(); 204b4bc342cSJuan Quintela 205b4bc342cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 206b4bc342cSJuan Quintela } 207*f774fde5SJuan Quintela 208*f774fde5SJuan Quintela /* pseudo capabilities */ 209*f774fde5SJuan Quintela 210*f774fde5SJuan Quintela bool migrate_postcopy(void) 211*f774fde5SJuan Quintela { 212*f774fde5SJuan Quintela return migrate_postcopy_ram() || migrate_dirty_bitmaps(); 213*f774fde5SJuan Quintela } 214*f774fde5SJuan Quintela 21577608706SJuan Quintela typedef enum WriteTrackingSupport { 21677608706SJuan Quintela WT_SUPPORT_UNKNOWN = 0, 21777608706SJuan Quintela WT_SUPPORT_ABSENT, 21877608706SJuan Quintela WT_SUPPORT_AVAILABLE, 21977608706SJuan Quintela WT_SUPPORT_COMPATIBLE 22077608706SJuan Quintela } WriteTrackingSupport; 22177608706SJuan Quintela 22277608706SJuan Quintela static 22377608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void) 22477608706SJuan Quintela { 22577608706SJuan Quintela /* Check if kernel supports required UFFD features */ 22677608706SJuan Quintela if (!ram_write_tracking_available()) { 22777608706SJuan Quintela return WT_SUPPORT_ABSENT; 22877608706SJuan Quintela } 22977608706SJuan Quintela /* 23077608706SJuan Quintela * Check if current memory configuration is 23177608706SJuan Quintela * compatible with required UFFD features. 23277608706SJuan Quintela */ 23377608706SJuan Quintela if (!ram_write_tracking_compatible()) { 23477608706SJuan Quintela return WT_SUPPORT_AVAILABLE; 23577608706SJuan Quintela } 23677608706SJuan Quintela 23777608706SJuan Quintela return WT_SUPPORT_COMPATIBLE; 23877608706SJuan Quintela } 23977608706SJuan Quintela 24077608706SJuan Quintela /* Migration capabilities set */ 24177608706SJuan Quintela struct MigrateCapsSet { 24277608706SJuan Quintela int size; /* Capability set size */ 24377608706SJuan Quintela MigrationCapability caps[]; /* Variadic array of capabilities */ 24477608706SJuan Quintela }; 24577608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet; 24677608706SJuan Quintela 24777608706SJuan Quintela /* Define and initialize MigrateCapsSet */ 24877608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 24977608706SJuan Quintela MigrateCapsSet _name = { \ 25077608706SJuan Quintela .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 25177608706SJuan Quintela .caps = { __VA_ARGS__ } \ 25277608706SJuan Quintela } 25377608706SJuan Quintela 25477608706SJuan Quintela /* Background-snapshot compatibility check list */ 25577608706SJuan Quintela static const 25677608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 25777608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_RAM, 25877608706SJuan Quintela MIGRATION_CAPABILITY_DIRTY_BITMAPS, 25977608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 26077608706SJuan Quintela MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 26177608706SJuan Quintela MIGRATION_CAPABILITY_RETURN_PATH, 26277608706SJuan Quintela MIGRATION_CAPABILITY_MULTIFD, 26377608706SJuan Quintela MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 26477608706SJuan Quintela MIGRATION_CAPABILITY_AUTO_CONVERGE, 26577608706SJuan Quintela MIGRATION_CAPABILITY_RELEASE_RAM, 26677608706SJuan Quintela MIGRATION_CAPABILITY_RDMA_PIN_ALL, 26777608706SJuan Quintela MIGRATION_CAPABILITY_COMPRESS, 26877608706SJuan Quintela MIGRATION_CAPABILITY_XBZRLE, 26977608706SJuan Quintela MIGRATION_CAPABILITY_X_COLO, 27077608706SJuan Quintela MIGRATION_CAPABILITY_VALIDATE_UUID, 27177608706SJuan Quintela MIGRATION_CAPABILITY_ZERO_COPY_SEND); 27277608706SJuan Quintela 27377608706SJuan Quintela /** 27477608706SJuan Quintela * @migration_caps_check - check capability compatibility 27577608706SJuan Quintela * 27677608706SJuan Quintela * @old_caps: old capability list 27777608706SJuan Quintela * @new_caps: new capability list 27877608706SJuan Quintela * @errp: set *errp if the check failed, with reason 27977608706SJuan Quintela * 28077608706SJuan Quintela * Returns true if check passed, otherwise false. 28177608706SJuan Quintela */ 28277608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 28377608706SJuan Quintela { 28477608706SJuan Quintela MigrationIncomingState *mis = migration_incoming_get_current(); 28577608706SJuan Quintela 28677608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 28777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 28877608706SJuan Quintela error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 28977608706SJuan Quintela "block migration"); 29077608706SJuan Quintela error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 29177608706SJuan Quintela return false; 29277608706SJuan Quintela } 29377608706SJuan Quintela #endif 29477608706SJuan Quintela 29577608706SJuan Quintela #ifndef CONFIG_REPLICATION 29677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 29777608706SJuan Quintela error_setg(errp, "QEMU compiled without replication module" 29877608706SJuan Quintela " can't enable COLO"); 29977608706SJuan Quintela error_append_hint(errp, "Please enable replication before COLO.\n"); 30077608706SJuan Quintela return false; 30177608706SJuan Quintela } 30277608706SJuan Quintela #endif 30377608706SJuan Quintela 30477608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 30577608706SJuan Quintela /* This check is reasonably expensive, so only when it's being 30677608706SJuan Quintela * set the first time, also it's only the destination that needs 30777608706SJuan Quintela * special support. 30877608706SJuan Quintela */ 30977608706SJuan Quintela if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 31077608706SJuan Quintela runstate_check(RUN_STATE_INMIGRATE) && 31177608706SJuan Quintela !postcopy_ram_supported_by_host(mis)) { 31277608706SJuan Quintela /* postcopy_ram_supported_by_host will have emitted a more 31377608706SJuan Quintela * detailed message 31477608706SJuan Quintela */ 31577608706SJuan Quintela error_setg(errp, "Postcopy is not supported"); 31677608706SJuan Quintela return false; 31777608706SJuan Quintela } 31877608706SJuan Quintela 31977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 32077608706SJuan Quintela error_setg(errp, "Postcopy is not compatible with ignore-shared"); 32177608706SJuan Quintela return false; 32277608706SJuan Quintela } 32377608706SJuan Quintela } 32477608706SJuan Quintela 32577608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 32677608706SJuan Quintela WriteTrackingSupport wt_support; 32777608706SJuan Quintela int idx; 32877608706SJuan Quintela /* 32977608706SJuan Quintela * Check if 'background-snapshot' capability is supported by 33077608706SJuan Quintela * host kernel and compatible with guest memory configuration. 33177608706SJuan Quintela */ 33277608706SJuan Quintela wt_support = migrate_query_write_tracking(); 33377608706SJuan Quintela if (wt_support < WT_SUPPORT_AVAILABLE) { 33477608706SJuan Quintela error_setg(errp, "Background-snapshot is not supported by host kernel"); 33577608706SJuan Quintela return false; 33677608706SJuan Quintela } 33777608706SJuan Quintela if (wt_support < WT_SUPPORT_COMPATIBLE) { 33877608706SJuan Quintela error_setg(errp, "Background-snapshot is not compatible " 33977608706SJuan Quintela "with guest memory configuration"); 34077608706SJuan Quintela return false; 34177608706SJuan Quintela } 34277608706SJuan Quintela 34377608706SJuan Quintela /* 34477608706SJuan Quintela * Check if there are any migration capabilities 34577608706SJuan Quintela * incompatible with 'background-snapshot'. 34677608706SJuan Quintela */ 34777608706SJuan Quintela for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 34877608706SJuan Quintela int incomp_cap = check_caps_background_snapshot.caps[idx]; 34977608706SJuan Quintela if (new_caps[incomp_cap]) { 35077608706SJuan Quintela error_setg(errp, 35177608706SJuan Quintela "Background-snapshot is not compatible with %s", 35277608706SJuan Quintela MigrationCapability_str(incomp_cap)); 35377608706SJuan Quintela return false; 35477608706SJuan Quintela } 35577608706SJuan Quintela } 35677608706SJuan Quintela } 35777608706SJuan Quintela 35877608706SJuan Quintela #ifdef CONFIG_LINUX 35977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 36077608706SJuan Quintela (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 36177608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_COMPRESS] || 36277608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_XBZRLE] || 36377608706SJuan Quintela migrate_multifd_compression() || 36477608706SJuan Quintela migrate_use_tls())) { 36577608706SJuan Quintela error_setg(errp, 36677608706SJuan Quintela "Zero copy only available for non-compressed non-TLS multifd migration"); 36777608706SJuan Quintela return false; 36877608706SJuan Quintela } 36977608706SJuan Quintela #else 37077608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 37177608706SJuan Quintela error_setg(errp, 37277608706SJuan Quintela "Zero copy currently only available on Linux"); 37377608706SJuan Quintela return false; 37477608706SJuan Quintela } 37577608706SJuan Quintela #endif 37677608706SJuan Quintela 37777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 37877608706SJuan Quintela if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 37977608706SJuan Quintela error_setg(errp, "Postcopy preempt requires postcopy-ram"); 38077608706SJuan Quintela return false; 38177608706SJuan Quintela } 38277608706SJuan Quintela 38377608706SJuan Quintela /* 38477608706SJuan Quintela * Preempt mode requires urgent pages to be sent in separate 38577608706SJuan Quintela * channel, OTOH compression logic will disorder all pages into 38677608706SJuan Quintela * different compression channels, which is not compatible with the 38777608706SJuan Quintela * preempt assumptions on channel assignments. 38877608706SJuan Quintela */ 38977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 39077608706SJuan Quintela error_setg(errp, "Postcopy preempt not compatible with compress"); 39177608706SJuan Quintela return false; 39277608706SJuan Quintela } 39377608706SJuan Quintela } 39477608706SJuan Quintela 39577608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 39677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 39777608706SJuan Quintela error_setg(errp, "Multifd is not compatible with compress"); 39877608706SJuan Quintela return false; 39977608706SJuan Quintela } 40077608706SJuan Quintela } 40177608706SJuan Quintela 40277608706SJuan Quintela return true; 40377608706SJuan Quintela } 4044d0c6b69SJuan Quintela 405f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp) 406f80196b7SJuan Quintela { 407f80196b7SJuan Quintela MigrationState *s = migrate_get_current(); 408f80196b7SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 409f80196b7SJuan Quintela 410f80196b7SJuan Quintela if (migration_is_running(s->state)) { 411f80196b7SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 412f80196b7SJuan Quintela return false; 413f80196b7SJuan Quintela } 414f80196b7SJuan Quintela 415f80196b7SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 416f80196b7SJuan Quintela new_caps[cap] = value; 417f80196b7SJuan Quintela 418f80196b7SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 419f80196b7SJuan Quintela return false; 420f80196b7SJuan Quintela } 421f80196b7SJuan Quintela s->capabilities[cap] = value; 422f80196b7SJuan Quintela return true; 423f80196b7SJuan Quintela } 424f80196b7SJuan Quintela 4254d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) 4264d0c6b69SJuan Quintela { 4274d0c6b69SJuan Quintela MigrationCapabilityStatusList *head = NULL, **tail = &head; 4284d0c6b69SJuan Quintela MigrationCapabilityStatus *caps; 4294d0c6b69SJuan Quintela MigrationState *s = migrate_get_current(); 4304d0c6b69SJuan Quintela int i; 4314d0c6b69SJuan Quintela 4324d0c6b69SJuan Quintela for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { 4334d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 4344d0c6b69SJuan Quintela if (i == MIGRATION_CAPABILITY_BLOCK) { 4354d0c6b69SJuan Quintela continue; 4364d0c6b69SJuan Quintela } 4374d0c6b69SJuan Quintela #endif 4384d0c6b69SJuan Quintela caps = g_malloc0(sizeof(*caps)); 4394d0c6b69SJuan Quintela caps->capability = i; 4404d0c6b69SJuan Quintela caps->state = s->capabilities[i]; 4414d0c6b69SJuan Quintela QAPI_LIST_APPEND(tail, caps); 4424d0c6b69SJuan Quintela } 4434d0c6b69SJuan Quintela 4444d0c6b69SJuan Quintela return head; 4454d0c6b69SJuan Quintela } 44645c1de13SJuan Quintela 44745c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, 44845c1de13SJuan Quintela Error **errp) 44945c1de13SJuan Quintela { 45045c1de13SJuan Quintela MigrationState *s = migrate_get_current(); 45145c1de13SJuan Quintela MigrationCapabilityStatusList *cap; 45245c1de13SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 45345c1de13SJuan Quintela 45445c1de13SJuan Quintela if (migration_is_running(s->state)) { 45545c1de13SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 45645c1de13SJuan Quintela return; 45745c1de13SJuan Quintela } 45845c1de13SJuan Quintela 45945c1de13SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 46045c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 46145c1de13SJuan Quintela new_caps[cap->value->capability] = cap->value->state; 46245c1de13SJuan Quintela } 46345c1de13SJuan Quintela 46445c1de13SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 46545c1de13SJuan Quintela return; 46645c1de13SJuan Quintela } 46745c1de13SJuan Quintela 46845c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 46945c1de13SJuan Quintela s->capabilities[cap->value->capability] = cap->value->state; 47045c1de13SJuan Quintela } 47145c1de13SJuan Quintela } 4721dfc4b9eSJuan Quintela 4731dfc4b9eSJuan Quintela /* parameters */ 4741dfc4b9eSJuan Quintela 4756f8be708SJuan Quintela bool migrate_block_incremental(void) 4766f8be708SJuan Quintela { 4776f8be708SJuan Quintela MigrationState *s; 4786f8be708SJuan Quintela 4796f8be708SJuan Quintela s = migrate_get_current(); 4806f8be708SJuan Quintela 4816f8be708SJuan Quintela return s->parameters.block_incremental; 4826f8be708SJuan Quintela } 4836f8be708SJuan Quintela 484f94a858fSJuan Quintela uint32_t migrate_checkpoint_delay(void) 485f94a858fSJuan Quintela { 486f94a858fSJuan Quintela MigrationState *s; 487f94a858fSJuan Quintela 488f94a858fSJuan Quintela s = migrate_get_current(); 489f94a858fSJuan Quintela 490f94a858fSJuan Quintela return s->parameters.x_checkpoint_delay; 491f94a858fSJuan Quintela } 492f94a858fSJuan Quintela 4931dfc4b9eSJuan Quintela int migrate_compress_level(void) 4941dfc4b9eSJuan Quintela { 4951dfc4b9eSJuan Quintela MigrationState *s; 4961dfc4b9eSJuan Quintela 4971dfc4b9eSJuan Quintela s = migrate_get_current(); 4981dfc4b9eSJuan Quintela 4991dfc4b9eSJuan Quintela return s->parameters.compress_level; 5001dfc4b9eSJuan Quintela } 5011dfc4b9eSJuan Quintela 5021dfc4b9eSJuan Quintela int migrate_compress_threads(void) 5031dfc4b9eSJuan Quintela { 5041dfc4b9eSJuan Quintela MigrationState *s; 5051dfc4b9eSJuan Quintela 5061dfc4b9eSJuan Quintela s = migrate_get_current(); 5071dfc4b9eSJuan Quintela 5081dfc4b9eSJuan Quintela return s->parameters.compress_threads; 5091dfc4b9eSJuan Quintela } 5101dfc4b9eSJuan Quintela 5111dfc4b9eSJuan Quintela int migrate_compress_wait_thread(void) 5121dfc4b9eSJuan Quintela { 5131dfc4b9eSJuan Quintela MigrationState *s; 5141dfc4b9eSJuan Quintela 5151dfc4b9eSJuan Quintela s = migrate_get_current(); 5161dfc4b9eSJuan Quintela 5171dfc4b9eSJuan Quintela return s->parameters.compress_wait_thread; 5181dfc4b9eSJuan Quintela } 5191dfc4b9eSJuan Quintela 5209605c2acSJuan Quintela uint8_t migrate_cpu_throttle_increment(void) 5219605c2acSJuan Quintela { 5229605c2acSJuan Quintela MigrationState *s; 5239605c2acSJuan Quintela 5249605c2acSJuan Quintela s = migrate_get_current(); 5259605c2acSJuan Quintela 5269605c2acSJuan Quintela return s->parameters.cpu_throttle_increment; 5279605c2acSJuan Quintela } 5289605c2acSJuan Quintela 5292a8ec380SJuan Quintela uint8_t migrate_cpu_throttle_initial(void) 5302a8ec380SJuan Quintela { 5312a8ec380SJuan Quintela MigrationState *s; 5322a8ec380SJuan Quintela 5332a8ec380SJuan Quintela s = migrate_get_current(); 5342a8ec380SJuan Quintela 5352a8ec380SJuan Quintela return s->parameters.cpu_throttle_initial; 5362a8ec380SJuan Quintela } 5372a8ec380SJuan Quintela 538873f674cSJuan Quintela bool migrate_cpu_throttle_tailslow(void) 539873f674cSJuan Quintela { 540873f674cSJuan Quintela MigrationState *s; 541873f674cSJuan Quintela 542873f674cSJuan Quintela s = migrate_get_current(); 543873f674cSJuan Quintela 544873f674cSJuan Quintela return s->parameters.cpu_throttle_tailslow; 545873f674cSJuan Quintela } 546873f674cSJuan Quintela 5471dfc4b9eSJuan Quintela int migrate_decompress_threads(void) 5481dfc4b9eSJuan Quintela { 5491dfc4b9eSJuan Quintela MigrationState *s; 5501dfc4b9eSJuan Quintela 5511dfc4b9eSJuan Quintela s = migrate_get_current(); 5521dfc4b9eSJuan Quintela 5531dfc4b9eSJuan Quintela return s->parameters.decompress_threads; 5541dfc4b9eSJuan Quintela } 5551dfc4b9eSJuan Quintela 55624155bd0SJuan Quintela uint8_t migrate_max_cpu_throttle(void) 55724155bd0SJuan Quintela { 55824155bd0SJuan Quintela MigrationState *s; 55924155bd0SJuan Quintela 56024155bd0SJuan Quintela s = migrate_get_current(); 56124155bd0SJuan Quintela 56224155bd0SJuan Quintela return s->parameters.max_cpu_throttle; 56324155bd0SJuan Quintela } 56424155bd0SJuan Quintela 5651dfc4b9eSJuan Quintela int64_t migrate_max_postcopy_bandwidth(void) 5661dfc4b9eSJuan Quintela { 5671dfc4b9eSJuan Quintela MigrationState *s; 5681dfc4b9eSJuan Quintela 5691dfc4b9eSJuan Quintela s = migrate_get_current(); 5701dfc4b9eSJuan Quintela 5711dfc4b9eSJuan Quintela return s->parameters.max_postcopy_bandwidth; 5721dfc4b9eSJuan Quintela } 5731dfc4b9eSJuan Quintela 5741dfc4b9eSJuan Quintela int migrate_multifd_channels(void) 5751dfc4b9eSJuan Quintela { 5761dfc4b9eSJuan Quintela MigrationState *s; 5771dfc4b9eSJuan Quintela 5781dfc4b9eSJuan Quintela s = migrate_get_current(); 5791dfc4b9eSJuan Quintela 5801dfc4b9eSJuan Quintela return s->parameters.multifd_channels; 5811dfc4b9eSJuan Quintela } 5821dfc4b9eSJuan Quintela 5831dfc4b9eSJuan Quintela MultiFDCompression migrate_multifd_compression(void) 5841dfc4b9eSJuan Quintela { 5851dfc4b9eSJuan Quintela MigrationState *s; 5861dfc4b9eSJuan Quintela 5871dfc4b9eSJuan Quintela s = migrate_get_current(); 5881dfc4b9eSJuan Quintela 5891dfc4b9eSJuan Quintela assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX); 5901dfc4b9eSJuan Quintela return s->parameters.multifd_compression; 5911dfc4b9eSJuan Quintela } 5921dfc4b9eSJuan Quintela 5931dfc4b9eSJuan Quintela int migrate_multifd_zlib_level(void) 5941dfc4b9eSJuan Quintela { 5951dfc4b9eSJuan Quintela MigrationState *s; 5961dfc4b9eSJuan Quintela 5971dfc4b9eSJuan Quintela s = migrate_get_current(); 5981dfc4b9eSJuan Quintela 5991dfc4b9eSJuan Quintela return s->parameters.multifd_zlib_level; 6001dfc4b9eSJuan Quintela } 6011dfc4b9eSJuan Quintela 6021dfc4b9eSJuan Quintela int migrate_multifd_zstd_level(void) 6031dfc4b9eSJuan Quintela { 6041dfc4b9eSJuan Quintela MigrationState *s; 6051dfc4b9eSJuan Quintela 6061dfc4b9eSJuan Quintela s = migrate_get_current(); 6071dfc4b9eSJuan Quintela 6081dfc4b9eSJuan Quintela return s->parameters.multifd_zstd_level; 6091dfc4b9eSJuan Quintela } 6101dfc4b9eSJuan Quintela 6116499efdbSJuan Quintela uint8_t migrate_throttle_trigger_threshold(void) 6126499efdbSJuan Quintela { 6136499efdbSJuan Quintela MigrationState *s; 6146499efdbSJuan Quintela 6156499efdbSJuan Quintela s = migrate_get_current(); 6166499efdbSJuan Quintela 6176499efdbSJuan Quintela return s->parameters.throttle_trigger_threshold; 6186499efdbSJuan Quintela } 6196499efdbSJuan Quintela 6201dfc4b9eSJuan Quintela uint64_t migrate_xbzrle_cache_size(void) 6211dfc4b9eSJuan Quintela { 6221dfc4b9eSJuan Quintela MigrationState *s; 6231dfc4b9eSJuan Quintela 6241dfc4b9eSJuan Quintela s = migrate_get_current(); 6251dfc4b9eSJuan Quintela 6261dfc4b9eSJuan Quintela return s->parameters.xbzrle_cache_size; 6271dfc4b9eSJuan Quintela } 6282682c4eeSJuan Quintela 6292682c4eeSJuan Quintela /* parameters helpers */ 6302682c4eeSJuan Quintela 6312682c4eeSJuan Quintela AnnounceParameters *migrate_announce_params(void) 6322682c4eeSJuan Quintela { 6332682c4eeSJuan Quintela static AnnounceParameters ap; 6342682c4eeSJuan Quintela 6352682c4eeSJuan Quintela MigrationState *s = migrate_get_current(); 6362682c4eeSJuan Quintela 6372682c4eeSJuan Quintela ap.initial = s->parameters.announce_initial; 6382682c4eeSJuan Quintela ap.max = s->parameters.announce_max; 6392682c4eeSJuan Quintela ap.rounds = s->parameters.announce_rounds; 6402682c4eeSJuan Quintela ap.step = s->parameters.announce_step; 6412682c4eeSJuan Quintela 6422682c4eeSJuan Quintela return ≈ 6432682c4eeSJuan Quintela } 644