kvm: Introduce kvm_set_migration_log

Introduce a global dirty logging flag that enforces logging for all
slots. This can be used by the live migration code to enable/disable
global logging withouth destroying the per-slot setting.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Jan Kiszka 2009-05-01 20:52:46 +02:00 committed by Anthony Liguori
parent e69917e29a
commit 4495d6a745
2 changed files with 40 additions and 7 deletions

View File

@ -58,6 +58,7 @@ struct KVMState
int vmfd; int vmfd;
int coalesced_mmio; int coalesced_mmio;
int broken_set_mem_region; int broken_set_mem_region;
int migration_log;
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints; struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif #endif
@ -135,7 +136,9 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
mem.memory_size = slot->memory_size; mem.memory_size = slot->memory_size;
mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset); mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset);
mem.flags = slot->flags; mem.flags = slot->flags;
if (s->migration_log) {
mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
}
return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
} }
@ -196,11 +199,12 @@ int kvm_sync_vcpus(void)
* dirty pages logging control * dirty pages logging control
*/ */
static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
ram_addr_t size, unsigned flags, ram_addr_t size, int flags, int mask)
unsigned mask)
{ {
KVMState *s = kvm_state; KVMState *s = kvm_state;
KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size); KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
int old_flags;
if (mem == NULL) { if (mem == NULL) {
fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
TARGET_FMT_plx "\n", __func__, phys_addr, TARGET_FMT_plx "\n", __func__, phys_addr,
@ -208,13 +212,19 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
return -EINVAL; return -EINVAL;
} }
flags = (mem->flags & ~mask) | flags; old_flags = mem->flags;
/* Nothing changed, no need to issue ioctl */
if (flags == mem->flags)
return 0;
flags = (mem->flags & ~mask) | flags;
mem->flags = flags; mem->flags = flags;
/* If nothing changed effectively, no need to issue ioctl */
if (s->migration_log) {
flags |= KVM_MEM_LOG_DIRTY_PAGES;
}
if (flags == old_flags) {
return 0;
}
return kvm_set_user_memory_region(s, mem); return kvm_set_user_memory_region(s, mem);
} }
@ -232,6 +242,28 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
KVM_MEM_LOG_DIRTY_PAGES); KVM_MEM_LOG_DIRTY_PAGES);
} }
int kvm_set_migration_log(int enable)
{
KVMState *s = kvm_state;
KVMSlot *mem;
int i, err;
s->migration_log = enable;
for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
mem = &s->slots[i];
if (!!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES) == enable) {
continue;
}
err = kvm_set_user_memory_region(s, mem);
if (err) {
return err;
}
}
return 0;
}
/** /**
* kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
* This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty(). * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().

1
kvm.h
View File

@ -45,6 +45,7 @@ void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);
int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
int kvm_set_migration_log(int enable);
int kvm_has_sync_mmu(void); int kvm_has_sync_mmu(void);