mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
replay: interrupts and exceptions
This patch includes modifications of common cpu files. All interrupts and exceptions occured during recording are written into the replay log. These events allow correct replaying the execution by kicking cpu thread when one of these events is found in the log. Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> Message-Id: <20150917162416.8676.57647.stgit@PASHA-ISP.def.inno> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
8b42704441
commit
6f0609697f
5 changed files with 146 additions and 10 deletions
48
cpu-exec.c
48
cpu-exec.c
|
@ -30,6 +30,7 @@
|
|||
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/i386/apic.h"
|
||||
#endif
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
/* -icount align implementation. */
|
||||
|
||||
|
@ -346,21 +347,25 @@ int cpu_exec(CPUState *cpu)
|
|||
uintptr_t next_tb;
|
||||
SyncClocks sc;
|
||||
|
||||
/* replay_interrupt may need current_cpu */
|
||||
current_cpu = cpu;
|
||||
|
||||
if (cpu->halted) {
|
||||
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
||||
if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
|
||||
&& replay_interrupt()) {
|
||||
apic_poll_irq(x86_cpu->apic_state);
|
||||
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
||||
}
|
||||
#endif
|
||||
if (!cpu_has_work(cpu)) {
|
||||
current_cpu = NULL;
|
||||
return EXCP_HALTED;
|
||||
}
|
||||
|
||||
cpu->halted = 0;
|
||||
}
|
||||
|
||||
current_cpu = cpu;
|
||||
atomic_mb_set(&tcg_current_cpu, cpu);
|
||||
rcu_read_lock();
|
||||
|
||||
|
@ -402,10 +407,22 @@ int cpu_exec(CPUState *cpu)
|
|||
cpu->exception_index = -1;
|
||||
break;
|
||||
#else
|
||||
cc->do_interrupt(cpu);
|
||||
cpu->exception_index = -1;
|
||||
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
|
||||
}
|
||||
} else if (replay_has_exception()
|
||||
&& cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
/* try to cause an exception pending in the log */
|
||||
cpu_exec_nocache(cpu, 1, tb_find_fast(cpu), true);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
next_tb = 0; /* force lookup of first TB */
|
||||
|
@ -421,30 +438,40 @@ int cpu_exec(CPUState *cpu)
|
|||
cpu->exception_index = EXCP_DEBUG;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||
if (replay_mode == REPLAY_MODE_PLAY
|
||||
&& !replay_has_interrupt()) {
|
||||
/* Do nothing */
|
||||
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||
replay_interrupt();
|
||||
cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
|
||||
cpu->halted = 1;
|
||||
cpu->exception_index = EXCP_HLT;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
#if defined(TARGET_I386)
|
||||
if (interrupt_request & CPU_INTERRUPT_INIT) {
|
||||
else if (interrupt_request & CPU_INTERRUPT_INIT) {
|
||||
replay_interrupt();
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
|
||||
do_cpu_init(x86_cpu);
|
||||
cpu->exception_index = EXCP_HALTED;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
#else
|
||||
if (interrupt_request & CPU_INTERRUPT_RESET) {
|
||||
else if (interrupt_request & CPU_INTERRUPT_RESET) {
|
||||
replay_interrupt();
|
||||
cpu_reset(cpu);
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
#endif
|
||||
/* The target hook has 3 exit conditions:
|
||||
False when the interrupt isn't processed,
|
||||
True when it is, and we should restart on a new TB,
|
||||
and via longjmp via cpu_loop_exit. */
|
||||
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
next_tb = 0;
|
||||
else {
|
||||
replay_interrupt();
|
||||
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
next_tb = 0;
|
||||
}
|
||||
}
|
||||
/* Don't use the cached interrupt_request value,
|
||||
do_interrupt may have updated the EXITTB flag. */
|
||||
|
@ -455,7 +482,8 @@ int cpu_exec(CPUState *cpu)
|
|||
next_tb = 0;
|
||||
}
|
||||
}
|
||||
if (unlikely(cpu->exit_request)) {
|
||||
if (unlikely(cpu->exit_request
|
||||
|| replay_has_interrupt())) {
|
||||
cpu->exit_request = 0;
|
||||
cpu->exception_index = EXCP_INTERRUPT;
|
||||
cpu_loop_exit(cpu);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue