From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: tianyu.lan@intel.com, kevin.tian@intel.com, mst@redhat.com,
jan.kiszka@siemens.com, bd.aviv@gmail.com, peterx@redhat.com,
alex.williamson@redhat.com, jasowang@redhat.com
Subject: [Qemu-devel] [RFC PATCH 13/13] intel_iommu: use page_walk for iotlb inv notify
Date: Tue, 6 Dec 2016 18:36:28 +0800 [thread overview]
Message-ID: <1481020588-4245-14-git-send-email-peterx@redhat.com> (raw)
In-Reply-To: <1481020588-4245-1-git-send-email-peterx@redhat.com>
Instead of translate() every page for iotlb invalidations (which is
slower), we walk the pages when needed and notify in a hook function.
This will also simplify the code a bit.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 64 +++++++++++++++------------------------------------
1 file changed, 19 insertions(+), 45 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 0220e63..226dbcd 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -149,23 +149,6 @@ static uint64_t vtd_set_clear_mask_quad(IntelIOMMUState *s, hwaddr addr,
return new_val;
}
-static int vtd_get_did_dev(IntelIOMMUState *s, uint8_t bus_num, uint8_t devfn,
- uint16_t *domain_id)
-{
- VTDContextEntry ce;
- int ret_fr;
-
- assert(domain_id);
-
- ret_fr = vtd_dev_to_context_entry(s, bus_num, devfn, &ce);
- if (ret_fr) {
- return -1;
- }
-
- *domain_id = VTD_CONTEXT_ENTRY_DID(ce.hi);
- return 0;
-}
-
/* GHashTable functions */
static gboolean vtd_uint64_equal(gconstpointer v1, gconstpointer v2)
{
@@ -868,7 +851,8 @@ next:
* @private: private data for the hook function
*/
static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end,
- vtd_page_walk_hook hook_fn, void *private)
+ vtd_page_walk_hook hook_fn, void *private,
+ bool notify_unmap)
{
dma_addr_t addr = vtd_get_slpt_base_from_context(ce);
uint32_t level = vtd_get_level_from_context_entry(ce);
@@ -887,7 +871,7 @@ static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end,
trace_vtd_page_walk(ce->hi, ce->lo, start, end);
return vtd_page_walk_level(addr, start, end, hook_fn, private,
- level, true, true, NULL, false);
+ level, true, true, NULL, notify_unmap);
}
/* Map a device to its corresponding domain (context-entry) */
@@ -1238,39 +1222,29 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
&domain_id);
}
+static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
+ void *private)
+{
+ memory_region_notify_iommu((MemoryRegion *)private, *entry);
+ return 0;
+}
+
static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
uint16_t domain_id, hwaddr addr,
uint8_t am)
{
IntelIOMMUNotifierNode *node;
+ VTDContextEntry ce;
+ int ret;
QLIST_FOREACH(node, &(s->notifiers_list), next) {
VTDAddressSpace *vtd_as = node->vtd_as;
- uint16_t vfio_domain_id;
- int ret = vtd_get_did_dev(s, pci_bus_num(vtd_as->bus), vtd_as->devfn,
- &vfio_domain_id);
- if (!ret && domain_id == vfio_domain_id) {
- hwaddr original_addr = addr;
-
- while (addr < original_addr + (1 << am) * VTD_PAGE_SIZE) {
- IOMMUTLBEntry entry = s->iommu_ops.translate(
- &node->vtd_as->iommu,
- addr,
- IOMMU_NO_FAIL);
-
- if (entry.perm == IOMMU_NONE &&
- node->notifier_flag & IOMMU_NOTIFIER_UNMAP) {
- entry.target_as = &address_space_memory;
- entry.iova = addr & VTD_PAGE_MASK_4K;
- entry.translated_addr = 0;
- entry.addr_mask = ~VTD_PAGE_MASK(VTD_PAGE_SHIFT);
- memory_region_notify_iommu(&node->vtd_as->iommu, entry);
- addr += VTD_PAGE_SIZE;
- } else if (node->notifier_flag & IOMMU_NOTIFIER_MAP) {
- memory_region_notify_iommu(&node->vtd_as->iommu, entry);
- addr += entry.addr_mask + 1;
- }
- }
+ ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
+ vtd_as->devfn, &ce);
+ if (!ret && domain_id == VTD_CONTEXT_ENTRY_DID(ce.hi)) {
+ vtd_page_walk(&ce, addr, addr + (1 << am) * VTD_PAGE_SIZE,
+ vtd_page_invalidate_notify_hook,
+ (void *)&vtd_as->iommu, true);
}
}
}
@@ -2623,7 +2597,7 @@ static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
*/
trace_vtd_replay_ce_valid(bus_n, PCI_SLOT(vtd_as->devfn),
PCI_FUNC(vtd_as->devfn), ce.hi, ce.lo);
- vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n);
+ vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n, false);
} else {
trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn),
PCI_FUNC(vtd_as->devfn));
--
2.7.4
next prev parent reply other threads:[~2016-12-06 10:37 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-06 10:36 [Qemu-devel] [RFC PATCH 00/13] VT-d replay and misc cleanup Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 01/13] intel_iommu: allocate new key when creating new address space Peter Xu
2016-12-12 8:16 ` Liu, Yi L
2016-12-14 3:05 ` Peter Xu
2016-12-14 3:24 ` Liu, Yi L
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 02/13] intel_iommu: simplify irq region translation Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 03/13] intel_iommu: renaming gpa to iova where proper Peter Xu
2016-12-18 8:39 ` Liu, Yi L
2016-12-19 9:23 ` Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 04/13] intel_iommu: fix trace for inv desc handling Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 05/13] intel_iommu: fix trace for addr translation Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 06/13] intel_iommu: vtd_slpt_level_shift check level Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 07/13] memory: add section range info for IOMMU notifier Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 08/13] memory: provide iommu_replay_all() Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 09/13] memory: introduce memory_region_notify_one() Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 10/13] memory: add MemoryRegionIOMMUOps.replay() callback Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 11/13] intel_iommu: provide its own replay() callback Peter Xu
2016-12-08 3:01 ` Lan Tianyu
2016-12-09 1:56 ` Peter Xu
2016-12-06 10:36 ` [Qemu-devel] [RFC PATCH 12/13] intel_iommu: do replay when context invalidate Peter Xu
2016-12-06 10:36 ` Peter Xu [this message]
2016-12-06 10:49 ` [Qemu-devel] [RFC PATCH 00/13] VT-d replay and misc cleanup Peter Xu
2016-12-13 7:45 ` Peter Xu
2016-12-18 8:42 ` Liu, Yi L
2016-12-19 9:22 ` Peter Xu
2016-12-19 11:25 ` Liu, Yi L
2016-12-19 9:33 ` Peter Xu
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=1481020588-4245-14-git-send-email-peterx@redhat.com \
--to=peterx@redhat.com \
--cc=alex.williamson@redhat.com \
--cc=bd.aviv@gmail.com \
--cc=jan.kiszka@siemens.com \
--cc=jasowang@redhat.com \
--cc=kevin.tian@intel.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=tianyu.lan@intel.com \
/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).