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>
This commit is contained in:
		
							parent
							
								
									151f7749f2
								
							
						
					
					
						commit
						b0a46a333a
					
				
							
								
								
									
										6
									
								
								exec.c
								
								
								
								
							
							
						
						
									
										6
									
								
								exec.c
								
								
								
								
							| 
						 | 
					@ -516,6 +516,8 @@ static void cpu_common_save(QEMUFile *f, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *env = opaque;
 | 
					    CPUState *env = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_put_be32s(f, &env->halted);
 | 
					    qemu_put_be32s(f, &env->halted);
 | 
				
			||||||
    qemu_put_be32s(f, &env->interrupt_request);
 | 
					    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. */
 | 
					       version_id is increased. */
 | 
				
			||||||
    env->interrupt_request &= ~0x01;
 | 
					    env->interrupt_request &= ~0x01;
 | 
				
			||||||
    tlb_flush(env, 1);
 | 
					    tlb_flush(env, 1);
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    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)
 | 
					int cpu_physical_memory_set_dirty_tracking(int enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    in_migration = enable;
 | 
					    in_migration = enable;
 | 
				
			||||||
 | 
					    if (kvm_enabled()) {
 | 
				
			||||||
 | 
					        return kvm_set_migration_log(enable);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include "hw/isa.h"
 | 
					#include "hw/isa.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "exec-all.h"
 | 
					#include "exec-all.h"
 | 
				
			||||||
 | 
					#include "kvm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
 | 
					static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -29,6 +30,8 @@ void cpu_save(QEMUFile *f, void *opaque)
 | 
				
			||||||
    int32_t a20_mask;
 | 
					    int32_t a20_mask;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(i = 0; i < CPU_NB_REGS; i++)
 | 
					    for(i = 0; i < CPU_NB_REGS; i++)
 | 
				
			||||||
        qemu_put_betls(f, &env->regs[i]);
 | 
					        qemu_put_betls(f, &env->regs[i]);
 | 
				
			||||||
    qemu_put_betls(f, &env->eip);
 | 
					    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 */
 | 
					    /* XXX: compute redundant hflags bits */
 | 
				
			||||||
    env->hflags = hflags;
 | 
					    env->hflags = hflags;
 | 
				
			||||||
    tlb_flush(env, 1);
 | 
					    tlb_flush(env, 1);
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 1);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,14 @@
 | 
				
			||||||
#include "hw/hw.h"
 | 
					#include "hw/hw.h"
 | 
				
			||||||
#include "hw/boards.h"
 | 
					#include "hw/boards.h"
 | 
				
			||||||
 | 
					#include "kvm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cpu_save(QEMUFile *f, void *opaque)
 | 
					void cpu_save(QEMUFile *f, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *env = (CPUState *)opaque;
 | 
					    CPUState *env = (CPUState *)opaque;
 | 
				
			||||||
    unsigned int i, j;
 | 
					    unsigned int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < 32; i++)
 | 
					    for (i = 0; i < 32; i++)
 | 
				
			||||||
        qemu_put_betls(f, &env->gpr[i]);
 | 
					        qemu_put_betls(f, &env->gpr[i]);
 | 
				
			||||||
#if !defined(TARGET_PPC64)
 | 
					#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->mmu_idx);
 | 
				
			||||||
    qemu_get_sbe32s(f, &env->power_mode);
 | 
					    qemu_get_sbe32s(f, &env->power_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								vl.c
								
								
								
								
							
							
						
						
									
										7
									
								
								vl.c
								
								
								
								
							| 
						 | 
					@ -3232,13 +3232,18 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ram_addr_t addr;
 | 
					    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) {
 | 
					    if (stage == 1) {
 | 
				
			||||||
        /* Make sure all dirty bits are set */
 | 
					        /* Make sure all dirty bits are set */
 | 
				
			||||||
        for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
 | 
					        for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
 | 
				
			||||||
            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
 | 
					            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
 | 
				
			||||||
                cpu_physical_memory_set_dirty(addr);
 | 
					                cpu_physical_memory_set_dirty(addr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* Enable dirty memory tracking */
 | 
					        /* Enable dirty memory tracking */
 | 
				
			||||||
        cpu_physical_memory_set_dirty_tracking(1);
 | 
					        cpu_physical_memory_set_dirty_tracking(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue