diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7fa89c39c64f..1b270fd60634 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2797,7 +2797,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2797 | struct kvm_memory_slot *memslot; | 2797 | struct kvm_memory_slot *memslot; |
2798 | unsigned long n; | 2798 | unsigned long n; |
2799 | unsigned long is_dirty = 0; | 2799 | unsigned long is_dirty = 0; |
2800 | unsigned long *dirty_bitmap = NULL; | ||
2801 | 2800 | ||
2802 | mutex_lock(&kvm->slots_lock); | 2801 | mutex_lock(&kvm->slots_lock); |
2803 | 2802 | ||
@@ -2812,27 +2811,30 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2812 | 2811 | ||
2813 | n = kvm_dirty_bitmap_bytes(memslot); | 2812 | n = kvm_dirty_bitmap_bytes(memslot); |
2814 | 2813 | ||
2815 | r = -ENOMEM; | ||
2816 | dirty_bitmap = vmalloc(n); | ||
2817 | if (!dirty_bitmap) | ||
2818 | goto out; | ||
2819 | memset(dirty_bitmap, 0, n); | ||
2820 | |||
2821 | for (i = 0; !is_dirty && i < n/sizeof(long); i++) | 2814 | for (i = 0; !is_dirty && i < n/sizeof(long); i++) |
2822 | is_dirty = memslot->dirty_bitmap[i]; | 2815 | is_dirty = memslot->dirty_bitmap[i]; |
2823 | 2816 | ||
2824 | /* If nothing is dirty, don't bother messing with page tables. */ | 2817 | /* If nothing is dirty, don't bother messing with page tables. */ |
2825 | if (is_dirty) { | 2818 | if (is_dirty) { |
2826 | struct kvm_memslots *slots, *old_slots; | 2819 | struct kvm_memslots *slots, *old_slots; |
2820 | unsigned long *dirty_bitmap; | ||
2827 | 2821 | ||
2828 | spin_lock(&kvm->mmu_lock); | 2822 | spin_lock(&kvm->mmu_lock); |
2829 | kvm_mmu_slot_remove_write_access(kvm, log->slot); | 2823 | kvm_mmu_slot_remove_write_access(kvm, log->slot); |
2830 | spin_unlock(&kvm->mmu_lock); | 2824 | spin_unlock(&kvm->mmu_lock); |
2831 | 2825 | ||
2832 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | 2826 | r = -ENOMEM; |
2833 | if (!slots) | 2827 | dirty_bitmap = vmalloc(n); |
2834 | goto out_free; | 2828 | if (!dirty_bitmap) |
2829 | goto out; | ||
2830 | memset(dirty_bitmap, 0, n); | ||
2835 | 2831 | ||
2832 | r = -ENOMEM; | ||
2833 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | ||
2834 | if (!slots) { | ||
2835 | vfree(dirty_bitmap); | ||
2836 | goto out; | ||
2837 | } | ||
2836 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); | 2838 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); |
2837 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; | 2839 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; |
2838 | 2840 | ||
@@ -2841,13 +2843,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2841 | synchronize_srcu_expedited(&kvm->srcu); | 2843 | synchronize_srcu_expedited(&kvm->srcu); |
2842 | dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; | 2844 | dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; |
2843 | kfree(old_slots); | 2845 | kfree(old_slots); |
2846 | |||
2847 | r = -EFAULT; | ||
2848 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { | ||
2849 | vfree(dirty_bitmap); | ||
2850 | goto out; | ||
2851 | } | ||
2852 | vfree(dirty_bitmap); | ||
2853 | } else { | ||
2854 | r = -EFAULT; | ||
2855 | if (clear_user(log->dirty_bitmap, n)) | ||
2856 | goto out; | ||
2844 | } | 2857 | } |
2845 | 2858 | ||
2846 | r = 0; | 2859 | r = 0; |
2847 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) | ||
2848 | r = -EFAULT; | ||
2849 | out_free: | ||
2850 | vfree(dirty_bitmap); | ||
2851 | out: | 2860 | out: |
2852 | mutex_unlock(&kvm->slots_lock); | 2861 | mutex_unlock(&kvm->slots_lock); |
2853 | return r; | 2862 | return r; |