016a62
From 064565e76b986a42d9cdcba72965887528cea90a Mon Sep 17 00:00:00 2001
016a62
From: Maxim Levitsky <mlevitsk@redhat.com>
016a62
Date: Sun, 22 Dec 2019 11:02:06 +0100
016a62
Subject: [PATCH 1/7] exec: Fix MAP_RAM for cached access
016a62
016a62
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
016a62
Message-id: <20191222110207.21384-2-mlevitsk@redhat.com>
016a62
Patchwork-id: 93207
016a62
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] exec: Fix MAP_RAM for cached access
016a62
Bugzilla: 1769613
016a62
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
016a62
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
016a62
RH-Acked-by: Peter Xu <peterx@redhat.com>
016a62
016a62
From: Eric Auger <eric.auger@redhat.com>
016a62
016a62
When an IOMMUMemoryRegion is in front of a virtio device,
016a62
address_space_cache_init does not set cache->ptr as the memory
016a62
region is not RAM. However when the device performs an access,
016a62
we end up in glue() which performs the translation and then uses
016a62
MAP_RAM. This latter uses the unset ptr and returns a wrong value
016a62
which leads to a SIGSEV in address_space_lduw_internal_cached_slow,
016a62
for instance.
016a62
016a62
In slow path cache->ptr is NULL and MAP_RAM must redirect to
016a62
qemu_map_ram_ptr((mr)->ram_block, ofs).
016a62
016a62
As MAP_RAM, IS_DIRECT and INVALIDATE are the same in _cached_slow
016a62
and non cached mode, let's remove those macros.
016a62
016a62
This fixes the use cases featuring vIOMMU (Intel and ARM SMMU)
016a62
which lead to a SIGSEV.
016a62
016a62
Fixes: 48564041a73a (exec: reintroduce MemoryRegion caching)
016a62
Signed-off-by: Eric Auger <eric.auger@redhat.com>
016a62
016a62
Message-Id: <1528895946-28677-1-git-send-email-eric.auger@redhat.com>
016a62
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
016a62
(cherry picked from commit a99761d3c85679da380c0f597468acd3dc1b53b3)
016a62
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
016a62
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
016a62
---
016a62
 exec.c            |  6 ------
016a62
 memory_ldst.inc.c | 47 ++++++++++++++++++++++-------------------------
016a62
 2 files changed, 22 insertions(+), 31 deletions(-)
016a62
016a62
diff --git a/exec.c b/exec.c
016a62
index 9112d8b..86218ef 100644
016a62
--- a/exec.c
016a62
+++ b/exec.c
016a62
@@ -3608,9 +3608,6 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
016a62
 #define ARG1                     as
016a62
 #define SUFFIX
016a62
 #define TRANSLATE(...)           address_space_translate(as, __VA_ARGS__)
016a62
-#define IS_DIRECT(mr, is_write)  memory_access_is_direct(mr, is_write)
016a62
-#define MAP_RAM(mr, ofs)         qemu_map_ram_ptr((mr)->ram_block, ofs)
016a62
-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
016a62
 #define RCU_READ_LOCK(...)       rcu_read_lock()
016a62
 #define RCU_READ_UNLOCK(...)     rcu_read_unlock()
016a62
 #include "memory_ldst.inc.c"
016a62
@@ -3643,9 +3640,6 @@ void address_space_cache_destroy(MemoryRegionCache *cache)
016a62
 #define SUFFIX                   _cached
016a62
 #define TRANSLATE(addr, ...)     \
016a62
     address_space_translate(cache->as, cache->xlat + (addr), __VA_ARGS__)
016a62
-#define IS_DIRECT(mr, is_write)  true
016a62
-#define MAP_RAM(mr, ofs)         qemu_map_ram_ptr((mr)->ram_block, ofs)
016a62
-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
016a62
 #define RCU_READ_LOCK()          rcu_read_lock()
016a62
 #define RCU_READ_UNLOCK()        rcu_read_unlock()
016a62
 #include "memory_ldst.inc.c"
