Skip to content

Commit d8945ec

Browse files
YongjiXiemstsirkin
authored andcommitted
vdpa: Support transferring virtual addressing during DMA mapping
This patch introduces an attribute for vDPA device to indicate whether virtual address can be used. If vDPA device driver set it, vhost-vdpa bus driver will not pin user page and transfer userspace virtual address instead of physical address during DMA mapping. And corresponding vma->vm_file and offset will be also passed as an opaque pointer. Suggested-by: Jason Wang <[email protected]> Signed-off-by: Xie Yongji <[email protected]> Acked-by: Jason Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 22af48c commit d8945ec

File tree

7 files changed

+117
-19
lines changed

7 files changed

+117
-19
lines changed

drivers/vdpa/ifcvf/ifcvf_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ static int ifcvf_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name)
515515
pdev = ifcvf_mgmt_dev->pdev;
516516
dev = &pdev->dev;
517517
adapter = vdpa_alloc_device(struct ifcvf_adapter, vdpa,
518-
dev, &ifc_vdpa_ops, name);
518+
dev, &ifc_vdpa_ops, name, false);
519519
if (IS_ERR(adapter)) {
520520
IFCVF_ERR(pdev, "Failed to allocate vDPA structure");
521521
return PTR_ERR(adapter);

drivers/vdpa/mlx5/net/mlx5_vnet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2425,7 +2425,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
24252425
max_vqs = min_t(u32, max_vqs, MLX5_MAX_SUPPORTED_VQS);
24262426

24272427
ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mlx5_vdpa_ops,
2428-
name);
2428+
name, false);
24292429
if (IS_ERR(ndev))
24302430
return PTR_ERR(ndev);
24312431

drivers/vdpa/vdpa.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static void vdpa_release_dev(struct device *d)
7171
* @config: the bus operations that is supported by this device
7272
* @size: size of the parent structure that contains private data
7373
* @name: name of the vdpa device; optional.
74+
* @use_va: indicate whether virtual address must be used by this device
7475
*
7576
* Driver should use vdpa_alloc_device() wrapper macro instead of
7677
* using this directly.
@@ -80,7 +81,8 @@ static void vdpa_release_dev(struct device *d)
8081
*/
8182
struct vdpa_device *__vdpa_alloc_device(struct device *parent,
8283
const struct vdpa_config_ops *config,
83-
size_t size, const char *name)
84+
size_t size, const char *name,
85+
bool use_va)
8486
{
8587
struct vdpa_device *vdev;
8688
int err = -EINVAL;
@@ -91,6 +93,10 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
9193
if (!!config->dma_map != !!config->dma_unmap)
9294
goto err;
9395

96+
/* It should only work for the device that use on-chip IOMMU */
97+
if (use_va && !(config->dma_map || config->set_map))
98+
goto err;
99+
94100
err = -ENOMEM;
95101
vdev = kzalloc(size, GFP_KERNEL);
96102
if (!vdev)
@@ -106,6 +112,7 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
106112
vdev->index = err;
107113
vdev->config = config;
108114
vdev->features_valid = false;
115+
vdev->use_va = use_va;
109116

110117
if (name)
111118
err = dev_set_name(&vdev->dev, "%s", name);

drivers/vdpa/vdpa_sim/vdpa_sim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
251251
ops = &vdpasim_config_ops;
252252

253253
vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops,
254-
dev_attr->name);
254+
dev_attr->name, false);
255255
if (IS_ERR(vdpasim)) {
256256
ret = PTR_ERR(vdpasim);
257257
goto err_alloc;

drivers/vdpa/virtio_pci/vp_vdpa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id)
446446
return ret;
447447

448448
vp_vdpa = vdpa_alloc_device(struct vp_vdpa, vdpa,
449-
dev, &vp_vdpa_ops, NULL);
449+
dev, &vp_vdpa_ops, NULL, false);
450450
if (IS_ERR(vp_vdpa)) {
451451
dev_err(dev, "vp_vdpa: Failed to allocate vDPA structure\n");
452452
return PTR_ERR(vp_vdpa);

drivers/vhost/vdpa.c

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,28 @@ static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, u64 start, u64 last)
526526
}
527527
}
528528

