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

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