aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/platform
diff options
context:
space:
mode:
authorAntonios Motakis <a.motakis@virtualopensystems.com>2015-03-16 16:08:48 -0400
committerAlex Williamson <alex.williamson@redhat.com>2015-03-16 16:08:48 -0400
commitfad4d5b1f042a659e07ceba3a6d1744b30f8ff7c (patch)
treec20de7c799dbdde0533a5715689f6e74c8094acd /drivers/vfio/platform
parent6e3f264560099869f68830cb14b3b3e71e5ac76a (diff)
vfio/platform: support MMAP of MMIO regions
Allow to memory map the MMIO regions of the device so userspace can directly access them. PIO regions are not being handled at this point. Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com> Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com> Reviewed-by: Eric Auger <eric.auger@linaro.org> Tested-by: Eric Auger <eric.auger@linaro.org> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio/platform')
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 4df66f5fb313..d7fe2c71e8bc 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -55,6 +55,16 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
55 if (!(res->flags & IORESOURCE_READONLY)) 55 if (!(res->flags & IORESOURCE_READONLY))
56 vdev->regions[i].flags |= 56 vdev->regions[i].flags |=
57 VFIO_REGION_INFO_FLAG_WRITE; 57 VFIO_REGION_INFO_FLAG_WRITE;
58
59 /*
60 * Only regions addressed with PAGE granularity may be
61 * MMAPed securely.
62 */
63 if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
64 !(vdev->regions[i].size & ~PAGE_MASK))
65 vdev->regions[i].flags |=
66 VFIO_REGION_INFO_FLAG_MMAP;
67
58 break; 68 break;
59 case IORESOURCE_IO: 69 case IORESOURCE_IO:
60 vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO; 70 vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -334,8 +344,63 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
334 return -EINVAL; 344 return -EINVAL;
335} 345}
336 346
347static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
348 struct vm_area_struct *vma)
349{
350 u64 req_len, pgoff, req_start;
351
352 req_len = vma->vm_end - vma->vm_start;
353 pgoff = vma->vm_pgoff &
354 ((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
355 req_start = pgoff << PAGE_SHIFT;
356
357 if (region.size < PAGE_SIZE || req_start + req_len > region.size)
358 return -EINVAL;
359
360 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
361 vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
362
363 return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
364 req_len, vma->vm_page_prot);
365}
366
337static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma) 367static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
338{ 368{
369 struct vfio_platform_device *vdev = device_data;
370 unsigned int index;
371
372 index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
373
374 if (vma->vm_end < vma->vm_start)
375 return -EINVAL;
376 if (!(vma->vm_flags & VM_SHARED))
377 return -EINVAL;
378 if (index >= vdev->num_regions)
379 return -EINVAL;
380 if (vma->vm_start & ~PAGE_MASK)
381 return -EINVAL;
382 if (vma->vm_end & ~PAGE_MASK)
383 return -EINVAL;
384
385 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
386 return -EINVAL;
387
388 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
389 && (vma->vm_flags & VM_READ))
390 return -EINVAL;
391
392 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
393 && (vma->vm_flags & VM_WRITE))
394 return -EINVAL;
395
396 vma->vm_private_data = vdev;
397
398 if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
399 return vfio_platform_mmap_mmio(vdev->regions[index], vma);
400
401 else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
402 return -EINVAL; /* not implemented */
403
339 return -EINVAL; 404 return -EINVAL;
340} 405}
341 406