aboutsummaryrefslogtreecommitdiff
path: root/accel
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-11-16 14:42:54 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-11-16 14:42:54 +0000
commit62955e101e4bdc113e3205174567c9c8e12ec1b4 (patch)
treea0b1aae9f11f65501f9096720bd652bb1171cfa0 /accel
parent6a7cb8c3d674815cab08d884740d203fded12249 (diff)
parent4950b1a766a16bd3feef4c9471b9794e6fe0e1b2 (diff)
downloadqemu-62955e101e4bdc113e3205174567c9c8e12ec1b4.zip
qemu-62955e101e4bdc113e3205174567c9c8e12ec1b4.tar.gz
qemu-62955e101e4bdc113e3205174567c9c8e12ec1b4.tar.bz2
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.c99
1 files changed, 57 insertions, 42 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 61297f8..f3de96f 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;
}