529+
static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, u64 start, u64 last)
530+
{
531+
struct vhost_dev *dev = &v->vdev;
532+
struct vhost_iotlb *iotlb = dev->iotlb;
533+
struct vhost_iotlb_map *map;
534+
struct vdpa_map_file *map_file;
535+
536+
while ((map = vhost_iotlb_itree_first(iotlb, start, last)) != NULL) {
537+
map_file = (struct vdpa_map_file *)map->opaque;
538+
fput(map_file->file);
539+
kfree(map_file);
540+
vhost_iotlb_map_free(iotlb, map);
541+
}
542+
}
543+
529544
static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, u64 start, u64 last)
530545
{
546+
struct vdpa_device *vdpa = v->vdpa;
547+
548+
if (vdpa->use_va)
549+
return vhost_vdpa_va_unmap(v, start, last);
550+
531551
return vhost_vdpa_pa_unmap(v, start, last);
532552
}
533553

@@ -562,35 +582,37 @@ static int perm_to_iommu_flags(u32 perm)
562582
return flags | IOMMU_CACHE;
563583
}
564584

565-
static int vhost_vdpa_map(struct vhost_vdpa *v,
566-
u64 iova, u64 size, u64 pa, u32 perm)
585+
static int vhost_vdpa_map(struct vhost_vdpa *v, u64 iova,
586+
u64 size, u64 pa, u32 perm, void *opaque)
567587
{
568588
struct vhost_dev *dev = &v->vdev;
569589
struct vdpa_device *vdpa = v->vdpa;
570590
const struct vdpa_config_ops *ops = vdpa->config;
571591
int r = 0;
572592

573-
r = vhost_iotlb_add_range(dev->iotlb, iova, iova + size - 1,
574-
pa, perm);
593+
r = vhost_iotlb_add_range_ctx(dev->iotlb, iova, iova + size - 1,
594+
pa, perm, opaque);
575595
if (r)
576596
return r;
577597

578598
if (ops->dma_map) {
579-
r = ops->dma_map(vdpa, iova, size, pa, perm, NULL);
599+
r = ops->dma_map(vdpa, iova, size, pa, perm, opaque);
580600
} else if (ops->set_map) {
581601
if (!v->in_batch)
582602
r = ops->set_map(vdpa, dev->iotlb);
583603
} else {
584604
r = iommu_map(v->domain, iova, pa, size,
585605
perm_to_iommu_flags(perm));
586606
}
587-
588-
if (r)
607+
if (r) {
589608
vhost_iotlb_del_range(dev->iotlb, iova, iova + size - 1);
590-
else
609+
return r;
610+
}
611+
612+
if (!vdpa->use_va)
591613
atomic64_add(PFN_DOWN(size), &dev->mm->pinned_vm);
592614

593-
return r;
615+
return 0;
594616
}
595617

596618
static void vhost_vdpa_unmap(struct vhost_vdpa *v, u64 iova, u64 size)
@@ -611,6 +633,56 @@ static void vhost_vdpa_unmap(struct vhost_vdpa *v, u64 iova, u64 size)
611633
}
612634
}
613635

