Skip to content

Commit cade075

Browse files
Kirti Wankhedeawilliam
authored andcommitted
vfio iommu: Cache pgsize_bitmap in struct vfio_iommu
Calculate and cache pgsize_bitmap when iommu->domain_list is updated and iommu->external_domain is set for mdev device. Add iommu->lock protection when cached pgsize_bitmap is accessed. Signed-off-by: Kirti Wankhede <[email protected]> Reviewed-by: Neo Jia <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Reviewed-by: Yan Zhao <[email protected]> Signed-off-by: Alex Williamson <[email protected]>
1 parent 6581708 commit cade075

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed

drivers/vfio/vfio_iommu_type1.c

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct vfio_iommu {
6969
struct rb_root dma_list;
7070
struct blocking_notifier_head notifier;
7171
unsigned int dma_avail;
72+
uint64_t pgsize_bitmap;
7273
bool v2;
7374
bool nesting;
7475
};
@@ -835,15 +836,14 @@ static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
835836
iommu->dma_avail++;
836837
}
837838

838-
static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
839+
static void vfio_update_pgsize_bitmap(struct vfio_iommu *iommu)
839840
{
840841
struct vfio_domain *domain;
841-
unsigned long bitmap = ULONG_MAX;
842842

843-
mutex_lock(&iommu->lock);
843+
iommu->pgsize_bitmap = ULONG_MAX;
844+
844845
list_for_each_entry(domain, &iommu->domain_list, next)
845-
bitmap &= domain->domain->pgsize_bitmap;
846-
mutex_unlock(&iommu->lock);
846+
iommu->pgsize_bitmap &= domain->domain->pgsize_bitmap;
847847

848848
/*
849849
* In case the IOMMU supports page sizes smaller than PAGE_SIZE
@@ -853,12 +853,10 @@ static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
853853
* granularity while iommu driver can use the sub-PAGE_SIZE size
854854
* to map the buffer.
855855
*/
856-
if (bitmap & ~PAGE_MASK) {
857-
bitmap &= PAGE_MASK;
858-
bitmap |= PAGE_SIZE;
856+
if (iommu->pgsize_bitmap & ~PAGE_MASK) {
857+
iommu->pgsize_bitmap &= PAGE_MASK;
858+
iommu->pgsize_bitmap |= PAGE_SIZE;
859859
}
860-
861-
return bitmap;
862860
}
863861

864862
static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
@@ -869,19 +867,28 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
869867
size_t unmapped = 0;
870868
int ret = 0, retries = 0;
871869

872-
mask = ((uint64_t)1 << __ffs(vfio_pgsize_bitmap(iommu))) - 1;
870+
mutex_lock(&iommu->lock);
871+
872+
mask = ((uint64_t)1 << __ffs(iommu->pgsize_bitmap)) - 1;
873+
874+
if (unmap->iova & mask) {
875+
ret = -EINVAL;
876+
goto unlock;
877+
}
878+
879+
if (!unmap->size || unmap->size & mask) {
880+
ret = -EINVAL;
881+
goto unlock;
882+
}
873883

874-
if (unmap->iova & mask)
875-
return -EINVAL;
876-
if (!unmap->size || unmap->size & mask)
877-
return -EINVAL;
878884
if (unmap->iova + unmap->size - 1 < unmap->iova ||
879-
unmap->size > SIZE_MAX)
880-
return -EINVAL;
885+
unmap->size > SIZE_MAX) {
886+
ret = -EINVAL;
887+
goto unlock;
888+
}
881889

882890
WARN_ON(mask & PAGE_MASK);
883891
again:
884-
mutex_lock(&iommu->lock);
885892

886893
/*
887894
* vfio-iommu-type1 (v1) - User mappings were coalesced together to
@@ -960,6 +967,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
960967
blocking_notifier_call_chain(&iommu->notifier,
961968
VFIO_IOMMU_NOTIFY_DMA_UNMAP,
962969
&nb_unmap);
970+
mutex_lock(&iommu->lock);
963971
goto again;
964972
}
965973
unmapped += dma->size;
@@ -1075,24 +1083,28 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
10751083
if (map->size != size || map->vaddr != vaddr || map->iova != iova)
10761084
return -EINVAL;
10771085

1078-
mask = ((uint64_t)1 << __ffs(vfio_pgsize_bitmap(iommu))) - 1;
1079-
1080-
WARN_ON(mask & PAGE_MASK);
1081-
10821086
/* READ/WRITE from device perspective */
10831087
if (map->flags & VFIO_DMA_MAP_FLAG_WRITE)
10841088
prot |= IOMMU_WRITE;
10851089
if (map->flags & VFIO_DMA_MAP_FLAG_READ)
10861090
prot |= IOMMU_READ;
10871091

