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,7 +901,8 @@ int cpu_physical_memory_set_dirty_tracking(int enable); | ||
901 | 901 | ||
902 | int cpu_physical_memory_get_dirty_tracking(void); | 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 | void dump_exec_info(FILE *f, | 907 | void dump_exec_info(FILE *f, |
907 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); | 908 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); |
exec.c
@@ -1931,10 +1931,14 @@ int cpu_physical_memory_get_dirty_tracking(void) | @@ -1931,10 +1931,14 @@ int cpu_physical_memory_get_dirty_tracking(void) | ||
1931 | return in_migration; | 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 | if (kvm_enabled()) | 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 | static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) | 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,47 +272,58 @@ int kvm_set_migration_log(int enable) | ||
272 | * @start_add: start of logged region. | 272 | * @start_add: start of logged region. |
273 | * @end_addr: end of logged region. | 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 | KVMState *s = kvm_state; | 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 | ram_addr_t addr; | 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 | qemu_free(d.dirty_bitmap); | 324 | qemu_free(d.dirty_bitmap); |
325 | + | ||
326 | + return ret; | ||
316 | } | 327 | } |
317 | 328 | ||
318 | int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) | 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,8 +40,8 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, | ||
40 | ram_addr_t size, | 40 | ram_addr_t size, |
41 | ram_addr_t phys_offset); | 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 | int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); | 46 | int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); |
47 | int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); | 47 | int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); |