Loading arch/x86/kvm/x86.c +41 −8 Original line number Diff line number Diff line Loading @@ -2415,27 +2415,60 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm, int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) { int r; int n; int r, n, i; struct kvm_memory_slot *memslot; int is_dirty = 0; unsigned long is_dirty = 0; unsigned long *dirty_bitmap = NULL; down_write(&kvm->slots_lock); r = kvm_get_dirty_log(kvm, log, &is_dirty); if (r) r = -EINVAL; if (log->slot >= KVM_MEMORY_SLOTS) goto out; memslot = &kvm->memslots->memslots[log->slot]; r = -ENOENT; if (!memslot->dirty_bitmap) goto out; n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; r = -ENOMEM; dirty_bitmap = vmalloc(n); if (!dirty_bitmap) goto out; memset(dirty_bitmap, 0, n); for (i = 0; !is_dirty && i < n/sizeof(long); i++) is_dirty = memslot->dirty_bitmap[i]; /* If nothing is dirty, don't bother messing with page tables. */ if (is_dirty) { struct kvm_memslots *slots, *old_slots; spin_lock(&kvm->mmu_lock); kvm_mmu_slot_remove_write_access(kvm, log->slot); spin_unlock(&kvm->mmu_lock); memslot = &kvm->memslots->memslots[log->slot]; n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; memset(memslot->dirty_bitmap, 0, n); slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); if (!slots) goto out_free; memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; old_slots = kvm->memslots; rcu_assign_pointer(kvm->memslots, slots); synchronize_srcu_expedited(&kvm->srcu); dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; kfree(old_slots); } r = 0; if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) r = -EFAULT; out_free: vfree(dirty_bitmap); out: up_write(&kvm->slots_lock); return r; Loading Loading
arch/x86/kvm/x86.c +41 −8 Original line number Diff line number Diff line Loading @@ -2415,27 +2415,60 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm, int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) { int r; int n; int r, n, i; struct kvm_memory_slot *memslot; int is_dirty = 0; unsigned long is_dirty = 0; unsigned long *dirty_bitmap = NULL; down_write(&kvm->slots_lock); r = kvm_get_dirty_log(kvm, log, &is_dirty); if (r) r = -EINVAL; if (log->slot >= KVM_MEMORY_SLOTS) goto out; memslot = &kvm->memslots->memslots[log->slot]; r = -ENOENT; if (!memslot->dirty_bitmap) goto out; n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; r = -ENOMEM; dirty_bitmap = vmalloc(n); if (!dirty_bitmap) goto out; memset(dirty_bitmap, 0, n); for (i = 0; !is_dirty && i < n/sizeof(long); i++) is_dirty = memslot->dirty_bitmap[i]; /* If nothing is dirty, don't bother messing with page tables. */ if (is_dirty) { struct kvm_memslots *slots, *old_slots; spin_lock(&kvm->mmu_lock); kvm_mmu_slot_remove_write_access(kvm, log->slot); spin_unlock(&kvm->mmu_lock); memslot = &kvm->memslots->memslots[log->slot]; n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; memset(memslot->dirty_bitmap, 0, n); slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); if (!slots) goto out_free; memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; old_slots = kvm->memslots; rcu_assign_pointer(kvm->memslots, slots); synchronize_srcu_expedited(&kvm->srcu); dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; kfree(old_slots); } r = 0; if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) r = -EFAULT; out_free: vfree(dirty_bitmap); out: up_write(&kvm->slots_lock); return r; Loading