diff options
| author | Peter Maydell | 2015-07-06 15:03:44 +0200 |
|---|---|---|
| committer | Peter Maydell | 2015-07-06 15:03:44 +0200 |
| commit | 7edd8e4660beb301d527257f8e04ebec0f841cb0 (patch) | |
| tree | 49ed5104cd81447d68c9131dbface7bf8781ac61 /exec.c | |
| parent | Merge remote-tracking branch 'remotes/xtensa/tags/20150706-xtensa' into staging (diff) | |
| parent | exec: skip MMIO regions correctly in cpu_physical_memory_write_rom_internal (diff) | |
| download | qemu-7edd8e4660beb301d527257f8e04ebec0f841cb0.tar.gz qemu-7edd8e4660beb301d527257f8e04ebec0f841cb0.tar.xz qemu-7edd8e4660beb301d527257f8e04ebec0f841cb0.zip | |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* more of Peter Crosthwaite's multiarch preparation patches
* unlocked MMIO support in KVM
* support for compilation with ICC
# gpg: Signature made Mon Jul 6 13:59:20 2015 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream:
exec: skip MMIO regions correctly in cpu_physical_memory_write_rom_internal
Stop including qemu-common.h in memory.h
kvm: Switch to unlocked MMIO
acpi: mark PMTIMER as unlocked
kvm: Switch to unlocked PIO
kvm: First step to push iothread lock out of inner run loop
memory: let address_space_rw/ld*/st* run outside the BQL
exec: pull qemu_flush_coalesced_mmio_buffer() into address_space_rw/ld*/st*
memory: Add global-locking property to memory regions
main-loop: introduce qemu_mutex_iothread_locked
main-loop: use qemu_mutex_lock_iothread consistently
Fix irq route entries exceeding KVM_MAX_IRQ_ROUTES
cpu-defs: Move out TB_JMP defines
include/exec: Move tb hash functions out
include/exec: Move standard exceptions to cpu-all.h
cpu-defs: Move CPU_TEMP_BUF_NLONGS to tcg
memory_mapping: Rework cpu related includes
cutils: allow compilation with icc
qemu-common: add VEC_OR macro
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'exec.c')
| -rw-r--r-- | exec.c | 83 |
1 files changed, 82 insertions, 1 deletions
@@ -48,6 +48,7 @@ #endif #include "exec/cpu-all.h" #include "qemu/rcu_queue.h" +#include "qemu/main-loop.h" #include "exec/cputlb.h" #include "translate-all.h" @@ -352,6 +353,18 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x *xlat = addr + section->offset_within_region; mr = section->mr; + + /* MMIO registers can be expected to perform full-width accesses based only + * on their address, without considering adjacent registers that could + * decode to completely different MemoryRegions. When such registers + * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO + * regions overlap wildly. For this reason we cannot clamp the accesses + * here. + * + * If the length is small (as is the case for address_space_ldl/stl), + * everything works fine. If the incoming length is large, however, + * the caller really has to do the clamping through memory_access_size. + */ if (memory_region_is_ram(mr)) { diff = int128_sub(section->size, int128_make64(addr)); *plen = int128_get64(int128_min(diff, int128_make64(*plen))); @@ -2316,6 +2329,29 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) return l; } +static bool prepare_mmio_access(MemoryRegion *mr) +{ + bool unlocked = !qemu_mutex_iothread_locked(); + bool release_lock = false; + + if (unlocked && mr->global_locking) { + qemu_mutex_lock_iothread(); + unlocked = false; + release_lock = true; + } + if (mr->flush_coalesced_mmio) { + if (unlocked) { + qemu_mutex_lock_iothread(); + } + qemu_flush_coalesced_mmio_buffer(); + if (unlocked) { + qemu_mutex_unlock_iothread(); + } + } + + return release_lock; +} + MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, uint8_t *buf, int len, bool is_write) { @@ -2325,6 +2361,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, hwaddr addr1; MemoryRegion *mr; MemTxResult result = MEMTX_OK; + bool release_lock = false; rcu_read_lock(); while (len > 0) { @@ -2333,6 +2370,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, if (is_write) { if (!memory_access_is_direct(mr, is_write)) { + release_lock |= prepare_mmio_access(mr); l = memory_access_size(mr, l, addr1); /* XXX: could force current_cpu to NULL to avoid potential bugs */ @@ -2374,6 +2412,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, } else { if (!memory_access_is_direct(mr, is_write)) { /* I/O case */ + release_lock |= prepare_mmio_access(mr); l = memory_access_size(mr, l, addr1); switch (l) { case 8: @@ -2409,6 +2448,12 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, memcpy(buf, ptr, l); } } + + if (release_lock) { + qemu_mutex_unlock_iothread(); + release_lock = false; + } + len -= l; buf += l; addr += l; @@ -2458,7 +2503,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, if (!(memory_region_is_ram(mr) || memory_region_is_romd(mr))) { - /* do nothing */ + l = memory_access_size(mr, l, addr1); } else { addr1 += memory_region_get_ram_addr(mr); /* ROM/RAM case */ @@ -2735,10 +2780,13 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr, hwaddr l = 4; hwaddr addr1; MemTxResult r; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 4 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + /* I/O case */ r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs); #if defined(TARGET_WORDS_BIGENDIAN) @@ -2771,6 +2819,9 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); return val; } @@ -2823,11 +2874,14 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr, hwaddr l = 8; hwaddr addr1; MemTxResult r; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 8 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + /* I/O case */ r = memory_region_dispatch_read(mr, addr1, &val, 8, attrs); #if defined(TARGET_WORDS_BIGENDIAN) @@ -2860,6 +2914,9 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); return val; } @@ -2932,11 +2989,14 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as, hwaddr l = 2; hwaddr addr1; MemTxResult r; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 2 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + /* I/O case */ r = memory_region_dispatch_read(mr, addr1, &val, 2, attrs); #if defined(TARGET_WORDS_BIGENDIAN) @@ -2969,6 +3029,9 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); return val; } @@ -3021,11 +3084,14 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val, hwaddr addr1; MemTxResult r; uint8_t dirty_log_mask; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, 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 { addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; @@ -3040,6 +3106,9 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); } @@ -3060,11 +3129,14 @@ static inline void address_space_stl_internal(AddressSpace *as, hwaddr l = 4; hwaddr addr1; MemTxResult r; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, true); if (l < 4 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap32(val); @@ -3096,6 +3168,9 @@ static inline void address_space_stl_internal(AddressSpace *as, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); } @@ -3165,10 +3240,13 @@ static inline void address_space_stw_internal(AddressSpace *as, hwaddr l = 2; hwaddr addr1; MemTxResult r; + bool release_lock = false; rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, true); if (l < 2 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap16(val); @@ -3200,6 +3278,9 @@ static inline void address_space_stw_internal(AddressSpace *as, if (result) { *result = r; } + if (release_lock) { + qemu_mutex_unlock_iothread(); + } rcu_read_unlock(); } |
