Blame SOURCES/kvm-intel_iommu-handle-invalid-ce-for-shadow-sync.patch

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