Merge tag 'drm-for-v4.16-part2-fixes' of git://people.freedesktop.org/~airlied/linux
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / gvt / kvmgt.c
index 554d1db1f3c8d02c2396cac49cf413067c6ccc72..909499b73d03acba1a1af1f6f5b77c7ccdd07b5c 100644 (file)
@@ -651,6 +651,39 @@ static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off,
        return ret;
 }
 
+static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off)
+{
+       return off >= vgpu_aperture_offset(vgpu) &&
+              off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu);
+}
+
+static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t off,
+               void *buf, unsigned long count, bool is_write)
+{
+       void *aperture_va;
+
+       if (!intel_vgpu_in_aperture(vgpu, off) ||
+           !intel_vgpu_in_aperture(vgpu, off + count)) {
+               gvt_vgpu_err("Invalid aperture offset %llu\n", off);
+               return -EINVAL;
+       }
+
+       aperture_va = io_mapping_map_wc(&vgpu->gvt->dev_priv->ggtt.iomap,
+                                       ALIGN_DOWN(off, PAGE_SIZE),
+                                       count + offset_in_page(off));
+       if (!aperture_va)
+               return -EIO;
+
+       if (is_write)
+               memcpy(aperture_va + offset_in_page(off), buf, count);
+       else
+               memcpy(buf, aperture_va + offset_in_page(off), count);
+
+       io_mapping_unmap(aperture_va);
+
+       return 0;
+}
+
 static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
                        size_t count, loff_t *ppos, bool is_write)
 {
@@ -679,8 +712,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
                                        buf, count, is_write);
                break;
        case VFIO_PCI_BAR2_REGION_INDEX:
-               ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos,
-                                       buf, count, is_write);
+               ret = intel_vgpu_aperture_rw(vgpu, pos, buf, count, is_write);
                break;
        case VFIO_PCI_BAR1_REGION_INDEX:
        case VFIO_PCI_BAR3_REGION_INDEX:
@@ -1575,6 +1607,21 @@ static unsigned long kvmgt_virt_to_pfn(void *addr)
        return PFN_DOWN(__pa(addr));
 }
 
+static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn)
+{
+       struct kvmgt_guest_info *info;
+       struct kvm *kvm;
+
+       if (!handle_valid(handle))
+               return false;
+
+       info = (struct kvmgt_guest_info *)handle;
+       kvm = info->kvm;
+
+       return kvm_is_visible_gfn(kvm, gfn);
+
+}
+
 struct intel_gvt_mpt kvmgt_mpt = {
        .host_init = kvmgt_host_init,
        .host_exit = kvmgt_host_exit,
@@ -1590,6 +1637,7 @@ struct intel_gvt_mpt kvmgt_mpt = {
        .set_opregion = kvmgt_set_opregion,
        .get_vfio_device = kvmgt_get_vfio_device,
        .put_vfio_device = kvmgt_put_vfio_device,
+       .is_valid_gfn = kvmgt_is_valid_gfn,
 };
 EXPORT_SYMBOL_GPL(kvmgt_mpt);