Currently x86's kvm_vm_ioctl_get_dirty_log() needs to allocate a bitmap by vmalloc() which will be used in the next logging and this has been causing bad effects to VGA and live-migration: vmalloc() consumes extra systime, triggers tlb flush, etc. This patch resolves this issue by pre-allocating one more bitmap and switching between the two bitmaps during dirty logging. Performance improvement: In the usual Desktop environment, kvm_vm_ioctl_get_dirty_log() get about twice faster than the original one for graphical updates. During live-migration with low work load, the improvement ratio was about three when guest memory was 4GB. Note: Though this patch introduces some ifdefs, we tried not to mixing these with other parts to keep the code as clean as possible. Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> Signed-off-by: Fernando Luis Vazquez Cao <fernando@xxxxxxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/x86.c | 16 +++++----------- include/linux/kvm_host.h | 3 +++ virt/kvm/kvm_main.c | 12 ++++++++++-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0cd0f29..c516f1c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -81,6 +81,8 @@ #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 +#define __KVM_DIRTY_LOG_DOUBLE_BUFFERING + extern spinlock_t kvm_lock; extern struct list_head vm_list; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5e5cd8d..0871ef8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2804,18 +2804,15 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, kvm_mmu_slot_remove_write_access(kvm, log->slot); spin_unlock(&kvm->mmu_lock); - r = -ENOMEM; - dirty_bitmap = vmalloc(n); - if (!dirty_bitmap) - goto out; + dirty_bitmap = memslot->dirty_bitmap_head; + if (memslot->dirty_bitmap == dirty_bitmap) + dirty_bitmap += n / sizeof(long); memset(dirty_bitmap, 0, n); r = -ENOMEM; slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); - if (!slots) { - vfree(dirty_bitmap); + if (!slots) goto out; - } memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; @@ -2826,11 +2823,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, kfree(old_slots); r = -EFAULT; - if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { - vfree(dirty_bitmap); + if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) goto out; - } - vfree(dirty_bitmap); } else { r = -EFAULT; if (clear_user(log->dirty_bitmap, n)) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2c62319..199a464 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -118,6 +118,9 @@ struct kvm_memory_slot { unsigned long flags; unsigned long *rmap; unsigned long *dirty_bitmap; +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + unsigned long *dirty_bitmap_head; +#endif struct { unsigned long rmap_pde; int write_count; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e4f5762..6f73b42 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -443,7 +443,10 @@ static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) { if (!memslot->dirty_bitmap) return; - +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + memslot->dirty_bitmap = memslot->dirty_bitmap_head; + memslot->dirty_bitmap_head = NULL; +#endif vfree(memslot->dirty_bitmap); memslot->dirty_bitmap = NULL; } @@ -535,12 +538,17 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) { unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot); - +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + dirty_bytes *= 2; +#endif memslot->dirty_bitmap = vmalloc(dirty_bytes); if (!memslot->dirty_bitmap) return -ENOMEM; memset(memslot->dirty_bitmap, 0, dirty_bytes); +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + memslot->dirty_bitmap_head = memslot->dirty_bitmap; +#endif return 0; } -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html