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