This patch removes "static" specifier from several qemu function to make them visible to the replay module. It also invents several system functions that will be used by replay.
Signed-off-by: Pavel Dovgalyuk <pavel.dovga...@ispras.ru> --- arch_init.c | 8 ++++++++ cpu-exec.c | 6 ++++-- cpus.c | 4 ++-- include/exec/exec-all.h | 4 +++- include/sysemu/cpus.h | 1 + include/sysemu/sysemu.h | 1 + savevm.c | 32 ++++++++++++++++++++++++++------ translate-all.c | 8 ++++++++ 8 files changed, 53 insertions(+), 11 deletions(-) diff --git a/arch_init.c b/arch_init.c index 8ddaf35..5ee33d9 100644 --- a/arch_init.c +++ b/arch_init.c @@ -52,6 +52,7 @@ #include "exec/ram_addr.h" #include "hw/acpi/acpi.h" #include "qemu/host-utils.h" +#include "replay/replay.h" #ifdef DEBUG_ARCH_INIT #define DPRINTF(fmt, ...) \ @@ -1092,6 +1093,13 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) total_ram_bytes -= length; } + if (replay_mode == REPLAY_PLAY) { + RAMBlock *block; + /* Clear the blocks' memory instead of resetting the machine */ + QTAILQ_FOREACH(block, &ram_list.blocks, next) { + memset(block->host, 0, block->length); + } + } } else if (flags & RAM_SAVE_FLAG_COMPRESS) { void *host; uint8_t ch; diff --git a/cpu-exec.c b/cpu-exec.c index 38e5f02..66a693c 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -189,12 +189,14 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env) static CPUDebugExcpHandler *debug_excp_handler; -void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) +CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) { + CPUDebugExcpHandler *old = debug_excp_handler; debug_excp_handler = handler; + return old; } -static void cpu_handle_debug_exception(CPUArchState *env) +void cpu_handle_debug_exception(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp; diff --git a/cpus.c b/cpus.c index 5e7f2cf..bbad529 100644 --- a/cpus.c +++ b/cpus.c @@ -85,7 +85,7 @@ static bool cpu_thread_is_idle(CPUState *cpu) return true; } -static bool all_cpu_threads_idle(void) +bool all_cpu_threads_idle(void) { CPUState *cpu; @@ -1033,7 +1033,7 @@ bool qemu_cpu_is_self(CPUState *cpu) return qemu_thread_is_self(cpu->thread); } -static bool qemu_in_vcpu_thread(void) +bool qemu_in_vcpu_thread(void) { return current_cpu && qemu_cpu_is_self(current_cpu); } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 528928f..4b7a241 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -212,6 +212,7 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc) void tb_free(TranslationBlock *tb); void tb_flush(CPUArchState *env); +void tb_flush_all(void); void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); #if defined(USE_DIRECT_JUMP) @@ -385,7 +386,8 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr); typedef void (CPUDebugExcpHandler)(CPUArchState *env); -void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler); +CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler); +void cpu_handle_debug_exception(CPUArchState *env); /* vl.c */ extern int singlestep; diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 4f79081..8455e0e 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -6,6 +6,7 @@ void qemu_init_cpu_loop(void); void resume_all_vcpus(void); void pause_all_vcpus(void); void cpu_stop_current(void); +bool all_cpu_threads_idle(void); void cpu_synchronize_all_states(void); void cpu_synchronize_all_post_reset(void); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index d8539fd..1ebfef9 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -76,6 +76,7 @@ void qemu_add_machine_init_done_notifier(Notifier *notify); void do_savevm(Monitor *mon, const QDict *qdict); int load_vmstate(const char *name); +int save_vmstate(Monitor *mon, const char *name); void do_delvm(Monitor *mon, const QDict *qdict); void do_info_snapshots(Monitor *mon, const QDict *qdict); diff --git a/savevm.c b/savevm.c index e19ae0a..9136778 100644 --- a/savevm.c +++ b/savevm.c @@ -42,7 +42,7 @@ #include "qemu/iov.h" #include "block/snapshot.h" #include "block/qapi.h" - +#include "replay/replay.h" #ifndef ETH_P_RARP #define ETH_P_RARP 0x8035 @@ -1039,7 +1039,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name) return 0; } -void do_savevm(Monitor *mon, const QDict *qdict) +int save_vmstate(Monitor *mon, const char *name) { BlockDriverState *bs, *bs1; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; @@ -1049,7 +1049,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) uint64_t vm_state_size; qemu_timeval tv; struct tm tm; - const char *name = qdict_get_try_str(qdict, "name"); + int success = 0; /* Verify if there is a device that doesn't support snapshots and is writable */ bs = NULL; @@ -1062,14 +1062,18 @@ void do_savevm(Monitor *mon, const QDict *qdict) if (!bdrv_can_snapshot(bs)) { monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n", bdrv_get_device_name(bs)); - return; + return success; } } bs = find_vmstate_bs(); if (!bs) { monitor_printf(mon, "No block device can accept snapshots\n"); - return; + if (replay_mode != REPLAY_NONE) { + fprintf(stderr, "At least one hdd should be attached to QEMU for replay\n"); + exit(1); + } + return success; } saved_vm_running = runstate_is_running(); @@ -1118,6 +1122,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) /* create the snapshots */ + success = 1; bs1 = NULL; while ((bs1 = bdrv_next(bs1))) { if (bdrv_can_snapshot(bs1)) { @@ -1127,6 +1132,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) if (ret < 0) { monitor_printf(mon, "Error while creating snapshot on '%s'\n", bdrv_get_device_name(bs1)); + success = 0; } } } @@ -1135,6 +1141,14 @@ void do_savevm(Monitor *mon, const QDict *qdict) if (saved_vm_running) { vm_start(); } + + return success; +} + +void do_savevm(Monitor *mon, const QDict *qdict) +{ + const char *name = qdict_get_try_str(qdict, "name"); + save_vmstate(mon, name); } void qmp_xen_save_devices_state(const char *filename, Error **errp) @@ -1231,7 +1245,13 @@ int load_vmstate(const char *name) return -EINVAL; } - qemu_system_reset(VMRESET_SILENT); + /* Do not reset in replay mode. + 1. Reset will alter the behavior in play mode compared to save one + 2. Timers read by reset handlers are not correct, because + replay reads them from the unknown part of the log */ + if (replay_mode == REPLAY_NONE) { + qemu_system_reset(VMRESET_SILENT); + } ret = qemu_loadvm_state(f); qemu_fclose(f); diff --git a/translate-all.c b/translate-all.c index 8f7e11b..fcb0697 100644 --- a/translate-all.c +++ b/translate-all.c @@ -803,6 +803,14 @@ void tb_flush(CPUArchState *env1) tcg_ctx.tb_ctx.tb_flush_count++; } +void tb_flush_all(void) +{ + CPUState *cpu; + for (cpu = first_cpu ; cpu != NULL ; cpu = CPU_NEXT(cpu)) { + tb_flush(cpu->env_ptr); + } +} + #ifdef DEBUG_TB_CHECK static void tb_invalidate_check(target_ulong address)