016a62
diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c
016a62
index 5dbff9c..a30060c 100644
016a62
--- a/memory_ldst.inc.c
016a62
+++ b/memory_ldst.inc.c
016a62
@@ -34,7 +34,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, false);
016a62
-    if (l < 4 || !IS_DIRECT(mr, false)) {
016a62
+    if (l < 4 || !memory_access_is_direct(mr, false)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
         /* I/O case */
016a62
@@ -50,7 +50,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
016a62
 #endif
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             val = ldl_le_p(ptr);
016a62
@@ -128,7 +128,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, false);
016a62
-    if (l < 8 || !IS_DIRECT(mr, false)) {
016a62
+    if (l < 8 || !memory_access_is_direct(mr, false)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
         /* I/O case */
016a62
@@ -144,7 +144,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
016a62
 #endif
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             val = ldq_le_p(ptr);
016a62
@@ -220,14 +220,14 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, false);
016a62
-    if (!IS_DIRECT(mr, false)) {
016a62
+    if (!memory_access_is_direct(mr, false)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
         /* I/O case */
016a62
         r = memory_region_dispatch_read(mr, addr1, &val, 1, attrs);
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         val = ldub_p(ptr);
016a62
         r = MEMTX_OK;
016a62
     }
016a62
@@ -262,7 +262,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, false);
016a62
-    if (l < 2 || !IS_DIRECT(mr, false)) {
016a62
+    if (l < 2 || !memory_access_is_direct(mr, false)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
         /* I/O case */
016a62
@@ -278,7 +278,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
016a62
 #endif
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             val = lduw_le_p(ptr);
016a62
@@ -357,12 +357,12 @@ void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, true);
016a62
-    if (l < 4 || !IS_DIRECT(mr, true)) {
016a62
+    if (l < 4 || !memory_access_is_direct(mr, true)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
         r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
016a62
     } else {
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         stl_p(ptr, val);
016a62
 
016a62
         dirty_log_mask = memory_region_get_dirty_log_mask(mr);
016a62
@@ -400,7 +400,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, true);
016a62
-    if (l < 4 || !IS_DIRECT(mr, true)) {
016a62
+    if (l < 4 || !memory_access_is_direct(mr, true)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
 #if defined(TARGET_WORDS_BIGENDIAN)
016a62
@@ -415,7 +415,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
016a62
         r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             stl_le_p(ptr, val);
016a62
@@ -427,7 +427,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
016a62
             stl_p(ptr, val);
016a62
             break;
016a62
         }
016a62
-        INVALIDATE(mr, addr1, 4);
016a62
+        invalidate_and_set_dirty(mr, addr1, 4);
016a62
         r = MEMTX_OK;
016a62
     }
016a62
     if (result) {
016a62
@@ -490,14 +490,14 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, true);
016a62
-    if (!IS_DIRECT(mr, true)) {
016a62
+    if (!memory_access_is_direct(mr, true)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
         r = memory_region_dispatch_write(mr, addr1, val, 1, attrs);
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         stb_p(ptr, val);
016a62
-        INVALIDATE(mr, addr1, 1);
016a62
+        invalidate_and_set_dirty(mr, addr1, 1);
016a62
         r = MEMTX_OK;
016a62
     }
016a62
     if (result) {
016a62
@@ -529,7 +529,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, true);
016a62
-    if (l < 2 || !IS_DIRECT(mr, true)) {
016a62
+    if (l < 2 || !memory_access_is_direct(mr, true)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
 #if defined(TARGET_WORDS_BIGENDIAN)
016a62
@@ -544,7 +544,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
016a62
         r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             stw_le_p(ptr, val);
016a62
@@ -556,7 +556,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
016a62
             stw_p(ptr, val);
016a62
             break;
016a62
         }
016a62
-        INVALIDATE(mr, addr1, 2);
016a62
+        invalidate_and_set_dirty(mr, addr1, 2);
016a62
         r = MEMTX_OK;
016a62
     }
016a62
     if (result) {
016a62
@@ -620,7 +620,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
016a62
 
016a62
     RCU_READ_LOCK();
016a62
     mr = TRANSLATE(addr, &addr1, &l, true);
016a62
-    if (l < 8 || !IS_DIRECT(mr, true)) {
016a62
+    if (l < 8 || !memory_access_is_direct(mr, true)) {
016a62
         release_lock |= prepare_mmio_access(mr);
016a62
 
016a62
 #if defined(TARGET_WORDS_BIGENDIAN)
016a62
@@ -635,7 +635,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
016a62
         r = memory_region_dispatch_write(mr, addr1, val, 8, attrs);
016a62
     } else {
016a62
         /* RAM case */
016a62
-        ptr = MAP_RAM(mr, addr1);
016a62
+        ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
016a62
         switch (endian) {
016a62
         case DEVICE_LITTLE_ENDIAN:
016a62
             stq_le_p(ptr, val);
016a62
@@ -647,7 +647,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
016a62
             stq_p(ptr, val);
016a62
             break;
016a62
         }
016a62
-        INVALIDATE(mr, addr1, 8);
016a62
+        invalidate_and_set_dirty(mr, addr1, 8);
016a62
         r = MEMTX_OK;
016a62
     }
016a62
     if (result) {
016a62
@@ -702,8 +702,5 @@ void glue(stq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
016a62
 #undef ARG1
016a62
 #undef SUFFIX
016a62
 #undef TRANSLATE
016a62
-#undef IS_DIRECT
016a62
-#undef MAP_RAM
016a62
-#undef INVALIDATE
016a62
 #undef RCU_READ_LOCK
016a62
 #undef RCU_READ_UNLOCK
016a62
-- 
016a62
1.8.3.1
016a62