@@ -36,7 +36,7 @@ static struct mock_bus_type iommufd_mock_bus_type = {
36
36
},
37
37
};
38
38
39
- static atomic_t mock_dev_num ;
39
+ static DEFINE_IDA ( mock_dev_ida ) ;
40
40
41
41
enum {
42
42
MOCK_DIRTY_TRACK = 1 ,
63
63
* In syzkaller mode the 64 bit IOVA is converted into an nth area and offset
64
64
* value. This has a much smaller randomization space and syzkaller can hit it.
65
65
*/
66
- static unsigned long iommufd_test_syz_conv_iova (struct io_pagetable * iopt ,
67
- u64 * iova )
66
+ static unsigned long __iommufd_test_syz_conv_iova (struct io_pagetable * iopt ,
67
+ u64 * iova )
68
68
{
69
69
struct syz_layout {
70
70
__u32 nth_area ;
@@ -88,6 +88,21 @@ static unsigned long iommufd_test_syz_conv_iova(struct io_pagetable *iopt,
88
88
return 0 ;
89
89
}
90
90
91
+ static unsigned long iommufd_test_syz_conv_iova (struct iommufd_access * access ,
92
+ u64 * iova )
93
+ {
94
+ unsigned long ret ;
95
+
96
+ mutex_lock (& access -> ioas_lock );
97
+ if (!access -> ioas ) {
98
+ mutex_unlock (& access -> ioas_lock );
99
+ return 0 ;
100
+ }
101
+ ret = __iommufd_test_syz_conv_iova (& access -> ioas -> iopt , iova );
102
+ mutex_unlock (& access -> ioas_lock );
103
+ return ret ;
104
+ }
105
+
91
106
void iommufd_test_syz_conv_iova_id (struct iommufd_ucmd * ucmd ,
92
107
unsigned int ioas_id , u64 * iova , u32 * flags )
93
108
{
@@ -100,7 +115,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
100
115
ioas = iommufd_get_ioas (ucmd -> ictx , ioas_id );
101
116
if (IS_ERR (ioas ))
102
117
return ;
103
- * iova = iommufd_test_syz_conv_iova (& ioas -> iopt , iova );
118
+ * iova = __iommufd_test_syz_conv_iova (& ioas -> iopt , iova );
104
119
iommufd_put_object (ucmd -> ictx , & ioas -> obj );
105
120
}
106
121
@@ -123,6 +138,7 @@ enum selftest_obj_type {
123
138
struct mock_dev {
124
139
struct device dev ;
125
140
unsigned long flags ;
141
+ int id ;
126
142
};
127
143
128
144
struct selftest_obj {
@@ -430,20 +446,27 @@ static size_t mock_domain_unmap_pages(struct iommu_domain *domain,
430
446
431
447
/*
432
448
* iommufd generates unmaps that must be a strict
433
- * superset of the map's performend So every starting
434
- * IOVA should have been an iova passed to map, and the
449
+ * superset of the map's performend So every
450
+ * starting/ending IOVA should have been an iova passed
451
+ * to map.
435
452
*
436
- * First IOVA must be present and have been a first IOVA
437
- * passed to map_pages
453
+ * This simple logic doesn't work when the HUGE_PAGE is
454
+ * turned on since the core code will automatically
455
+ * switch between the two page sizes creating a break in
456
+ * the unmap calls. The break can land in the middle of
457
+ * contiguous IOVA.
438
458
*/
439
- if (first ) {
440
- WARN_ON (ent && !(xa_to_value (ent ) &
441
- MOCK_PFN_START_IOVA ));
442
- first = false;
459
+ if (!(domain -> pgsize_bitmap & MOCK_HUGE_PAGE_SIZE )) {
460
+ if (first ) {
461
+ WARN_ON (ent && !(xa_to_value (ent ) &
462
+ MOCK_PFN_START_IOVA ));
463
+ first = false;
464
+ }
465
+ if (pgcount == 1 &&
466
+ cur + MOCK_IO_PAGE_SIZE == pgsize )
467
+ WARN_ON (ent && !(xa_to_value (ent ) &
468
+ MOCK_PFN_LAST_IOVA ));
443
469
}
444
- if (pgcount == 1 && cur + MOCK_IO_PAGE_SIZE == pgsize )
445
- WARN_ON (ent && !(xa_to_value (ent ) &
446
- MOCK_PFN_LAST_IOVA ));
447
470
448
471
iova += MOCK_IO_PAGE_SIZE ;
449
472
ret += MOCK_IO_PAGE_SIZE ;
@@ -631,7 +654,7 @@ static void mock_dev_release(struct device *dev)
631
654
{
632
655
struct mock_dev * mdev = container_of (dev , struct mock_dev , dev );
633
656
634
- atomic_dec ( & mock_dev_num );
657
+ ida_free ( & mock_dev_ida , mdev -> id );
635
658
kfree (mdev );
636
659
}
637
660
@@ -653,8 +676,12 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
653
676
mdev -> dev .release = mock_dev_release ;
654
677
mdev -> dev .bus = & iommufd_mock_bus_type .bus ;
655
678
656
- rc = dev_set_name (& mdev -> dev , "iommufd_mock%u" ,
657
- atomic_inc_return (& mock_dev_num ));
679
+ rc = ida_alloc (& mock_dev_ida , GFP_KERNEL );
680
+ if (rc < 0 )
681
+ goto err_put ;
682
+ mdev -> id = rc ;
683
+
684
+ rc = dev_set_name (& mdev -> dev , "iommufd_mock%u" , mdev -> id );
658
685
if (rc )
659
686
goto err_put ;
660
687
@@ -1156,7 +1183,7 @@ static int iommufd_test_access_pages(struct iommufd_ucmd *ucmd,
1156
1183
}
1157
1184
1158
1185
if (flags & MOCK_FLAGS_ACCESS_SYZ )
1159
- iova = iommufd_test_syz_conv_iova (& staccess -> access -> ioas -> iopt ,
1186
+ iova = iommufd_test_syz_conv_iova (staccess -> access ,
1160
1187
& cmd -> access_pages .iova );
1161
1188
1162
1189
npages = (ALIGN (iova + length , PAGE_SIZE ) -
@@ -1258,8 +1285,8 @@ static int iommufd_test_access_rw(struct iommufd_ucmd *ucmd,
1258
1285
}
1259
1286
1260
1287
if (flags & MOCK_FLAGS_ACCESS_SYZ )
1261
- iova = iommufd_test_syz_conv_iova (& staccess -> access -> ioas -> iopt ,
1262
- & cmd -> access_rw .iova );
1288
+ iova = iommufd_test_syz_conv_iova (staccess -> access ,
1289
+ & cmd -> access_rw .iova );
1263
1290
1264
1291
rc = iommufd_access_rw (staccess -> access , iova , tmp , length , flags );
1265
1292
if (rc )
0 commit comments