|
|
7711c0 |
From 8bd172d00ceb35cd2a625f1a86fe50a786d8564a Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Date: Fri, 25 Jan 2019 22:50:06 +0100
|
|
|
7711c0 |
Subject: [PATCH 06/23] exec: Fix MAP_RAM for cached access
|
|
|
7711c0 |
MIME-Version: 1.0
|
|
|
7711c0 |
Content-Type: text/plain; charset=UTF-8
|
|
|
7711c0 |
Content-Transfer-Encoding: 8bit
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Message-id: <20190125225007.8197-7-jsnow@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 84123
|
|
|
7711c0 |
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH v2 6/7] exec: Fix MAP_RAM for cached access
|
|
|
7711c0 |
Bugzilla: 1597482
|
|
|
7711c0 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Peter Xu <peterx@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
From: Eric Auger <eric.auger@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
When an IOMMUMemoryRegion is in front of a virtio device,
|
|
|
7711c0 |
address_space_cache_init does not set cache->ptr as the memory
|
|
|
7711c0 |
region is not RAM. However when the device performs an access,
|
|
|
7711c0 |
we end up in glue() which performs the translation and then uses
|
|
|
7711c0 |
MAP_RAM. This latter uses the unset ptr and returns a wrong value
|
|
|
7711c0 |
which leads to a SIGSEV in address_space_lduw_internal_cached_slow,
|
|
|
7711c0 |
for instance.
|
|
|
7711c0 |
|
|
|
7711c0 |
In slow path cache->ptr is NULL and MAP_RAM must redirect to
|
|
|
7711c0 |
qemu_map_ram_ptr((mr)->ram_block, ofs).
|
|
|
7711c0 |
|
|
|
7711c0 |
As MAP_RAM, IS_DIRECT and INVALIDATE are the same in _cached_slow
|
|
|
7711c0 |
and non cached mode, let's remove those macros.
|
|
|
7711c0 |
|
|
|
7711c0 |
This fixes the use cases featuring vIOMMU (Intel and ARM SMMU)
|
|
|
7711c0 |
which lead to a SIGSEV.
|
|
|
7711c0 |
|
|
|
7711c0 |
Fixes: 48564041a73a (exec: reintroduce MemoryRegion caching)
|
|
|
7711c0 |
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
Message-Id: <1528895946-28677-1-git-send-email-eric.auger@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
7711c0 |
(cherry picked from commit a99761d3c85679da380c0f597468acd3dc1b53b3)
|
|
|
7711c0 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
exec.c | 6 ------
|
|
|
7711c0 |
memory_ldst.inc.c | 47 ++++++++++++++++++++++-------------------------
|
|
|
7711c0 |
2 files changed, 22 insertions(+), 31 deletions(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/exec.c b/exec.c
|
|
|
7711c0 |
index 805a2d4..d87a51a 100644
|
|
|
7711c0 |
--- a/exec.c
|
|
|
7711c0 |
+++ b/exec.c
|
|
|
7711c0 |
@@ -3643,9 +3643,6 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
|
|
|
7711c0 |
#define ARG1 as
|
|
|
7711c0 |
#define SUFFIX
|
|
|
7711c0 |
#define TRANSLATE(...) address_space_translate(as, __VA_ARGS__)
|
|
|
7711c0 |
-#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write)
|
|
|
7711c0 |
-#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs)
|
|
|
7711c0 |
-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
|
|
|
7711c0 |
#define RCU_READ_LOCK(...) rcu_read_lock()
|
|
|
7711c0 |
#define RCU_READ_UNLOCK(...) rcu_read_unlock()
|
|
|
7711c0 |
#include "memory_ldst.inc.c"
|
|
|
7711c0 |
@@ -3775,9 +3772,6 @@ address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
|
|
7711c0 |
#define ARG1 cache
|
|
|
7711c0 |
#define SUFFIX _cached_slow
|
|
|
7711c0 |
#define TRANSLATE(...) address_space_translate_cached(cache, __VA_ARGS__)
|
|
|
7711c0 |
-#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write)
|
|
|
7711c0 |
-#define MAP_RAM(mr, ofs) (cache->ptr + (ofs - cache->xlat))
|
|
|
7711c0 |
-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
|
|
|
7711c0 |
#define RCU_READ_LOCK() ((void)0)
|
|
|
7711c0 |
#define RCU_READ_UNLOCK() ((void)0)
|
|
|
7711c0 |
#include "memory_ldst.inc.c"
|
|
|
7711c0 |
diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c
|
|
|
7711c0 |
index 25d6125..e09c2b5 100644
|
|
|
7711c0 |
--- a/memory_ldst.inc.c
|
|
|
7711c0 |
+++ b/memory_ldst.inc.c
|
|
|
7711c0 |
@@ -34,7 +34,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, false);
|
|
|
7711c0 |
- if (l < 4 || !IS_DIRECT(mr, false)) {
|
|
|
7711c0 |
+ if (l < 4 || !memory_access_is_direct(mr, false)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* I/O case */
|
|
|
7711c0 |
@@ -50,7 +50,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
#endif
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
val = ldl_le_p(ptr);
|
|
|
7711c0 |
@@ -110,7 +110,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, false);
|
|
|
7711c0 |
- if (l < 8 || !IS_DIRECT(mr, false)) {
|
|
|
7711c0 |
+ if (l < 8 || !memory_access_is_direct(mr, false)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* I/O case */
|
|
|
7711c0 |
@@ -126,7 +126,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
#endif
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
val = ldq_le_p(ptr);
|
|
|
7711c0 |
@@ -184,14 +184,14 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, false);
|
|
|
7711c0 |
- if (!IS_DIRECT(mr, false)) {
|
|
|
7711c0 |
+ if (!memory_access_is_direct(mr, false)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* I/O case */
|
|
|
7711c0 |
r = memory_region_dispatch_read(mr, addr1, &val, 1, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
val = ldub_p(ptr);
|
|
|
7711c0 |
r = MEMTX_OK;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
@@ -220,7 +220,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, false);
|
|
|
7711c0 |
- if (l < 2 || !IS_DIRECT(mr, false)) {
|
|
|
7711c0 |
+ if (l < 2 || !memory_access_is_direct(mr, false)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* I/O case */
|
|
|
7711c0 |
@@ -236,7 +236,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
#endif
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
val = lduw_le_p(ptr);
|
|
|
7711c0 |
@@ -297,12 +297,12 @@ void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, true);
|
|
|
7711c0 |
- if (l < 4 || !IS_DIRECT(mr, true)) {
|
|
|
7711c0 |
+ if (l < 4 || !memory_access_is_direct(mr, true)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
stl_p(ptr, val);
|
|
|
7711c0 |
|
|
|
7711c0 |
dirty_log_mask = memory_region_get_dirty_log_mask(mr);
|
|
|
7711c0 |
@@ -334,7 +334,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, true);
|
|
|
7711c0 |
- if (l < 4 || !IS_DIRECT(mr, true)) {
|
|
|
7711c0 |
+ if (l < 4 || !memory_access_is_direct(mr, true)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
7711c0 |
@@ -349,7 +349,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
stl_le_p(ptr, val);
|
|
|
7711c0 |
@@ -361,7 +361,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
stl_p(ptr, val);
|
|
|
7711c0 |
break;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
- INVALIDATE(mr, addr1, 4);
|
|
|
7711c0 |
+ invalidate_and_set_dirty(mr, addr1, 4);
|
|
|
7711c0 |
r = MEMTX_OK;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
if (result) {
|
|
|
7711c0 |
@@ -406,14 +406,14 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, true);
|
|
|
7711c0 |
- if (!IS_DIRECT(mr, true)) {
|
|
|
7711c0 |
+ if (!memory_access_is_direct(mr, true)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
r = memory_region_dispatch_write(mr, addr1, val, 1, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
stb_p(ptr, val);
|
|
|
7711c0 |
- INVALIDATE(mr, addr1, 1);
|
|
|
7711c0 |
+ invalidate_and_set_dirty(mr, addr1, 1);
|
|
|
7711c0 |
r = MEMTX_OK;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
if (result) {
|
|
|
7711c0 |
@@ -439,7 +439,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, true);
|
|
|
7711c0 |
- if (l < 2 || !IS_DIRECT(mr, true)) {
|
|
|
7711c0 |
+ if (l < 2 || !memory_access_is_direct(mr, true)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
7711c0 |
@@ -454,7 +454,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
stw_le_p(ptr, val);
|
|
|
7711c0 |
@@ -466,7 +466,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
stw_p(ptr, val);
|
|
|
7711c0 |
break;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
- INVALIDATE(mr, addr1, 2);
|
|
|
7711c0 |
+ invalidate_and_set_dirty(mr, addr1, 2);
|
|
|
7711c0 |
r = MEMTX_OK;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
if (result) {
|
|
|
7711c0 |
@@ -512,7 +512,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
|
|
|
7711c0 |
RCU_READ_LOCK();
|
|
|
7711c0 |
mr = TRANSLATE(addr, &addr1, &l, true);
|
|
|
7711c0 |
- if (l < 8 || !IS_DIRECT(mr, true)) {
|
|
|
7711c0 |
+ if (l < 8 || !memory_access_is_direct(mr, true)) {
|
|
|
7711c0 |
release_lock |= prepare_mmio_access(mr);
|
|
|
7711c0 |
|
|
|
7711c0 |
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
7711c0 |
@@ -527,7 +527,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
r = memory_region_dispatch_write(mr, addr1, val, 8, attrs);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
/* RAM case */
|
|
|
7711c0 |
- ptr = MAP_RAM(mr, addr1);
|
|
|
7711c0 |
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
7711c0 |
switch (endian) {
|
|
|
7711c0 |
case DEVICE_LITTLE_ENDIAN:
|
|
|
7711c0 |
stq_le_p(ptr, val);
|
|
|
7711c0 |
@@ -539,7 +539,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
stq_p(ptr, val);
|
|
|
7711c0 |
break;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
- INVALIDATE(mr, addr1, 8);
|
|
|
7711c0 |
+ invalidate_and_set_dirty(mr, addr1, 8);
|
|
|
7711c0 |
r = MEMTX_OK;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
if (result) {
|
|
|
7711c0 |
@@ -576,8 +576,5 @@ void glue(address_space_stq_be, SUFFIX)(ARG1_DECL,
|
|
|
7711c0 |
#undef ARG1
|
|
|
7711c0 |
#undef SUFFIX
|
|
|
7711c0 |
#undef TRANSLATE
|
|
|
7711c0 |
-#undef IS_DIRECT
|
|
|
7711c0 |
-#undef MAP_RAM
|
|
|
7711c0 |
-#undef INVALIDATE
|
|
|
7711c0 |
#undef RCU_READ_LOCK
|
|
|
7711c0 |
#undef RCU_READ_UNLOCK
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|