From: KONRAD Frederic <fred.kon...@greensocs.com> We don't want to warp on host clock as it is not deterministic for replay. So this patch warp icount on the next QEMU_VIRTUAL_CLOCK event if reverse execution is enabled.
The normal behaviour is kept when reverse execution is disabled. Signed-off-by: KONRAD Frederic <fred.kon...@greensocs.com> --- cpus.c | 19 +++++++++++++++++-- include/qemu/timer.h | 8 ++++++++ include/reverse-execution.h | 2 ++ main-loop.c | 10 ++++++++++ stubs/Makefile.objs | 1 + stubs/cpu-get-icount.c | 8 ++++++++ stubs/reverse-execution-stub.c | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 stubs/reverse-execution-stub.c diff --git a/cpus.c b/cpus.c index 39f4e98..742fc84 100644 --- a/cpus.c +++ b/cpus.c @@ -341,8 +341,10 @@ static int64_t qemu_icount_round(int64_t count) return (count + (1 << icount_time_shift) - 1) >> icount_time_shift; } -static void icount_warp_rt(void *opaque) +void icount_warp_rt(void *opaque) { + int64_t next_vm_deadline = -1; + /* The icount_warp_timer is rescheduled soon after vm_clock_warp_start * changes from -1 to another value, so the race here is okay. */ @@ -350,6 +352,13 @@ static void icount_warp_rt(void *opaque) return; } + if (rexec_is_enabled()) { + /* + * We need this because the standard warp_delta is not deterministic. + */ + next_vm_deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); + } + seqlock_write_lock(&timers_state.vm_clock_seqlock); if (runstate_is_running()) { int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); @@ -366,7 +375,13 @@ static void icount_warp_rt(void *opaque) int64_t delta = cur_time - cur_icount; warp_delta = MIN(warp_delta, delta); } - timers_state.qemu_icount_bias += warp_delta; + if (rexec_is_enabled()) { + if (next_vm_deadline > 0) { + timers_state.qemu_icount_bias += next_vm_deadline; + } + } else { + timers_state.qemu_icount_bias += warp_delta; + } } vm_clock_warp_start = -1; seqlock_write_unlock(&timers_state.vm_clock_seqlock); diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 16bafde..74f3d94 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -755,6 +755,14 @@ int64_t cpu_get_clock(void); int64_t cpu_get_clock_offset(void); int64_t cpu_icount_to_ns(int64_t icount); +/** + * void icount_warp_rt: + * + * Move icount to the realtime clock or to the next QEMU_VIRTUAL_CLOCK event + * when reverse execution is enabled. + */ +void icount_warp_rt(void *opaque); + /*******************************************/ /* host CPU ticks (if available) */ diff --git a/include/reverse-execution.h b/include/reverse-execution.h index 9951549..871d5ee 100644 --- a/include/reverse-execution.h +++ b/include/reverse-execution.h @@ -25,6 +25,8 @@ #ifndef REVERSE_EXECUTION #define REVERSE_EXECUTION +#include "qom/cpu.h" + void rexec_setup(void); void rexec_step_backward(CPUState *cpu, uint64_t steps); void rexec_stop_stepping_back_mode(void); diff --git a/main-loop.c b/main-loop.c index 3cc79f8..44ae29a 100644 --- a/main-loop.c +++ b/main-loop.c @@ -34,6 +34,8 @@ #include "qemu/compatfd.h" +#include "reverse-execution.h" + /* If we have signalfd, we mask out the signals we want to handle and then * use signalfd to listen for them. We rely on whatever the current signal * handler is to dispatch the signals when we receive them. @@ -489,6 +491,14 @@ int main_loop_wait(int nonblocking) qemu_clock_run_all_timers(); + /* + * Sometimes deadlock can appears because there is no pending event on + * virtual clock. + */ + if (rexec_is_enabled()) { + icount_warp_rt(NULL); + } + return ret; } diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 5e347d0..aa42bca 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -40,3 +40,4 @@ stub-obj-$(CONFIG_WIN32) += fd-register.o stub-obj-y += cpus.o stub-obj-y += kvm.o stub-obj-y += qmp_pc_dimm_device_list.o +stub-obj-y += reverse-execution-stub.o diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c index 1968de7..d35948f 100644 --- a/stubs/cpu-get-icount.c +++ b/stubs/cpu-get-icount.c @@ -7,3 +7,11 @@ int64_t cpu_get_icount(int with_bias) { abort(); } + +void icount_warp_rt(void *opaque) +{ + /* + * Should not happen, as rexec_is_enabled() always return false. + */ + abort(); +} diff --git a/stubs/reverse-execution-stub.c b/stubs/reverse-execution-stub.c new file mode 100644 index 0000000..e417d31 --- /dev/null +++ b/stubs/reverse-execution-stub.c @@ -0,0 +1,32 @@ +/* + * reverse-execution-stub.c + * + * Copyright (C) 2014 : GreenSocs Ltd + * http://www.greensocs.com/ , email: i...@greensocs.com + * + * Developed by : + * Frederic Konrad <fred.kon...@greensocs.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <stdbool.h> + +bool rexec_is_enabled(void); + +bool rexec_is_enabled(void) +{ + return false; +} -- 1.9.0