[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 55/97] intel_iommu: better handling of dmar state sw
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 55/97] intel_iommu: better handling of dmar state switch |
Date: |
Mon, 1 Apr 2019 15:59:29 -0500 |
From: Peter Xu <address@hidden>
QEMU is not handling the global DMAR switch well, especially when from
"on" to "off".
Let's first take the example of system reset.
Assuming that a guest has IOMMU enabled. When it reboots, we will drop
all the existing DMAR mappings to handle the system reset, however we'll
still keep the existing memory layouts which has the IOMMU memory region
enabled. So after the reboot and before the kernel reloads again, there
will be no mapping at all for the host device. That's problematic since
any software (for example, SeaBIOS) that runs earlier than the kernel
after the reboot will assume the IOMMU is disabled, so any DMA from the
software will fail.
For example, a guest that boots on an assigned NVMe device might fail to
find the boot device after a system reboot/reset and we'll be able to
observe SeaBIOS errors if we capture the debugging log:
WARNING - Timeout at nvme_wait:144!
Meanwhile, we should see DMAR errors on the host of that NVMe device.
It's the DMA fault that caused a NVMe driver timeout.
The correct fix should be that we do proper switching of device DMA
address spaces when system resets, which will setup correct memory
regions and notify the backend of the devices. This might not affect
much on non-assigned devices since QEMU VT-d emulation will assume a
default passthrough mapping if DMAR is not enabled in the GCMD
register (please refer to vtd_iommu_translate). However that's required
for an assigned devices, since that'll rebuild the correct GPA to HPA
mapping that is needed for any DMA operation during guest bootstrap.
Besides the system reset, we have some other places that might change
the global DMAR status and we'd better do the same thing there. For
example, when we change the state of GCMD register, or the DMAR root
pointer. Do the same refresh for all these places. For these two
places we'll also need to explicitly invalidate the context entry cache
and iotlb cache.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1625173
CC: QEMU Stable <address@hidden>
Reported-by: Cong Li <address@hidden>
Signed-off-by: Peter Xu <address@hidden>
--
v2:
- do the same for GCMD write, or root pointer update [Alex]
- test is carried out by me this time, by observing the
vtd_switch_address_space tracepoint after system reboot
v3:
- rewrite commit message as suggested by Alex
Signed-off-by: Peter Xu <address@hidden>
Reviewed-by: Eric Auger <address@hidden>
Reviewed-by: Jason Wang <address@hidden>
Reviewed-by: Michael S. Tsirkin <address@hidden>
Signed-off-by: Michael S. Tsirkin <address@hidden>
(cherry picked from commit 2cc9ddccebcaa48b3debfc279a83761fcbb7616c)
Signed-off-by: Michael Roth <address@hidden>
---
hw/i386/intel_iommu.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f66e93ed2c..4dfa9d5e2b 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -37,6 +37,8 @@
#include "kvm_i386.h"
#include "trace.h"
+static void vtd_address_space_refresh_all(IntelIOMMUState *s);
+
static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val,
uint64_t wmask, uint64_t w1cmask)
{
@@ -1426,7 +1428,7 @@ static void vtd_context_global_invalidate(IntelIOMMUState
*s)
vtd_reset_context_cache_locked(s);
}
vtd_iommu_unlock(s);
- vtd_switch_address_space_all(s);
+ vtd_address_space_refresh_all(s);
/*
* From VT-d spec 6.5.2.1, a global context entry invalidation
* should be followed by a IOTLB global invalidation, so we should
@@ -1711,6 +1713,8 @@ static void vtd_handle_gcmd_srtp(IntelIOMMUState *s)
vtd_root_table_setup(s);
/* Ok - report back to driver */
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_RTPS);
+ vtd_reset_caches(s);
+ vtd_address_space_refresh_all(s);
}
/* Set Interrupt Remap Table Pointer */
@@ -1743,7 +1747,8 @@ static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool
en)
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, VTD_GSTS_TES, 0);
}
- vtd_switch_address_space_all(s);
+ vtd_reset_caches(s);
+ vtd_address_space_refresh_all(s);
}
/* Handle Interrupt Remap Enable/Disable */
@@ -3022,6 +3027,12 @@ static void vtd_address_space_unmap_all(IntelIOMMUState
*s)
}
}
+static void vtd_address_space_refresh_all(IntelIOMMUState *s)
+{
+ vtd_address_space_unmap_all(s);
+ vtd_switch_address_space_all(s);
+}
+
static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
{
memory_region_notify_one((IOMMUNotifier *)private, entry);
@@ -3194,11 +3205,7 @@ static void vtd_reset(DeviceState *dev)
IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev);
vtd_init(s);
-
- /*
- * When device reset, throw away all mappings and external caches
- */
- vtd_address_space_unmap_all(s);
+ vtd_address_space_refresh_all(s);
}
static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
--
2.17.1
- [Qemu-devel] [PATCH 43/97] block/rbd: add deprecation documentation for filename keyvalue pairs, (continued)
- [Qemu-devel] [PATCH 43/97] block/rbd: add deprecation documentation for filename keyvalue pairs, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 42/97] block/rbd: add iotest for rbd legacy keyvalue filename parsing, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 45/97] ne2000: fix possible out of bound access in ne2000_receive, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 47/97] pcnet: fix possible buffer overflow, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 52/97] target/arm: Correct condition for v8M callee stack push, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 46/97] rtl8139: fix possible out of bound access, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 53/97] nbd/server: fix NBD_CMD_CACHE, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 54/97] intel_iommu: introduce vtd_reset_caches(), Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 56/97] nbd: fix NBD_FLAG_SEND_CACHE value, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 57/97] migration: Stop postcopy fault thread before notifying, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 55/97] intel_iommu: better handling of dmar state switch,
Michael Roth <=
- [Qemu-devel] [PATCH 61/97] net: drop too large packet early, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 65/97] fmops: fix off-by-one in AR_TABLE and DR_TABLE array size, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 66/97] vfio-helpers: Fix qemu_vfio_open_pci() crash, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 67/97] i2c: Move typedef of bitbang_i2c_interface to i2c.h, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 70/97] nbd/client: Make x-dirty-bitmap more reliable, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 72/97] mirror: fix dead-lock, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 73/97] iotests: simple mirror test with kvm on 1G image, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 68/97] i2c: Add a length check to the SMBus write handling, Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 78/97] hw/s390x: Fix bad mask in time2tod(), Michael Roth, 2019/04/01
- [Qemu-devel] [PATCH 35/97] block: Fix use after free error in bdrv_open_inherit(), Michael Roth, 2019/04/01