636+
static int vhost_vdpa_va_map(struct vhost_vdpa *v,
637+
u64 iova, u64 size, u64 uaddr, u32 perm)
638+
{
639+
struct vhost_dev *dev = &v->vdev;
640+
u64 offset, map_size, map_iova = iova;
641+
struct vdpa_map_file *map_file;
642+
struct vm_area_struct *vma;
643+
int ret;
644+
645+
mmap_read_lock(dev->mm);
646+
647+
while (size) {
648+
vma = find_vma(dev->mm, uaddr);
649+
if (!vma) {
650+
ret = -EINVAL;
651+
break;
652+
}
653+
map_size = min(size, vma->vm_end - uaddr);
654+
if (!(vma->vm_file && (vma->vm_flags & VM_SHARED) &&
655+
!(vma->vm_flags & (VM_IO | VM_PFNMAP))))
656+
goto next;
657+
658+
map_file = kzalloc(sizeof(*map_file), GFP_KERNEL);
659+
if (!map_file) {
660+
ret = -ENOMEM;
661+
break;
662+
}
663+
offset = (vma->vm_pgoff << PAGE_SHIFT) + uaddr - vma->vm_start;
664+
map_file->offset = offset;
665+
map_file->file = get_file(vma->vm_file);
666+
ret = vhost_vdpa_map(v, map_iova, map_size, uaddr,
667+
perm, map_file);
668+
if (ret) {
669+
fput(map_file->file);
670+
kfree(map_file);
671+
break;
672+
}
673+
next:
674+
size -= map_size;
675+
uaddr += map_size;
676+
map_iova += map_size;
677+
}
678+
if (ret)
679+
vhost_vdpa_unmap(v, iova, map_iova - iova);
680+
681+
mmap_read_unlock(dev->mm);
682+
683+
return ret;
684+
}
685+
614686
static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
615687
u64 iova, u64 size, u64 uaddr, u32 perm)
616688
{
@@ -677,7 +749,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
677749
csize = PFN_PHYS(last_pfn - map_pfn + 1);
678750
ret = vhost_vdpa_map(v, iova, csize,
679751
PFN_PHYS(map_pfn),
680-
perm);
752+
perm, NULL);
681753
if (ret) {
682754
/*
683755
* Unpin the pages that are left unmapped
@@ -706,7 +778,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
706778

707779
/* Pin the rest chunk */
708780
ret = vhost_vdpa_map(v, iova, PFN_PHYS(last_pfn - map_pfn + 1),
709-
PFN_PHYS(map_pfn), perm);
781+
PFN_PHYS(map_pfn), perm, NULL);
710782
out:
711783
if (ret) {
712784
if (nchunks) {
@@ -739,6 +811,7 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
739811
struct vhost_iotlb_msg *msg)
740812
{
741813
struct vhost_dev *dev = &v->vdev;
814+
struct vdpa_device *vdpa = v->vdpa;
742815
struct vhost_iotlb *iotlb = dev->iotlb;
743816

744817
if (msg->iova < v->range.first || !msg->size ||
@@ -750,6 +823,10 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
750823
msg->iova + msg->size - 1))
751824
return -EEXIST;
752825

826+
if (vdpa->use_va)
827+
return vhost_vdpa_va_map(v, msg->iova, msg->size,
828+
msg->uaddr, msg->perm);
829+
753830
return vhost_vdpa_pa_map(v, msg->iova, msg->size, msg->uaddr,
754831
msg->perm);
755832
}

include/linux/vdpa.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct vdpa_mgmt_dev;
6565
* @config: the configuration ops for this device.
6666
* @index: device index
6767
* @features_valid: were features initialized? for legacy guests
68+
* @use_va: indicate whether virtual address must be used by this device
6869
* @nvqs: maximum number of supported virtqueues
6970
* @mdev: management device pointer; caller must setup when registering device as part
7071
* of dev_add() mgmtdev ops callback before invoking _vdpa_register_device().
@@ -75,6 +76,7 @@ struct vdpa_device {
7576
const struct vdpa_config_ops *config;
7677
unsigned int index;
7778
bool features_valid;
79+
bool use_va;
7880
int nvqs;
7981
struct vdpa_mgmt_dev *mdev;
8082
};
@@ -89,6 +91,16 @@ struct vdpa_iova_range {
8991
u64 last;
9092
};
9193

94+
/**
95+
* Corresponding file area for device memory mapping
96+
* @file: vma->vm_file for the mapping
97+
* @offset: mapping offset in the vm_file
98+
*/
99+
struct vdpa_map_file {
100+
struct file *file;
101+
u64 offset;
102+
};
103+
92104
/**
93105
* struct vdpa_config_ops - operations for configuring a vDPA device.
94106
* Note: vDPA device drivers are required to implement all of the
@@ -279,7 +291,8 @@ struct vdpa_config_ops {
279291

280292
struct vdpa_device *__vdpa_alloc_device(struct device *parent,
281293
const struct vdpa_config_ops *config,
282-
size_t size, const char *name);
294+
size_t size, const char *name,
295+
bool use_va);
283296

284297
/**
285298
* vdpa_alloc_device - allocate and initilaize a vDPA device
@@ -289,15 +302,16 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
289302
* @parent: the parent device
290303
* @config: the bus operations that is supported by this device
291304
* @name: name of the vdpa device
305+
* @use_va: indicate whether virtual address must be used by this device
292306
*
293307
* Return allocated data structure or ERR_PTR upon error
294308
*/
295-
#define vdpa_alloc_device(dev_struct, member, parent, config, name) \
309+
#define vdpa_alloc_device(dev_struct, member, parent, config, name, use_va) \
296310
container_of(__vdpa_alloc_device( \
297311
parent, config, \
298312
sizeof(dev_struct) + \
299313
BUILD_BUG_ON_ZERO(offsetof( \
300-
dev_struct, member)), name), \
314+
dev_struct, member)), name, use_va), \
301315
dev_struct, member)
302316

303317
int vdpa_register_device(struct vdpa_device *vdev, int nvqs);

0 commit comments

Comments
 (0)