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

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