Signed-off-by: Antonios Motakis <a.mota...@virtualopensystems.com> --- drivers/vfio/vfio_platform.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/drivers/vfio/vfio_platform.c b/drivers/vfio/vfio_platform.c index a0abcfa..6364316 100644 --- a/drivers/vfio/vfio_platform.c +++ b/drivers/vfio/vfio_platform.c @@ -103,6 +103,10 @@ static long vfio_platform_ioctl(void *device_data, info.offset = res.start; /* map phys addr with offset */ info.size = resource_size(&res); info.flags = 0; + /* Only regions addressed with PAGE granularity can be MMAPed + * securely. */ + if (!(info.offset & ~PAGE_MASK) && !(info.size & ~PAGE_MASK)) + info.flags |= VFIO_REGION_INFO_FLAG_MMAP; return copy_to_user((void __user *)arg, &info, minsz); @@ -134,6 +138,18 @@ static long vfio_platform_ioctl(void *device_data, return -ENOTTY; } +static bool is_in_resource(struct resource res, u64 addr, u64 size) +{ + if (addr < res.start) + return false; + if (addr > res.end) + return false; + if (addr + size - 1 > res.end) + return false; + + return true; +} + static ssize_t vfio_platform_read(void *device_data, char __user *buf, size_t count, loff_t *ppos) { @@ -148,6 +164,34 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf, static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma) { + struct vfio_platform_device *vdev = device_data; + struct device_node *of_node = vdev->pdev->dev.of_node; + u64 req_len = vma->vm_end - vma->vm_start; + u64 addr = vma->vm_pgoff << PAGE_SHIFT; + struct resource res; + int i; + + if (vma->vm_end < vma->vm_start) + return -EINVAL; + if (vma->vm_start & ~PAGE_MASK) + return -EINVAL; + if (vma->vm_end & ~PAGE_MASK) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + + for (i = 0; !of_address_to_resource(of_node, i, &res); i++) { + if (!is_in_resource(res, addr, req_len)) + continue; + + vma->vm_private_data = vdev; + vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + return remap_pfn_range(vma, vma->vm_start, addr, + req_len, vma->vm_page_prot); + } + return -EINVAL; } -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html