Blame SOURCES/kvm-exec-add-page_mask-for-address_space_do_translate.patch

4a2fec
From 59ad61373f73de6a3eb17e0c1989bc048b51b55c Mon Sep 17 00:00:00 2001
4a2fec
From: Maxime Coquelin <maxime.coquelin@redhat.com>
4a2fec
Date: Fri, 20 Oct 2017 14:17:06 +0200
4a2fec
Subject: [PATCH 04/19] exec: add page_mask for address_space_do_translate
4a2fec
4a2fec
RH-Author: Maxime Coquelin <maxime.coquelin@redhat.com>
4a2fec
Message-id: <20171020141707.17637-2-maxime.coquelin@redhat.com>
4a2fec
Patchwork-id: 77417
4a2fec
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH 1/2] exec: add page_mask for address_space_do_translate
4a2fec
Bugzilla: 1498817
4a2fec
RH-Acked-by: Peter Xu <peterx@redhat.com>
4a2fec
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
4a2fec
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
4a2fec
4a2fec
From: Peter Xu <peterx@redhat.com>
4a2fec
4a2fec
The function is originally used for address_space_space_translate() and
4a2fec
what we care about most is (xlat, plen) range. However for iotlb
4a2fec
requests, we don't really care about "plen", but the size of the page
4a2fec
that "xlat" is located on. While, plen cannot really contain this
4a2fec
information.
4a2fec
4a2fec
A simple example to show why "plen" is not good for IOTLB translations:
4a2fec
4a2fec
E.g., for huge pages, it is possible that guest mapped 1G huge page on
4a2fec
device side that used this GPA range:
4a2fec
4a2fec
  0x100000000 - 0x13fffffff
4a2fec
4a2fec
Then let's say we want to translate one IOVA that finally mapped to GPA
4a2fec
0x13ffffe00 (which is located on this 1G huge page). Then here we'll
4a2fec
get:
4a2fec
4a2fec
  (xlat, plen) = (0x13fffe00, 0x200)
4a2fec
4a2fec
So the IOTLB would be only covering a very small range since from
4a2fec
"plen" (which is 0x200 bytes) we cannot tell the size of the page.
4a2fec
4a2fec
Actually we can really know that this is a huge page - we just throw the
4a2fec
information away in address_space_do_translate().
4a2fec
4a2fec
This patch introduced "page_mask" optional parameter to capture that
4a2fec
page mask info. Also, I made "plen" an optional parameter as well, with
4a2fec
some comments for the whole function.
4a2fec
4a2fec
No functional change yet.
4a2fec
4a2fec
Signed-off-by: Peter Xu <peterx@redhat.com>
4a2fec
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
4a2fec
Message-Id: <20171010094247.10173-2-maxime.coquelin@redhat.com>
4a2fec
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
(cherry picked from commit d5e5fafd11be4458443c43f19c1ebdd24d99a751)
4a2fec
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
4a2fec
Conflicts:
4a2fec
	exec.c (Skipping 166206845f7f)
4a2fec
---
4a2fec
 exec.c | 32 +++++++++++++++++++++++++++-----
4a2fec
 1 file changed, 27 insertions(+), 5 deletions(-)
4a2fec
4a2fec
diff --git a/exec.c b/exec.c
4a2fec
index d20c34c..e5f97fd 100644
4a2fec
--- a/exec.c
4a2fec
+++ b/exec.c
4a2fec
@@ -475,7 +475,8 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
4a2fec
 static MemoryRegionSection address_space_do_translate(AddressSpace *as,
4a2fec
                                                       hwaddr addr,
4a2fec
                                                       hwaddr *xlat,
4a2fec
-                                                      hwaddr *plen,
4a2fec
+                                                      hwaddr *plen_out,
4a2fec
+                                                      hwaddr *page_mask_out,
4a2fec
                                                       bool is_write,
4a2fec
                                                       bool is_mmio)
4a2fec
 {
4a2fec
@@ -483,10 +484,16 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
4a2fec
     MemoryRegionSection *section;
4a2fec
     IOMMUMemoryRegion *iommu_mr;
4a2fec
     IOMMUMemoryRegionClass *imrc;
4a2fec
+    hwaddr page_mask = (hwaddr)(-1);
4a2fec
+    hwaddr plen = (hwaddr)(-1);
4a2fec
+
4a2fec
+    if (plen_out) {
4a2fec
+        plen = *plen_out;
4a2fec
+    }
4a2fec
 
4a2fec
     for (;;) {
4a2fec
         AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
4a2fec
-        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
4a2fec
+        section = address_space_translate_internal(d, addr, &addr, &plen, is_mmio);
4a2fec
 
4a2fec
         iommu_mr = memory_region_get_iommu(section->mr);
4a2fec
         if (!iommu_mr) {
4a2fec
@@ -498,7 +505,8 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
4a2fec
                                 IOMMU_WO : IOMMU_RO);
4a2fec
         addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
4a2fec
                 | (addr & iotlb.addr_mask));
4a2fec
-        *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
4a2fec
+        page_mask &= iotlb.addr_mask;
4a2fec
+        plen = MIN(plen, (addr | iotlb.addr_mask) - addr + 1);
4a2fec
         if (!(iotlb.perm & (1 << is_write))) {
4a2fec
             goto translate_fail;
4a2fec
         }
4a2fec
@@ -508,6 +516,19 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
4a2fec
 
4a2fec
     *xlat = addr;
4a2fec
 
4a2fec
+    if (page_mask == (hwaddr)(-1)) {
4a2fec
+        /* Not behind an IOMMU, use default page size. */
4a2fec
+        page_mask = ~TARGET_PAGE_MASK;
4a2fec
+    }
4a2fec
+
4a2fec
+    if (page_mask_out) {
4a2fec
+        *page_mask_out = page_mask;
4a2fec
+    }
4a2fec
+
4a2fec
+    if (plen_out) {
4a2fec
+        *plen_out = plen;
4a2fec
+    }
4a2fec
+
4a2fec
     return *section;
4a2fec
 
4a2fec
 translate_fail:
4a2fec
@@ -526,7 +547,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
4a2fec
 
4a2fec
     /* This can never be MMIO. */
4a2fec
     section = address_space_do_translate(as, addr, &xlat, &plen,
4a2fec
-                                         is_write, false);
4a2fec
+                                         NULL, is_write, false);
4a2fec
 
4a2fec
     /* Illegal translation */
4a2fec
     if (section.mr == &io_mem_unassigned) {
4a2fec
@@ -570,7 +591,8 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
4a2fec
     MemoryRegionSection section;
4a2fec
 
4a2fec
     /* This can be MMIO, so setup MMIO bit. */
4a2fec
-    section = address_space_do_translate(as, addr, xlat, plen, is_write, true);
4a2fec
+    section = address_space_do_translate(as, addr, xlat, plen, NULL,
4a2fec
+                                         is_write, true);
4a2fec
     mr = section.mr;
4a2fec
 
4a2fec
     if (xen_enabled() && memory_access_is_direct(mr, is_write)) {
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec