Commit 151f7749f26e8b0eaca517376a89c01430c584e5
Committed by
Anthony Liguori
1 parent
62518b8b
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>
Showing
4 changed files
with
52 additions
and
36 deletions
cpu-all.h
| ... | ... | @@ -901,7 +901,8 @@ int cpu_physical_memory_set_dirty_tracking(int enable); |
| 901 | 901 | |
| 902 | 902 | int cpu_physical_memory_get_dirty_tracking(void); |
| 903 | 903 | |
| 904 | -void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr); | |
| 904 | +int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 905 | + target_phys_addr_t end_addr); | |
| 905 | 906 | |
| 906 | 907 | void dump_exec_info(FILE *f, |
| 907 | 908 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); | ... | ... |
exec.c
| ... | ... | @@ -1931,10 +1931,14 @@ int cpu_physical_memory_get_dirty_tracking(void) |
| 1931 | 1931 | return in_migration; |
| 1932 | 1932 | } |
| 1933 | 1933 | |
| 1934 | -void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr) | |
| 1934 | +int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 1935 | + target_phys_addr_t end_addr) | |
| 1935 | 1936 | { |
| 1937 | + int ret = 0; | |
| 1938 | + | |
| 1936 | 1939 | if (kvm_enabled()) |
| 1937 | - kvm_physical_sync_dirty_bitmap(start_addr, end_addr); | |
| 1940 | + ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr); | |
| 1941 | + return ret; | |
| 1938 | 1942 | } |
| 1939 | 1943 | |
| 1940 | 1944 | static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) | ... | ... |
kvm-all.c
| ... | ... | @@ -272,47 +272,58 @@ int kvm_set_migration_log(int enable) |
| 272 | 272 | * @start_add: start of logged region. |
| 273 | 273 | * @end_addr: end of logged region. |
| 274 | 274 | */ |
| 275 | -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 276 | - target_phys_addr_t end_addr) | |
| 275 | +int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 276 | + target_phys_addr_t end_addr) | |
| 277 | 277 | { |
| 278 | 278 | KVMState *s = kvm_state; |
| 279 | - KVMDirtyLog d; | |
| 280 | - KVMSlot *mem = kvm_lookup_matching_slot(s, start_addr, end_addr); | |
| 281 | - unsigned long alloc_size; | |
| 279 | + unsigned long size, allocated_size = 0; | |
| 280 | + target_phys_addr_t phys_addr; | |
| 282 | 281 | ram_addr_t addr; |
| 283 | - target_phys_addr_t phys_addr = start_addr; | |
| 282 | + KVMDirtyLog d; | |
| 283 | + KVMSlot *mem; | |
| 284 | + int ret = 0; | |
| 284 | 285 | |
| 285 | - dprintf("sync addr: " TARGET_FMT_lx " into %lx\n", start_addr, | |
| 286 | - mem->phys_offset); | |
| 287 | - if (mem == NULL) { | |
| 288 | - fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" | |
| 289 | - TARGET_FMT_plx "\n", __func__, phys_addr, end_addr - 1); | |
| 290 | - return; | |
| 291 | - } | |
| 286 | + d.dirty_bitmap = NULL; | |
| 287 | + while (start_addr < end_addr) { | |
| 288 | + mem = kvm_lookup_overlapping_slot(s, start_addr, end_addr); | |
| 289 | + if (mem == NULL) { | |
| 290 | + break; | |
| 291 | + } | |
| 292 | 292 | |
| 293 | - alloc_size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8; | |
| 294 | - d.dirty_bitmap = qemu_mallocz(alloc_size); | |
| 293 | + size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8; | |
| 294 | + if (!d.dirty_bitmap) { | |
| 295 | + d.dirty_bitmap = qemu_malloc(size); | |
| 296 | + } else if (size > allocated_size) { | |
| 297 | + d.dirty_bitmap = qemu_realloc(d.dirty_bitmap, size); | |
| 298 | + } | |
| 299 | + allocated_size = size; | |
| 300 | + memset(d.dirty_bitmap, 0, allocated_size); | |
| 295 | 301 | |
| 296 | - d.slot = mem->slot; | |
| 297 | - dprintf("slot %d, phys_addr %llx, uaddr: %llx\n", | |
| 298 | - d.slot, mem->start_addr, mem->phys_offset); | |
| 302 | + d.slot = mem->slot; | |
| 299 | 303 | |
| 300 | - if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { | |
| 301 | - dprintf("ioctl failed %d\n", errno); | |
| 302 | - goto out; | |
| 303 | - } | |
| 304 | + if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { | |
| 305 | + dprintf("ioctl failed %d\n", errno); | |
| 306 | + ret = -1; | |
| 307 | + break; | |
| 308 | + } | |
| 309 | + | |
| 310 | + for (phys_addr = mem->start_addr, addr = mem->phys_offset; | |
| 311 | + phys_addr < mem->start_addr + mem->memory_size; | |
| 312 | + phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { | |
| 313 | + unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; | |
| 314 | + unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS; | |
| 315 | + unsigned word = nr / (sizeof(*bitmap) * 8); | |
| 316 | + unsigned bit = nr % (sizeof(*bitmap) * 8); | |
| 304 | 317 | |
| 305 | - phys_addr = start_addr; | |
| 306 | - for (addr = mem->phys_offset; phys_addr < end_addr; phys_addr+= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { | |
| 307 | - unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; | |
| 308 | - unsigned nr = (phys_addr - start_addr) >> TARGET_PAGE_BITS; | |
| 309 | - unsigned word = nr / (sizeof(*bitmap) * 8); | |
| 310 | - unsigned bit = nr % (sizeof(*bitmap) * 8); | |
| 311 | - if ((bitmap[word] >> bit) & 1) | |
| 312 | - cpu_physical_memory_set_dirty(addr); | |
| 318 | + if ((bitmap[word] >> bit) & 1) { | |
| 319 | + cpu_physical_memory_set_dirty(addr); | |
| 320 | + } | |
| 321 | + } | |
| 322 | + start_addr = phys_addr; | |
| 313 | 323 | } |
| 314 | -out: | |
| 315 | 324 | qemu_free(d.dirty_bitmap); |
| 325 | + | |
| 326 | + return ret; | |
| 316 | 327 | } |
| 317 | 328 | |
| 318 | 329 | int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) | ... | ... |
kvm.h
| ... | ... | @@ -40,8 +40,8 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, |
| 40 | 40 | ram_addr_t size, |
| 41 | 41 | ram_addr_t phys_offset); |
| 42 | 42 | |
| 43 | -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 44 | - target_phys_addr_t end_addr); | |
| 43 | +int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | |
| 44 | + target_phys_addr_t end_addr); | |
| 45 | 45 | |
| 46 | 46 | int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); |
| 47 | 47 | int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); | ... | ... |