1 /* 2 * Copyright (c) 2021-2025 Oracle and/or its affiliates. 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #include <sys/ioctl.h> 8 #include <linux/vfio.h> 9 #include "qemu/osdep.h" 10 #include "hw/vfio/vfio-container.h" 11 #include "migration/blocker.h" 12 #include "migration/cpr.h" 13 #include "migration/migration.h" 14 #include "migration/vmstate.h" 15 #include "qapi/error.h" 16 17 static bool vfio_cpr_supported(VFIOContainer *container, Error **errp) 18 { 19 if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UPDATE_VADDR)) { 20 error_setg(errp, "VFIO container does not support VFIO_UPDATE_VADDR"); 21 return false; 22 23 } else if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UNMAP_ALL)) { 24 error_setg(errp, "VFIO container does not support VFIO_UNMAP_ALL"); 25 return false; 26 27 } else { 28 return true; 29 } 30 } 31 32 static const VMStateDescription vfio_container_vmstate = { 33 .name = "vfio-container", 34 .version_id = 0, 35 .minimum_version_id = 0, 36 .needed = cpr_incoming_needed, 37 .fields = (VMStateField[]) { 38 VMSTATE_END_OF_LIST() 39 } 40 }; 41 42 bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp) 43 { 44 VFIOContainerBase *bcontainer = &container->bcontainer; 45 Error **cpr_blocker = &container->cpr.blocker; 46 47 migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier, 48 vfio_cpr_reboot_notifier, 49 MIG_MODE_CPR_REBOOT); 50 51 if (!vfio_cpr_supported(container, cpr_blocker)) { 52 return migrate_add_blocker_modes(cpr_blocker, errp, 53 MIG_MODE_CPR_TRANSFER, -1) == 0; 54 } 55 56 vmstate_register(NULL, -1, &vfio_container_vmstate, container); 57 58 return true; 59 } 60 61 void vfio_legacy_cpr_unregister_container(VFIOContainer *container) 62 { 63 VFIOContainerBase *bcontainer = &container->bcontainer; 64 65 migration_remove_notifier(&bcontainer->cpr_reboot_notifier); 66 migrate_del_blocker(&container->cpr.blocker); 67 vmstate_unregister(NULL, &vfio_container_vmstate, container); 68 } 69