From: Huguanshen Chen <chen...@chinatelecom.cn>

On arm64 virtualization platform, vfio-user devices lose their interrupts after
migration to the destination. This issue occurs because qemu fails to deliver
the msi device id to the vGIC. The error device id is calculated based on the
device's parent bus, so it is essential to save the parent pci config to
prevent this issue.

Backtrace:
QEMU:
 #0 qdev_get_parent_bus
 #1 pci_dev_bus_num
 #2 pci_req_id_cache_extract
 #3 pci_requester_id
 #4 kvm_irqchip_update_msi_route delivers 0(error id) to vGIC

KVM:
 #0 find_its_device returns error
 #1 find_ite
 #2 vgic_its_resolve_lpi
 #3 vgic_its_trigger_msi
 #4 vgic_its_inject_msi
 #5 kvm_set_msi
 #6 kvm_send_userspace_msi

Reported-by: Heng Zhang <zhangh...@chinatelecom.cn>
Signed-off-by: Huguanshen Chen <chen...@chinatelecom.cn>
Signed-off-by: Huaitong Han <han...@chinatelecom.cn>
---
 hw/vfio/pci.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index a1bfdfe375..442113d0b7 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2654,6 +2654,11 @@ static int vfio_pci_save_config(VFIODevice *vbasedev, 
QEMUFile *f, Error **errp)
 {
     VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
 
+    PCIDevice *pdev = &vdev->pdev;
+    BusState *qbus = qdev_get_parent_bus(DEVICE(pdev));
+
+    pci_device_save(PCI_DEVICE(qbus->parent), f);
+
     return vmstate_save_state_with_err(f, &vmstate_vfio_pci_config, vdev, NULL,
                                        errp);
 }
@@ -2662,6 +2667,7 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, 
QEMUFile *f)
 {
     VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
     PCIDevice *pdev = &vdev->pdev;
+    BusState *qbus = qdev_get_parent_bus(DEVICE(pdev));
     pcibus_t old_addr[PCI_NUM_REGIONS - 1];
     int bar, ret;
 
@@ -2669,6 +2675,11 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, 
QEMUFile *f)
         old_addr[bar] = pdev->io_regions[bar].addr;
     }
 
+    ret = pci_device_load(PCI_DEVICE(qbus->parent), f);
+    if (ret) {
+        return ret;
+    }
+
     ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1);
     if (ret) {
         return ret;
-- 
2.43.5


Reply via email to