diff options
Diffstat (limited to 'hw/vfio')
| -rw-r--r-- | hw/vfio/common.c | 19 | ||||
| -rw-r--r-- | hw/vfio/container.c | 12 | ||||
| -rw-r--r-- | hw/vfio/cpr.c | 39 | ||||
| -rw-r--r-- | hw/vfio/iommufd.c | 6 | ||||
| -rw-r--r-- | hw/vfio/meson.build | 1 | ||||
| -rw-r--r-- | hw/vfio/migration.c | 26 |
6 files changed, 72 insertions, 31 deletions
diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 059bfdc07a..011ceaab89 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -39,7 +39,6 @@ #include "sysemu/runstate.h" #include "trace.h" #include "qapi/error.h" -#include "migration/migration.h" #include "migration/misc.h" #include "migration/blocker.h" #include "migration/qemu-file.h" @@ -128,7 +127,7 @@ int vfio_block_multiple_devices_migration(VFIODevice *vbasedev, Error **errp) error_setg(&multiple_devices_migration_blocker, "Multiple VFIO devices migration is supported only if all of " "them support P2P migration"); - ret = migrate_add_blocker(&multiple_devices_migration_blocker, errp); + ret = migrate_add_blocker_normal(&multiple_devices_migration_blocker, errp); return ret; } @@ -150,14 +149,8 @@ bool vfio_viommu_preset(VFIODevice *vbasedev) static void vfio_set_migration_error(int err) { - MigrationState *ms = migrate_get_current(); - - if (migration_is_setup_or_active(ms->state)) { - WITH_QEMU_LOCK_GUARD(&ms->qemu_file_lock) { - if (ms->to_dst_file) { - qemu_file_set_error(ms->to_dst_file, err); - } - } + if (migration_is_setup_or_active()) { + migration_file_set_error(err); } } @@ -180,10 +173,8 @@ bool vfio_device_state_is_precopy(VFIODevice *vbasedev) static bool vfio_devices_all_dirty_tracking(VFIOContainerBase *bcontainer) { VFIODevice *vbasedev; - MigrationState *ms = migrate_get_current(); - if (ms->state != MIGRATION_STATUS_ACTIVE && - ms->state != MIGRATION_STATUS_DEVICE) { + if (!migration_is_active() && !migration_is_device()) { return false; } @@ -225,7 +216,7 @@ vfio_devices_all_running_and_mig_active(const VFIOContainerBase *bcontainer) { VFIODevice *vbasedev; - if (!migration_is_active(migrate_get_current())) { + if (!migration_is_active()) { return false; } diff --git a/hw/vfio/container.c b/hw/vfio/container.c index bd25b9fbad..9a775e4efc 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -32,7 +32,6 @@ #include "sysemu/reset.h" #include "trace.h" #include "qapi/error.h" -#include "migration/migration.h" #include "pci.h" VFIOGroupList vfio_group_list = @@ -621,10 +620,15 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, goto free_container_exit; } + ret = vfio_cpr_register_container(bcontainer, errp); + if (ret) { + goto free_container_exit; + } + ret = vfio_ram_block_discard_disable(container, true); if (ret) { error_setg_errno(errp, -ret, "Cannot set discarding of RAM broken"); - goto free_container_exit; + goto unregister_container_exit; } assert(bcontainer->ops->setup); @@ -667,6 +671,9 @@ listener_release_exit: enable_discards_exit: vfio_ram_block_discard_disable(container, false); +unregister_container_exit: + vfio_cpr_unregister_container(bcontainer); + free_container_exit: g_free(container); @@ -710,6 +717,7 @@ static void vfio_disconnect_container(VFIOGroup *group) vfio_container_destroy(bcontainer); trace_vfio_disconnect_container(container->fd); + vfio_cpr_unregister_container(bcontainer); close(container->fd); g_free(container); diff --git a/hw/vfio/cpr.c b/hw/vfio/cpr.c new file mode 100644 index 0000000000..392c2dd95d --- /dev/null +++ b/hw/vfio/cpr.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-2024 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/vfio/vfio-common.h" +#include "migration/misc.h" +#include "qapi/error.h" +#include "sysemu/runstate.h" + +static int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier, + MigrationEvent *e, Error **errp) +{ + if (e->type == MIG_EVENT_PRECOPY_SETUP && + !runstate_check(RUN_STATE_SUSPENDED) && !vm_get_suspended()) { + + error_setg(errp, + "VFIO device only supports cpr-reboot for runstate suspended"); + + return -1; + } + return 0; +} + +int vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp) +{ + migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier, + vfio_cpr_reboot_notifier, + MIG_MODE_CPR_REBOOT); + return 0; +} + +void vfio_cpr_unregister_container(VFIOContainerBase *bcontainer) +{ + migration_remove_notifier(&bcontainer->cpr_reboot_notifier); +} diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 9bfddc1360..e1be224494 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -411,6 +411,11 @@ found_container: goto err_listener_register; } + ret = vfio_cpr_register_container(bcontainer, errp); + if (ret) { + goto err_listener_register; + } + /* * TODO: examine RAM_BLOCK_DISCARD stuff, should we do group level * for discarding incompatibility check as well? @@ -461,6 +466,7 @@ static void iommufd_cdev_detach(VFIODevice *vbasedev) iommufd_cdev_ram_block_discard_disable(false); } + vfio_cpr_unregister_container(bcontainer); iommufd_cdev_detach_container(vbasedev, container); iommufd_cdev_container_destroy(container); vfio_put_address_space(space); diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build index bb98493b53..bba776f75c 100644 --- a/hw/vfio/meson.build +++ b/hw/vfio/meson.build @@ -5,6 +5,7 @@ vfio_ss.add(files( 'container-base.c', 'container.c', 'migration.c', + 'cpr.c', )) vfio_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr.c')) vfio_ss.add(when: 'CONFIG_IOMMUFD', if_true: files( diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 50140eda87..1149c6b374 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -17,14 +17,12 @@ #include "sysemu/runstate.h" #include "hw/vfio/vfio-common.h" -#include "migration/migration.h" -#include "migration/options.h" +#include "migration/misc.h" #include "migration/savevm.h" #include "migration/vmstate.h" #include "migration/qemu-file.h" #include "migration/register.h" #include "migration/blocker.h" -#include "migration/misc.h" #include "qapi/error.h" #include "exec/ramlist.h" #include "exec/ram_addr.h" @@ -505,6 +503,12 @@ static bool vfio_is_active_iterate(void *opaque) return vfio_device_state_is_precopy(vbasedev); } +/* + * Note about migration rate limiting: VFIO migration buffer size is currently + * limited to 1MB, so there is no need to check if migration rate exceeded (as + * in the worst case it will exceed by 1MB). However, if the buffer size is + * later changed to a bigger value, migration rate should be enforced here. + */ static int vfio_save_iterate(QEMUFile *f, void *opaque) { VFIODevice *vbasedev = opaque; @@ -529,11 +533,7 @@ static int vfio_save_iterate(QEMUFile *f, void *opaque) trace_vfio_save_iterate(vbasedev->name, migration->precopy_init_size, migration->precopy_dirty_size); - /* - * A VFIO device's pre-copy dirty_bytes is not guaranteed to reach zero. - * Return 1 so following handlers will not be potentially blocked. - */ - return 1; + return !migration->precopy_init_size && !migration->precopy_dirty_size; } static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) @@ -713,9 +713,7 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running, * Migration should be aborted in this case, but vm_state_notify() * currently does not support reporting failures. */ - if (migrate_get_current()->to_dst_file) { - qemu_file_set_error(migrate_get_current()->to_dst_file, ret); - } + migration_file_set_error(ret); } trace_vfio_vmstate_change_prepare(vbasedev->name, running, @@ -745,9 +743,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state) * Migration should be aborted in this case, but vm_state_notify() * currently does not support reporting failures. */ - if (migrate_get_current()->to_dst_file) { - qemu_file_set_error(migrate_get_current()->to_dst_file, ret); - } + migration_file_set_error(ret); } trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state), @@ -889,7 +885,7 @@ static int vfio_block_migration(VFIODevice *vbasedev, Error *err, Error **errp) vbasedev->migration_blocker = error_copy(err); error_free(err); - return migrate_add_blocker(&vbasedev->migration_blocker, errp); + return migrate_add_blocker_normal(&vbasedev->migration_blocker, errp); } /* ---------------------------------------------------------------------- */ |