From: Uri Lublin <[EMAIL PROTECTED]> Since c79baa60813812e8d0e34d998d609e848c093000 qemu does not know about slots, it uses addresses. Getting the dirty-page-bitmap needs to adapt to that change.
The user (qemu) requests (from libkvm) dirty page log for all pages within a specific address range (specifically [0,phys_ram_size-1]). libkvm iterates through all slots in the address range, calling a qemu-kvm callback to update qemu's bytemap for each slot within the requested range. Signed-off-by: Izik Eidus <[EMAIL PROTECTED]> Signed-off-by: Uri Lublin <[EMAIL PROTECTED]> Signed-off-by: Avi Kivity <[EMAIL PROTECTED]> diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c index cf0c249..ad90e0b 100644 --- a/libkvm/libkvm.c +++ b/libkvm/libkvm.c @@ -608,6 +608,32 @@ int kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf) return kvm_get_map(kvm, KVM_GET_DIRTY_LOG, slot, buf); } +#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1)) +#define BITMAP_SIZE(m) (ALIGN(((m)/PAGE_SIZE), sizeof(long) * 8) / 8) + +int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr, + unsigned long len, void *buf, void *opaque, + int (*cb)(unsigned long start, unsigned long len, + void*bitmap, void *opaque)) +{ + int i; + int r; + unsigned long end_addr = phys_addr + len; + + for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i) { + if ((slots[i].len && slots[i].phys_addr >= phys_addr) && + (slots[i].phys_addr + slots[i].len <= end_addr)) { + r = kvm_get_map(kvm, KVM_GET_DIRTY_LOG, i, buf); + if (r) + return r; + r = cb(slots[i].phys_addr, slots[i].len, buf, opaque); + if (r) + return r; + } + } + return 0; +} + int kvm_get_mem_map(kvm_context_t kvm, unsigned long phys_addr, void *buf) { int slot; diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h index ff260f4..d999ce9 100644 --- a/libkvm/libkvm.h +++ b/libkvm/libkvm.h @@ -423,7 +423,10 @@ int kvm_register_userspace_phys_mem(kvm_context_t kvm, unsigned long phys_start, void *userspace_addr, unsigned long len, int log); int kvm_get_dirty_pages(kvm_context_t, unsigned long phys_addr, void *buf); - +int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr, + unsigned long end_addr, void *buf, void*opaque, + int (*cb)(unsigned long start, unsigned long len, + void*bitmap, void *opaque)); /*! * \brief Create a memory alias diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c index 3aeba39..5580bb4 100644 --- a/qemu/qemu-kvm.c +++ b/qemu/qemu-kvm.c @@ -710,20 +710,15 @@ int kvm_physical_memory_set_dirty_tracking(int enable) } /* get kvm's dirty pages bitmap and update qemu's */ -int kvm_get_dirty_pages_log_slot(unsigned long start_addr, - unsigned char *bitmap, - unsigned int offset, - unsigned int len) +int kvm_get_dirty_pages_log_range(unsigned long start_addr, + unsigned char *bitmap, + unsigned int offset, + unsigned long mem_size) { - int r; unsigned int i, j, n=0; unsigned char c; unsigned page_number, addr, addr1; - - memset(bitmap, 0, len); - r = kvm_get_dirty_pages(kvm_context, start_addr, bitmap); - if (r) - return r; + unsigned int len = ((mem_size/TARGET_PAGE_SIZE) + 7) / 8; /* * bitmap-traveling is faster than memory-traveling (for addr...) @@ -743,6 +738,11 @@ int kvm_get_dirty_pages_log_slot(unsigned long start_addr, } return 0; } +int kvm_get_dirty_bitmap_cb(unsigned long start, unsigned long len, + void *bitmap, void *opaque) +{ + return kvm_get_dirty_pages_log_range(start, bitmap, start, len); +} /* * get kvm's dirty pages bitmap and update qemu's @@ -750,12 +750,12 @@ int kvm_get_dirty_pages_log_slot(unsigned long start_addr, */ int kvm_update_dirty_pages_log(void) { - int r = 0, len; + int r = 0; + - len = BITMAP_SIZE(0xa0000); - r = kvm_get_dirty_pages_log_slot(0, kvm_dirty_bitmap, 0 , len); - len = BITMAP_SIZE(phys_ram_size - 0xc0000); - r = r || kvm_get_dirty_pages_log_slot(0xc0000, kvm_dirty_bitmap, 0xc0000, len); + r = kvm_get_dirty_pages_range(kvm_context, 0, phys_ram_size, + kvm_dirty_bitmap, NULL, + kvm_get_dirty_bitmap_cb); return r; } ------------------------------------------------------------------------- SF.Net email is sponsored by: Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ kvm-commits mailing list kvm-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-commits