mirror of https://github.com/xqemu/xqemu.git
tcg: handle EXCP_ATOMIC exception for system emulation
The patch enables handling atomic code in the guest. This should be preferably done in cpu_handle_exception(), but the current assumptions regarding when we can execute atomic sections cause a deadlock. The current mechanism discards the flags which were set in atomic execution. We ensure they are properly saved by calling the cc->cpu_exec_enter/leave() functions around the loop. As we are running cpu_exec_step_atomic() from the outermost loop we need to avoid an abort() when single stepping over atomic code since debug exception longjmp will point to the the setlongjmp in cpu_exec(). We do this by setting a new jmp_env so that it jumps back here on an exception. Signed-off-by: Pranith Kumar <bobby.prani@gmail.com> [AJB: tweak title, merge with new patches, add mmap_lock] Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net> CC: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
372579427a
commit
08e73c48b0
19
cpu-exec.c
19
cpu-exec.c
|
@ -228,24 +228,43 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
|
||||||
|
|
||||||
static void cpu_exec_step(CPUState *cpu)
|
static void cpu_exec_step(CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
|
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
target_ulong cs_base, pc;
|
target_ulong cs_base, pc;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
||||||
|
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
||||||
|
mmap_lock();
|
||||||
tb_lock();
|
tb_lock();
|
||||||
tb = tb_gen_code(cpu, pc, cs_base, flags,
|
tb = tb_gen_code(cpu, pc, cs_base, flags,
|
||||||
1 | CF_NOCACHE | CF_IGNORE_ICOUNT);
|
1 | CF_NOCACHE | CF_IGNORE_ICOUNT);
|
||||||
tb->orig_tb = NULL;
|
tb->orig_tb = NULL;
|
||||||
tb_unlock();
|
tb_unlock();
|
||||||
|
mmap_unlock();
|
||||||
|
|
||||||
|
cc->cpu_exec_enter(cpu);
|
||||||
/* execute the generated code */
|
/* execute the generated code */
|
||||||
trace_exec_tb_nocache(tb, pc);
|
trace_exec_tb_nocache(tb, pc);
|
||||||
cpu_tb_exec(cpu, tb);
|
cpu_tb_exec(cpu, tb);
|
||||||
|
cc->cpu_exec_exit(cpu);
|
||||||
|
|
||||||
tb_lock();
|
tb_lock();
|
||||||
tb_phys_invalidate(tb, -1);
|
tb_phys_invalidate(tb, -1);
|
||||||
tb_free(tb);
|
tb_free(tb);
|
||||||
tb_unlock();
|
tb_unlock();
|
||||||
|
} else {
|
||||||
|
/* We may have exited due to another problem here, so we need
|
||||||
|
* to reset any tb_locks we may have taken but didn't release.
|
||||||
|
* The mmap_lock is dropped by tb_gen_code if it runs out of
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_SOFTMMU
|
||||||
|
tcg_debug_assert(!have_mmap_lock());
|
||||||
|
#endif
|
||||||
|
tb_lock_reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_exec_step_atomic(CPUState *cpu)
|
void cpu_exec_step_atomic(CPUState *cpu)
|
||||||
|
|
9
cpus.c
9
cpus.c
|
@ -1348,6 +1348,11 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||||
if (r == EXCP_DEBUG) {
|
if (r == EXCP_DEBUG) {
|
||||||
cpu_handle_guest_debug(cpu);
|
cpu_handle_guest_debug(cpu);
|
||||||
break;
|
break;
|
||||||
|
} else if (r == EXCP_ATOMIC) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
cpu_exec_step_atomic(cpu);
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (cpu->stop) {
|
} else if (cpu->stop) {
|
||||||
if (cpu->unplug) {
|
if (cpu->unplug) {
|
||||||
|
@ -1458,6 +1463,10 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||||
*/
|
*/
|
||||||
g_assert(cpu->halted);
|
g_assert(cpu->halted);
|
||||||
break;
|
break;
|
||||||
|
case EXCP_ATOMIC:
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
cpu_exec_step_atomic(cpu);
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
default:
|
default:
|
||||||
/* Ignore everything else? */
|
/* Ignore everything else? */
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue