diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-11-16 14:42:54 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-11-16 14:42:54 +0000 |
commit | 62955e101e4bdc113e3205174567c9c8e12ec1b4 (patch) | |
tree | a0b1aae9f11f65501f9096720bd652bb1171cfa0 /accel | |
parent | 6a7cb8c3d674815cab08d884740d203fded12249 (diff) | |
parent | 4950b1a766a16bd3feef4c9471b9794e6fe0e1b2 (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
Miscellaneous bugfixes
# gpg: Signature made Wed 15 Nov 2017 15:27:25 GMT
# gpg: using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# 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:
fix scripts/update-linux-headers.sh here document
exec: Do not resolve subpage in mru_section
util/stats64: Fix min/max comparisons
cpu-exec: avoid cpu_exec_nocache infinite loop with record/replay
cpu-exec: don't overwrite exception_index
vhost-user-scsi: add missing virtqueue_size param
target-i386: adds PV_TLB_FLUSH CPUID feature bit
thread-posix: fix qemu_rec_mutex_trylock macro
Makefile: simpler/faster "make help"
ioapic/tracing: Remove last DPRINTFs
Enable 8-byte wide MMIO for 16550 serial devices
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'accel')
-rw-r--r-- | accel/tcg/cpu-exec.c | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 61297f8f4a..f3de96f346 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -470,48 +470,51 @@ static inline void cpu_handle_debug_exception(CPUState *cpu) static inline bool cpu_handle_exception(CPUState *cpu, int *ret) { - if (cpu->exception_index >= 0) { - if (cpu->exception_index >= EXCP_INTERRUPT) { - /* exit request from the cpu execution loop */ - *ret = cpu->exception_index; - if (*ret == EXCP_DEBUG) { - cpu_handle_debug_exception(cpu); - } - cpu->exception_index = -1; - return true; - } else { + if (cpu->exception_index < 0) { +#ifndef CONFIG_USER_ONLY + if (replay_has_exception() + && cpu->icount_decr.u16.low + cpu->icount_extra == 0) { + /* try to cause an exception pending in the log */ + cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true); + } +#endif + if (cpu->exception_index < 0) { + return false; + } + } + + if (cpu->exception_index >= EXCP_INTERRUPT) { + /* exit request from the cpu execution loop */ + *ret = cpu->exception_index; + if (*ret == EXCP_DEBUG) { + cpu_handle_debug_exception(cpu); + } + cpu->exception_index = -1; + return true; + } else { #if defined(CONFIG_USER_ONLY) - /* if user mode only, we simulate a fake exception - which will be handled outside the cpu execution - loop */ + /* if user mode only, we simulate a fake exception + which will be handled outside the cpu execution + loop */ #if defined(TARGET_I386) + CPUClass *cc = CPU_GET_CLASS(cpu); + cc->do_interrupt(cpu); +#endif + *ret = cpu->exception_index; + cpu->exception_index = -1; + return true; +#else + if (replay_exception()) { CPUClass *cc = CPU_GET_CLASS(cpu); + qemu_mutex_lock_iothread(); cc->do_interrupt(cpu); -#endif - *ret = cpu->exception_index; + qemu_mutex_unlock_iothread(); cpu->exception_index = -1; + } else if (!replay_has_interrupt()) { + /* give a chance to iothread in replay mode */ + *ret = EXCP_INTERRUPT; return true; -#else - if (replay_exception()) { - CPUClass *cc = CPU_GET_CLASS(cpu); - qemu_mutex_lock_iothread(); - cc->do_interrupt(cpu); - qemu_mutex_unlock_iothread(); - cpu->exception_index = -1; - } else if (!replay_has_interrupt()) { - /* give a chance to iothread in replay mode */ - *ret = EXCP_INTERRUPT; - return true; - } -#endif } -#ifndef CONFIG_USER_ONLY - } else if (replay_has_exception() - && cpu->icount_decr.u16.low + cpu->icount_extra == 0) { - /* try to cause an exception pending in the log */ - cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true); - *ret = -1; - return true; #endif } @@ -522,6 +525,19 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, TranslationBlock **last_tb) { CPUClass *cc = CPU_GET_CLASS(cpu); + int32_t insns_left; + + /* Clear the interrupt flag now since we're processing + * cpu->interrupt_request and cpu->exit_request. + */ + insns_left = atomic_read(&cpu->icount_decr.u32); + atomic_set(&cpu->icount_decr.u16.high, 0); + if (unlikely(insns_left < 0)) { + /* Ensure the zeroing of icount_decr comes before the next read + * of cpu->exit_request or cpu->interrupt_request. + */ + smp_mb(); + } if (unlikely(atomic_read(&cpu->interrupt_request))) { int interrupt_request; @@ -594,7 +610,9 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, if (unlikely(atomic_read(&cpu->exit_request) || (use_icount && cpu->icount_decr.u16.low + cpu->icount_extra == 0))) { atomic_set(&cpu->exit_request, 0); - cpu->exception_index = EXCP_INTERRUPT; + if (cpu->exception_index == -1) { + cpu->exception_index = EXCP_INTERRUPT; + } return true; } @@ -618,17 +636,14 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, *last_tb = NULL; insns_left = atomic_read(&cpu->icount_decr.u32); - atomic_set(&cpu->icount_decr.u16.high, 0); if (insns_left < 0) { /* Something asked us to stop executing chained TBs; just * continue round the main loop. Whatever requested the exit * will also have set something else (eg exit_request or - * interrupt_request) which we will handle next time around - * the loop. But we need to ensure the zeroing of icount_decr - * comes before the next read of cpu->exit_request - * or cpu->interrupt_request. + * interrupt_request) which will be handled by + * cpu_handle_interrupt. cpu_handle_interrupt will also + * clear cpu->icount_decr.u16.high. */ - smp_mb(); return; } |