Commit 5809e8f8 authored by Rodrigo Vivi's avatar Rodrigo Vivi

Merge tag 'gvt-fixes-2020-04-14' of https://github.com/intel/gvt-linux into drm-intel-fixes

gvt-fixes-2020-04-14

- Fix guest page access by using VFIO dma r/w interface (Yan)
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200414083626.GQ11247@zhen-hp.sh.intel.com
parents bcad588d ec7301d5
...@@ -131,6 +131,7 @@ struct kvmgt_vdev { ...@@ -131,6 +131,7 @@ struct kvmgt_vdev {
struct work_struct release_work; struct work_struct release_work;
atomic_t released; atomic_t released;
struct vfio_device *vfio_device; struct vfio_device *vfio_device;
struct vfio_group *vfio_group;
}; };
static inline struct kvmgt_vdev *kvmgt_vdev(struct intel_vgpu *vgpu) static inline struct kvmgt_vdev *kvmgt_vdev(struct intel_vgpu *vgpu)
...@@ -151,6 +152,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, ...@@ -151,6 +152,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size) unsigned long size)
{ {
struct drm_i915_private *i915 = vgpu->gvt->gt->i915; struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
int total_pages; int total_pages;
int npage; int npage;
int ret; int ret;
...@@ -160,7 +162,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, ...@@ -160,7 +162,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
for (npage = 0; npage < total_pages; npage++) { for (npage = 0; npage < total_pages; npage++) {
unsigned long cur_gfn = gfn + npage; unsigned long cur_gfn = gfn + npage;
ret = vfio_unpin_pages(mdev_dev(kvmgt_vdev(vgpu)->mdev), &cur_gfn, 1); ret = vfio_group_unpin_pages(vdev->vfio_group, &cur_gfn, 1);
drm_WARN_ON(&i915->drm, ret != 1); drm_WARN_ON(&i915->drm, ret != 1);
} }
} }
...@@ -169,6 +171,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, ...@@ -169,6 +171,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size, struct page **page) unsigned long size, struct page **page)
{ {
struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
unsigned long base_pfn = 0; unsigned long base_pfn = 0;
int total_pages; int total_pages;
int npage; int npage;
...@@ -183,8 +186,8 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, ...@@ -183,8 +186,8 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long cur_gfn = gfn + npage; unsigned long cur_gfn = gfn + npage;
unsigned long pfn; unsigned long pfn;
ret = vfio_pin_pages(mdev_dev(kvmgt_vdev(vgpu)->mdev), &cur_gfn, 1, ret = vfio_group_pin_pages(vdev->vfio_group, &cur_gfn, 1,
IOMMU_READ | IOMMU_WRITE, &pfn); IOMMU_READ | IOMMU_WRITE, &pfn);
if (ret != 1) { if (ret != 1) {
gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n", gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n",
cur_gfn, ret); cur_gfn, ret);
...@@ -792,6 +795,7 @@ static int intel_vgpu_open(struct mdev_device *mdev) ...@@ -792,6 +795,7 @@ static int intel_vgpu_open(struct mdev_device *mdev)
struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu); struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
unsigned long events; unsigned long events;
int ret; int ret;
struct vfio_group *vfio_group;
vdev->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier; vdev->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier;
vdev->group_notifier.notifier_call = intel_vgpu_group_notifier; vdev->group_notifier.notifier_call = intel_vgpu_group_notifier;
...@@ -814,6 +818,14 @@ static int intel_vgpu_open(struct mdev_device *mdev) ...@@ -814,6 +818,14 @@ static int intel_vgpu_open(struct mdev_device *mdev)
goto undo_iommu; goto undo_iommu;
} }
vfio_group = vfio_group_get_external_user_from_dev(mdev_dev(mdev));
if (IS_ERR_OR_NULL(vfio_group)) {
ret = !vfio_group ? -EFAULT : PTR_ERR(vfio_group);
gvt_vgpu_err("vfio_group_get_external_user_from_dev failed\n");
goto undo_register;
}
vdev->vfio_group = vfio_group;
/* Take a module reference as mdev core doesn't take /* Take a module reference as mdev core doesn't take
* a reference for vendor driver. * a reference for vendor driver.
*/ */
...@@ -830,6 +842,10 @@ static int intel_vgpu_open(struct mdev_device *mdev) ...@@ -830,6 +842,10 @@ static int intel_vgpu_open(struct mdev_device *mdev)
return ret; return ret;
undo_group: undo_group:
vfio_group_put_external_user(vdev->vfio_group);
vdev->vfio_group = NULL;
undo_register:
vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
&vdev->group_notifier); &vdev->group_notifier);
...@@ -884,6 +900,7 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu) ...@@ -884,6 +900,7 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
kvmgt_guest_exit(info); kvmgt_guest_exit(info);
intel_vgpu_release_msi_eventfd_ctx(vgpu); intel_vgpu_release_msi_eventfd_ctx(vgpu);
vfio_group_put_external_user(vdev->vfio_group);
vdev->kvm = NULL; vdev->kvm = NULL;
vgpu->handle = 0; vgpu->handle = 0;
...@@ -2035,33 +2052,14 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa, ...@@ -2035,33 +2052,14 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
void *buf, unsigned long len, bool write) void *buf, unsigned long len, bool write)
{ {
struct kvmgt_guest_info *info; struct kvmgt_guest_info *info;
struct kvm *kvm;
int idx, ret;
bool kthread = current->mm == NULL;
if (!handle_valid(handle)) if (!handle_valid(handle))
return -ESRCH; return -ESRCH;
info = (struct kvmgt_guest_info *)handle; info = (struct kvmgt_guest_info *)handle;
kvm = info->kvm;
if (kthread) {
if (!mmget_not_zero(kvm->mm))
return -EFAULT;
use_mm(kvm->mm);
}
idx = srcu_read_lock(&kvm->srcu);
ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
kvm_read_guest(kvm, gpa, buf, len);
srcu_read_unlock(&kvm->srcu, idx);
if (kthread) {
unuse_mm(kvm->mm);
mmput(kvm->mm);
}
return ret; return vfio_dma_rw(kvmgt_vdev(info->vgpu)->vfio_group,
gpa, buf, len, write);
} }
static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa, static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment