diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2009-05-01 20:52:47 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-05-22 10:50:33 -0500 |
commit | 151f7749f26e8b0eaca517376a89c01430c584e5 (patch) | |
tree | 2ccfe9051ffcf589965e7af7c9ad7a5e8f30f0f3 | |
parent | 62518b8b1dccb67969688228f14fb379f1918ede (diff) | |
download | qemu-151f7749f26e8b0eaca517376a89c01430c584e5.zip qemu-151f7749f26e8b0eaca517376a89c01430c584e5.tar.gz qemu-151f7749f26e8b0eaca517376a89c01430c584e5.tar.bz2 |
kvm: Rework dirty bitmap synchronization
Extend kvm_physical_sync_dirty_bitmap() so that is can sync across
multiple slots. Useful for updating the whole dirty log during
migration. Moreover, properly pass down errors the whole call chain.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | cpu-all.h | 3 | ||||
-rw-r--r-- | exec.c | 8 | ||||
-rw-r--r-- | kvm-all.c | 73 | ||||
-rw-r--r-- | kvm.h | 4 |
4 files changed, 52 insertions, 36 deletions
@@ -901,7 +901,8 @@ int cpu_physical_memory_set_dirty_tracking(int enable); int cpu_physical_memory_get_dirty_tracking(void); -void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr); +int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, + target_phys_addr_t end_addr); void dump_exec_info(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); @@ -1931,10 +1931,14 @@ int cpu_physical_memory_get_dirty_tracking(void) return in_migration; } -void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr) +int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, + target_phys_addr_t end_addr) { + int ret = 0; + if (kvm_enabled()) - kvm_physical_sync_dirty_bitmap(start_addr, end_addr); + ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr); + return ret; } static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) @@ -272,47 +272,58 @@ int kvm_set_migration_log(int enable) * @start_add: start of logged region. * @end_addr: end of logged region. */ -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, - target_phys_addr_t end_addr) +int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, + target_phys_addr_t end_addr) { KVMState *s = kvm_state; - KVMDirtyLog d; - KVMSlot *mem = kvm_lookup_matching_slot(s, start_addr, end_addr); - unsigned long alloc_size; + unsigned long size, allocated_size = 0; + target_phys_addr_t phys_addr; ram_addr_t addr; - target_phys_addr_t phys_addr = start_addr; + KVMDirtyLog d; + KVMSlot *mem; + int ret = 0; - dprintf("sync addr: " TARGET_FMT_lx " into %lx\n", start_addr, - mem->phys_offset); - if (mem == NULL) { - fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" - TARGET_FMT_plx "\n", __func__, phys_addr, end_addr - 1); - return; - } + d.dirty_bitmap = NULL; + while (start_addr < end_addr) { + mem = kvm_lookup_overlapping_slot(s, start_addr, end_addr); + if (mem == NULL) { + break; + } - alloc_size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8; - d.dirty_bitmap = qemu_mallocz(alloc_size); + size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8; + if (!d.dirty_bitmap) { + d.dirty_bitmap = qemu_malloc(size); + } else if (size > allocated_size) { + d.dirty_bitmap = qemu_realloc(d.dirty_bitmap, size); + } + allocated_size = size; + memset(d.dirty_bitmap, 0, allocated_size); - d.slot = mem->slot; - dprintf("slot %d, phys_addr %llx, uaddr: %llx\n", - d.slot, mem->start_addr, mem->phys_offset); + d.slot = mem->slot; - if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { - dprintf("ioctl failed %d\n", errno); - goto out; - } + if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { + dprintf("ioctl failed %d\n", errno); + ret = -1; + break; + } + + for (phys_addr = mem->start_addr, addr = mem->phys_offset; + phys_addr < mem->start_addr + mem->memory_size; + phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { + unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; + unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS; + unsigned word = nr / (sizeof(*bitmap) * 8); + unsigned bit = nr % (sizeof(*bitmap) * 8); - phys_addr = start_addr; - for (addr = mem->phys_offset; phys_addr < end_addr; phys_addr+= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { - unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; - unsigned nr = (phys_addr - start_addr) >> TARGET_PAGE_BITS; - unsigned word = nr / (sizeof(*bitmap) * 8); - unsigned bit = nr % (sizeof(*bitmap) * 8); - if ((bitmap[word] >> bit) & 1) - cpu_physical_memory_set_dirty(addr); + if ((bitmap[word] >> bit) & 1) { + cpu_physical_memory_set_dirty(addr); + } + } + start_addr = phys_addr; } -out: qemu_free(d.dirty_bitmap); + + return ret; } int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) @@ -40,8 +40,8 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset); -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, - target_phys_addr_t end_addr); +int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, + target_phys_addr_t end_addr); 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); |