* more of Peter Crosthwaite's multiarch preparation patches
* unlocked MMIO support in KVM * support for compilation with ICC -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJVmnuoAAoJEL/70l94x66DKTUH/RFrc20KXRkn/Pb/8qHY/wFz Wt3YaS5VYPHElHbxHSdpwlV3K50FAX4QaC25Dnw4dsTelyxe5k7od+I7x8PQxD9v 3N+mFFF1BV6PqXTPVnUCnb14EXprJX524E97O6Z3lDGcwSLHDxeveSCk3IvMFErz JzP3vtigSvtdPPQXlGcndP/r1EXeVjgNIsZ+NKaI/kmoSz1fHFrCN8hTnrxA9RSI ZPhfmgHI5EMFtAf/HiZID6GSHOHajgeRT2bIiiy1okS++no0uRZlVMvcnFNPZHoG e9XCGBXJSdmCoi7sIgShXirKszxYkRTbCyxxjz6aYfhrQzo0h+Yn9OPuvQrgynE= =+YEv -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
7edd8e4660
|
@ -27,6 +27,7 @@
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "exec/memory-internal.h"
|
#include "exec/memory-internal.h"
|
||||||
#include "qemu/rcu.h"
|
#include "qemu/rcu.h"
|
||||||
|
#include "exec/tb-hash.h"
|
||||||
|
|
||||||
/* -icount align implementation. */
|
/* -icount align implementation. */
|
||||||
|
|
||||||
|
|
19
cpus.c
19
cpus.c
|
@ -954,7 +954,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
qemu_mutex_lock(&qemu_global_mutex);
|
qemu_mutex_lock_iothread();
|
||||||
qemu_thread_get_self(cpu->thread);
|
qemu_thread_get_self(cpu->thread);
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
cpu->can_do_io = 1;
|
cpu->can_do_io = 1;
|
||||||
|
@ -1034,10 +1034,10 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||||
{
|
{
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
qemu_tcg_init_cpu_signals();
|
qemu_tcg_init_cpu_signals();
|
||||||
qemu_thread_get_self(cpu->thread);
|
qemu_thread_get_self(cpu->thread);
|
||||||
|
|
||||||
qemu_mutex_lock(&qemu_global_mutex);
|
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
cpu->created = true;
|
cpu->created = true;
|
||||||
|
@ -1146,10 +1146,21 @@ bool qemu_in_vcpu_thread(void)
|
||||||
return current_cpu && qemu_cpu_is_self(current_cpu);
|
return current_cpu && qemu_cpu_is_self(current_cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __thread bool iothread_locked = false;
|
||||||
|
|
||||||
|
bool qemu_mutex_iothread_locked(void)
|
||||||
|
{
|
||||||
|
return iothread_locked;
|
||||||
|
}
|
||||||
|
|
||||||
void qemu_mutex_lock_iothread(void)
|
void qemu_mutex_lock_iothread(void)
|
||||||
{
|
{
|
||||||
atomic_inc(&iothread_requesting_mutex);
|
atomic_inc(&iothread_requesting_mutex);
|
||||||
if (!tcg_enabled() || !first_cpu || !first_cpu->thread) {
|
/* In the simple case there is no need to bump the VCPU thread out of
|
||||||
|
* TCG code execution.
|
||||||
|
*/
|
||||||
|
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
|
||||||
|
!first_cpu || !first_cpu->thread) {
|
||||||
qemu_mutex_lock(&qemu_global_mutex);
|
qemu_mutex_lock(&qemu_global_mutex);
|
||||||
atomic_dec(&iothread_requesting_mutex);
|
atomic_dec(&iothread_requesting_mutex);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1160,10 +1171,12 @@ void qemu_mutex_lock_iothread(void)
|
||||||
atomic_dec(&iothread_requesting_mutex);
|
atomic_dec(&iothread_requesting_mutex);
|
||||||
qemu_cond_broadcast(&qemu_io_proceeded_cond);
|
qemu_cond_broadcast(&qemu_io_proceeded_cond);
|
||||||
}
|
}
|
||||||
|
iothread_locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_mutex_unlock_iothread(void)
|
void qemu_mutex_unlock_iothread(void)
|
||||||
{
|
{
|
||||||
|
iothread_locked = false;
|
||||||
qemu_mutex_unlock(&qemu_global_mutex);
|
qemu_mutex_unlock(&qemu_global_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
83
exec.c
83
exec.c
|
@ -48,6 +48,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "exec/cpu-all.h"
|
#include "exec/cpu-all.h"
|
||||||
#include "qemu/rcu_queue.h"
|
#include "qemu/rcu_queue.h"
|
||||||
|
#include "qemu/main-loop.h"
|
||||||
#include "exec/cputlb.h"
|
#include "exec/cputlb.h"
|
||||||
#include "translate-all.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;
|
*xlat = addr + section->offset_within_region;
|
||||||
|
|
||||||
mr = section->mr;
|
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)) {
|
if (memory_region_is_ram(mr)) {
|
||||||
diff = int128_sub(section->size, int128_make64(addr));
|
diff = int128_sub(section->size, int128_make64(addr));
|
||||||
*plen = int128_get64(int128_min(diff, int128_make64(*plen)));
|
*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;
|
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,
|
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
||||||
uint8_t *buf, int len, bool is_write)
|
uint8_t *buf, int len, bool is_write)
|
||||||
{
|
{
|
||||||
|
@ -2325,6 +2361,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
MemTxResult result = MEMTX_OK;
|
MemTxResult result = MEMTX_OK;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
|
@ -2333,6 +2370,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
||||||
|
|
||||||
if (is_write) {
|
if (is_write) {
|
||||||
if (!memory_access_is_direct(mr, is_write)) {
|
if (!memory_access_is_direct(mr, is_write)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
l = memory_access_size(mr, l, addr1);
|
l = memory_access_size(mr, l, addr1);
|
||||||
/* XXX: could force current_cpu to NULL to avoid
|
/* XXX: could force current_cpu to NULL to avoid
|
||||||
potential bugs */
|
potential bugs */
|
||||||
|
@ -2374,6 +2412,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
||||||
} else {
|
} else {
|
||||||
if (!memory_access_is_direct(mr, is_write)) {
|
if (!memory_access_is_direct(mr, is_write)) {
|
||||||
/* I/O case */
|
/* I/O case */
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
l = memory_access_size(mr, l, addr1);
|
l = memory_access_size(mr, l, addr1);
|
||||||
switch (l) {
|
switch (l) {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -2409,6 +2448,12 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
||||||
memcpy(buf, ptr, l);
|
memcpy(buf, ptr, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
release_lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
len -= l;
|
len -= l;
|
||||||
buf += l;
|
buf += l;
|
||||||
addr += l;
|
addr += l;
|
||||||
|
@ -2458,7 +2503,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
|
||||||
|
|
||||||
if (!(memory_region_is_ram(mr) ||
|
if (!(memory_region_is_ram(mr) ||
|
||||||
memory_region_is_romd(mr))) {
|
memory_region_is_romd(mr))) {
|
||||||
/* do nothing */
|
l = memory_access_size(mr, l, addr1);
|
||||||
} else {
|
} else {
|
||||||
addr1 += memory_region_get_ram_addr(mr);
|
addr1 += memory_region_get_ram_addr(mr);
|
||||||
/* ROM/RAM case */
|
/* ROM/RAM case */
|
||||||
|
@ -2735,10 +2780,13 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
|
||||||
hwaddr l = 4;
|
hwaddr l = 4;
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l, false);
|
mr = address_space_translate(as, addr, &addr1, &l, false);
|
||||||
if (l < 4 || !memory_access_is_direct(mr, false)) {
|
if (l < 4 || !memory_access_is_direct(mr, false)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
|
|
||||||
/* I/O case */
|
/* I/O case */
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs);
|
r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs);
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
|
@ -2771,6 +2819,9 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -2823,11 +2874,14 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
|
||||||
hwaddr l = 8;
|
hwaddr l = 8;
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
mr = address_space_translate(as, addr, &addr1, &l,
|
||||||
false);
|
false);
|
||||||
if (l < 8 || !memory_access_is_direct(mr, false)) {
|
if (l < 8 || !memory_access_is_direct(mr, false)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
|
|
||||||
/* I/O case */
|
/* I/O case */
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 8, attrs);
|
r = memory_region_dispatch_read(mr, addr1, &val, 8, attrs);
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
|
@ -2860,6 +2914,9 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -2932,11 +2989,14 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as,
|
||||||
hwaddr l = 2;
|
hwaddr l = 2;
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
mr = address_space_translate(as, addr, &addr1, &l,
|
||||||
false);
|
false);
|
||||||
if (l < 2 || !memory_access_is_direct(mr, false)) {
|
if (l < 2 || !memory_access_is_direct(mr, false)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
|
|
||||||
/* I/O case */
|
/* I/O case */
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 2, attrs);
|
r = memory_region_dispatch_read(mr, addr1, &val, 2, attrs);
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
|
@ -2969,6 +3029,9 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as,
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -3021,11 +3084,14 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
uint8_t dirty_log_mask;
|
uint8_t dirty_log_mask;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
mr = address_space_translate(as, addr, &addr1, &l,
|
||||||
true);
|
true);
|
||||||
if (l < 4 || !memory_access_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);
|
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
|
||||||
} else {
|
} else {
|
||||||
addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
|
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) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3060,11 +3129,14 @@ static inline void address_space_stl_internal(AddressSpace *as,
|
||||||
hwaddr l = 4;
|
hwaddr l = 4;
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
mr = address_space_translate(as, addr, &addr1, &l,
|
||||||
true);
|
true);
|
||||||
if (l < 4 || !memory_access_is_direct(mr, true)) {
|
if (l < 4 || !memory_access_is_direct(mr, true)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
if (endian == DEVICE_LITTLE_ENDIAN) {
|
||||||
val = bswap32(val);
|
val = bswap32(val);
|
||||||
|
@ -3096,6 +3168,9 @@ static inline void address_space_stl_internal(AddressSpace *as,
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3165,10 +3240,13 @@ static inline void address_space_stw_internal(AddressSpace *as,
|
||||||
hwaddr l = 2;
|
hwaddr l = 2;
|
||||||
hwaddr addr1;
|
hwaddr addr1;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
bool release_lock = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
mr = address_space_translate(as, addr, &addr1, &l, true);
|
mr = address_space_translate(as, addr, &addr1, &l, true);
|
||||||
if (l < 2 || !memory_access_is_direct(mr, true)) {
|
if (l < 2 || !memory_access_is_direct(mr, true)) {
|
||||||
|
release_lock |= prepare_mmio_access(mr);
|
||||||
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
if (endian == DEVICE_LITTLE_ENDIAN) {
|
||||||
val = bswap16(val);
|
val = bswap16(val);
|
||||||
|
@ -3200,6 +3278,9 @@ static inline void address_space_stw_internal(AddressSpace *as,
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = r;
|
*result = r;
|
||||||
}
|
}
|
||||||
|
if (release_lock) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,7 @@ void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
|
||||||
ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar);
|
ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar);
|
||||||
memory_region_init_io(&ar->tmr.io, memory_region_owner(parent),
|
memory_region_init_io(&ar->tmr.io, memory_region_owner(parent),
|
||||||
&acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
|
&acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
|
||||||
|
memory_region_clear_global_locking(&ar->tmr.io);
|
||||||
memory_region_add_subregion(parent, 8, &ar->tmr.io);
|
memory_region_add_subregion(parent, 8, &ar->tmr.io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
#include "qemu/rcu.h"
|
#include "qemu/rcu.h"
|
||||||
|
|
||||||
|
#define EXCP_INTERRUPT 0x10000 /* async interruption */
|
||||||
|
#define EXCP_HLT 0x10001 /* hlt instruction reached */
|
||||||
|
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
|
||||||
|
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
|
||||||
|
#define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */
|
||||||
|
|
||||||
/* some important defines:
|
/* some important defines:
|
||||||
*
|
*
|
||||||
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
|
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#include "qemu/bswap.h"
|
#include "qemu/bswap.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
|
#include "qemu/fprintf-fn.h"
|
||||||
|
#include "qemu/typedefs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPUListState:
|
* CPUListState:
|
||||||
|
|
|
@ -56,20 +56,6 @@ typedef uint64_t target_ulong;
|
||||||
#error TARGET_LONG_SIZE undefined
|
#error TARGET_LONG_SIZE undefined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EXCP_INTERRUPT 0x10000 /* async interruption */
|
|
||||||
#define EXCP_HLT 0x10001 /* hlt instruction reached */
|
|
||||||
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
|
|
||||||
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
|
|
||||||
#define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */
|
|
||||||
|
|
||||||
/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
|
|
||||||
addresses on the same page. The top bits are the same. This allows
|
|
||||||
TLB invalidation to quickly clear a subset of the hash table. */
|
|
||||||
#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
|
|
||||||
#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
|
|
||||||
#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
|
|
||||||
#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
|
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
/* use a fully associative victim tlb of 8 entries */
|
/* use a fully associative victim tlb of 8 entries */
|
||||||
#define CPU_VTLB_SIZE 8
|
#define CPU_VTLB_SIZE 8
|
||||||
|
@ -161,7 +147,6 @@ typedef struct CPUIOTLBEntry {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define CPU_TEMP_BUF_NLONGS 128
|
|
||||||
#define CPU_COMMON \
|
#define CPU_COMMON \
|
||||||
/* soft mmu support */ \
|
/* soft mmu support */ \
|
||||||
CPU_COMMON_TLB \
|
CPU_COMMON_TLB \
|
||||||
|
|
|
@ -195,26 +195,6 @@ struct TBContext {
|
||||||
int tb_invalidated_flag;
|
int tb_invalidated_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
|
|
||||||
{
|
|
||||||
target_ulong tmp;
|
|
||||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
|
||||||
return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
|
|
||||||
{
|
|
||||||
target_ulong tmp;
|
|
||||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
|
||||||
return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK)
|
|
||||||
| (tmp & TB_JMP_ADDR_MASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
|
||||||
{
|
|
||||||
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tb_free(TranslationBlock *tb);
|
void tb_free(TranslationBlock *tb);
|
||||||
void tb_flush(CPUArchState *env);
|
void tb_flush(CPUArchState *env);
|
||||||
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/cpu-common.h"
|
#include "exec/cpu-common.h"
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "exec/hwaddr.h"
|
#include "exec/hwaddr.h"
|
||||||
|
@ -180,6 +179,7 @@ struct MemoryRegion {
|
||||||
bool rom_device;
|
bool rom_device;
|
||||||
bool warning_printed; /* For reservations */
|
bool warning_printed; /* For reservations */
|
||||||
bool flush_coalesced_mmio;
|
bool flush_coalesced_mmio;
|
||||||
|
bool global_locking;
|
||||||
MemoryRegion *alias;
|
MemoryRegion *alias;
|
||||||
hwaddr alias_offset;
|
hwaddr alias_offset;
|
||||||
int32_t priority;
|
int32_t priority;
|
||||||
|
@ -824,6 +824,31 @@ void memory_region_set_flush_coalesced(MemoryRegion *mr);
|
||||||
*/
|
*/
|
||||||
void memory_region_clear_flush_coalesced(MemoryRegion *mr);
|
void memory_region_clear_flush_coalesced(MemoryRegion *mr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* memory_region_set_global_locking: Declares the access processing requires
|
||||||
|
* QEMU's global lock.
|
||||||
|
*
|
||||||
|
* When this is invoked, accesses to the memory region will be processed while
|
||||||
|
* holding the global lock of QEMU. This is the default behavior of memory
|
||||||
|
* regions.
|
||||||
|
*
|
||||||
|
* @mr: the memory region to be updated.
|
||||||
|
*/
|
||||||
|
void memory_region_set_global_locking(MemoryRegion *mr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* memory_region_clear_global_locking: Declares that access processing does
|
||||||
|
* not depend on the QEMU global lock.
|
||||||
|
*
|
||||||
|
* By clearing this property, accesses to the memory region will be processed
|
||||||
|
* outside of QEMU's global lock (unless the lock is held on when issuing the
|
||||||
|
* access request). In this case, the device model implementing the access
|
||||||
|
* handlers is responsible for synchronization of concurrency.
|
||||||
|
*
|
||||||
|
* @mr: the memory region to be updated.
|
||||||
|
*/
|
||||||
|
void memory_region_clear_global_locking(MemoryRegion *mr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* memory_region_add_eventfd: Request an eventfd to be triggered when a word
|
* memory_region_add_eventfd: Request an eventfd to be triggered when a word
|
||||||
* is written to a location.
|
* is written to a location.
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* internal execution defines for qemu
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXEC_TB_HASH
|
||||||
|
#define EXEC_TB_HASH
|
||||||
|
|
||||||
|
/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
|
||||||
|
addresses on the same page. The top bits are the same. This allows
|
||||||
|
TLB invalidation to quickly clear a subset of the hash table. */
|
||||||
|
#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
|
||||||
|
#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
|
||||||
|
#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
|
||||||
|
#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
|
||||||
|
|
||||||
|
static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
|
||||||
|
{
|
||||||
|
target_ulong tmp;
|
||||||
|
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||||
|
return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
|
||||||
|
{
|
||||||
|
target_ulong tmp;
|
||||||
|
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||||
|
return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK)
|
||||||
|
| (tmp & TB_JMP_ADDR_MASK));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
||||||
|
{
|
||||||
|
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
/* armv7m.c */
|
/* armv7m.c */
|
||||||
qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "qemu/compiler.h"
|
#include "qemu/compiler.h"
|
||||||
#include "config-host.h"
|
#include "config-host.h"
|
||||||
#include "qemu/typedefs.h"
|
#include "qemu/typedefs.h"
|
||||||
|
#include "qemu/fprintf-fn.h"
|
||||||
|
|
||||||
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
|
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
|
||||||
#define WORDS_ALIGNED
|
#define WORDS_ALIGNED
|
||||||
|
@ -85,9 +86,6 @@
|
||||||
# error Unknown pointer size
|
# error Unknown pointer size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
|
|
||||||
GCC_FMT_ATTR(2, 3);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define fsync _commit
|
#define fsync _commit
|
||||||
#if !defined(lseek)
|
#if !defined(lseek)
|
||||||
|
@ -455,6 +453,7 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
|
||||||
#define VECTYPE __vector unsigned char
|
#define VECTYPE __vector unsigned char
|
||||||
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
|
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
|
||||||
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
|
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
|
||||||
|
#define VEC_OR(v1, v2) ((v1) | (v2))
|
||||||
/* altivec.h may redefine the bool macro as vector type.
|
/* altivec.h may redefine the bool macro as vector type.
|
||||||
* Reset it to POSIX semantics. */
|
* Reset it to POSIX semantics. */
|
||||||
#define bool _Bool
|
#define bool _Bool
|
||||||
|
@ -463,10 +462,12 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
|
||||||
#define VECTYPE __m128i
|
#define VECTYPE __m128i
|
||||||
#define SPLAT(p) _mm_set1_epi8(*(p))
|
#define SPLAT(p) _mm_set1_epi8(*(p))
|
||||||
#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
|
#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
|
||||||
|
#define VEC_OR(v1, v2) (_mm_or_si128(v1, v2))
|
||||||
#else
|
#else
|
||||||
#define VECTYPE unsigned long
|
#define VECTYPE unsigned long
|
||||||
#define SPLAT(p) (*(p) * (~0UL / 255))
|
#define SPLAT(p) (*(p) * (~0UL / 255))
|
||||||
#define ALL_EQ(v1, v2) ((v1) == (v2))
|
#define ALL_EQ(v1, v2) ((v1) == (v2))
|
||||||
|
#define VEC_OR(v1, v2) ((v1) | (v2))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8
|
#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Typedef for fprintf-alike function pointers.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_FPRINTF_FN_H
|
||||||
|
#define QEMU_FPRINTF_FN_H 1
|
||||||
|
|
||||||
|
#include "qemu/compiler.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
|
||||||
|
GCC_FMT_ATTR(2, 3);
|
||||||
|
|
||||||
|
#endif
|
|
@ -222,6 +222,16 @@ void qemu_set_fd_handler(int fd,
|
||||||
int qemu_add_child_watch(pid_t pid);
|
int qemu_add_child_watch(pid_t pid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemu_mutex_iothread_locked: Return lock status of the main loop mutex.
|
||||||
|
*
|
||||||
|
* The main loop mutex is the coarsest lock in QEMU, and as such it
|
||||||
|
* must always be taken outside other locks. This function helps
|
||||||
|
* functions take different paths depending on whether the current
|
||||||
|
* thread is running within the main loop mutex.
|
||||||
|
*/
|
||||||
|
bool qemu_mutex_iothread_locked(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemu_mutex_lock_iothread: Lock the main loop mutex.
|
* qemu_mutex_lock_iothread: Lock the main loop mutex.
|
||||||
*
|
*
|
||||||
|
|
25
kvm-all.c
25
kvm-all.c
|
@ -1099,9 +1099,17 @@ static int kvm_irqchip_get_virq(KVMState *s)
|
||||||
uint32_t *word = s->used_gsi_bitmap;
|
uint32_t *word = s->used_gsi_bitmap;
|
||||||
int max_words = ALIGN(s->gsi_count, 32) / 32;
|
int max_words = ALIGN(s->gsi_count, 32) / 32;
|
||||||
int i, zeroes;
|
int i, zeroes;
|
||||||
bool retry = true;
|
|
||||||
|
|
||||||
again:
|
/*
|
||||||
|
* PIC and IOAPIC share the first 16 GSI numbers, thus the available
|
||||||
|
* GSI numbers are more than the number of IRQ route. Allocating a GSI
|
||||||
|
* number can succeed even though a new route entry cannot be added.
|
||||||
|
* When this happens, flush dynamic MSI entries to free IRQ route entries.
|
||||||
|
*/
|
||||||
|
if (!s->direct_msi && s->irq_routes->nr == s->gsi_count) {
|
||||||
|
kvm_flush_dynamic_msi_routes(s);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the lowest unused GSI in the bitmap */
|
/* Return the lowest unused GSI in the bitmap */
|
||||||
for (i = 0; i < max_words; i++) {
|
for (i = 0; i < max_words; i++) {
|
||||||
zeroes = ctz32(~word[i]);
|
zeroes = ctz32(~word[i]);
|
||||||
|
@ -1111,11 +1119,6 @@ again:
|
||||||
|
|
||||||
return zeroes + i * 32;
|
return zeroes + i * 32;
|
||||||
}
|
}
|
||||||
if (!s->direct_msi && retry) {
|
|
||||||
retry = false;
|
|
||||||
kvm_flush_dynamic_msi_routes(s);
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1752,6 +1755,8 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
return EXCP_HLT;
|
return EXCP_HLT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
MemTxAttrs attrs;
|
MemTxAttrs attrs;
|
||||||
|
|
||||||
|
@ -1770,11 +1775,9 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
*/
|
*/
|
||||||
qemu_cpu_kick_self();
|
qemu_cpu_kick_self();
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
|
|
||||||
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
|
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
|
||||||
attrs = kvm_arch_post_run(cpu, run);
|
attrs = kvm_arch_post_run(cpu, run);
|
||||||
|
|
||||||
if (run_ret < 0) {
|
if (run_ret < 0) {
|
||||||
|
@ -1801,6 +1804,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
case KVM_EXIT_IO:
|
case KVM_EXIT_IO:
|
||||||
DPRINTF("handle_io\n");
|
DPRINTF("handle_io\n");
|
||||||
|
/* Called outside BQL */
|
||||||
kvm_handle_io(run->io.port, attrs,
|
kvm_handle_io(run->io.port, attrs,
|
||||||
(uint8_t *)run + run->io.data_offset,
|
(uint8_t *)run + run->io.data_offset,
|
||||||
run->io.direction,
|
run->io.direction,
|
||||||
|
@ -1810,6 +1814,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_MMIO:
|
case KVM_EXIT_MMIO:
|
||||||
DPRINTF("handle_mmio\n");
|
DPRINTF("handle_mmio\n");
|
||||||
|
/* Called outside BQL */
|
||||||
address_space_rw(&address_space_memory,
|
address_space_rw(&address_space_memory,
|
||||||
run->mmio.phys_addr, attrs,
|
run->mmio.phys_addr, attrs,
|
||||||
run->mmio.data,
|
run->mmio.data,
|
||||||
|
@ -1857,6 +1862,8 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
}
|
}
|
||||||
} while (ret == 0);
|
} while (ret == 0);
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE);
|
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE);
|
||||||
vm_stop(RUN_STATE_INTERNAL_ERROR);
|
vm_stop(RUN_STATE_INTERNAL_ERROR);
|
||||||
|
|
23
memory.c
23
memory.c
|
@ -396,9 +396,6 @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr,
|
||||||
{
|
{
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
|
|
||||||
if (mr->flush_coalesced_mmio) {
|
|
||||||
qemu_flush_coalesced_mmio_buffer();
|
|
||||||
}
|
|
||||||
tmp = mr->ops->read(mr->opaque, addr, size);
|
tmp = mr->ops->read(mr->opaque, addr, size);
|
||||||
trace_memory_region_ops_read(mr, addr, tmp, size);
|
trace_memory_region_ops_read(mr, addr, tmp, size);
|
||||||
*value |= (tmp & mask) << shift;
|
*value |= (tmp & mask) << shift;
|
||||||
|
@ -416,9 +413,6 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
|
||||||
uint64_t tmp = 0;
|
uint64_t tmp = 0;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
|
||||||
if (mr->flush_coalesced_mmio) {
|
|
||||||
qemu_flush_coalesced_mmio_buffer();
|
|
||||||
}
|
|
||||||
r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
|
r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
|
||||||
trace_memory_region_ops_read(mr, addr, tmp, size);
|
trace_memory_region_ops_read(mr, addr, tmp, size);
|
||||||
*value |= (tmp & mask) << shift;
|
*value |= (tmp & mask) << shift;
|
||||||
|
@ -451,9 +445,6 @@ static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
|
||||||
{
|
{
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
|
|
||||||
if (mr->flush_coalesced_mmio) {
|
|
||||||
qemu_flush_coalesced_mmio_buffer();
|
|
||||||
}
|
|
||||||
tmp = (*value >> shift) & mask;
|
tmp = (*value >> shift) & mask;
|
||||||
trace_memory_region_ops_write(mr, addr, tmp, size);
|
trace_memory_region_ops_write(mr, addr, tmp, size);
|
||||||
mr->ops->write(mr->opaque, addr, tmp, size);
|
mr->ops->write(mr->opaque, addr, tmp, size);
|
||||||
|
@ -470,9 +461,6 @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
|
||||||
{
|
{
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
|
|
||||||
if (mr->flush_coalesced_mmio) {
|
|
||||||
qemu_flush_coalesced_mmio_buffer();
|
|
||||||
}
|
|
||||||
tmp = (*value >> shift) & mask;
|
tmp = (*value >> shift) & mask;
|
||||||
trace_memory_region_ops_write(mr, addr, tmp, size);
|
trace_memory_region_ops_write(mr, addr, tmp, size);
|
||||||
return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
|
return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
|
||||||
|
@ -1012,6 +1000,7 @@ static void memory_region_initfn(Object *obj)
|
||||||
mr->ram_addr = RAM_ADDR_INVALID;
|
mr->ram_addr = RAM_ADDR_INVALID;
|
||||||
mr->enabled = true;
|
mr->enabled = true;
|
||||||
mr->romd_mode = true;
|
mr->romd_mode = true;
|
||||||
|
mr->global_locking = true;
|
||||||
mr->destructor = memory_region_destructor_none;
|
mr->destructor = memory_region_destructor_none;
|
||||||
QTAILQ_INIT(&mr->subregions);
|
QTAILQ_INIT(&mr->subregions);
|
||||||
QTAILQ_INIT(&mr->coalesced);
|
QTAILQ_INIT(&mr->coalesced);
|
||||||
|
@ -1646,6 +1635,16 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memory_region_set_global_locking(MemoryRegion *mr)
|
||||||
|
{
|
||||||
|
mr->global_locking = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_region_clear_global_locking(MemoryRegion *mr)
|
||||||
|
{
|
||||||
|
mr->global_locking = false;
|
||||||
|
}
|
||||||
|
|
||||||
void memory_region_add_eventfd(MemoryRegion *mr,
|
void memory_region_add_eventfd(MemoryRegion *mr,
|
||||||
hwaddr addr,
|
hwaddr addr,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/cpu-all.h"
|
|
||||||
#include "sysemu/memory_mapping.h"
|
#include "sysemu/memory_mapping.h"
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
|
|
||||||
|
bool qemu_mutex_iothread_locked(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void qemu_mutex_lock_iothread(void)
|
void qemu_mutex_lock_iothread(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -2191,7 +2191,10 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||||
|
|
||||||
/* Inject NMI */
|
/* Inject NMI */
|
||||||
if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
|
if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
|
cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
DPRINTF("injected NMI\n");
|
DPRINTF("injected NMI\n");
|
||||||
ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
|
ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -2200,6 +2203,10 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!kvm_irqchip_in_kernel()) {
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
}
|
||||||
|
|
||||||
/* Force the VCPU out of its inner loop to process any INIT requests
|
/* Force the VCPU out of its inner loop to process any INIT requests
|
||||||
* or (for userspace APIC, but it is cheap to combine the checks here)
|
* or (for userspace APIC, but it is cheap to combine the checks here)
|
||||||
* pending TPR access reports.
|
* pending TPR access reports.
|
||||||
|
@ -2243,6 +2250,8 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||||
|
|
||||||
DPRINTF("setting tpr\n");
|
DPRINTF("setting tpr\n");
|
||||||
run->cr8 = cpu_get_apic_tpr(x86_cpu->apic_state);
|
run->cr8 = cpu_get_apic_tpr(x86_cpu->apic_state);
|
||||||
|
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2256,8 +2265,17 @@ MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
|
||||||
} else {
|
} else {
|
||||||
env->eflags &= ~IF_MASK;
|
env->eflags &= ~IF_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to protect the apic state against concurrent accesses from
|
||||||
|
* different threads in case the userspace irqchip is used. */
|
||||||
|
if (!kvm_irqchip_in_kernel()) {
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
}
|
||||||
cpu_set_apic_tpr(x86_cpu->apic_state, run->cr8);
|
cpu_set_apic_tpr(x86_cpu->apic_state, run->cr8);
|
||||||
cpu_set_apic_base(x86_cpu->apic_state, run->apic_base);
|
cpu_set_apic_base(x86_cpu->apic_state, run->apic_base);
|
||||||
|
if (!kvm_irqchip_in_kernel()) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
}
|
||||||
return cpu_get_mem_attrs(env);
|
return cpu_get_mem_attrs(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2550,13 +2568,17 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
case KVM_EXIT_HLT:
|
case KVM_EXIT_HLT:
|
||||||
DPRINTF("handle_hlt\n");
|
DPRINTF("handle_hlt\n");
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
ret = kvm_handle_halt(cpu);
|
ret = kvm_handle_halt(cpu);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_SET_TPR:
|
case KVM_EXIT_SET_TPR:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_TPR_ACCESS:
|
case KVM_EXIT_TPR_ACCESS:
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
ret = kvm_handle_tpr_access(cpu);
|
ret = kvm_handle_tpr_access(cpu);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_FAIL_ENTRY:
|
case KVM_EXIT_FAIL_ENTRY:
|
||||||
code = run->fail_entry.hardware_entry_failure_reason;
|
code = run->fail_entry.hardware_entry_failure_reason;
|
||||||
|
@ -2582,7 +2604,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_DEBUG:
|
case KVM_EXIT_DEBUG:
|
||||||
DPRINTF("kvm_exit_debug\n");
|
DPRINTF("kvm_exit_debug\n");
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
ret = kvm_handle_debug(cpu, &run->debug.arch);
|
ret = kvm_handle_debug(cpu, &run->debug.arch);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||||
|
|
|
@ -99,6 +99,8 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||||
int r;
|
int r;
|
||||||
struct kvm_mips_interrupt intr;
|
struct kvm_mips_interrupt intr;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
|
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
cpu_mips_io_interrupts_pending(cpu)) {
|
cpu_mips_io_interrupts_pending(cpu)) {
|
||||||
intr.cpu = -1;
|
intr.cpu = -1;
|
||||||
|
@ -109,6 +111,8 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||||
__func__, cs->cpu_index, intr.irq);
|
__func__, cs->cpu_index, intr.irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
|
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
|
||||||
|
|
|
@ -1242,6 +1242,8 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||||
int r;
|
int r;
|
||||||
unsigned irq;
|
unsigned irq;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
/* PowerPC QEMU tracks the various core input pins (interrupt, critical
|
/* PowerPC QEMU tracks the various core input pins (interrupt, critical
|
||||||
* interrupt, reset, etc) in PPC-specific env->irq_input_state. */
|
* interrupt, reset, etc) in PPC-specific env->irq_input_state. */
|
||||||
if (!cap_interrupt_level &&
|
if (!cap_interrupt_level &&
|
||||||
|
@ -1269,6 +1271,8 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||||
/* We don't know if there are more interrupts pending after this. However,
|
/* We don't know if there are more interrupts pending after this. However,
|
||||||
* the guest will return to userspace in the course of handling this one
|
* the guest will return to userspace in the course of handling this one
|
||||||
* anyways, so we will get a chance to deliver the rest. */
|
* anyways, so we will get a chance to deliver the rest. */
|
||||||
|
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
|
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
|
||||||
|
@ -1570,6 +1574,8 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
CPUPPCState *env = &cpu->env;
|
CPUPPCState *env = &cpu->env;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
case KVM_EXIT_DCR:
|
case KVM_EXIT_DCR:
|
||||||
if (run->dcr.is_write) {
|
if (run->dcr.is_write) {
|
||||||
|
@ -1620,6 +1626,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2007,6 +2007,8 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
S390CPU *cpu = S390_CPU(cs);
|
S390CPU *cpu = S390_CPU(cs);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
case KVM_EXIT_S390_SIEIC:
|
case KVM_EXIT_S390_SIEIC:
|
||||||
ret = handle_intercept(cpu);
|
ret = handle_intercept(cpu);
|
||||||
|
@ -2027,6 +2029,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
|
fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = EXCP_INTERRUPT;
|
ret = EXCP_INTERRUPT;
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "sysemu/kvm.h"
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
|
|
||||||
/* #define DEBUG_S390 */
|
/* #define DEBUG_S390 */
|
||||||
/* #define DEBUG_S390_PTE */
|
/* #define DEBUG_S390_PTE */
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "tcg-target.h"
|
#include "tcg-target.h"
|
||||||
|
|
||||||
|
#define CPU_TEMP_BUF_NLONGS 128
|
||||||
|
|
||||||
/* Default target word size to pointer size. */
|
/* Default target word size to pointer size. */
|
||||||
#ifndef TCG_TARGET_REG_BITS
|
#ifndef TCG_TARGET_REG_BITS
|
||||||
# if UINTPTR_MAX == UINT32_MAX
|
# if UINTPTR_MAX == UINT32_MAX
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "exec/cputlb.h"
|
#include "exec/cputlb.h"
|
||||||
|
#include "exec/tb-hash.h"
|
||||||
#include "translate-all.h"
|
#include "translate-all.h"
|
||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
|
|
|
@ -207,13 +207,13 @@ size_t buffer_find_nonzero_offset(const void *buf, size_t len)
|
||||||
for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
|
for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
|
||||||
i < len / sizeof(VECTYPE);
|
i < len / sizeof(VECTYPE);
|
||||||
i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
|
i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
|
||||||
VECTYPE tmp0 = p[i + 0] | p[i + 1];
|
VECTYPE tmp0 = VEC_OR(p[i + 0], p[i + 1]);
|
||||||
VECTYPE tmp1 = p[i + 2] | p[i + 3];
|
VECTYPE tmp1 = VEC_OR(p[i + 2], p[i + 3]);
|
||||||
VECTYPE tmp2 = p[i + 4] | p[i + 5];
|
VECTYPE tmp2 = VEC_OR(p[i + 4], p[i + 5]);
|
||||||
VECTYPE tmp3 = p[i + 6] | p[i + 7];
|
VECTYPE tmp3 = VEC_OR(p[i + 6], p[i + 7]);
|
||||||
VECTYPE tmp01 = tmp0 | tmp1;
|
VECTYPE tmp01 = VEC_OR(tmp0, tmp1);
|
||||||
VECTYPE tmp23 = tmp2 | tmp3;
|
VECTYPE tmp23 = VEC_OR(tmp2, tmp3);
|
||||||
if (!ALL_EQ(tmp01 | tmp23, zero)) {
|
if (!ALL_EQ(VEC_OR(tmp01, tmp23), zero)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue