Skip to content

Commit 55a0165

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd/selftest: Add coverage for IOMMU_HWPT_ALLOC with nested HWPTs
The IOMMU_HWPT_ALLOC ioctl now supports passing user_data to allocate a user-managed domain for nested HWPTs. Add its coverage for that. Also, update _test_cmd_hwpt_alloc() and add test_cmd/err_hwpt_alloc_nested(). Link: https://lore.kernel.org/r/20231026043938.63898-11-yi.l.liu@intel.com Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 65fe32f commit 55a0165

File tree

3 files changed

+140
-8
lines changed

3 files changed

+140
-8
lines changed

tools/testing/selftests/iommu/iommufd.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,121 @@ TEST_F(iommufd_ioas, ioas_destroy)
264264
}
265265
}
266266

267+
TEST_F(iommufd_ioas, alloc_hwpt_nested)
268+
{
269+
const uint32_t min_data_len =
270+
offsetofend(struct iommu_hwpt_selftest, iotlb);
271+
struct iommu_hwpt_selftest data = {
272+
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
273+
};
274+
uint32_t nested_hwpt_id[2] = {};
275+
uint32_t parent_hwpt_id = 0;
276+
uint32_t parent_hwpt_id_not_work = 0;
277+
uint32_t test_hwpt_id = 0;
278+
279+
if (self->device_id) {
280+
/* Negative tests */
281+
test_err_hwpt_alloc(ENOENT, self->ioas_id, self->device_id, 0,
282+
&test_hwpt_id);
283+
test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
284+
&test_hwpt_id);
285+
286+
test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
287+
IOMMU_HWPT_ALLOC_NEST_PARENT,
288+
&parent_hwpt_id);
289+
290+
test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
291+
&parent_hwpt_id_not_work);
292+
293+
/* Negative nested tests */
294+
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
295+
parent_hwpt_id, 0,
296+
&nested_hwpt_id[0],
297+
IOMMU_HWPT_DATA_NONE, &data,
298+
sizeof(data));
299+
test_err_hwpt_alloc_nested(EOPNOTSUPP, self->device_id,
300+
parent_hwpt_id, 0,
301+
&nested_hwpt_id[0],
302+
IOMMU_HWPT_DATA_SELFTEST + 1, &data,
303+
sizeof(data));
304+
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
305+
parent_hwpt_id, 0,
306+
&nested_hwpt_id[0],
307+
IOMMU_HWPT_DATA_SELFTEST, &data,
308+
min_data_len - 1);
309+
test_err_hwpt_alloc_nested(EFAULT, self->device_id,
310+
parent_hwpt_id, 0,
311+
&nested_hwpt_id[0],
312+
IOMMU_HWPT_DATA_SELFTEST, NULL,
313+
sizeof(data));
314+
test_err_hwpt_alloc_nested(
315+
EOPNOTSUPP, self->device_id, parent_hwpt_id,
316+
IOMMU_HWPT_ALLOC_NEST_PARENT, &nested_hwpt_id[0],
317+
IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
318+
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
319+
parent_hwpt_id_not_work, 0,
320+
&nested_hwpt_id[0],
321+
IOMMU_HWPT_DATA_SELFTEST, &data,
322+
sizeof(data));
323+
324+
/* Allocate two nested hwpts sharing one common parent hwpt */
325+
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
326+
&nested_hwpt_id[0],
327+
IOMMU_HWPT_DATA_SELFTEST, &data,
328+
sizeof(data));
329+
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
330+
&nested_hwpt_id[1],
331+
IOMMU_HWPT_DATA_SELFTEST, &data,
332+
sizeof(data));
333+
334+
/* Negative test: a nested hwpt on top of a nested hwpt */
335+
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
336+
nested_hwpt_id[0], 0, &test_hwpt_id,
337+
IOMMU_HWPT_DATA_SELFTEST, &data,
338+
sizeof(data));
339+
/* Negative test: parent hwpt now cannot be freed */
340+
EXPECT_ERRNO(EBUSY,
341+
_test_ioctl_destroy(self->fd, parent_hwpt_id));
342+
343+
/* Attach device to nested_hwpt_id[0] that then will be busy */
344+
test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
345+
EXPECT_ERRNO(EBUSY,
346+
_test_ioctl_destroy(self->fd, nested_hwpt_id[0]));
347+
348+
/* Switch from nested_hwpt_id[0] to nested_hwpt_id[1] */
349+
test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[1]);
350+
EXPECT_ERRNO(EBUSY,
351+
_test_ioctl_destroy(self->fd, nested_hwpt_id[1]));
352+
test_ioctl_destroy(nested_hwpt_id[0]);
353+
354+
/* Detach from nested_hwpt_id[1] and destroy it */
355+
test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
356+
test_ioctl_destroy(nested_hwpt_id[1]);
357+
358+
/* Detach from the parent hw_pagetable and destroy it */
359+
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
360+
test_ioctl_destroy(parent_hwpt_id);
361+
test_ioctl_destroy(parent_hwpt_id_not_work);
362+
} else {
363+
test_err_hwpt_alloc(ENOENT, self->device_id, self->ioas_id, 0,
364+
&parent_hwpt_id);
365+
test_err_hwpt_alloc_nested(ENOENT, self->device_id,
366+
parent_hwpt_id, 0,
367+
&nested_hwpt_id[0],
368+
IOMMU_HWPT_DATA_SELFTEST, &data,
369+
sizeof(data));
370+
test_err_hwpt_alloc_nested(ENOENT, self->device_id,
371+
parent_hwpt_id, 0,
372+
&nested_hwpt_id[1],
373+
IOMMU_HWPT_DATA_SELFTEST, &data,
374+
sizeof(data));
375+
test_err_mock_domain_replace(ENOENT, self->stdev_id,
376+
nested_hwpt_id[0]);
377+
test_err_mock_domain_replace(ENOENT, self->stdev_id,
378+
nested_hwpt_id[1]);
379+
}
380+
}
381+
267382
TEST_F(iommufd_ioas, hwpt_attach)
268383
{
269384
/* Create a device attached directly to a hwpt */

tools/testing/selftests/iommu/iommufd_fail_nth.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,8 @@ TEST_FAIL_NTH(basic_fail_nth, device)
615615
if (_test_cmd_get_hw_info(self->fd, idev_id, &info, sizeof(info), NULL))
616616
return -1;
617617

618-
if (_test_cmd_hwpt_alloc(self->fd, idev_id, ioas_id, 0, &hwpt_id))
618+
if (_test_cmd_hwpt_alloc(self->fd, idev_id, ioas_id, 0, &hwpt_id,
619+
IOMMU_HWPT_DATA_NONE, 0, 0))
619620
return -1;
620621

621622
if (_test_cmd_mock_domain_replace(self->fd, stdev_id, ioas_id2, NULL))

tools/testing/selftests/iommu/iommufd_utils.h

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,17 @@ static int _test_cmd_mock_domain_replace(int fd, __u32 stdev_id, __u32 pt_id,
154154
pt_id, NULL))
155155

156156
static int _test_cmd_hwpt_alloc(int fd, __u32 device_id, __u32 pt_id,
157-
__u32 flags, __u32 *hwpt_id)
157+
__u32 flags, __u32 *hwpt_id, __u32 data_type,
158+
void *data, size_t data_len)
158159
{
159160
struct iommu_hwpt_alloc cmd = {
160161
.size = sizeof(cmd),
161162
.flags = flags,
162163
.dev_id = device_id,
163164
.pt_id = pt_id,
165+
.data_type = data_type,
166+
.data_len = data_len,
167+
.data_uptr = (uint64_t)data,
164168
};
165169
int ret;
166170

@@ -172,12 +176,24 @@ static int _test_cmd_hwpt_alloc(int fd, __u32 device_id, __u32 pt_id,
172176
return 0;
173177
}
174178

175-
#define test_cmd_hwpt_alloc(device_id, pt_id, flags, hwpt_id) \
176-
ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, \
177-
pt_id, flags, hwpt_id))
178-
#define test_err_hwpt_alloc(_errno, device_id, pt_id, flags, hwpt_id) \
179-
EXPECT_ERRNO(_errno, _test_cmd_hwpt_alloc(self->fd, device_id, \
180-
pt_id, flags, hwpt_id))
179+
#define test_cmd_hwpt_alloc(device_id, pt_id, flags, hwpt_id) \
180+
ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, flags, \
181+
hwpt_id, IOMMU_HWPT_DATA_NONE, NULL, \
182+
0))
183+
#define test_err_hwpt_alloc(_errno, device_id, pt_id, flags, hwpt_id) \
184+
EXPECT_ERRNO(_errno, _test_cmd_hwpt_alloc( \
185+
self->fd, device_id, pt_id, flags, \
186+
hwpt_id, IOMMU_HWPT_DATA_NONE, NULL, 0))
187+
188+
#define test_cmd_hwpt_alloc_nested(device_id, pt_id, flags, hwpt_id, \
189+
data_type, data, data_len) \
190+
ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, flags, \
191+
hwpt_id, data_type, data, data_len))
192+
#define test_err_hwpt_alloc_nested(_errno, device_id, pt_id, flags, hwpt_id, \
193+
data_type, data, data_len) \
194+
EXPECT_ERRNO(_errno, \
195+
_test_cmd_hwpt_alloc(self->fd, device_id, pt_id, flags, \
196+
hwpt_id, data_type, data, data_len))
181197

182198
static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
183199
unsigned int ioas_id)

0 commit comments

Comments
 (0)