Commit b0a46a333acfd78da56cf6aebb95f4a5dfb3a4f2

Authored by Jan Kiszka
Committed by Anthony Liguori
1 parent 151f7749

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 <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
@@ -516,6 +516,8 @@ static void cpu_common_save(QEMUFile *f, void *opaque) @@ -516,6 +516,8 @@ static void cpu_common_save(QEMUFile *f, void *opaque)
516 { 516 {
517 CPUState *env = opaque; 517 CPUState *env = opaque;
518 518
  519 + cpu_synchronize_state(env, 0);
  520 +
519 qemu_put_be32s(f, &env->halted); 521 qemu_put_be32s(f, &env->halted);
520 qemu_put_be32s(f, &env->interrupt_request); 522 qemu_put_be32s(f, &env->interrupt_request);
521 } 523 }
@@ -533,6 +535,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) @@ -533,6 +535,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
533 version_id is increased. */ 535 version_id is increased. */
534 env->interrupt_request &= ~0x01; 536 env->interrupt_request &= ~0x01;
535 tlb_flush(env, 1); 537 tlb_flush(env, 1);
  538 + cpu_synchronize_state(env, 1);
536 539
537 return 0; 540 return 0;
538 } 541 }
@@ -1923,6 +1926,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, @@ -1923,6 +1926,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1923 int cpu_physical_memory_set_dirty_tracking(int enable) 1926 int cpu_physical_memory_set_dirty_tracking(int enable)
1924 { 1927 {
1925 in_migration = enable; 1928 in_migration = enable;
  1929 + if (kvm_enabled()) {
  1930 + return kvm_set_migration_log(enable);
  1931 + }
1926 return 0; 1932 return 0;
1927 } 1933 }
1928 1934
target-i386/machine.c
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 #include "hw/isa.h" 4 #include "hw/isa.h"
5 5
6 #include "exec-all.h" 6 #include "exec-all.h"
  7 +#include "kvm.h"
7 8
8 static void cpu_put_seg(QEMUFile *f, SegmentCache *dt) 9 static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
9 { 10 {
@@ -29,6 +30,8 @@ void cpu_save(QEMUFile *f, void *opaque) @@ -29,6 +30,8 @@ void cpu_save(QEMUFile *f, void *opaque)
29 int32_t a20_mask; 30 int32_t a20_mask;
30 int i; 31 int i;
31 32
  33 + cpu_synchronize_state(env, 0);
  34 +
32 for(i = 0; i < CPU_NB_REGS; i++) 35 for(i = 0; i < CPU_NB_REGS; i++)
33 qemu_put_betls(f, &env->regs[i]); 36 qemu_put_betls(f, &env->regs[i]);
34 qemu_put_betls(f, &env->eip); 37 qemu_put_betls(f, &env->eip);
@@ -321,5 +324,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -321,5 +324,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
321 /* XXX: compute redundant hflags bits */ 324 /* XXX: compute redundant hflags bits */
322 env->hflags = hflags; 325 env->hflags = hflags;
323 tlb_flush(env, 1); 326 tlb_flush(env, 1);
  327 + cpu_synchronize_state(env, 1);
324 return 0; 328 return 0;
325 } 329 }
target-ppc/machine.c
1 #include "hw/hw.h" 1 #include "hw/hw.h"
2 #include "hw/boards.h" 2 #include "hw/boards.h"
  3 +#include "kvm.h"
3 4
4 void cpu_save(QEMUFile *f, void *opaque) 5 void cpu_save(QEMUFile *f, void *opaque)
5 { 6 {
6 CPUState *env = (CPUState *)opaque; 7 CPUState *env = (CPUState *)opaque;
7 unsigned int i, j; 8 unsigned int i, j;
8 9
  10 + cpu_synchronize_state(env, 0);
  11 +
9 for (i = 0; i < 32; i++) 12 for (i = 0; i < 32; i++)
10 qemu_put_betls(f, &env->gpr[i]); 13 qemu_put_betls(f, &env->gpr[i]);
11 #if !defined(TARGET_PPC64) 14 #if !defined(TARGET_PPC64)
@@ -174,5 +177,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -174,5 +177,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
174 qemu_get_sbe32s(f, &env->mmu_idx); 177 qemu_get_sbe32s(f, &env->mmu_idx);
175 qemu_get_sbe32s(f, &env->power_mode); 178 qemu_get_sbe32s(f, &env->power_mode);
176 179
  180 + cpu_synchronize_state(env, 1);
  181 +
177 return 0; 182 return 0;
178 } 183 }
@@ -3232,13 +3232,18 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) @@ -3232,13 +3232,18 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
3232 { 3232 {
3233 ram_addr_t addr; 3233 ram_addr_t addr;
3234 3234
  3235 + if (cpu_physical_sync_dirty_bitmap(0, last_ram_offset) != 0) {
  3236 + qemu_file_set_error(f);
  3237 + return 0;
  3238 + }
  3239 +
3235 if (stage == 1) { 3240 if (stage == 1) {
3236 /* Make sure all dirty bits are set */ 3241 /* Make sure all dirty bits are set */
3237 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) { 3242 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
3238 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) 3243 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
3239 cpu_physical_memory_set_dirty(addr); 3244 cpu_physical_memory_set_dirty(addr);
3240 } 3245 }
3241 - 3246 +
3242 /* Enable dirty memory tracking */ 3247 /* Enable dirty memory tracking */
3243 cpu_physical_memory_set_dirty_tracking(1); 3248 cpu_physical_memory_set_dirty_tracking(1);
3244 3249