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.

Backports relevant parts of commit 08e73c48b053566bfe0c994f154f73991cd0ff0e from qemu
This commit is contained in:
Alex Bennée 2018-03-02 09:56:35 -05:00 committed by Lioncash
parent 6760605e1c
commit d56a4b0be4
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 26 additions and 10 deletions

View file

@ -452,15 +452,31 @@ static void cpu_exec_step(struct uc_struct *uc, CPUState *cpu)
uint32_t flags;
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
tb = tb_gen_code(cpu, pc, cs_base, flags,
1 | CF_NOCACHE | CF_IGNORE_ICOUNT);
tb->orig_tb = NULL;
/* execute the generated code */
// Unicorn: commented out
//trace_exec_tb_nocache(tb, pc);
cpu_tb_exec(cpu, tb);
tb_phys_invalidate(uc, tb, -1);
tb_free(uc, tb);
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags,
1 | CF_NOCACHE | CF_IGNORE_ICOUNT);
tb->orig_tb = NULL;
mmap_unlock();
/* execute the generated code */
cpu_tb_exec(cpu, tb);
tb_phys_invalidate(uc, tb, -1);
tb_free(uc, tb);
} 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
// Unicorn: Commented out
//tcg_debug_assert(!have_mmap_lock());
#endif
// Unicorn: commented out
//tb_lock_reset();
}
}
void cpu_exec_step_atomic(struct uc_struct *uc, CPUState *cpu)

View file

@ -187,7 +187,7 @@ static bool tcg_exec_all(struct uc_struct* uc)
} else if (r == EXCP_ATOMIC) {
cpu_exec_step_atomic(uc, cpu);
}
} else if (cpu->stop || cpu->stopped) {
} else if (cpu->stop) {
printf(">>> got stopped!!!\n");
break;
}