mirror of https://gitlab.com/qemu-project/qemu
cpu-exec: Move exception handling out of cpu_exec()
Simplify cpu_exec() by extracting exception handling code out of cpu_exec() into a new static inline function cpu_handle_exception(). Also make cpu_handle_debug_exception() inline as it is used only once. Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com> Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net> Message-Id: <1462962111-32237-3-git-send-email-sergey.fedorov@linaro.org> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
8b2d34e997
commit
ea284766ec
93
cpu-exec.c
93
cpu-exec.c
|
@ -374,7 +374,7 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_handle_debug_exception(CPUState *cpu)
|
static inline void cpu_handle_debug_exception(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
|
@ -388,6 +388,55 @@ static void cpu_handle_debug_exception(CPUState *cpu)
|
||||||
cc->debug_excp_handler(cpu);
|
cc->debug_excp_handler(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 defined(CONFIG_USER_ONLY)
|
||||||
|
/* 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);
|
||||||
|
cc->do_interrupt(cpu);
|
||||||
|
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 */
|
||||||
|
TranslationBlock *last_tb = NULL; /* Avoid chaining TBs */
|
||||||
|
cpu_exec_nocache(cpu, 1, tb_find_fast(cpu, &last_tb, 0), true);
|
||||||
|
*ret = -1;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* main execution loop */
|
/* main execution loop */
|
||||||
|
|
||||||
int cpu_exec(CPUState *cpu)
|
int cpu_exec(CPUState *cpu)
|
||||||
|
@ -425,50 +474,12 @@ int cpu_exec(CPUState *cpu)
|
||||||
*/
|
*/
|
||||||
init_delay_params(&sc, cpu);
|
init_delay_params(&sc, cpu);
|
||||||
|
|
||||||
/* prepare setjmp context for exception handling */
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
/* prepare setjmp context for exception handling */
|
||||||
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
||||||
/* if an exception is pending, we execute it here */
|
/* if an exception is pending, we execute it here */
|
||||||
if (cpu->exception_index >= 0) {
|
if (cpu_handle_exception(cpu, &ret)) {
|
||||||
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;
|
|
||||||
break;
|
|
||||||
} 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 defined(TARGET_I386)
|
|
||||||
cc->do_interrupt(cpu);
|
|
||||||
#endif
|
|
||||||
ret = cpu->exception_index;
|
|
||||||
cpu->exception_index = -1;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
if (replay_exception()) {
|
|
||||||
cc->do_interrupt(cpu);
|
|
||||||
cpu->exception_index = -1;
|
|
||||||
} else if (!replay_has_interrupt()) {
|
|
||||||
/* give a chance to iothread in replay mode */
|
|
||||||
ret = EXCP_INTERRUPT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#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 */
|
|
||||||
last_tb = NULL; /* Avoid chaining TBs */
|
|
||||||
cpu_exec_nocache(cpu, 1, tb_find_fast(cpu, &last_tb, 0), true);
|
|
||||||
ret = -1;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last_tb = NULL; /* forget the last executed TB after exception */
|
last_tb = NULL; /* forget the last executed TB after exception */
|
||||||
|
|
Loading…
Reference in New Issue