@@ -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+
529544static 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
596618static 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+
614686static 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 );
710782out :
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}
0 commit comments