1088-
if (!prot || !size || (size | iova | vaddr) & mask)
1089-
return -EINVAL;
1092+
mutex_lock(&iommu->lock);
10901093

1091-
/* Don't allow IOVA or virtual address wrap */
1092-
if (iova + size - 1 < iova || vaddr + size - 1 < vaddr)
1093-
return -EINVAL;
1094+
mask = ((uint64_t)1 << __ffs(iommu->pgsize_bitmap)) - 1;
10941095

1095-
mutex_lock(&iommu->lock);
1096+
WARN_ON(mask & PAGE_MASK);
1097+
1098+
if (!prot || !size || (size | iova | vaddr) & mask) {
1099+
ret = -EINVAL;
1100+
goto out_unlock;
1101+
}
1102+
1103+
/* Don't allow IOVA or virtual address wrap */
1104+
if (iova + size - 1 < iova || vaddr + size - 1 < vaddr) {
1105+
ret = -EINVAL;
1106+
goto out_unlock;
1107+
}
10961108

10971109
if (vfio_find_dma(iommu, iova, size)) {
10981110
ret = -EEXIST;
@@ -1698,6 +1710,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
16981710
if (!iommu->external_domain) {
16991711
INIT_LIST_HEAD(&domain->group_list);
17001712
iommu->external_domain = domain;
1713+
vfio_update_pgsize_bitmap(iommu);
17011714
} else {
17021715
kfree(domain);
17031716
}
@@ -1823,6 +1836,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
18231836
}
18241837

18251838
list_add(&domain->next, &iommu->domain_list);
1839+
vfio_update_pgsize_bitmap(iommu);
18261840
done:
18271841
/* Delete the old one and insert new iova list */
18281842
vfio_iommu_iova_insert_copy(iommu, &iova_copy);
@@ -2034,6 +2048,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data,
20342048
list_del(&domain->next);
20352049
kfree(domain);
20362050
vfio_iommu_aper_expand(iommu, &iova_copy);
2051+
vfio_update_pgsize_bitmap(iommu);
20372052
}
20382053
break;
20392054
}
@@ -2166,8 +2181,6 @@ static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
21662181
size_t size;
21672182
int iovas = 0, i = 0, ret;
21682183

2169-
mutex_lock(&iommu->lock);
2170-
21712184
list_for_each_entry(iova, &iommu->iova_list, list)
21722185
iovas++;
21732186

@@ -2176,17 +2189,14 @@ static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
21762189
* Return 0 as a container with a single mdev device
21772190
* will have an empty list
21782191
*/
2179-
ret = 0;
2180-
goto out_unlock;
2192+
return 0;
21812193
}
21822194

21832195
size = sizeof(*cap_iovas) + (iovas * sizeof(*cap_iovas->iova_ranges));
21842196

21852197
cap_iovas = kzalloc(size, GFP_KERNEL);
2186-
if (!cap_iovas) {
2187-
ret = -ENOMEM;
2188-
goto out_unlock;
2189-
}
2198+
if (!cap_iovas)
2199+
return -ENOMEM;
21902200

21912201
cap_iovas->nr_iovas = iovas;
21922202

@@ -2199,8 +2209,6 @@ static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
21992209
ret = vfio_iommu_iova_add_cap(caps, cap_iovas, size);
22002210

22012211
kfree(cap_iovas);
2202-
out_unlock:
2203-
mutex_unlock(&iommu->lock);
22042212
return ret;
22052213
}
22062214

@@ -2245,11 +2253,13 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
22452253
info.cap_offset = 0; /* output, no-recopy necessary */
22462254
}
22472255

2256+
mutex_lock(&iommu->lock);
22482257
info.flags = VFIO_IOMMU_INFO_PGSIZES;
22492258

2250-
info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
2259+
info.iova_pgsizes = iommu->pgsize_bitmap;
22512260

22522261
ret = vfio_iommu_iova_build_caps(iommu, &caps);
2262+
mutex_unlock(&iommu->lock);
22532263
if (ret)
22542264
return ret;
22552265

0 commit comments

Comments
 (0)