From b0a46a333acfd78da56cf6aebb95f4a5dfb3a4f2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 2 May 2009 00:22:51 +0200 Subject: [PATCH] kvm: Add missing bits to support live migration This patch adds the missing hooks to allow live migration in KVM mode. It adds proper synchronization before/after saving/restoring the VCPU states (note: PPC is untested), hooks into cpu_physical_memory_set_dirty_tracking() to enable dirty memory logging at KVM level, and synchronizes that drity log into QEMU's view before running ram_live_save(). Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- exec.c | 6 ++++++ target-i386/machine.c | 4 ++++ target-ppc/machine.c | 5 +++++ vl.c | 7 ++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 544fb43..723de89 100644 --- a/exec.c +++ b/exec.c @@ -516,6 +516,8 @@ static void cpu_common_save(QEMUFile *f, void *opaque) { CPUState *env = opaque; + cpu_synchronize_state(env, 0); + qemu_put_be32s(f, &env->halted); qemu_put_be32s(f, &env->interrupt_request); } @@ -533,6 +535,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) version_id is increased. */ env->interrupt_request &= ~0x01; tlb_flush(env, 1); + cpu_synchronize_state(env, 1); return 0; } @@ -1923,6 +1926,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int cpu_physical_memory_set_dirty_tracking(int enable) { in_migration = enable; + if (kvm_enabled()) { + return kvm_set_migration_log(enable); + } return 0; } diff --git a/target-i386/machine.c b/target-i386/machine.c index 55716fe..69a03a4 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -4,6 +4,7 @@ #include "hw/isa.h" #include "exec-all.h" +#include "kvm.h" static void cpu_put_seg(QEMUFile *f, SegmentCache *dt) { @@ -29,6 +30,8 @@ void cpu_save(QEMUFile *f, void *opaque) int32_t a20_mask; int i; + cpu_synchronize_state(env, 0); + for(i = 0; i < CPU_NB_REGS; i++) qemu_put_betls(f, &env->regs[i]); qemu_put_betls(f, &env->eip); @@ -321,5 +324,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) /* XXX: compute redundant hflags bits */ env->hflags = hflags; tlb_flush(env, 1); + cpu_synchronize_state(env, 1); return 0; } diff --git a/target-ppc/machine.c b/target-ppc/machine.c index c15776f..99ba3eb 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -1,11 +1,14 @@ #include "hw/hw.h" #include "hw/boards.h" +#include "kvm.h" void cpu_save(QEMUFile *f, void *opaque) { CPUState *env = (CPUState *)opaque; unsigned int i, j; + cpu_synchronize_state(env, 0); + for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); #if !defined(TARGET_PPC64) @@ -174,5 +177,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_sbe32s(f, &env->mmu_idx); qemu_get_sbe32s(f, &env->power_mode); + cpu_synchronize_state(env, 1); + return 0; } diff --git a/vl.c b/vl.c index c9b2aa4..5079a1c 100644 --- a/vl.c +++ b/vl.c @@ -3232,13 +3232,18 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) { ram_addr_t addr; + if (cpu_physical_sync_dirty_bitmap(0, last_ram_offset) != 0) { + qemu_file_set_error(f); + return 0; + } + if (stage == 1) { /* Make sure all dirty bits are set */ for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) { if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) cpu_physical_memory_set_dirty(addr); } - + /* Enable dirty memory tracking */ cpu_physical_memory_set_dirty_tracking(1); -- 1.7.9.5