cpu-exec: avoid repeated sigsetjmp on interrupts

The sigsetjmp only needs to be prepared once for the whole execution
of cpu_exec. This patch takes care of the "== 0" side, using a
nested loop so that cpu_handle_interrupt goes straight back to
cpu_handle_exception without doing another sigsetjmp.

Backports commit a42cf3f3f266a97ceb13e8b99bc7b13f7bf4192a from qemu
This commit is contained in:
Paolo Bonzini 2018-03-02 08:07:08 -05:00 committed by Lioncash
parent 28b615a8b7
commit af524401ad
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -503,9 +503,6 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
env->invalid_error = UC_ERR_OK;
for(;;) {
TranslationBlock *last_tb = NULL;
int tb_exit = 0;
/* prepare setjmp context for exception handling */
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
if (uc->stop_request || uc->invalid_error) {
@ -513,21 +510,21 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu)
}
/* if an exception is pending, we execute it here */
if (cpu_handle_exception(uc, cpu, &ret)) {
break;
}
while (!cpu_handle_exception(uc, cpu, &ret)) {
TranslationBlock *last_tb = NULL;
int tb_exit = 0;
last_tb = NULL; /* forget the last executed TB after exception */
atomic_mb_set(&cpu->tb_flushed, false); /* reset before first TB lookup */
while (!cpu_handle_interrupt(cpu, &last_tb)) {
TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit);
if (!tb) { // invalid TB due to invalid code?
uc->invalid_error = UC_ERR_FETCH_UNMAPPED;
ret = EXCP_HLT;
break;
while (!cpu_handle_interrupt(cpu, &last_tb)) {
TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit);
if (!tb) { // invalid TB due to invalid code?
uc->invalid_error = UC_ERR_FETCH_UNMAPPED;
ret = EXCP_HLT;
break;
}
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
}
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
}
break;
} else {
#if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6)
/* Some compilers wrongly smash all local variables after