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