Skip to content

Commit 1b48dc0

Browse files
jasowangmstsirkin
authored andcommitted
vhost: vdpa: report iova range
This patch introduces a new ioctl for vhost-vdpa device that can report the iova range by the device. For device that implements get_iova_range() method, we fetch it from the vDPA device. If device doesn't implement get_iova_range() but depends on platform IOMMU, we will query via DOMAIN_ATTR_GEOMETRY, otherwise [0, ULLONG_MAX] is assumed. For safety, this patch also rules out the map request which is not in the valid range. Signed-off-by: Jason Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 3f1b623 commit 1b48dc0

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

drivers/vhost/vdpa.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct vhost_vdpa {
4747
int minor;
4848
struct eventfd_ctx *config_ctx;
4949
int in_batch;
50+
struct vdpa_iova_range range;
5051
};
5152

5253
static DEFINE_IDA(vhost_vdpa_ida);
@@ -337,6 +338,16 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
337338
return 0;
338339
}
339340

341+
static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp)
342+
{
343+
struct vhost_vdpa_iova_range range = {
344+
.first = v->range.first,
345+
.last = v->range.last,
346+
};
347+
348+
return copy_to_user(argp, &range, sizeof(range));
349+
}
350+
340351
static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
341352
void __user *argp)
342353
{
@@ -471,6 +482,9 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
471482
features = VHOST_VDPA_BACKEND_FEATURES;
472483
r = copy_to_user(featurep, &features, sizeof(features));
473484
break;
485+
case VHOST_VDPA_GET_IOVA_RANGE:
486+
r = vhost_vdpa_get_iova_range(v, argp);
487+
break;
474488
default:
475489
r = vhost_dev_ioctl(&v->vdev, cmd, argp);
476490
if (r == -ENOIOCTLCMD)
@@ -597,6 +611,10 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
597611
long pinned;
598612
int ret = 0;
599613

614+
if (msg->iova < v->range.first ||
615+
msg->iova + msg->size - 1 > v->range.last)
616+
return -EINVAL;
617+
600618
if (vhost_iotlb_itree_first(iotlb, msg->iova,
601619
msg->iova + msg->size - 1))
602620
return -EEXIST;
@@ -783,6 +801,27 @@ static void vhost_vdpa_free_domain(struct vhost_vdpa *v)
783801
v->domain = NULL;
784802
}
785803

804+
static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v)
805+
{
806+
struct vdpa_iova_range *range = &v->range;
807+
struct iommu_domain_geometry geo;
808+
struct vdpa_device *vdpa = v->vdpa;
809+
const struct vdpa_config_ops *ops = vdpa->config;
810+
811+
if (ops->get_iova_range) {
812+
*range = ops->get_iova_range(vdpa);
813+
} else if (v->domain &&
814+
!iommu_domain_get_attr(v->domain,
815+
DOMAIN_ATTR_GEOMETRY, &geo) &&
816+
geo.force_aperture) {
817+
range->first = geo.aperture_start;
818+
range->last = geo.aperture_end;
819+
} else {
820+
range->first = 0;
821+
range->last = ULLONG_MAX;
822+
}
823+
}
824+
786825
static int vhost_vdpa_open(struct inode *inode, struct file *filep)
787826
{
788827
struct vhost_vdpa *v;
@@ -823,6 +862,8 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
823862
if (r)
824863
goto err_init_iotlb;
825864

865+
vhost_vdpa_set_iova_range(v);
866+
826867
filep->private_data = v;
827868

828869
return 0;

include/uapi/linux/vhost.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,8 @@
146146

147147
/* Set event fd for config interrupt*/
148148
#define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int)
149+
150+
/* Get the valid iova range */
151+
#define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \
152+
struct vhost_vdpa_iova_range)
149153
#endif

include/uapi/linux/vhost_types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ struct vhost_vdpa_config {
138138
__u8 buf[0];
139139
};
140140

141+
/* vhost vdpa IOVA range
142+
* @first: First address that can be mapped by vhost-vDPA
143+
* @last: Last address that can be mapped by vhost-vDPA
144+
*/
145+
struct vhost_vdpa_iova_range {
146+
__u64 first;
147+
__u64 last;
148+
};
149+
141150
/* Feature bits */
142151
/* Log all write descriptors. Can be changed while device is active. */
143152
#define VHOST_F_LOG_ALL 26

0 commit comments

Comments
 (0)