diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 16 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 11 |
3 files changed, 15 insertions, 13 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a2a785472431..35f82f2c66f6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3208,18 +3208,15 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
3208 | struct kvm_memslots *slots, *old_slots; | 3208 | struct kvm_memslots *slots, *old_slots; |
3209 | unsigned long *dirty_bitmap; | 3209 | unsigned long *dirty_bitmap; |
3210 | 3210 | ||
3211 | r = -ENOMEM; | 3211 | dirty_bitmap = memslot->dirty_bitmap_head; |
3212 | dirty_bitmap = vmalloc(n); | 3212 | if (memslot->dirty_bitmap == dirty_bitmap) |
3213 | if (!dirty_bitmap) | 3213 | dirty_bitmap += n / sizeof(long); |
3214 | goto out; | ||
3215 | memset(dirty_bitmap, 0, n); | 3214 | memset(dirty_bitmap, 0, n); |
3216 | 3215 | ||
3217 | r = -ENOMEM; | 3216 | r = -ENOMEM; |
3218 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | 3217 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); |
3219 | if (!slots) { | 3218 | if (!slots) |
3220 | vfree(dirty_bitmap); | ||
3221 | goto out; | 3219 | goto out; |
3222 | } | ||
3223 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); | 3220 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); |
3224 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; | 3221 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; |
3225 | slots->generation++; | 3222 | slots->generation++; |
@@ -3235,11 +3232,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
3235 | spin_unlock(&kvm->mmu_lock); | 3232 | spin_unlock(&kvm->mmu_lock); |
3236 | 3233 | ||
3237 | r = -EFAULT; | 3234 | r = -EFAULT; |
3238 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { | 3235 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) |
3239 | vfree(dirty_bitmap); | ||
3240 | goto out; | 3236 | goto out; |
3241 | } | ||
3242 | vfree(dirty_bitmap); | ||
3243 | } else { | 3237 | } else { |
3244 | r = -EFAULT; | 3238 | r = -EFAULT; |
3245 | if (clear_user(log->dirty_bitmap, n)) | 3239 | if (clear_user(log->dirty_bitmap, n)) |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 462b982fedfb..bcf71c7730f0 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -150,6 +150,7 @@ struct kvm_memory_slot { | |||
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | unsigned long *rmap; | 151 | unsigned long *rmap; |
152 | unsigned long *dirty_bitmap; | 152 | unsigned long *dirty_bitmap; |
153 | unsigned long *dirty_bitmap_head; | ||
153 | struct { | 154 | struct { |
154 | unsigned long rmap_pde; | 155 | unsigned long rmap_pde; |
155 | int write_count; | 156 | int write_count; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0021c2862140..27649fdaa007 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -449,8 +449,9 @@ static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) | |||
449 | if (!memslot->dirty_bitmap) | 449 | if (!memslot->dirty_bitmap) |
450 | return; | 450 | return; |
451 | 451 | ||
452 | vfree(memslot->dirty_bitmap); | 452 | vfree(memslot->dirty_bitmap_head); |
453 | memslot->dirty_bitmap = NULL; | 453 | memslot->dirty_bitmap = NULL; |
454 | memslot->dirty_bitmap_head = NULL; | ||
454 | } | 455 | } |
455 | 456 | ||
456 | /* | 457 | /* |
@@ -537,15 +538,21 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) | |||
537 | return 0; | 538 | return 0; |
538 | } | 539 | } |
539 | 540 | ||
541 | /* | ||
542 | * Allocation size is twice as large as the actual dirty bitmap size. | ||
543 | * This makes it possible to do double buffering: see x86's | ||
544 | * kvm_vm_ioctl_get_dirty_log(). | ||
545 | */ | ||
540 | static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) | 546 | static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) |
541 | { | 547 | { |
542 | unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot); | 548 | unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot); |
543 | 549 | ||
544 | memslot->dirty_bitmap = vmalloc(dirty_bytes); | 550 | memslot->dirty_bitmap = vmalloc(dirty_bytes); |
545 | if (!memslot->dirty_bitmap) | 551 | if (!memslot->dirty_bitmap) |
546 | return -ENOMEM; | 552 | return -ENOMEM; |
547 | 553 | ||
548 | memset(memslot->dirty_bitmap, 0, dirty_bytes); | 554 | memset(memslot->dirty_bitmap, 0, dirty_bytes); |
555 | memslot->dirty_bitmap_head = memslot->dirty_bitmap; | ||
549 | return 0; | 556 | return 0; |
550 | } | 557 | } |
551 | 558 | ||