26ba25
From f7e1caa3302f705abe196b8a021cfa52750749ff Mon Sep 17 00:00:00 2001
26ba25
From: Peter Xu <peterx@redhat.com>
26ba25
Date: Thu, 8 Nov 2018 06:29:38 +0000
26ba25
Subject: [PATCH 10/35] intel_iommu: handle invalid ce for shadow sync
26ba25
26ba25
RH-Author: Peter Xu <peterx@redhat.com>
26ba25
Message-id: <20181108062938.21143-8-peterx@redhat.com>
26ba25
Patchwork-id: 82966
26ba25
O-Subject: [RHEL-8 qemu-kvm PATCH 7/7] intel_iommu: handle invalid ce for shadow sync
26ba25
Bugzilla: 1625173
26ba25
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
26ba25
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
26ba25
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
26ba25
26ba25
Bugzilla: 1629616
26ba25
26ba25
We should handle VTD_FR_CONTEXT_ENTRY_P properly when synchronizing
26ba25
shadow page tables.  Having invalid context entry there is perfectly
26ba25
valid when we move a device out of an existing domain.  When that
26ba25
happens, instead of posting an error we invalidate the whole region.
26ba25
26ba25
Without this patch, QEMU will crash if we do these steps:
26ba25
26ba25
(1) start QEMU with VT-d IOMMU and two 10G NICs (ixgbe)
26ba25
(2) bind the NICs with vfio-pci in the guest
26ba25
(3) start testpmd with the NICs applied
26ba25
(4) stop testpmd
26ba25
(5) rebind the NIC back to ixgbe kernel driver
26ba25
26ba25
The patch should fix it.
26ba25
26ba25
Reported-by: Pei Zhang <pezhang@redhat.com>
26ba25
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1627272
26ba25
Signed-off-by: Peter Xu <peterx@redhat.com>
26ba25
Reviewed-by: Eric Auger <eric.auger@redhat.com>
26ba25
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
26ba25
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
26ba25
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
26ba25
(cherry picked from commit c28b535d083d0a263d38d9ceeada83cdae8c64f0)
26ba25
Signed-off-by: Peter Xu <peterx@redhat.com>
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 hw/i386/intel_iommu.c | 17 +++++++++++++++++
26ba25
 1 file changed, 17 insertions(+)
26ba25
26ba25
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
26ba25
index c95128d..12af410 100644
26ba25
--- a/hw/i386/intel_iommu.c
26ba25
+++ b/hw/i386/intel_iommu.c
26ba25
@@ -38,6 +38,7 @@
26ba25
 #include "trace.h"
26ba25
 
26ba25
 static void vtd_address_space_refresh_all(IntelIOMMUState *s);
26ba25
+static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
26ba25
 
26ba25
 static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val,
26ba25
                             uint64_t wmask, uint64_t w1cmask)
26ba25
@@ -1066,11 +1067,27 @@ static int vtd_sync_shadow_page_table(VTDAddressSpace *vtd_as)
26ba25
 {
26ba25
     int ret;
26ba25
     VTDContextEntry ce;
26ba25
+    IOMMUNotifier *n;
26ba25
 
26ba25
     ret = vtd_dev_to_context_entry(vtd_as->iommu_state,
26ba25
                                    pci_bus_num(vtd_as->bus),
26ba25
                                    vtd_as->devfn, &ce);
26ba25
     if (ret) {
26ba25
+        if (ret == -VTD_FR_CONTEXT_ENTRY_P) {
26ba25
+            /*
26ba25
+             * It's a valid scenario to have a context entry that is
26ba25
+             * not present.  For example, when a device is removed
26ba25
+             * from an existing domain then the context entry will be
26ba25
+             * zeroed by the guest before it was put into another
26ba25
+             * domain.  When this happens, instead of synchronizing
26ba25
+             * the shadow pages we should invalidate all existing
26ba25
+             * mappings and notify the backends.
26ba25
+             */
26ba25
+            IOMMU_NOTIFIER_FOREACH(n, &vtd_as->iommu) {
26ba25
+                vtd_address_space_unmap(vtd_as, n);
26ba25
+            }
26ba25
+            ret = 0;
26ba25
+        }
26ba25
         return ret;
26ba25
     }
26ba25
 
26ba25
-- 
26ba25
1.8.3.1
26ba25