OSDN Git Service

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[tomoyo/tomoyo-test1.git] / drivers / gpu / drm / i915 / gvt / kvmgt.c
index 9cd9e9d..42ce20e 100644 (file)
@@ -106,12 +106,10 @@ struct gvt_dma {
 #define vfio_dev_to_vgpu(vfio_dev) \
        container_of((vfio_dev), struct intel_vgpu, vfio_device)
 
-static void kvmgt_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-               const u8 *val, int len,
-               struct kvm_page_track_notifier_node *node);
-static void kvmgt_page_track_flush_slot(struct kvm *kvm,
-               struct kvm_memory_slot *slot,
-               struct kvm_page_track_notifier_node *node);
+static void kvmgt_page_track_write(gpa_t gpa, const u8 *val, int len,
+                                  struct kvm_page_track_notifier_node *node);
+static void kvmgt_page_track_remove_region(gfn_t gfn, unsigned long nr_pages,
+                                          struct kvm_page_track_notifier_node *node);
 
 static ssize_t intel_vgpu_show_description(struct mdev_type *mtype, char *buf)
 {
@@ -161,8 +159,7 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
 
                if (npage == 0)
                        base_page = cur_page;
-               else if (base_page + npage != cur_page) {
-                       gvt_vgpu_err("The pages are not continuous\n");
+               else if (page_to_pfn(base_page) + npage != page_to_pfn(cur_page)) {
                        ret = -EINVAL;
                        npage++;
                        goto err;
@@ -172,7 +169,8 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
        *page = base_page;
        return 0;
 err:
-       gvt_unpin_guest_page(vgpu, gfn, npage * PAGE_SIZE);
+       if (npage)
+               gvt_unpin_guest_page(vgpu, gfn, npage * PAGE_SIZE);
        return ret;
 }
 
@@ -352,6 +350,8 @@ __kvmgt_protect_table_find(struct intel_vgpu *info, gfn_t gfn)
 {
        struct kvmgt_pgfn *p, *res = NULL;
 
+       lockdep_assert_held(&info->vgpu_lock);
+
        hash_for_each_possible(info->ptable, p, hnode, gfn) {
                if (gfn == p->gfn) {
                        res = p;
@@ -654,21 +654,19 @@ out:
 static int intel_vgpu_open_device(struct vfio_device *vfio_dev)
 {
        struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
-
-       if (!vgpu->vfio_device.kvm ||
-           vgpu->vfio_device.kvm->mm != current->mm) {
-               gvt_vgpu_err("KVM is required to use Intel vGPU\n");
-               return -ESRCH;
-       }
+       int ret;
 
        if (__kvmgt_vgpu_exist(vgpu))
                return -EEXIST;
 
        vgpu->track_node.track_write = kvmgt_page_track_write;
-       vgpu->track_node.track_flush_slot = kvmgt_page_track_flush_slot;
-       kvm_get_kvm(vgpu->vfio_device.kvm);
-       kvm_page_track_register_notifier(vgpu->vfio_device.kvm,
-                                        &vgpu->track_node);
+       vgpu->track_node.track_remove_region = kvmgt_page_track_remove_region;
+       ret = kvm_page_track_register_notifier(vgpu->vfio_device.kvm,
+                                              &vgpu->track_node);
+       if (ret) {
+               gvt_vgpu_err("KVM is required to use Intel vGPU\n");
+               return ret;
+       }
 
        set_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status);
 
@@ -703,7 +701,6 @@ static void intel_vgpu_close_device(struct vfio_device *vfio_dev)
 
        kvm_page_track_unregister_notifier(vgpu->vfio_device.kvm,
                                           &vgpu->track_node);
-       kvm_put_kvm(vgpu->vfio_device.kvm);
 
        kvmgt_protect_table_destroy(vgpu);
        gvt_cache_destroy(vgpu);
@@ -1547,95 +1544,70 @@ static struct mdev_driver intel_vgpu_mdev_driver = {
 
 int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn)
 {
-       struct kvm *kvm = info->vfio_device.kvm;
-       struct kvm_memory_slot *slot;
-       int idx;
+       int r;
 
        if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, info->status))
                return -ESRCH;
 
-       idx = srcu_read_lock(&kvm->srcu);
-       slot = gfn_to_memslot(kvm, gfn);
-       if (!slot) {
-               srcu_read_unlock(&kvm->srcu, idx);
-               return -EINVAL;
-       }
-
-       write_lock(&kvm->mmu_lock);
-
        if (kvmgt_gfn_is_write_protected(info, gfn))
-               goto out;
+               return 0;
 
-       kvm_slot_page_track_add_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
-       kvmgt_protect_table_add(info, gfn);
+       r = kvm_write_track_add_gfn(info->vfio_device.kvm, gfn);
+       if (r)
+               return r;
 
-out:
-       write_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
+       kvmgt_protect_table_add(info, gfn);
        return 0;
 }
 
 int intel_gvt_page_track_remove(struct intel_vgpu *info, u64 gfn)
 {
-       struct kvm *kvm = info->vfio_device.kvm;
-       struct kvm_memory_slot *slot;
-       int idx;
+       int r;
 
        if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, info->status))
                return -ESRCH;
 
-       idx = srcu_read_lock(&kvm->srcu);
-       slot = gfn_to_memslot(kvm, gfn);
-       if (!slot) {
-               srcu_read_unlock(&kvm->srcu, idx);
-               return -EINVAL;
-       }
-
-       write_lock(&kvm->mmu_lock);
-
        if (!kvmgt_gfn_is_write_protected(info, gfn))
-               goto out;
+               return 0;
 
-       kvm_slot_page_track_remove_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
-       kvmgt_protect_table_del(info, gfn);
+       r = kvm_write_track_remove_gfn(info->vfio_device.kvm, gfn);
+       if (r)
+               return r;
 
-out:
-       write_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
+       kvmgt_protect_table_del(info, gfn);
        return 0;
 }
 
-static void kvmgt_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-               const u8 *val, int len,
-               struct kvm_page_track_notifier_node *node)
+static void kvmgt_page_track_write(gpa_t gpa, const u8 *val, int len,
+                                  struct kvm_page_track_notifier_node *node)
 {
        struct intel_vgpu *info =
                container_of(node, struct intel_vgpu, track_node);
 
-       if (kvmgt_gfn_is_write_protected(info, gpa_to_gfn(gpa)))
+       mutex_lock(&info->vgpu_lock);
+
+       if (kvmgt_gfn_is_write_protected(info, gpa >> PAGE_SHIFT))
                intel_vgpu_page_track_handler(info, gpa,
                                                     (void *)val, len);
+
+       mutex_unlock(&info->vgpu_lock);
 }
 
