1 From 10abb46294d1569826854f77bcdb5d38d8db8e79 Mon Sep 17 00:00:00 2001
2 From: Diana Craciun <diana.craciun@nxp.com>
3 Date: Thu, 26 Sep 2019 15:13:24 +0300
4 Subject: [PATCH] vfio/fsl-mc: Implement VFIO_DEVICE_GET_REGION_INFO ioctl call
6 Expose to userspace information about the memory regions.
8 Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
9 Signed-off-by: Diana Craciun <diana.craciun@nxp.com>
11 drivers/vfio/fsl-mc/vfio_fsl_mc.c | 76 ++++++++++++++++++++++++++++++-
12 drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 19 ++++++++
13 2 files changed, 94 insertions(+), 1 deletion(-)
15 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
16 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
18 #include "vfio_fsl_mc_private.h"
21 +static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
23 + struct fsl_mc_device *mc_dev = vdev->mc_dev;
24 + int count = mc_dev->obj_desc.region_count;
27 + vdev->regions = kcalloc(count, sizeof(struct vfio_fsl_mc_region),
32 + for (i = 0; i < count; i++) {
33 + struct resource *res = &mc_dev->regions[i];
35 + vdev->regions[i].addr = res->start;
36 + vdev->regions[i].size = PAGE_ALIGN((resource_size(res)));
37 + vdev->regions[i].flags = 0;
40 + vdev->num_regions = mc_dev->obj_desc.region_count;
43 +static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
45 + vdev->num_regions = 0;
46 + kfree(vdev->regions);
49 static int vfio_fsl_mc_open(void *device_data)
51 + struct vfio_fsl_mc_device *vdev = device_data;
54 if (!try_module_get(THIS_MODULE))
57 + mutex_lock(&vdev->driver_lock);
58 + if (!vdev->refcnt) {
59 + ret = vfio_fsl_mc_regions_init(vdev);
65 + mutex_unlock(&vdev->driver_lock);
69 + mutex_unlock(&vdev->driver_lock);
70 + module_put(THIS_MODULE);
74 static void vfio_fsl_mc_release(void *device_data)
76 + struct vfio_fsl_mc_device *vdev = device_data;
78 + mutex_lock(&vdev->driver_lock);
80 + if (!(--vdev->refcnt))
81 + vfio_fsl_mc_regions_cleanup(vdev);
83 + mutex_unlock(&vdev->driver_lock);
85 module_put(THIS_MODULE);
88 @@ -59,7 +113,26 @@ static long vfio_fsl_mc_ioctl(void *devi
90 case VFIO_DEVICE_GET_REGION_INFO:
93 + struct vfio_region_info info;
95 + minsz = offsetofend(struct vfio_region_info, offset);
97 + if (copy_from_user(&info, (void __user *)arg, minsz))
100 + if (info.argsz < minsz)
103 + if (info.index >= vdev->num_regions)
106 + /* map offset to the physical address */
107 + info.offset = VFIO_FSL_MC_INDEX_TO_OFFSET(info.index);
108 + info.size = vdev->regions[info.index].size;
109 + info.flags = vdev->regions[info.index].flags;
111 + return copy_to_user((void __user *)arg, &info, minsz);
114 case VFIO_DEVICE_GET_IRQ_INFO:
116 @@ -206,6 +279,7 @@ static int vfio_fsl_mc_probe(struct fsl_
117 vfio_iommu_group_put(group, dev);
120 + mutex_init(&vdev->driver_lock);
124 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
125 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
127 #ifndef VFIO_FSL_MC_PRIVATE_H
128 #define VFIO_FSL_MC_PRIVATE_H
130 +#define VFIO_FSL_MC_OFFSET_SHIFT 40
131 +#define VFIO_FSL_MC_OFFSET_MASK (((u64)(1) << VFIO_FSL_MC_OFFSET_SHIFT) - 1)
133 +#define VFIO_FSL_MC_OFFSET_TO_INDEX(off) (off >> VFIO_FSL_MC_OFFSET_SHIFT)
135 +#define VFIO_FSL_MC_INDEX_TO_OFFSET(index) \
136 + ((u64)(index) << VFIO_FSL_MC_OFFSET_SHIFT)
138 +struct vfio_fsl_mc_region {
142 + resource_size_t size;
145 struct vfio_fsl_mc_device {
146 struct fsl_mc_device *mc_dev;
149 + struct vfio_fsl_mc_region *regions;
150 + struct mutex driver_lock;
153 #endif /* VFIO_PCI_PRIVATE_H */