Hi Paolo, On 06/13/2018 03:36 PM, Paolo Bonzini wrote: > On 13/06/2018 15:19, Eric Auger wrote: >> When an IOMMUMemoryRegion is in front of a virtio device, >> address_space_cache_init does not set cache->ptr as the memory >> region is not RAM. However when the device performs an access, >> we end up in glue() which performs the translation and then uses >> MAP_RAM. This latter uses the unset ptr and returns a wrong value >> which leads to a SIGSEV in address_space_lduw_internal_cached_slow, >> for instance. >> >> In slow path cache->ptr is NULL and MAP_RAM must redirect to >> qemu_map_ram_ptr((mr)->ram_block, ofs). >> >> As MAP_RAM, IS_DIRECT and INVALIDATE are the same in _cached_slow >> and non cached mode, let's remove those macros. >> >> This fixes the use cases featuring vIOMMU (Intel and ARM SMMU) >> which lead to a SIGSEV. >> >> Fixes: 48564041a73a (exec: reintroduce MemoryRegion caching) >> Signed-off-by: Eric Auger <eric.au...@redhat.com> >> >> --- >> >> v1 -> v2: >> - directly use qemu_map_ram_ptr in place for MAP_RAM, >> memory_access_is_direct in place of IS_DIRECT and >> invalidate_and_set_dirty in place of INVALIDATE. The >> macros are removed. > > Thanks! FWIW it would have been just fine to fix MAP_RAM without > cleaning up after my mess. :) > > Queuing this patch. I'm not sure how I missed this, I have actually > tested it with SMMU. no problem. Strange also I was the only one facing the issue. > > Do you also need the MemTxAttrs so that the right PCI requestor id is > used, or do you get it from somewhere else? which call site do you have in mind, sorry?
Thanks Eric > > Paolo > > >> --- >> exec.c | 6 ------ >> memory_ldst.inc.c | 47 ++++++++++++++++++++++------------------------- >> 2 files changed, 22 insertions(+), 31 deletions(-) >> >> diff --git a/exec.c b/exec.c >> index f6645ed..f5a7caf 100644 >> --- a/exec.c >> +++ b/exec.c >> @@ -3660,9 +3660,6 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr >> len, >> #define ARG1 as >> #define SUFFIX >> #define TRANSLATE(...) address_space_translate(as, __VA_ARGS__) >> -#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write) >> -#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs) >> -#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) >> #define RCU_READ_LOCK(...) rcu_read_lock() >> #define RCU_READ_UNLOCK(...) rcu_read_unlock() >> #include "memory_ldst.inc.c" >> @@ -3799,9 +3796,6 @@ address_space_write_cached_slow(MemoryRegionCache >> *cache, hwaddr addr, >> #define ARG1 cache >> #define SUFFIX _cached_slow >> #define TRANSLATE(...) address_space_translate_cached(cache, >> __VA_ARGS__) >> -#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write) >> -#define MAP_RAM(mr, ofs) (cache->ptr + (ofs - cache->xlat)) >> -#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) >> #define RCU_READ_LOCK() ((void)0) >> #define RCU_READ_UNLOCK() ((void)0) >> #include "memory_ldst.inc.c" >> diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c >> index 1548398..acf865b 100644 >> --- a/memory_ldst.inc.c >> +++ b/memory_ldst.inc.c >> @@ -34,7 +34,7 @@ static inline uint32_t glue(address_space_ldl_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, false, attrs); >> - if (l < 4 || !IS_DIRECT(mr, false)) { >> + if (l < 4 || !memory_access_is_direct(mr, false)) { >> release_lock |= prepare_mmio_access(mr); >> >> /* I/O case */ >> @@ -50,7 +50,7 @@ static inline uint32_t glue(address_space_ldl_internal, >> SUFFIX)(ARG1_DECL, >> #endif >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> val = ldl_le_p(ptr); >> @@ -110,7 +110,7 @@ static inline uint64_t glue(address_space_ldq_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, false, attrs); >> - if (l < 8 || !IS_DIRECT(mr, false)) { >> + if (l < 8 || !memory_access_is_direct(mr, false)) { >> release_lock |= prepare_mmio_access(mr); >> >> /* I/O case */ >> @@ -126,7 +126,7 @@ static inline uint64_t glue(address_space_ldq_internal, >> SUFFIX)(ARG1_DECL, >> #endif >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> val = ldq_le_p(ptr); >> @@ -184,14 +184,14 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, false, attrs); >> - if (!IS_DIRECT(mr, false)) { >> + if (!memory_access_is_direct(mr, false)) { >> release_lock |= prepare_mmio_access(mr); >> >> /* I/O case */ >> r = memory_region_dispatch_read(mr, addr1, &val, 1, attrs); >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> val = ldub_p(ptr); >> r = MEMTX_OK; >> } >> @@ -220,7 +220,7 @@ static inline uint32_t glue(address_space_lduw_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, false, attrs); >> - if (l < 2 || !IS_DIRECT(mr, false)) { >> + if (l < 2 || !memory_access_is_direct(mr, false)) { >> release_lock |= prepare_mmio_access(mr); >> >> /* I/O case */ >> @@ -236,7 +236,7 @@ static inline uint32_t glue(address_space_lduw_internal, >> SUFFIX)(ARG1_DECL, >> #endif >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> val = lduw_le_p(ptr); >> @@ -297,12 +297,12 @@ void glue(address_space_stl_notdirty, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, true, attrs); >> - if (l < 4 || !IS_DIRECT(mr, true)) { >> + if (l < 4 || !memory_access_is_direct(mr, true)) { >> release_lock |= prepare_mmio_access(mr); >> >> r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); >> } else { >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> stl_p(ptr, val); >> >> dirty_log_mask = memory_region_get_dirty_log_mask(mr); >> @@ -334,7 +334,7 @@ static inline void glue(address_space_stl_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, true, attrs); >> - if (l < 4 || !IS_DIRECT(mr, true)) { >> + if (l < 4 || !memory_access_is_direct(mr, true)) { >> release_lock |= prepare_mmio_access(mr); >> >> #if defined(TARGET_WORDS_BIGENDIAN) >> @@ -349,7 +349,7 @@ static inline void glue(address_space_stl_internal, >> SUFFIX)(ARG1_DECL, >> r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> stl_le_p(ptr, val); >> @@ -361,7 +361,7 @@ static inline void glue(address_space_stl_internal, >> SUFFIX)(ARG1_DECL, >> stl_p(ptr, val); >> break; >> } >> - INVALIDATE(mr, addr1, 4); >> + invalidate_and_set_dirty(mr, addr1, 4); >> r = MEMTX_OK; >> } >> if (result) { >> @@ -406,14 +406,14 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, true, attrs); >> - if (!IS_DIRECT(mr, true)) { >> + if (!memory_access_is_direct(mr, true)) { >> release_lock |= prepare_mmio_access(mr); >> r = memory_region_dispatch_write(mr, addr1, val, 1, attrs); >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> stb_p(ptr, val); >> - INVALIDATE(mr, addr1, 1); >> + invalidate_and_set_dirty(mr, addr1, 1); >> r = MEMTX_OK; >> } >> if (result) { >> @@ -439,7 +439,7 @@ static inline void glue(address_space_stw_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, true, attrs); >> - if (l < 2 || !IS_DIRECT(mr, true)) { >> + if (l < 2 || !memory_access_is_direct(mr, true)) { >> release_lock |= prepare_mmio_access(mr); >> >> #if defined(TARGET_WORDS_BIGENDIAN) >> @@ -454,7 +454,7 @@ static inline void glue(address_space_stw_internal, >> SUFFIX)(ARG1_DECL, >> r = memory_region_dispatch_write(mr, addr1, val, 2, attrs); >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> stw_le_p(ptr, val); >> @@ -466,7 +466,7 @@ static inline void glue(address_space_stw_internal, >> SUFFIX)(ARG1_DECL, >> stw_p(ptr, val); >> break; >> } >> - INVALIDATE(mr, addr1, 2); >> + invalidate_and_set_dirty(mr, addr1, 2); >> r = MEMTX_OK; >> } >> if (result) { >> @@ -512,7 +512,7 @@ static void glue(address_space_stq_internal, >> SUFFIX)(ARG1_DECL, >> >> RCU_READ_LOCK(); >> mr = TRANSLATE(addr, &addr1, &l, true, attrs); >> - if (l < 8 || !IS_DIRECT(mr, true)) { >> + if (l < 8 || !memory_access_is_direct(mr, true)) { >> release_lock |= prepare_mmio_access(mr); >> >> #if defined(TARGET_WORDS_BIGENDIAN) >> @@ -527,7 +527,7 @@ static void glue(address_space_stq_internal, >> SUFFIX)(ARG1_DECL, >> r = memory_region_dispatch_write(mr, addr1, val, 8, attrs); >> } else { >> /* RAM case */ >> - ptr = MAP_RAM(mr, addr1); >> + ptr = qemu_map_ram_ptr(mr->ram_block, addr1); >> switch (endian) { >> case DEVICE_LITTLE_ENDIAN: >> stq_le_p(ptr, val); >> @@ -539,7 +539,7 @@ static void glue(address_space_stq_internal, >> SUFFIX)(ARG1_DECL, >> stq_p(ptr, val); >> break; >> } >> - INVALIDATE(mr, addr1, 8); >> + invalidate_and_set_dirty(mr, addr1, 8); >> r = MEMTX_OK; >> } >> if (result) { >> @@ -576,8 +576,5 @@ void glue(address_space_stq_be, SUFFIX)(ARG1_DECL, >> #undef ARG1 >> #undef SUFFIX >> #undef TRANSLATE >> -#undef IS_DIRECT >> -#undef MAP_RAM >> -#undef INVALIDATE >> #undef RCU_READ_LOCK >> #undef RCU_READ_UNLOCK >> >