1 /* 2 * Copyright (c) 2021-2024 Oracle and/or its affiliates. 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 */ 7 8 #include "qemu/osdep.h" 9 #include "hw/vfio/vfio-device.h" 10 #include "hw/vfio/vfio-cpr.h" 11 #include "hw/vfio/pci.h" 12 #include "migration/cpr.h" 13 #include "qapi/error.h" 14 #include "system/runstate.h" 15 16 int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier, 17 MigrationEvent *e, Error **errp) 18 { 19 if (e->type == MIG_EVENT_PRECOPY_SETUP && 20 !runstate_check(RUN_STATE_SUSPENDED) && !vm_get_suspended()) { 21 22 error_setg(errp, 23 "VFIO device only supports cpr-reboot for runstate suspended"); 24 25 return -1; 26 } 27 return 0; 28 } 29 30 bool vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp) 31 { 32 migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier, 33 vfio_cpr_reboot_notifier, 34 MIG_MODE_CPR_REBOOT); 35 return true; 36 } 37 38 void vfio_cpr_unregister_container(VFIOContainerBase *bcontainer) 39 { 40 migration_remove_notifier(&bcontainer->cpr_reboot_notifier); 41 } 42 43 /* 44 * The kernel may change non-emulated config bits. Exclude them from the 45 * changed-bits check in get_pci_config_device. 46 */ 47 static int vfio_cpr_pci_pre_load(void *opaque) 48 { 49 VFIOPCIDevice *vdev = opaque; 50 PCIDevice *pdev = &vdev->pdev; 51 int size = MIN(pci_config_size(pdev), vdev->config_size); 52 int i; 53 54 for (i = 0; i < size; i++) { 55 pdev->cmask[i] &= vdev->emulated_config_bits[i]; 56 } 57 58 return 0; 59 } 60 61 const VMStateDescription vfio_cpr_pci_vmstate = { 62 .name = "vfio-cpr-pci", 63 .version_id = 0, 64 .minimum_version_id = 0, 65 .pre_load = vfio_cpr_pci_pre_load, 66 .needed = cpr_incoming_needed, 67 .fields = (VMStateField[]) { 68 VMSTATE_END_OF_LIST() 69 } 70 }; 71