@@ -71,6 +71,8 @@ struct vdpasim {
71
71
u32 status ;
72
72
u32 generation ;
73
73
u64 features ;
74
+ /* spinlock to synchronize iommu table */
75
+ spinlock_t iommu_lock ;
74
76
};
75
77
76
78
/* TODO: cross-endian support */
@@ -136,7 +138,9 @@ static void vdpasim_reset(struct vdpasim *vdpasim)
136
138
for (i = 0 ; i < VDPASIM_VQ_NUM ; i ++ )
137
139
vdpasim_vq_reset (& vdpasim -> vqs [i ]);
138
140
141
+ spin_lock (& vdpasim -> iommu_lock );
139
142
vhost_iotlb_reset (vdpasim -> iommu );
143
+ spin_unlock (& vdpasim -> iommu_lock );
140
144
141
145
vdpasim -> features = 0 ;
142
146
vdpasim -> status = 0 ;
@@ -254,8 +258,10 @@ static dma_addr_t vdpasim_map_page(struct device *dev, struct page *page,
254
258
/* For simplicity, use identical mapping to avoid e.g iova
255
259
* allocator.
256
260
*/
261
+ spin_lock (& vdpasim -> iommu_lock );
257
262
ret = vhost_iotlb_add_range (iommu , pa , pa + size - 1 ,
258
263
pa , dir_to_perm (dir ));
264
+ spin_unlock (& vdpasim -> iommu_lock );
259
265
if (ret )
260
266
return DMA_MAPPING_ERROR ;
261
267
@@ -269,8 +275,10 @@ static void vdpasim_unmap_page(struct device *dev, dma_addr_t dma_addr,
269
275
struct vdpasim * vdpasim = dev_to_sim (dev );
270
276
struct vhost_iotlb * iommu = vdpasim -> iommu ;
271
277
278
+ spin_lock (& vdpasim -> iommu_lock );
272
279
vhost_iotlb_del_range (iommu , (u64 )dma_addr ,
273
280
(u64 )dma_addr + size - 1 );
281
+ spin_unlock (& vdpasim -> iommu_lock );
274
282
}
275
283
276
284
static void * vdpasim_alloc_coherent (struct device * dev , size_t size ,
@@ -282,9 +290,10 @@ static void *vdpasim_alloc_coherent(struct device *dev, size_t size,
282
290
void * addr = kmalloc (size , flag );
283
291
int ret ;
284
292
285
- if (!addr )
293
+ spin_lock (& vdpasim -> iommu_lock );
294
+ if (!addr ) {
286
295
* dma_addr = DMA_MAPPING_ERROR ;
287
- else {
296
+ } else {
288
297
u64 pa = virt_to_phys (addr );
289
298
290
299
ret = vhost_iotlb_add_range (iommu , (u64 )pa ,
@@ -297,6 +306,7 @@ static void *vdpasim_alloc_coherent(struct device *dev, size_t size,
297
306
} else
298
307
* dma_addr = (dma_addr_t )pa ;
299
308
}
309
+ spin_unlock (& vdpasim -> iommu_lock );
300
310
301
311
return addr ;
302
312
}
@@ -308,8 +318,11 @@ static void vdpasim_free_coherent(struct device *dev, size_t size,
308
318
struct vdpasim * vdpasim = dev_to_sim (dev );
309
319
struct vhost_iotlb * iommu = vdpasim -> iommu ;
310
320
321
+ spin_lock (& vdpasim -> iommu_lock );
311
322
vhost_iotlb_del_range (iommu , (u64 )dma_addr ,
312
323
(u64 )dma_addr + size - 1 );
324
+ spin_unlock (& vdpasim -> iommu_lock );
325
+
313
326
kfree (phys_to_virt ((uintptr_t )dma_addr ));
314
327
}
315
328
@@ -555,6 +568,7 @@ static int vdpasim_set_map(struct vdpa_device *vdpa,
555
568
u64 start = 0ULL , last = 0ULL - 1 ;
556
569
int ret ;
557
570
571
+ spin_lock (& vdpasim -> iommu_lock );
558
572
vhost_iotlb_reset (vdpasim -> iommu );
559
573
560
574
for (map = vhost_iotlb_itree_first (iotlb , start , last ); map ;
@@ -564,27 +578,36 @@ static int vdpasim_set_map(struct vdpa_device *vdpa,
564
578
if (ret )
565
579
goto err ;
566
580
}
581
+ spin_unlock (& vdpasim -> iommu_lock );
567
582
return 0 ;
568
583
569
584
err :
570
585
vhost_iotlb_reset (vdpasim -> iommu );
586
+ spin_unlock (& vdpasim -> iommu_lock );
571
587
return ret ;
572
588
}
573
589
574
590
static int vdpasim_dma_map (struct vdpa_device * vdpa , u64 iova , u64 size ,
575
591
u64 pa , u32 perm )
576
592
{
577
593
struct vdpasim * vdpasim = vdpa_to_sim (vdpa );
594
+ int ret ;
578
595
579
- return vhost_iotlb_add_range (vdpasim -> iommu , iova ,
580
- iova + size - 1 , pa , perm );
596
+ spin_lock (& vdpasim -> iommu_lock );
597
+ ret = vhost_iotlb_add_range (vdpasim -> iommu , iova , iova + size - 1 , pa ,
598
+ perm );
599
+ spin_unlock (& vdpasim -> iommu_lock );
600
+
601
+ return ret ;
581
602
}
582
603
583
604
static int vdpasim_dma_unmap (struct vdpa_device * vdpa , u64 iova , u64 size )
584
605
{
585
606
struct vdpasim * vdpasim = vdpa_to_sim (vdpa );
586
607
608
+ spin_lock (& vdpasim -> iommu_lock );
587
609
vhost_iotlb_del_range (vdpasim -> iommu , iova , iova + size - 1 );
610
+ spin_unlock (& vdpasim -> iommu_lock );
588
611
589
612
return 0 ;
590
613
}
0 commit comments