@@ -168,12 +168,14 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
168168{
169169 struct rb_node * node = iommu -> dma_list .rb_node ;
170170
171+ WARN_ON (!size );
172+
171173 while (node ) {
172174 struct vfio_dma * dma = rb_entry (node , struct vfio_dma , node );
173175
174- if (start + size <= dma -> iova )
176+ if (start + size - 1 < dma -> iova )
175177 node = node -> rb_left ;
176- else if (start >= dma -> iova + dma -> size )
178+ else if (start > dma -> iova + dma -> size - 1 )
177179 node = node -> rb_right ;
178180 else
179181 return dma ;
@@ -183,16 +185,19 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
183185}
184186
185187static struct rb_node * vfio_find_dma_first_node (struct vfio_iommu * iommu ,
186- dma_addr_t start , size_t size )
188+ dma_addr_t start ,
189+ dma_addr_t end )
187190{
188191 struct rb_node * res = NULL ;
189192 struct rb_node * node = iommu -> dma_list .rb_node ;
190193 struct vfio_dma * dma_res = NULL ;
191194
195+ WARN_ON (end < start );
196+
192197 while (node ) {
193198 struct vfio_dma * dma = rb_entry (node , struct vfio_dma , node );
194199
195- if (start < dma -> iova + dma -> size ) {
200+ if (start <= dma -> iova + dma -> size - 1 ) {
196201 res = node ;
197202 dma_res = dma ;
198203 if (start >= dma -> iova )
@@ -202,7 +207,7 @@ static struct rb_node *vfio_find_dma_first_node(struct vfio_iommu *iommu,
202207 node = node -> rb_right ;
203208 }
204209 }
205- if (res && size && dma_res -> iova >= start + size )
210+ if (res && dma_res -> iova > end )
206211 res = NULL ;
207212 return res ;
208213}
@@ -212,11 +217,13 @@ static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
212217 struct rb_node * * link = & iommu -> dma_list .rb_node , * parent = NULL ;
213218 struct vfio_dma * dma ;
214219
220+ WARN_ON (new -> size != 0 );
221+
215222 while (* link ) {
216223 parent = * link ;
217224 dma = rb_entry (parent , struct vfio_dma , node );
218225
219- if (new -> iova + new -> size <= dma -> iova )
226+ if (new -> iova <= dma -> iova )
220227 link = & (* link )-> rb_left ;
221228 else
222229 link = & (* link )-> rb_right ;
@@ -1141,12 +1148,12 @@ static size_t unmap_unpin_slow(struct vfio_domain *domain,
11411148static long vfio_unmap_unpin (struct vfio_iommu * iommu , struct vfio_dma * dma ,
11421149 bool do_accounting )
11431150{
1144- dma_addr_t iova = dma -> iova , end = dma -> iova + dma -> size ;
11451151 struct vfio_domain * domain , * d ;
11461152 LIST_HEAD (unmapped_region_list );
11471153 struct iommu_iotlb_gather iotlb_gather ;
11481154 int unmapped_region_cnt = 0 ;
11491155 long unlocked = 0 ;
1156+ size_t pos = 0 ;
11501157
11511158 if (!dma -> size )
11521159 return 0 ;
@@ -1170,13 +1177,14 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
11701177 }
11711178
11721179 iommu_iotlb_gather_init (& iotlb_gather );
1173- while (iova < end ) {
1180+ while (pos < dma -> size ) {
11741181 size_t unmapped , len ;
11751182 phys_addr_t phys , next ;
1183+ dma_addr_t iova = dma -> iova + pos ;
11761184
11771185 phys = iommu_iova_to_phys (domain -> domain , iova );
11781186 if (WARN_ON (!phys )) {
1179- iova += PAGE_SIZE ;
1187+ pos += PAGE_SIZE ;
11801188 continue ;
11811189 }
11821190
@@ -1185,7 +1193,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
11851193 * may require hardware cache flushing, try to find the
11861194 * largest contiguous physical memory chunk to unmap.
11871195 */
1188- for (len = PAGE_SIZE ; iova + len < end ; len += PAGE_SIZE ) {
1196+ for (len = PAGE_SIZE ; pos + len < dma -> size ; len += PAGE_SIZE ) {
11891197 next = iommu_iova_to_phys (domain -> domain , iova + len );
11901198 if (next != phys + len )
11911199 break ;
@@ -1206,7 +1214,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
12061214 break ;
12071215 }
12081216
1209- iova += unmapped ;
1217+ pos += unmapped ;
12101218 }
12111219
12121220 dma -> iommu_mapped = false;
@@ -1298,7 +1306,7 @@ static int update_user_bitmap(u64 __user *bitmap, struct vfio_iommu *iommu,
12981306}
12991307
13001308static int vfio_iova_dirty_bitmap (u64 __user * bitmap , struct vfio_iommu * iommu ,
1301- dma_addr_t iova , size_t size , size_t pgsize )
1309+ dma_addr_t iova , dma_addr_t iova_end , size_t pgsize )
13021310{
13031311 struct vfio_dma * dma ;
13041312 struct rb_node * n ;
@@ -1315,8 +1323,8 @@ static int vfio_iova_dirty_bitmap(u64 __user *bitmap, struct vfio_iommu *iommu,
13151323 if (dma && dma -> iova != iova )
13161324 return - EINVAL ;
13171325
1318- dma = vfio_find_dma (iommu , iova + size - 1 , 0 );
1319- if (dma && dma -> iova + dma -> size != iova + size )
1326+ dma = vfio_find_dma (iommu , iova_end , 1 );
1327+ if (dma && dma -> iova + dma -> size - 1 != iova_end )
13201328 return - EINVAL ;
13211329
13221330 for (n = rb_first (& iommu -> dma_list ); n ; n = rb_next (n )) {
@@ -1325,7 +1333,7 @@ static int vfio_iova_dirty_bitmap(u64 __user *bitmap, struct vfio_iommu *iommu,
13251333 if (dma -> iova < iova )
13261334 continue ;
13271335
1328- if (dma -> iova > iova + size - 1 )
1336+ if (dma -> iova > iova_end )
13291337 break ;
13301338
13311339 ret = update_user_bitmap (bitmap , iommu , dma , iova , pgsize );
@@ -1418,7 +1426,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
14181426 if (unmap_all ) {
14191427 if (iova || size )
14201428 goto unlock ;
1421- size = SIZE_MAX ;
1429+ iova_end = ~( dma_addr_t ) 0 ;
14221430 } else {
14231431 if (!size || size & (pgsize - 1 ))
14241432 goto unlock ;
@@ -1473,17 +1481,17 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
14731481 if (dma && dma -> iova != iova )
14741482 goto unlock ;
14751483
1476- dma = vfio_find_dma (iommu , iova_end , 0 );
1477- if (dma && dma -> iova + dma -> size != iova + size )
1484+ dma = vfio_find_dma (iommu , iova_end , 1 );
1485+ if (dma && dma -> iova + dma -> size - 1 != iova_end )
14781486 goto unlock ;
14791487 }
14801488
14811489 ret = 0 ;
1482- n = first_n = vfio_find_dma_first_node (iommu , iova , size );
1490+ n = first_n = vfio_find_dma_first_node (iommu , iova , iova_end );
14831491
14841492 while (n ) {
14851493 dma = rb_entry (n , struct vfio_dma , node );
1486- if (dma -> iova >= iova + size )
1494+ if (dma -> iova > iova_end )
14871495 break ;
14881496
14891497 if (!iommu -> v2 && iova > dma -> iova )
@@ -1813,12 +1821,12 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
18131821
18141822 for (; n ; n = rb_next (n )) {
18151823 struct vfio_dma * dma ;
1816- dma_addr_t iova ;
1824+ size_t pos = 0 ;
18171825
18181826 dma = rb_entry (n , struct vfio_dma , node );
1819- iova = dma -> iova ;
18201827
1821- while (iova < dma -> iova + dma -> size ) {
1828+ while (pos < dma -> size ) {
1829+ dma_addr_t iova = dma -> iova + pos ;
18221830 phys_addr_t phys ;
18231831 size_t size ;
18241832
@@ -1834,24 +1842,23 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
18341842 phys = iommu_iova_to_phys (d -> domain , iova );
18351843
18361844 if (WARN_ON (!phys )) {
1837- iova += PAGE_SIZE ;
1845+ pos += PAGE_SIZE ;
18381846 continue ;
18391847 }
18401848
18411849 size = PAGE_SIZE ;
18421850 p = phys + size ;
18431851 i = iova + size ;
1844- while (i < dma -> iova + dma -> size &&
1852+ while (pos + size < dma -> size &&
18451853 p == iommu_iova_to_phys (d -> domain , i )) {
18461854 size += PAGE_SIZE ;
18471855 p += PAGE_SIZE ;
18481856 i += PAGE_SIZE ;
18491857 }
18501858 } else {
18511859 unsigned long pfn ;
1852- unsigned long vaddr = dma -> vaddr +
1853- (iova - dma -> iova );
1854- size_t n = dma -> iova + dma -> size - iova ;
1860+ unsigned long vaddr = dma -> vaddr + pos ;
1861+ size_t n = dma -> size - pos ;
18551862 long npage ;
18561863
18571864 npage = vfio_pin_pages_remote (dma , vaddr ,
@@ -1882,7 +1889,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
18821889 goto unwind ;
18831890 }
18841891
1885- iova += size ;
1892+ pos += size ;
18861893 }
18871894 }
18881895
@@ -1899,29 +1906,29 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
18991906unwind :
19001907 for (; n ; n = rb_prev (n )) {
19011908 struct vfio_dma * dma = rb_entry (n , struct vfio_dma , node );
1902- dma_addr_t iova ;
1909+ size_t pos = 0 ;
19031910
19041911 if (dma -> iommu_mapped ) {
19051912 iommu_unmap (domain -> domain , dma -> iova , dma -> size );
19061913 continue ;
19071914 }
19081915
1909- iova = dma -> iova ;
1910- while ( iova < dma -> iova + dma -> size ) {
1916+ while ( pos < dma -> size ) {
1917+ dma_addr_t iova = dma -> iova + pos ;
19111918 phys_addr_t phys , p ;
19121919 size_t size ;
19131920 dma_addr_t i ;
19141921
19151922 phys = iommu_iova_to_phys (domain -> domain , iova );
19161923 if (!phys ) {
1917- iova += PAGE_SIZE ;
1924+ pos += PAGE_SIZE ;
19181925 continue ;
19191926 }
19201927
19211928 size = PAGE_SIZE ;
19221929 p = phys + size ;
19231930 i = iova + size ;
1924- while (i < dma -> iova + dma -> size &&
1931+ while (pos + size < dma -> size &&
19251932 p == iommu_iova_to_phys (domain -> domain , i )) {
19261933 size += PAGE_SIZE ;
19271934 p += PAGE_SIZE ;
@@ -3059,7 +3066,7 @@ static int vfio_iommu_type1_dirty_pages(struct vfio_iommu *iommu,
30593066
30603067 if (iommu -> dirty_page_tracking )
30613068 ret = vfio_iova_dirty_bitmap (range .bitmap .data ,
3062- iommu , iova , size ,
3069+ iommu , iova , iova_end ,
30633070 range .bitmap .pgsize );
30643071 else
30653072 ret = - EINVAL ;
0 commit comments