154857b08SSteve Sistare /* 254857b08SSteve Sistare * Copyright (c) 2021-2025 Oracle and/or its affiliates. 354857b08SSteve Sistare * 454857b08SSteve Sistare * SPDX-License-Identifier: GPL-2.0-or-later 554857b08SSteve Sistare */ 654857b08SSteve Sistare 754857b08SSteve Sistare #include <sys/ioctl.h> 854857b08SSteve Sistare #include <linux/vfio.h> 954857b08SSteve Sistare #include "qemu/osdep.h" 1054857b08SSteve Sistare #include "hw/vfio/vfio-container.h" 11c29a65edSSteve Sistare #include "hw/vfio/vfio-device.h" 12*7e9f2141SSteve Sistare #include "hw/vfio/vfio-listener.h" 1354857b08SSteve Sistare #include "migration/blocker.h" 1454857b08SSteve Sistare #include "migration/cpr.h" 1554857b08SSteve Sistare #include "migration/migration.h" 1654857b08SSteve Sistare #include "migration/vmstate.h" 1754857b08SSteve Sistare #include "qapi/error.h" 18*7e9f2141SSteve Sistare #include "qemu/error-report.h" 1954857b08SSteve Sistare 201faadd96SSteve Sistare static bool vfio_dma_unmap_vaddr_all(VFIOContainer *container, Error **errp) 211faadd96SSteve Sistare { 221faadd96SSteve Sistare struct vfio_iommu_type1_dma_unmap unmap = { 231faadd96SSteve Sistare .argsz = sizeof(unmap), 241faadd96SSteve Sistare .flags = VFIO_DMA_UNMAP_FLAG_VADDR | VFIO_DMA_UNMAP_FLAG_ALL, 251faadd96SSteve Sistare .iova = 0, 261faadd96SSteve Sistare .size = 0, 271faadd96SSteve Sistare }; 281faadd96SSteve Sistare if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { 291faadd96SSteve Sistare error_setg_errno(errp, errno, "vfio_dma_unmap_vaddr_all"); 301faadd96SSteve Sistare return false; 311faadd96SSteve Sistare } 321faadd96SSteve Sistare return true; 331faadd96SSteve Sistare } 341faadd96SSteve Sistare 35*7e9f2141SSteve Sistare /* 36*7e9f2141SSteve Sistare * Set the new @vaddr for any mappings registered during cpr load. 37*7e9f2141SSteve Sistare * The incoming state is cleared thereafter. 38*7e9f2141SSteve Sistare */ 39*7e9f2141SSteve Sistare static int vfio_legacy_cpr_dma_map(const VFIOContainerBase *bcontainer, 40*7e9f2141SSteve Sistare hwaddr iova, ram_addr_t size, void *vaddr, 41*7e9f2141SSteve Sistare bool readonly, MemoryRegion *mr) 42*7e9f2141SSteve Sistare { 43*7e9f2141SSteve Sistare const VFIOContainer *container = container_of(bcontainer, VFIOContainer, 44*7e9f2141SSteve Sistare bcontainer); 45*7e9f2141SSteve Sistare struct vfio_iommu_type1_dma_map map = { 46*7e9f2141SSteve Sistare .argsz = sizeof(map), 47*7e9f2141SSteve Sistare .flags = VFIO_DMA_MAP_FLAG_VADDR, 48*7e9f2141SSteve Sistare .vaddr = (__u64)(uintptr_t)vaddr, 49*7e9f2141SSteve Sistare .iova = iova, 50*7e9f2141SSteve Sistare .size = size, 51*7e9f2141SSteve Sistare }; 52*7e9f2141SSteve Sistare 53*7e9f2141SSteve Sistare g_assert(cpr_is_incoming()); 54*7e9f2141SSteve Sistare 55*7e9f2141SSteve Sistare if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) { 56*7e9f2141SSteve Sistare return -errno; 57*7e9f2141SSteve Sistare } 58*7e9f2141SSteve Sistare 59*7e9f2141SSteve Sistare return 0; 60*7e9f2141SSteve Sistare } 611faadd96SSteve Sistare 6254857b08SSteve Sistare static bool vfio_cpr_supported(VFIOContainer *container, Error **errp) 6354857b08SSteve Sistare { 6454857b08SSteve Sistare if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UPDATE_VADDR)) { 6554857b08SSteve Sistare error_setg(errp, "VFIO container does not support VFIO_UPDATE_VADDR"); 6654857b08SSteve Sistare return false; 6754857b08SSteve Sistare 6854857b08SSteve Sistare } else if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UNMAP_ALL)) { 6954857b08SSteve Sistare error_setg(errp, "VFIO container does not support VFIO_UNMAP_ALL"); 7054857b08SSteve Sistare return false; 7154857b08SSteve Sistare 7254857b08SSteve Sistare } else { 7354857b08SSteve Sistare return true; 7454857b08SSteve Sistare } 7554857b08SSteve Sistare } 7654857b08SSteve Sistare 771faadd96SSteve Sistare static int vfio_container_pre_save(void *opaque) 781faadd96SSteve Sistare { 791faadd96SSteve Sistare VFIOContainer *container = opaque; 801faadd96SSteve Sistare Error *local_err = NULL; 811faadd96SSteve Sistare 821faadd96SSteve Sistare if (!vfio_dma_unmap_vaddr_all(container, &local_err)) { 831faadd96SSteve Sistare error_report_err(local_err); 841faadd96SSteve Sistare return -1; 851faadd96SSteve Sistare } 861faadd96SSteve Sistare return 0; 871faadd96SSteve Sistare } 881faadd96SSteve Sistare 89*7e9f2141SSteve Sistare static int vfio_container_post_load(void *opaque, int version_id) 90*7e9f2141SSteve Sistare { 91*7e9f2141SSteve Sistare VFIOContainer *container = opaque; 92*7e9f2141SSteve Sistare VFIOContainerBase *bcontainer = &container->bcontainer; 93*7e9f2141SSteve Sistare VFIOGroup *group; 94*7e9f2141SSteve Sistare Error *local_err = NULL; 95*7e9f2141SSteve Sistare 96*7e9f2141SSteve Sistare if (!vfio_listener_register(bcontainer, &local_err)) { 97*7e9f2141SSteve Sistare error_report_err(local_err); 98*7e9f2141SSteve Sistare return -1; 99*7e9f2141SSteve Sistare } 100*7e9f2141SSteve Sistare 101*7e9f2141SSteve Sistare QLIST_FOREACH(group, &container->group_list, container_next) { 102*7e9f2141SSteve Sistare VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer); 103*7e9f2141SSteve Sistare 104*7e9f2141SSteve Sistare /* Restore original dma_map function */ 105*7e9f2141SSteve Sistare vioc->dma_map = container->cpr.saved_dma_map; 106*7e9f2141SSteve Sistare } 107*7e9f2141SSteve Sistare return 0; 108*7e9f2141SSteve Sistare } 109*7e9f2141SSteve Sistare 11054857b08SSteve Sistare static const VMStateDescription vfio_container_vmstate = { 11154857b08SSteve Sistare .name = "vfio-container", 11254857b08SSteve Sistare .version_id = 0, 11354857b08SSteve Sistare .minimum_version_id = 0, 114*7e9f2141SSteve Sistare .priority = MIG_PRI_LOW, /* Must happen after devices and groups */ 1151faadd96SSteve Sistare .pre_save = vfio_container_pre_save, 116*7e9f2141SSteve Sistare .post_load = vfio_container_post_load, 11754857b08SSteve Sistare .needed = cpr_incoming_needed, 11854857b08SSteve Sistare .fields = (VMStateField[]) { 11954857b08SSteve Sistare VMSTATE_END_OF_LIST() 12054857b08SSteve Sistare } 12154857b08SSteve Sistare }; 12254857b08SSteve Sistare 12354857b08SSteve Sistare bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp) 12454857b08SSteve Sistare { 12554857b08SSteve Sistare VFIOContainerBase *bcontainer = &container->bcontainer; 12654857b08SSteve Sistare Error **cpr_blocker = &container->cpr.blocker; 12754857b08SSteve Sistare 12854857b08SSteve Sistare migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier, 12954857b08SSteve Sistare vfio_cpr_reboot_notifier, 13054857b08SSteve Sistare MIG_MODE_CPR_REBOOT); 13154857b08SSteve Sistare 13254857b08SSteve Sistare if (!vfio_cpr_supported(container, cpr_blocker)) { 13354857b08SSteve Sistare return migrate_add_blocker_modes(cpr_blocker, errp, 13454857b08SSteve Sistare MIG_MODE_CPR_TRANSFER, -1) == 0; 13554857b08SSteve Sistare } 13654857b08SSteve Sistare 13754857b08SSteve Sistare vmstate_register(NULL, -1, &vfio_container_vmstate, container); 13854857b08SSteve Sistare 139*7e9f2141SSteve Sistare /* During incoming CPR, divert calls to dma_map. */ 140*7e9f2141SSteve Sistare if (cpr_is_incoming()) { 141*7e9f2141SSteve Sistare VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer); 142*7e9f2141SSteve Sistare container->cpr.saved_dma_map = vioc->dma_map; 143*7e9f2141SSteve Sistare vioc->dma_map = vfio_legacy_cpr_dma_map; 144*7e9f2141SSteve Sistare } 14554857b08SSteve Sistare return true; 14654857b08SSteve Sistare } 14754857b08SSteve Sistare 14854857b08SSteve Sistare void vfio_legacy_cpr_unregister_container(VFIOContainer *container) 14954857b08SSteve Sistare { 15054857b08SSteve Sistare VFIOContainerBase *bcontainer = &container->bcontainer; 15154857b08SSteve Sistare 15254857b08SSteve Sistare migration_remove_notifier(&bcontainer->cpr_reboot_notifier); 15354857b08SSteve Sistare migrate_del_blocker(&container->cpr.blocker); 15454857b08SSteve Sistare vmstate_unregister(NULL, &vfio_container_vmstate, container); 15554857b08SSteve Sistare } 156c29a65edSSteve Sistare 157c29a65edSSteve Sistare int vfio_cpr_group_get_device_fd(int d, const char *name) 158c29a65edSSteve Sistare { 159c29a65edSSteve Sistare const int id = 0; 160c29a65edSSteve Sistare int fd = cpr_find_fd(name, id); 161c29a65edSSteve Sistare 162c29a65edSSteve Sistare if (fd < 0) { 163c29a65edSSteve Sistare fd = ioctl(d, VFIO_GROUP_GET_DEVICE_FD, name); 164c29a65edSSteve Sistare if (fd >= 0) { 165c29a65edSSteve Sistare cpr_save_fd(name, id, fd); 166c29a65edSSteve Sistare } 167c29a65edSSteve Sistare } 168c29a65edSSteve Sistare return fd; 169c29a65edSSteve Sistare } 170c29a65edSSteve Sistare 171c29a65edSSteve Sistare static bool same_device(int fd1, int fd2) 172c29a65edSSteve Sistare { 173c29a65edSSteve Sistare struct stat st1, st2; 174c29a65edSSteve Sistare 175c29a65edSSteve Sistare return !fstat(fd1, &st1) && !fstat(fd2, &st2) && st1.st_dev == st2.st_dev; 176c29a65edSSteve Sistare } 177c29a65edSSteve Sistare 178c29a65edSSteve Sistare bool vfio_cpr_container_match(VFIOContainer *container, VFIOGroup *group, 179c29a65edSSteve Sistare int fd) 180c29a65edSSteve Sistare { 181c29a65edSSteve Sistare if (container->fd == fd) { 182c29a65edSSteve Sistare return true; 183c29a65edSSteve Sistare } 184c29a65edSSteve Sistare if (!same_device(container->fd, fd)) { 185c29a65edSSteve Sistare return false; 186c29a65edSSteve Sistare } 187c29a65edSSteve Sistare /* 188c29a65edSSteve Sistare * Same device, different fd. This occurs when the container fd is 189c29a65edSSteve Sistare * cpr_save'd multiple times, once for each groupid, so SCM_RIGHTS 190c29a65edSSteve Sistare * produces duplicates. De-dup it. 191c29a65edSSteve Sistare */ 192c29a65edSSteve Sistare cpr_delete_fd("vfio_container_for_group", group->groupid); 193c29a65edSSteve Sistare close(fd); 194c29a65edSSteve Sistare cpr_save_fd("vfio_container_for_group", group->groupid, container->fd); 195c29a65edSSteve Sistare return true; 196c29a65edSSteve Sistare } 197