yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-memory-clamp-cached-translation-in-case-it-points-to.patch

8fced6
From 354946f1e5fee0a69282bdf284c969b03a78a53e Mon Sep 17 00:00:00 2001
8fced6
From: Jon Maloy <jmaloy@redhat.com>
8fced6
Date: Wed, 13 Jan 2021 00:42:23 -0500
8fced6
Subject: [PATCH 15/17] memory: clamp cached translation in case it points to
8fced6
 an MMIO region
8fced6
8fced6
RH-Author: Jon Maloy <jmaloy@redhat.com>
8fced6
Message-id: <20210113004223.871394-2-jmaloy@redhat.com>
8fced6
Patchwork-id: 100618
8fced6
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/1] memory: clamp cached translation in case it points to an MMIO region
8fced6
Bugzilla: 1904393
8fced6
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
8fced6
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
8fced6
RH-Acked-by: Thomas Huth <thuth@redhat.com>
8fced6
8fced6
From: Paolo Bonzini <pbonzini@redhat.com>
8fced6
8fced6
In using the address_space_translate_internal API, address_space_cache_init
8fced6
forgot one piece of advice that can be found in the code for
8fced6
address_space_translate_internal:
8fced6
8fced6
    /* MMIO registers can be expected to perform full-width accesses based only
8fced6
     * on their address, without considering adjacent registers that could
8fced6
     * decode to completely different MemoryRegions.  When such registers
8fced6
     * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO
8fced6
     * regions overlap wildly.  For this reason we cannot clamp the accesses
8fced6
     * here.
8fced6
     *
8fced6
     * If the length is small (as is the case for address_space_ldl/stl),
8fced6
     * everything works fine.  If the incoming length is large, however,
8fced6
     * the caller really has to do the clamping through memory_access_size.
8fced6
     */
8fced6
8fced6
address_space_cache_init is exactly one such case where "the incoming length
8fced6
is large", therefore we need to clamp the resulting length---not to
8fced6
memory_access_size though, since we are not doing an access yet, but to
8fced6
the size of the resulting section.  This ensures that subsequent accesses
8fced6
to the cached MemoryRegionSection will be in range.
8fced6
8fced6
With this patch, the enclosed testcase notices that the used ring does
8fced6
not fit into the MSI-X table and prints a "qemu-system-x86_64: Cannot map used"
8fced6
error.
8fced6
8fced6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8fced6
8fced6
(cherry picked from 4bfb024bc76973d40a359476dc0291f46e435442)
8fced6
- Manually applied to file exec.c, where the code to correct
8fced6
  is located in this version.
8fced6
- Skipped the fuzzing test part, which is hard to apply on this code.
8fced6
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
8fced6
8fced6
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
8fced6
---
8fced6
 exec.c | 10 ++++++++++
8fced6
 1 file changed, 10 insertions(+)
8fced6
8fced6
diff --git a/exec.c b/exec.c
8fced6
index ffdb5185353..09ed0cfc756 100644
8fced6
--- a/exec.c
8fced6
+++ b/exec.c
8fced6
@@ -3620,6 +3620,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
8fced6
     AddressSpaceDispatch *d;
8fced6
     hwaddr l;
8fced6
     MemoryRegion *mr;
8fced6
+    Int128 diff;
8fced6
 
8fced6
     assert(len > 0);
8fced6
 
8fced6
@@ -3628,6 +3629,15 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
8fced6
     d = flatview_to_dispatch(cache->fv);
8fced6
     cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true);
8fced6
 
8fced6
+    /*
8fced6
+     * cache->xlat is now relative to cache->mrs.mr, not to the section itself.
8fced6
+     * Take that into account to compute how many bytes are there between
8fced6
+     * cache->xlat and the end of the section.
8fced6
+     */
8fced6
+    diff = int128_sub(cache->mrs.size,
8fced6
+                      int128_make64(cache->xlat - cache->mrs.offset_within_region));
8fced6
+    l = int128_get64(int128_min(diff, int128_make64(l)));
8fced6
+
8fced6
     mr = cache->mrs.mr;
8fced6
     memory_region_ref(mr);
8fced6
     if (memory_access_is_direct(mr, is_write)) {
8fced6
-- 
8fced6
2.27.0
8fced6