-static void kvmgt_page_track_flush_slot(struct kvm *kvm,
-               struct kvm_memory_slot *slot,
-               struct kvm_page_track_notifier_node *node)
+static void kvmgt_page_track_remove_region(gfn_t gfn, unsigned long nr_pages,
+                                          struct kvm_page_track_notifier_node *node)
 {
-       int i;
-       gfn_t gfn;
+       unsigned long i;
        struct intel_vgpu *info =
                container_of(node, struct intel_vgpu, track_node);
 
-       write_lock(&kvm->mmu_lock);
-       for (i = 0; i < slot->npages; i++) {
-               gfn = slot->base_gfn + i;
-               if (kvmgt_gfn_is_write_protected(info, gfn)) {
-                       kvm_slot_page_track_remove_page(kvm, slot, gfn,
-                                               KVM_PAGE_TRACK_WRITE);
-                       kvmgt_protect_table_del(info, gfn);
-               }
+       mutex_lock(&info->vgpu_lock);
+
+       for (i = 0; i < nr_pages; i++) {
+               if (kvmgt_gfn_is_write_protected(info, gfn + i))
+                       kvmgt_protect_table_del(info, gfn + i);
        }
-       write_unlock(&kvm->mmu_lock);
+
+       mutex_unlock(&info->vgpu_lock);
 }
 
 void intel_vgpu_detach_regions(struct intel_vgpu *vgpu)