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" 15*77608706SJuan Quintela #include "qapi/error.h" 16*77608706SJuan Quintela #include "sysemu/runstate.h" 171f0776f1SJuan Quintela #include "migration.h" 18*77608706SJuan Quintela #include "ram.h" 191f0776f1SJuan Quintela #include "options.h" 201f0776f1SJuan Quintela 211f0776f1SJuan Quintela bool migrate_auto_converge(void) 221f0776f1SJuan Quintela { 231f0776f1SJuan Quintela MigrationState *s; 241f0776f1SJuan Quintela 251f0776f1SJuan Quintela s = migrate_get_current(); 261f0776f1SJuan Quintela 271f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 281f0776f1SJuan Quintela } 291f0776f1SJuan Quintela 301f0776f1SJuan Quintela bool migrate_background_snapshot(void) 311f0776f1SJuan Quintela { 321f0776f1SJuan Quintela MigrationState *s; 331f0776f1SJuan Quintela 341f0776f1SJuan Quintela s = migrate_get_current(); 351f0776f1SJuan Quintela 361f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 371f0776f1SJuan Quintela } 381f0776f1SJuan Quintela 399d4b1e5fSJuan Quintela bool migrate_block(void) 409d4b1e5fSJuan Quintela { 419d4b1e5fSJuan Quintela MigrationState *s; 429d4b1e5fSJuan Quintela 439d4b1e5fSJuan Quintela s = migrate_get_current(); 449d4b1e5fSJuan Quintela 459d4b1e5fSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 469d4b1e5fSJuan Quintela } 479d4b1e5fSJuan Quintela 485e804644SJuan Quintela bool migrate_colo(void) 495e804644SJuan Quintela { 505e804644SJuan Quintela MigrationState *s = migrate_get_current(); 515e804644SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 525e804644SJuan Quintela } 535e804644SJuan Quintela 54a7a94d14SJuan Quintela bool migrate_compress(void) 55a7a94d14SJuan Quintela { 56a7a94d14SJuan Quintela MigrationState *s; 57a7a94d14SJuan Quintela 58a7a94d14SJuan Quintela s = migrate_get_current(); 59a7a94d14SJuan Quintela 60a7a94d14SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 61a7a94d14SJuan Quintela } 62a7a94d14SJuan Quintela 631f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void) 641f0776f1SJuan Quintela { 651f0776f1SJuan Quintela MigrationState *s; 661f0776f1SJuan Quintela 671f0776f1SJuan Quintela s = migrate_get_current(); 681f0776f1SJuan Quintela 691f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 701f0776f1SJuan Quintela } 711f0776f1SJuan Quintela 72b890902cSJuan Quintela bool migrate_events(void) 73b890902cSJuan Quintela { 74b890902cSJuan Quintela MigrationState *s; 75b890902cSJuan Quintela 76b890902cSJuan Quintela s = migrate_get_current(); 77b890902cSJuan Quintela 78b890902cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 79b890902cSJuan Quintela } 80b890902cSJuan Quintela 811f0776f1SJuan Quintela bool migrate_ignore_shared(void) 821f0776f1SJuan Quintela { 831f0776f1SJuan Quintela MigrationState *s; 841f0776f1SJuan Quintela 851f0776f1SJuan Quintela s = migrate_get_current(); 861f0776f1SJuan Quintela 871f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 881f0776f1SJuan Quintela } 891f0776f1SJuan Quintela 901f0776f1SJuan Quintela bool migrate_late_block_activate(void) 911f0776f1SJuan Quintela { 921f0776f1SJuan Quintela MigrationState *s; 931f0776f1SJuan Quintela 941f0776f1SJuan Quintela s = migrate_get_current(); 951f0776f1SJuan Quintela 961f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 971f0776f1SJuan Quintela } 981f0776f1SJuan Quintela 9951b07548SJuan Quintela bool migrate_multifd(void) 10051b07548SJuan Quintela { 10151b07548SJuan Quintela MigrationState *s; 10251b07548SJuan Quintela 10351b07548SJuan Quintela s = migrate_get_current(); 10451b07548SJuan Quintela 10551b07548SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 10651b07548SJuan Quintela } 10751b07548SJuan Quintela 1081f0776f1SJuan Quintela bool migrate_pause_before_switchover(void) 1091f0776f1SJuan Quintela { 1101f0776f1SJuan Quintela MigrationState *s; 1111f0776f1SJuan Quintela 1121f0776f1SJuan Quintela s = migrate_get_current(); 1131f0776f1SJuan Quintela 1141f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 1151f0776f1SJuan Quintela } 1161f0776f1SJuan Quintela 1171f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void) 1181f0776f1SJuan Quintela { 1191f0776f1SJuan Quintela MigrationState *s; 1201f0776f1SJuan Quintela 1211f0776f1SJuan Quintela s = migrate_get_current(); 1221f0776f1SJuan Quintela 1231f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 1241f0776f1SJuan Quintela } 1251f0776f1SJuan Quintela 1261f0776f1SJuan Quintela bool migrate_postcopy_preempt(void) 1271f0776f1SJuan Quintela { 1281f0776f1SJuan Quintela MigrationState *s; 1291f0776f1SJuan Quintela 1301f0776f1SJuan Quintela s = migrate_get_current(); 1311f0776f1SJuan Quintela 1321f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 1331f0776f1SJuan Quintela } 1341f0776f1SJuan Quintela 1351f0776f1SJuan Quintela bool migrate_postcopy_ram(void) 1361f0776f1SJuan Quintela { 1371f0776f1SJuan Quintela MigrationState *s; 1381f0776f1SJuan Quintela 1391f0776f1SJuan Quintela s = migrate_get_current(); 1401f0776f1SJuan Quintela 1411f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 1421f0776f1SJuan Quintela } 1431f0776f1SJuan Quintela 14417cba690SJuan Quintela bool migrate_rdma_pin_all(void) 14517cba690SJuan Quintela { 14617cba690SJuan Quintela MigrationState *s = migrate_get_current(); 14717cba690SJuan Quintela 14817cba690SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 14917cba690SJuan Quintela } 15017cba690SJuan Quintela 1511f0776f1SJuan Quintela bool migrate_release_ram(void) 1521f0776f1SJuan Quintela { 1531f0776f1SJuan Quintela MigrationState *s; 1541f0776f1SJuan Quintela 1551f0776f1SJuan Quintela s = migrate_get_current(); 1561f0776f1SJuan Quintela 1571f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 1581f0776f1SJuan Quintela } 1591f0776f1SJuan Quintela 16038ad1110SJuan Quintela bool migrate_return_path(void) 16138ad1110SJuan Quintela { 16238ad1110SJuan Quintela MigrationState *s; 16338ad1110SJuan Quintela 16438ad1110SJuan Quintela s = migrate_get_current(); 16538ad1110SJuan Quintela 16638ad1110SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 16738ad1110SJuan Quintela } 16838ad1110SJuan Quintela 1691f0776f1SJuan Quintela bool migrate_validate_uuid(void) 1701f0776f1SJuan Quintela { 1711f0776f1SJuan Quintela MigrationState *s; 1721f0776f1SJuan Quintela 1731f0776f1SJuan Quintela s = migrate_get_current(); 1741f0776f1SJuan Quintela 1751f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 1761f0776f1SJuan Quintela } 1771f0776f1SJuan Quintela 17887dca0c9SJuan Quintela bool migrate_xbzrle(void) 17987dca0c9SJuan Quintela { 18087dca0c9SJuan Quintela MigrationState *s; 18187dca0c9SJuan Quintela 18287dca0c9SJuan Quintela s = migrate_get_current(); 18387dca0c9SJuan Quintela 18487dca0c9SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 18587dca0c9SJuan Quintela } 18687dca0c9SJuan Quintela 1871f0776f1SJuan Quintela bool migrate_zero_blocks(void) 1881f0776f1SJuan Quintela { 1891f0776f1SJuan Quintela MigrationState *s; 1901f0776f1SJuan Quintela 1911f0776f1SJuan Quintela s = migrate_get_current(); 1921f0776f1SJuan Quintela 1931f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 1941f0776f1SJuan Quintela } 195b4bc342cSJuan Quintela 196b4bc342cSJuan Quintela bool migrate_zero_copy_send(void) 197b4bc342cSJuan Quintela { 198b4bc342cSJuan Quintela MigrationState *s; 199b4bc342cSJuan Quintela 200b4bc342cSJuan Quintela s = migrate_get_current(); 201b4bc342cSJuan Quintela 202b4bc342cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 203b4bc342cSJuan Quintela } 204*77608706SJuan Quintela typedef enum WriteTrackingSupport { 205*77608706SJuan Quintela WT_SUPPORT_UNKNOWN = 0, 206*77608706SJuan Quintela WT_SUPPORT_ABSENT, 207*77608706SJuan Quintela WT_SUPPORT_AVAILABLE, 208*77608706SJuan Quintela WT_SUPPORT_COMPATIBLE 209*77608706SJuan Quintela } WriteTrackingSupport; 210*77608706SJuan Quintela 211*77608706SJuan Quintela static 212*77608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void) 213*77608706SJuan Quintela { 214*77608706SJuan Quintela /* Check if kernel supports required UFFD features */ 215*77608706SJuan Quintela if (!ram_write_tracking_available()) { 216*77608706SJuan Quintela return WT_SUPPORT_ABSENT; 217*77608706SJuan Quintela } 218*77608706SJuan Quintela /* 219*77608706SJuan Quintela * Check if current memory configuration is 220*77608706SJuan Quintela * compatible with required UFFD features. 221*77608706SJuan Quintela */ 222*77608706SJuan Quintela if (!ram_write_tracking_compatible()) { 223*77608706SJuan Quintela return WT_SUPPORT_AVAILABLE; 224*77608706SJuan Quintela } 225*77608706SJuan Quintela 226*77608706SJuan Quintela return WT_SUPPORT_COMPATIBLE; 227*77608706SJuan Quintela } 228*77608706SJuan Quintela 229*77608706SJuan Quintela /* Migration capabilities set */ 230*77608706SJuan Quintela struct MigrateCapsSet { 231*77608706SJuan Quintela int size; /* Capability set size */ 232*77608706SJuan Quintela MigrationCapability caps[]; /* Variadic array of capabilities */ 233*77608706SJuan Quintela }; 234*77608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet; 235*77608706SJuan Quintela 236*77608706SJuan Quintela /* Define and initialize MigrateCapsSet */ 237*77608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 238*77608706SJuan Quintela MigrateCapsSet _name = { \ 239*77608706SJuan Quintela .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 240*77608706SJuan Quintela .caps = { __VA_ARGS__ } \ 241*77608706SJuan Quintela } 242*77608706SJuan Quintela 243*77608706SJuan Quintela /* Background-snapshot compatibility check list */ 244*77608706SJuan Quintela static const 245*77608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 246*77608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_RAM, 247*77608706SJuan Quintela MIGRATION_CAPABILITY_DIRTY_BITMAPS, 248*77608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 249*77608706SJuan Quintela MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 250*77608706SJuan Quintela MIGRATION_CAPABILITY_RETURN_PATH, 251*77608706SJuan Quintela MIGRATION_CAPABILITY_MULTIFD, 252*77608706SJuan Quintela MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 253*77608706SJuan Quintela MIGRATION_CAPABILITY_AUTO_CONVERGE, 254*77608706SJuan Quintela MIGRATION_CAPABILITY_RELEASE_RAM, 255*77608706SJuan Quintela MIGRATION_CAPABILITY_RDMA_PIN_ALL, 256*77608706SJuan Quintela MIGRATION_CAPABILITY_COMPRESS, 257*77608706SJuan Quintela MIGRATION_CAPABILITY_XBZRLE, 258*77608706SJuan Quintela MIGRATION_CAPABILITY_X_COLO, 259*77608706SJuan Quintela MIGRATION_CAPABILITY_VALIDATE_UUID, 260*77608706SJuan Quintela MIGRATION_CAPABILITY_ZERO_COPY_SEND); 261*77608706SJuan Quintela 262*77608706SJuan Quintela /** 263*77608706SJuan Quintela * @migration_caps_check - check capability compatibility 264*77608706SJuan Quintela * 265*77608706SJuan Quintela * @old_caps: old capability list 266*77608706SJuan Quintela * @new_caps: new capability list 267*77608706SJuan Quintela * @errp: set *errp if the check failed, with reason 268*77608706SJuan Quintela * 269*77608706SJuan Quintela * Returns true if check passed, otherwise false. 270*77608706SJuan Quintela */ 271*77608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 272*77608706SJuan Quintela { 273*77608706SJuan Quintela MigrationIncomingState *mis = migration_incoming_get_current(); 274*77608706SJuan Quintela 275*77608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 276*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 277*77608706SJuan Quintela error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 278*77608706SJuan Quintela "block migration"); 279*77608706SJuan Quintela error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 280*77608706SJuan Quintela return false; 281*77608706SJuan Quintela } 282*77608706SJuan Quintela #endif 283*77608706SJuan Quintela 284*77608706SJuan Quintela #ifndef CONFIG_REPLICATION 285*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 286*77608706SJuan Quintela error_setg(errp, "QEMU compiled without replication module" 287*77608706SJuan Quintela " can't enable COLO"); 288*77608706SJuan Quintela error_append_hint(errp, "Please enable replication before COLO.\n"); 289*77608706SJuan Quintela return false; 290*77608706SJuan Quintela } 291*77608706SJuan Quintela #endif 292*77608706SJuan Quintela 293*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 294*77608706SJuan Quintela /* This check is reasonably expensive, so only when it's being 295*77608706SJuan Quintela * set the first time, also it's only the destination that needs 296*77608706SJuan Quintela * special support. 297*77608706SJuan Quintela */ 298*77608706SJuan Quintela if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 299*77608706SJuan Quintela runstate_check(RUN_STATE_INMIGRATE) && 300*77608706SJuan Quintela !postcopy_ram_supported_by_host(mis)) { 301*77608706SJuan Quintela /* postcopy_ram_supported_by_host will have emitted a more 302*77608706SJuan Quintela * detailed message 303*77608706SJuan Quintela */ 304*77608706SJuan Quintela error_setg(errp, "Postcopy is not supported"); 305*77608706SJuan Quintela return false; 306*77608706SJuan Quintela } 307*77608706SJuan Quintela 308*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 309*77608706SJuan Quintela error_setg(errp, "Postcopy is not compatible with ignore-shared"); 310*77608706SJuan Quintela return false; 311*77608706SJuan Quintela } 312*77608706SJuan Quintela } 313*77608706SJuan Quintela 314*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 315*77608706SJuan Quintela WriteTrackingSupport wt_support; 316*77608706SJuan Quintela int idx; 317*77608706SJuan Quintela /* 318*77608706SJuan Quintela * Check if 'background-snapshot' capability is supported by 319*77608706SJuan Quintela * host kernel and compatible with guest memory configuration. 320*77608706SJuan Quintela */ 321*77608706SJuan Quintela wt_support = migrate_query_write_tracking(); 322*77608706SJuan Quintela if (wt_support < WT_SUPPORT_AVAILABLE) { 323*77608706SJuan Quintela error_setg(errp, "Background-snapshot is not supported by host kernel"); 324*77608706SJuan Quintela return false; 325*77608706SJuan Quintela } 326*77608706SJuan Quintela if (wt_support < WT_SUPPORT_COMPATIBLE) { 327*77608706SJuan Quintela error_setg(errp, "Background-snapshot is not compatible " 328*77608706SJuan Quintela "with guest memory configuration"); 329*77608706SJuan Quintela return false; 330*77608706SJuan Quintela } 331*77608706SJuan Quintela 332*77608706SJuan Quintela /* 333*77608706SJuan Quintela * Check if there are any migration capabilities 334*77608706SJuan Quintela * incompatible with 'background-snapshot'. 335*77608706SJuan Quintela */ 336*77608706SJuan Quintela for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 337*77608706SJuan Quintela int incomp_cap = check_caps_background_snapshot.caps[idx]; 338*77608706SJuan Quintela if (new_caps[incomp_cap]) { 339*77608706SJuan Quintela error_setg(errp, 340*77608706SJuan Quintela "Background-snapshot is not compatible with %s", 341*77608706SJuan Quintela MigrationCapability_str(incomp_cap)); 342*77608706SJuan Quintela return false; 343*77608706SJuan Quintela } 344*77608706SJuan Quintela } 345*77608706SJuan Quintela } 346*77608706SJuan Quintela 347*77608706SJuan Quintela #ifdef CONFIG_LINUX 348*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 349*77608706SJuan Quintela (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 350*77608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_COMPRESS] || 351*77608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_XBZRLE] || 352*77608706SJuan Quintela migrate_multifd_compression() || 353*77608706SJuan Quintela migrate_use_tls())) { 354*77608706SJuan Quintela error_setg(errp, 355*77608706SJuan Quintela "Zero copy only available for non-compressed non-TLS multifd migration"); 356*77608706SJuan Quintela return false; 357*77608706SJuan Quintela } 358*77608706SJuan Quintela #else 359*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 360*77608706SJuan Quintela error_setg(errp, 361*77608706SJuan Quintela "Zero copy currently only available on Linux"); 362*77608706SJuan Quintela return false; 363*77608706SJuan Quintela } 364*77608706SJuan Quintela #endif 365*77608706SJuan Quintela 366*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 367*77608706SJuan Quintela if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 368*77608706SJuan Quintela error_setg(errp, "Postcopy preempt requires postcopy-ram"); 369*77608706SJuan Quintela return false; 370*77608706SJuan Quintela } 371*77608706SJuan Quintela 372*77608706SJuan Quintela /* 373*77608706SJuan Quintela * Preempt mode requires urgent pages to be sent in separate 374*77608706SJuan Quintela * channel, OTOH compression logic will disorder all pages into 375*77608706SJuan Quintela * different compression channels, which is not compatible with the 376*77608706SJuan Quintela * preempt assumptions on channel assignments. 377*77608706SJuan Quintela */ 378*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 379*77608706SJuan Quintela error_setg(errp, "Postcopy preempt not compatible with compress"); 380*77608706SJuan Quintela return false; 381*77608706SJuan Quintela } 382*77608706SJuan Quintela } 383*77608706SJuan Quintela 384*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 385*77608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 386*77608706SJuan Quintela error_setg(errp, "Multifd is not compatible with compress"); 387*77608706SJuan Quintela return false; 388*77608706SJuan Quintela } 389*77608706SJuan Quintela } 390*77608706SJuan Quintela 391*77608706SJuan Quintela return true; 392*77608706SJuan Quintela } 393