Blame SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch

4ec855
From 3a528a458d4a2ba4236e98ef3f4efe5482323972 Mon Sep 17 00:00:00 2001
4ec855
From: Peter Xu <peterx@redhat.com>
4ec855
Date: Wed, 9 Oct 2019 12:39:44 +0100
4ec855
Subject: [PATCH 18/22] intel_iommu: Sanity check vfio-pci config on machine
4ec855
 init done
4ec855
4ec855
RH-Author: Peter Xu <peterx@redhat.com>
4ec855
Message-id: <20191009123947.21505-3-peterx@redhat.com>
4ec855
Patchwork-id: 91347
4ec855
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/5] intel_iommu: Sanity check vfio-pci config on machine init done
4ec855
Bugzilla: 1738440
4ec855
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4ec855
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
4ec855
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
4ec855
4ec855
This check was previously only happened when the IOMMU is enabled in
4ec855
the guest.  It was always too late because the enabling of IOMMU
4ec855
normally only happens during the boot of guest OS.  It means that we
4ec855
can bail out and exit directly during the guest OS boots if the
4ec855
configuration of devices are not supported.  Or, if the guest didn't
4ec855
enable vIOMMU at all, then the user can use the guest normally but as
4ec855
long as it reconfigure the guest OS to enable the vIOMMU then reboot,
4ec855
the user will see the panic right after the reset when the next boot
4ec855
starts.
4ec855
4ec855
Let's make this failure even earlier so that we force the user to use
4ec855
caching-mode for vfio-pci devices when with the vIOMMU.  So the user
4ec855
won't get surprise at least during execution of the guest, which seems
4ec855
a bit nicer.
4ec855
4ec855
This will affect some user who didn't enable vIOMMU in the guest OS
4ec855
but was using vfio-pci and the vtd device in the past.  However I hope
4ec855
it's not a majority because not enabling vIOMMU with the device
4ec855
attached is actually meaningless.
4ec855
4ec855
We still keep the old assertion for safety so far because the hotplug
4ec855
path could still reach it, so far.
4ec855
4ec855
Reviewed-by: Eric Auger <eric.auger@redhat.com>
4ec855
Signed-off-by: Peter Xu <peterx@redhat.com>
4ec855
Message-Id: <20190916080718.3299-2-peterx@redhat.com>
4ec855
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
4ec855
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
4ec855
(cherry picked from commit 28cf553afeb29b0c4f339c600171552a72a68cb7)
4ec855
Signed-off-by: Peter Xu <peterx@redhat.com>
4ec855
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
4ec855
---
4ec855
 hw/i386/intel_iommu.c | 39 ++++++++++++++++++++++++++++++++++++---
4ec855
 1 file changed, 36 insertions(+), 3 deletions(-)
4ec855
4ec855
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
4ec855
index 22d2e52..44d19cc 100644
4ec855
--- a/hw/i386/intel_iommu.c
4ec855
+++ b/hw/i386/intel_iommu.c
4ec855
@@ -33,6 +33,7 @@
4ec855
 #include "hw/i386/x86-iommu.h"
4ec855
 #include "hw/pci-host/q35.h"
4ec855
 #include "sysemu/kvm.h"
4ec855
+#include "sysemu/sysemu.h"
4ec855
 #include "hw/i386/apic_internal.h"
4ec855
 #include "kvm_i386.h"
4ec855
 #include "trace.h"
4ec855
@@ -40,6 +41,13 @@
4ec855
 static void vtd_address_space_refresh_all(IntelIOMMUState *s);
4ec855
 static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
4ec855
 
4ec855
+static void vtd_panic_require_caching_mode(void)
4ec855
+{
4ec855
+    error_report("We need to set caching-mode=on for intel-iommu to enable "
4ec855
+                 "device assignment with IOMMU protection.");
4ec855
+    exit(1);
4ec855
+}
4ec855
+
4ec855
 static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val,
4ec855
                             uint64_t wmask, uint64_t w1cmask)
4ec855
 {
4ec855
@@ -2554,9 +2562,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
4ec855
     IntelIOMMUState *s = vtd_as->iommu_state;
4ec855
 
4ec855
     if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) {
4ec855
-        error_report("We need to set caching-mode=on for intel-iommu to enable "
4ec855
-                     "device assignment with IOMMU protection.");
4ec855
-        exit(1);
4ec855
+        vtd_panic_require_caching_mode();
4ec855
     }
4ec855
 
4ec855
     /* Update per-address-space notifier flags */
4ec855
@@ -3303,6 +3309,32 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
4ec855
     return true;
4ec855
 }
4ec855
 
4ec855
+static int vtd_machine_done_notify_one(Object *child, void *unused)
4ec855
+{
4ec855
+    IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
4ec855
+
4ec855
+    /*
4ec855
+     * We hard-coded here because vfio-pci is the only special case
4ec855
+     * here.  Let's be more elegant in the future when we can, but so
4ec855
+     * far there seems to be no better way.
4ec855
+     */
4ec855
+    if (object_dynamic_cast(child, "vfio-pci") && !iommu->caching_mode) {
4ec855
+        vtd_panic_require_caching_mode();
4ec855
+    }
4ec855
+
4ec855
+    return 0;
4ec855
+}
4ec855
+
4ec855
+static void vtd_machine_done_hook(Notifier *notifier, void *unused)
4ec855
+{
4ec855
+    object_child_foreach_recursive(object_get_root(),
4ec855
+                                   vtd_machine_done_notify_one, NULL);
4ec855
+}
4ec855
+
4ec855
+static Notifier vtd_machine_done_notify = {
4ec855
+    .notify = vtd_machine_done_hook,
4ec855
+};
4ec855
+
4ec855
 static void vtd_realize(DeviceState *dev, Error **errp)
4ec855
 {
4ec855
     MachineState *ms = MACHINE(qdev_get_machine());
4ec855
@@ -3333,6 +3365,7 @@ static void vtd_realize(DeviceState *dev, Error **errp)
4ec855
     pci_setup_iommu(bus, vtd_host_dma_iommu, dev);
4ec855
     /* Pseudo address space under root PCI bus. */
4ec855
     pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC);
4ec855
+    qemu_add_machine_init_done_notifier(&vtd_machine_done_notify);
4ec855
 }
4ec855
 
4ec855
 static void vtd_class_init(ObjectClass *klass, void *data)
4ec855
-- 
4ec855
1.8.3.1
4ec855