From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Xu <peterx@redhat.com>
Subject: [Qemu-devel] [PULL 05/12] intel_iommu: Fix unexpected unmaps during global unmap
Date: Fri, 5 Jul 2019 21:50:32 +0200 [thread overview]
Message-ID: <1562356239-19391-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1562356239-19391-1-git-send-email-pbonzini@redhat.com>
From: Peter Xu <peterx@redhat.com>
This is an replacement work of Yan Zhao's patch:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg625340.html
vtd_address_space_unmap() will do proper page mask alignment to make
sure each IOTLB message will have correct masks for notification
messages (2^N-1), but sometimes it can be expanded to even supercede
the registered range. That could lead to unexpected UNMAP of already
mapped regions in some other notifiers.
Instead of doing mindless expension of the start address and address
mask, we split the range into smaller ones and guarantee that each
small range will have correct masks (2^N-1) and at the same time we
should also try our best to generate as less IOTLB messages as
possible.
Reported-by: Yan Zhao <yan.y.zhao@intel.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Yan Zhao <yan.y.zhao@intel.com>
Message-Id: <20190624091811.30412-3-peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/intel_iommu.c | 67 +++++++++++++++++++++++++++++++--------------------
1 file changed, 41 insertions(+), 26 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 719ce19..de86f53 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3363,11 +3363,28 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
return vtd_dev_as;
}
+static uint64_t get_naturally_aligned_size(uint64_t start,
+ uint64_t size, int gaw)
+{
+ uint64_t max_mask = 1ULL << gaw;
+ uint64_t alignment = start ? start & -start : max_mask;
+
+ alignment = MIN(alignment, max_mask);
+ size = MIN(size, max_mask);
+
+ if (alignment <= size) {
+ /* Increase the alignment of start */
+ return alignment;
+ } else {
+ /* Find the largest page mask from size */
+ return 1ULL << (63 - clz64(size));
+ }
+}
+
/* Unmap the whole range in the notifier's scope. */
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
{
- IOMMUTLBEntry entry;
- hwaddr size;
+ hwaddr size, remain;
hwaddr start = n->start;
hwaddr end = n->end;
IntelIOMMUState *s = as->iommu_state;
@@ -3388,39 +3405,37 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
}
assert(start <= end);
- size = end - start;
+ size = remain = end - start + 1;
- if (ctpop64(size) != 1) {
- /*
- * This size cannot format a correct mask. Let's enlarge it to
- * suite the minimum available mask.
- */
- int n = 64 - clz64(size);
- if (n > s->aw_bits) {
- /* should not happen, but in case it happens, limit it */
- n = s->aw_bits;
- }
- size = 1ULL << n;
+ while (remain >= VTD_PAGE_SIZE) {
+ IOMMUTLBEntry entry;
+ uint64_t mask = get_naturally_aligned_size(start, remain, s->aw_bits);
+
+ assert(mask);
+
+ entry.iova = start;
+ entry.addr_mask = mask - 1;
+ entry.target_as = &address_space_memory;
+ entry.perm = IOMMU_NONE;
+ /* This field is meaningless for unmap */
+ entry.translated_addr = 0;
+
+ memory_region_notify_one(n, &entry);
+
+ start += mask;
+ remain -= mask;
}
- entry.target_as = &address_space_memory;
- /* Adjust iova for the size */
- entry.iova = n->start & ~(size - 1);
- /* This field is meaningless for unmap */
- entry.translated_addr = 0;
- entry.perm = IOMMU_NONE;
- entry.addr_mask = size - 1;
+ assert(!remain);
trace_vtd_as_unmap_whole(pci_bus_num(as->bus),
VTD_PCI_SLOT(as->devfn),
VTD_PCI_FUNC(as->devfn),
- entry.iova, size);
+ n->start, size);
- map.iova = entry.iova;
- map.size = entry.addr_mask;
+ map.iova = n->start;
+ map.size = size;
iova_tree_remove(as->iova_tree, &map);
-
- memory_region_notify_one(n, &entry);
}
static void vtd_address_space_unmap_all(IntelIOMMUState *s)
--
1.8.3.1
next prev parent reply other threads:[~2019-07-05 19:55 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-05 19:50 [Qemu-devel] [PULL 00/12] Misc bugfixes for QEMU hard freeze Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 01/12] pc: fix possible NULL pointer dereference in pc_machine_get_device_memory_region_size() Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 02/12] checkpatch: do not warn for multiline parenthesized returned value Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 03/12] i386/kvm: Fix build with -m32 Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 04/12] intel_iommu: Fix incorrect "end" for vtd_address_space_unmap Paolo Bonzini
2019-07-05 19:50 ` Paolo Bonzini [this message]
2019-07-05 19:50 ` [Qemu-devel] [PULL 06/12] ioapic: clear irq_eoi when updating the ioapic redirect table entry Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 07/12] target/i386: fix feature check in hyperv-stub.c Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 08/12] minikconf: do not include variables from MINIKCONF_ARGS in config-all-devices.mak Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 09/12] target/i386: kvm: Fix when nested state is needed for migration Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 10/12] Makefile: generate header file with the list of devices enabled Paolo Bonzini
2019-07-05 19:50 ` [Qemu-devel] [PULL 11/12] hw/i386: Fix linker error when ISAPC is disabled Paolo Bonzini
2019-07-06 4:25 ` Markus Armbruster
2019-07-06 4:35 ` Markus Armbruster
2019-07-05 19:50 ` [Qemu-devel] [PULL 12/12] ioapic: use irq number instead of vector in ioapic_eoi_broadcast Paolo Bonzini
2019-07-05 20:24 ` [Qemu-devel] [PULL 00/12] Misc bugfixes for QEMU hard freeze Paolo Bonzini
2019-07-06 4:32 ` Eric Blake
2019-07-06 4:49 ` Eric Blake
2019-07-06 8:07 ` no-reply
-- strict thread matches above, loose matches on Subject: below --
2019-07-05 20:23 Paolo Bonzini
2019-07-05 20:23 ` [Qemu-devel] [PULL 05/12] intel_iommu: Fix unexpected unmaps during global unmap Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1562356239-19391-6-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).