|
@@ -29,6 +29,7 @@
|
|
|
#include "qemu/rcu.h"
|
|
|
#include "exec/tb-hash.h"
|
|
|
#include "exec/log.h"
|
|
|
+#include "qemu/main-loop.h"
|
|
|
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
|
|
#include "hw/i386/apic.h"
|
|
|
#endif
|
|
@@ -388,8 +389,10 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
|
|
if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
|
|
|
&& replay_interrupt()) {
|
|
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
|
|
+ qemu_mutex_lock_iothread();
|
|
|
apic_poll_irq(x86_cpu->apic_state);
|
|
|
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
}
|
|
|
#endif
|
|
|
if (!cpu_has_work(cpu)) {
|
|
@@ -443,7 +446,9 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
|
|
#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 */
|
|
@@ -469,9 +474,11 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|
|
TranslationBlock **last_tb)
|
|
|
{
|
|
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
|
|
- int interrupt_request = cpu->interrupt_request;
|
|
|
|
|
|
- if (unlikely(interrupt_request)) {
|
|
|
+ if (unlikely(atomic_read(&cpu->interrupt_request))) {
|
|
|
+ int interrupt_request;
|
|
|
+ qemu_mutex_lock_iothread();
|
|
|
+ interrupt_request = cpu->interrupt_request;
|
|
|
if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
|
|
|
/* Mask out external interrupts for this step. */
|
|
|
interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
|
|
@@ -479,6 +486,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|
|
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
|
|
|
cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
|
|
|
cpu->exception_index = EXCP_DEBUG;
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
return true;
|
|
|
}
|
|
|
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
|
|
@@ -488,6 +496,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|
|
cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
|
|
|
cpu->halted = 1;
|
|
|
cpu->exception_index = EXCP_HLT;
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
return true;
|
|
|
}
|
|
|
#if defined(TARGET_I386)
|
|
@@ -498,12 +507,14 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0, 0);
|
|
|
do_cpu_init(x86_cpu);
|
|
|
cpu->exception_index = EXCP_HALTED;
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
return true;
|
|
|
}
|
|
|
#else
|
|
|
else if (interrupt_request & CPU_INTERRUPT_RESET) {
|
|
|
replay_interrupt();
|
|
|
cpu_reset(cpu);
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
return true;
|
|
|
}
|
|
|
#endif
|
|
@@ -526,7 +537,12 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|
|
the program flow was changed */
|
|
|
*last_tb = NULL;
|
|
|
}
|
|
|
+
|
|
|
+ /* If we exit via cpu_loop_exit/longjmp it is reset in cpu_exec */
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
if (unlikely(atomic_read(&cpu->exit_request) || replay_has_interrupt())) {
|
|
|
atomic_set(&cpu->exit_request, 0);
|
|
|
cpu->exception_index = EXCP_INTERRUPT;
|
|
@@ -643,6 +659,9 @@ int cpu_exec(CPUState *cpu)
|
|
|
#endif /* buggy compiler */
|
|
|
cpu->can_do_io = 1;
|
|
|
tb_lock_reset();
|
|
|
+ if (qemu_mutex_iothread_locked()) {
|
|
|
+ qemu_mutex_unlock_iothread();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* if an exception is pending, we execute it here */
|