diff --git a/hw/core/machine.c b/hw/core/machine.c index 3442f31f94..8087026b45 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -43,6 +43,7 @@ GlobalProperty hw_compat_8_2[] = { { "migration", "zero-page-detection", "legacy"}, { TYPE_VIRTIO_IOMMU_PCI, "granule", "4k" }, { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" }, + { "virtio-gpu-device", "x-scanout-vmstate-version", "1" }, }; const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2); @@ -51,15 +52,15 @@ GlobalProperty hw_compat_8_1[] = { { "ramfb", "x-migrate", "off" }, { "vfio-pci-nohotplug", "x-ramfb-migrate", "off" }, { "igb", "x-pcie-flr-init", "off" }, + { TYPE_VIRTIO_NET, "host_uso", "off"}, + { TYPE_VIRTIO_NET, "guest_uso4", "off"}, + { TYPE_VIRTIO_NET, "guest_uso6", "off"}, }; const size_t hw_compat_8_1_len = G_N_ELEMENTS(hw_compat_8_1); GlobalProperty hw_compat_8_0[] = { { "migration", "multifd-flush-after-each-section", "on"}, { TYPE_PCI_DEVICE, "x-pcie-ari-nextfn-1", "on" }, - { TYPE_VIRTIO_NET, "host_uso", "off"}, - { TYPE_VIRTIO_NET, "guest_uso4", "off"}, - { TYPE_VIRTIO_NET, "guest_uso6", "off"}, }; const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0); diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index ae831b6b3e..d60b1b2973 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1166,10 +1166,17 @@ static void virtio_gpu_cursor_bh(void *opaque) virtio_gpu_handle_cursor(&g->parent_obj.parent_obj, g->cursor_vq); } +static bool scanout_vmstate_after_v2(void *opaque, int version) +{ + struct VirtIOGPUBase *base = container_of(opaque, VirtIOGPUBase, scanout); + struct VirtIOGPU *gpu = container_of(base, VirtIOGPU, parent_obj); + + return gpu->scanout_vmstate_version >= 2; +} + static const VMStateDescription vmstate_virtio_gpu_scanout = { .name = "virtio-gpu-one-scanout", - .version_id = 2, - .minimum_version_id = 1, + .version_id = 1, .fields = (const VMStateField[]) { VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout), VMSTATE_UINT32(width, struct virtio_gpu_scanout), @@ -1181,12 +1188,18 @@ static const VMStateDescription vmstate_virtio_gpu_scanout = { VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout), VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout), VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout), - VMSTATE_UINT32_V(fb.format, struct virtio_gpu_scanout, 2), - VMSTATE_UINT32_V(fb.bytes_pp, struct virtio_gpu_scanout, 2), - VMSTATE_UINT32_V(fb.width, struct virtio_gpu_scanout, 2), - VMSTATE_UINT32_V(fb.height, struct virtio_gpu_scanout, 2), - VMSTATE_UINT32_V(fb.stride, struct virtio_gpu_scanout, 2), - VMSTATE_UINT32_V(fb.offset, struct virtio_gpu_scanout, 2), + VMSTATE_UINT32_TEST(fb.format, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), + VMSTATE_UINT32_TEST(fb.bytes_pp, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), + VMSTATE_UINT32_TEST(fb.width, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), + VMSTATE_UINT32_TEST(fb.height, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), + VMSTATE_UINT32_TEST(fb.stride, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), + VMSTATE_UINT32_TEST(fb.offset, struct virtio_gpu_scanout, + scanout_vmstate_after_v2), VMSTATE_END_OF_LIST() }, }; @@ -1659,6 +1672,7 @@ static Property virtio_gpu_properties[] = { DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags, VIRTIO_GPU_FLAG_BLOB_ENABLED, false), DEFINE_PROP_SIZE("hostmem", VirtIOGPU, parent_obj.conf.hostmem, 0), + DEFINE_PROP_UINT8("x-scanout-vmstate-version", VirtIOGPU, scanout_vmstate_version, 2), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 56d6e821bf..7a59379f5a 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -177,6 +177,7 @@ typedef struct VGPUDMABuf { struct VirtIOGPU { VirtIOGPUBase parent_obj; + uint8_t scanout_vmstate_version; uint64_t conf_max_hostmem; VirtQueue *ctrl_vq; diff --git a/include/migration/colo.h b/include/migration/colo.h index eaac07f26d..43222ef5ae 100644 --- a/include/migration/colo.h +++ b/include/migration/colo.h @@ -49,7 +49,7 @@ void colo_checkpoint_delay_set(void); * * Called with BQL locked, may temporary release BQL. */ -int coroutine_fn colo_incoming_co(void); +void coroutine_fn colo_incoming_co(void); void colo_shutdown(void); #endif diff --git a/migration/colo-stubs.c b/migration/colo-stubs.c index f8c069b739..e22ce65234 100644 --- a/migration/colo-stubs.c +++ b/migration/colo-stubs.c @@ -9,9 +9,8 @@ void colo_shutdown(void) { } -int coroutine_fn colo_incoming_co(void) +void coroutine_fn colo_incoming_co(void) { - return 0; } void colo_checkpoint_delay_set(void) diff --git a/migration/colo.c b/migration/colo.c index e2b450c132..f96c2ee069 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -837,12 +837,11 @@ static void *colo_process_incoming_thread(void *opaque) /* Make sure all file formats throw away their mutable metadata */ bql_lock(); bdrv_activate_all(&local_err); + bql_unlock(); if (local_err) { - bql_unlock(); error_report_err(local_err); return NULL; } - bql_unlock(); failover_init_state(); @@ -928,16 +927,13 @@ out: return NULL; } -int coroutine_fn colo_incoming_co(void) +void coroutine_fn colo_incoming_co(void) { MigrationIncomingState *mis = migration_incoming_get_current(); QemuThread th; assert(bql_locked()); - - if (!migration_incoming_colo_enabled()) { - return 0; - } + assert(migration_incoming_colo_enabled()); qemu_thread_create(&th, "COLO incoming", colo_process_incoming_thread, mis, QEMU_THREAD_JOINABLE); @@ -953,6 +949,4 @@ int coroutine_fn colo_incoming_co(void) /* We hold the global BQL, so it is safe here */ colo_release_ram_cache(); - - return 0; } diff --git a/migration/migration.c b/migration/migration.c index 70d66a441b..e1b269624c 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -513,13 +513,13 @@ void migration_incoming_disable_colo(void) int migration_incoming_enable_colo(void) { #ifndef CONFIG_REPLICATION - error_report("ENABLE_COLO command come in migration stream, but COLO " - "module is not built in"); + error_report("ENABLE_COLO command come in migration stream, but the " + "replication module is not built in"); return -ENOTSUP; #endif if (!migrate_colo()) { - error_report("ENABLE_COLO command come in migration stream, but c-colo " + error_report("ENABLE_COLO command come in migration stream, but x-colo " "capability is not set"); return -EINVAL; } @@ -776,9 +776,9 @@ process_incoming_migration_co(void *opaque) goto fail; } - if (colo_incoming_co() < 0) { - error_setg(&local_err, "colo incoming failed"); - goto fail; + if (migration_incoming_colo_enabled()) { + /* yield until COLO exit */ + colo_incoming_co(); } migration_bh_schedule(process_incoming_migration_bh, mis); diff --git a/migration/trace-events b/migration/trace-events index d0c44c3853..0b7c3324fb 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -58,7 +58,7 @@ postcopy_page_req_sync(void *host_addr) "sync page req %p" vmstate_load_field_error(const char *field, int ret) "field \"%s\" load failed, ret = %d" vmstate_load_state(const char *name, int version_id) "%s v%d" vmstate_load_state_end(const char *name, const char *reason, int val) "%s %s/%d" -vmstate_load_state_field(const char *name, const char *field) "%s:%s" +vmstate_load_state_field(const char *name, const char *field, bool exists) "%s:%s exists=%d" vmstate_n_elems(const char *name, int n_elems) "%s: %d" vmstate_subsection_load(const char *parent) "%s" vmstate_subsection_load_bad(const char *parent, const char *sub, const char *sub2) "%s: %s/%s" diff --git a/migration/vmstate.c b/migration/vmstate.c index ef26f26ccd..ff5d589a6d 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -128,8 +128,9 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, } } while (field->name) { - trace_vmstate_load_state_field(vmsd->name, field->name); - if (vmstate_field_exists(vmsd, field, opaque, version_id)) { + bool exists = vmstate_field_exists(vmsd, field, opaque, version_id); + trace_vmstate_load_state_field(vmsd->name, field->name, exists); + if (exists) { void *first_elem = opaque + field->offset; int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); @@ -478,7 +479,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, len = qemu_peek_byte(f, 1); if (len < strlen(vmsd->name) + 1) { - /* subsection name has be be "section_name/a" */ + /* subsection name has to be "section_name/a" */ trace_vmstate_subsection_load_bad(vmsd->name, "(short)", ""); return 0; } diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index e8d3555f56..b7e3406471 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1604,7 +1604,7 @@ static void test_analyze_script(void) } g_assert(waitpid(pid, &wstatus, 0) == pid); - if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) { + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { g_test_message("Failed to analyze the migration stream"); g_test_fail(); } @@ -3437,26 +3437,6 @@ int main(int argc, char **argv) arch = qtest_get_arch(); is_x86 = !strcmp(arch, "i386") || !strcmp(arch, "x86_64"); - /* - * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG - * is touchy due to race conditions on dirty bits (especially on PPC for - * some reason) - */ - if (g_str_equal(arch, "ppc64") && - (!has_kvm || access("/sys/module/kvm_hv", F_OK))) { - g_test_message("Skipping test: kvm_hv not available"); - return g_test_run(); - } - - /* - * Similar to ppc64, s390x seems to be touchy with TCG, so disable it - * there until the problems are resolved - */ - if (g_str_equal(arch, "s390x") && !has_kvm) { - g_test_message("Skipping test: s390x host with KVM is required"); - return g_test_run(); - } - tmpfs = g_dir_make_tmp("migration-test-XXXXXX", &err); if (!tmpfs) { g_test_message("Can't create temporary directory in %s: %s", @@ -3466,6 +3446,31 @@ int main(int argc, char **argv) module_call_init(MODULE_INIT_QOM); + migration_test_add("/migration/bad_dest", test_baddest); +#ifndef _WIN32 + migration_test_add("/migration/analyze-script", test_analyze_script); +#endif + + /* + * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG + * is touchy due to race conditions on dirty bits (especially on PPC for + * some reason) + */ + if (g_str_equal(arch, "ppc64") && + (!has_kvm || access("/sys/module/kvm_hv", F_OK))) { + g_test_message("Skipping tests: kvm_hv not available"); + goto test_add_done; + } + + /* + * Similar to ppc64, s390x seems to be touchy with TCG, so disable it + * there until the problems are resolved + */ + if (g_str_equal(arch, "s390x") && !has_kvm) { + g_test_message("Skipping tests: s390x host with KVM is required"); + goto test_add_done; + } + if (is_x86) { migration_test_add("/migration/precopy/unix/suspend/live", test_precopy_unix_suspend_live); @@ -3491,12 +3496,6 @@ int main(int argc, char **argv) } } - migration_test_add("/migration/bad_dest", test_baddest); -#ifndef _WIN32 - if (!g_str_equal(arch, "s390x")) { - migration_test_add("/migration/analyze-script", test_analyze_script); - } -#endif migration_test_add("/migration/precopy/unix/plain", test_precopy_unix_plain); migration_test_add("/migration/precopy/unix/xbzrle", @@ -3653,6 +3652,8 @@ int main(int argc, char **argv) test_vcpu_dirty_limit); } +test_add_done: + ret = g_test_run(); g_assert_cmpint(ret, ==, 0);