Skip to content

Commit 80478a2

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd/selftest: Add coverage for the new mmap interface
Extend the loopback test to a new mmap page. Link: https://patch.msgid.link/r/b02b1220c955c3cf9ea5dd9fe9349ab1b4f8e20b.1752126748.git.nicolinc@nvidia.com Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Pranjal Shrivastava <praan@google.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 56e9a0d commit 80478a2

4 files changed

Lines changed: 59 additions & 1 deletion

File tree

drivers/iommu/iommufd/iommufd_test.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,16 @@ struct iommu_hwpt_invalidate_selftest {
232232
* (IOMMU_VIOMMU_TYPE_SELFTEST)
233233
* @in_data: Input random data from user space
234234
* @out_data: Output data (matching @in_data) to user space
235+
* @out_mmap_offset: The offset argument for mmap syscall
236+
* @out_mmap_length: The length argument for mmap syscall
235237
*
236238
* Simply set @out_data=@in_data for a loopback test
237239
*/
238240
struct iommu_viommu_selftest {
239241
__u32 in_data;
240242
__u32 out_data;
243+
__aligned_u64 out_mmap_offset;
244+
__aligned_u64 out_mmap_length;
241245
};
242246

243247
/* Should not be equal to any defined value in enum iommu_viommu_invalidate_data_type */

drivers/iommu/iommufd/selftest.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ struct mock_viommu {
152152
struct mock_iommu_domain *s2_parent;
153153
struct mock_hw_queue *hw_queue[IOMMU_TEST_HW_QUEUE_MAX];
154154
struct mutex queue_mutex;
155+
156+
unsigned long mmap_offset;
157+
u32 *page; /* Mmap page to test u32 type of in_data */
155158
};
156159

157160
static inline struct mock_viommu *to_mock_viommu(struct iommufd_viommu *viommu)
@@ -689,6 +692,10 @@ static void mock_viommu_destroy(struct iommufd_viommu *viommu)
689692

690693
if (refcount_dec_and_test(&mock_iommu->users))
691694
complete(&mock_iommu->complete);
695+
if (mock_viommu->mmap_offset)
696+
iommufd_viommu_destroy_mmap(&mock_viommu->core,
697+
mock_viommu->mmap_offset);
698+
free_page((unsigned long)mock_viommu->page);
692699
mutex_destroy(&mock_viommu->queue_mutex);
693700

694701
/* iommufd core frees mock_viommu and viommu */
@@ -887,11 +894,28 @@ static int mock_viommu_init(struct iommufd_viommu *viommu,
887894
if (rc)
888895
return rc;
889896

897+
/* Allocate two pages */
898+
mock_viommu->page =
899+
(u32 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
900+
if (!mock_viommu->page)
901+
return -ENOMEM;
902+
903+
rc = iommufd_viommu_alloc_mmap(&mock_viommu->core,
904+
__pa(mock_viommu->page),
905+
PAGE_SIZE * 2,
906+
&mock_viommu->mmap_offset);
907+
if (rc)
908+
goto err_free_page;
909+
910+
/* For loopback tests on both the page and out_data */
911+
*mock_viommu->page = data.in_data;
890912
data.out_data = data.in_data;
913+
data.out_mmap_length = PAGE_SIZE * 2;
914+
data.out_mmap_offset = mock_viommu->mmap_offset;
891915
rc = iommu_copy_struct_to_user(
892916
user_data, &data, IOMMU_VIOMMU_TYPE_SELFTEST, out_data);
893917
if (rc)
894-
return rc;
918+
goto err_destroy_mmap;
895919
}
896920

897921
refcount_inc(&mock_iommu->users);
@@ -900,6 +924,13 @@ static int mock_viommu_init(struct iommufd_viommu *viommu,
900924

901925
viommu->ops = &mock_viommu_ops;
902926
return 0;
927+
928+
err_destroy_mmap:
929+
iommufd_viommu_destroy_mmap(&mock_viommu->core,
930+
mock_viommu->mmap_offset);
931+
err_free_page:
932+
free_page((unsigned long)mock_viommu->page);
933+
return rc;
903934
}
904935

905936
static const struct iommu_ops mock_ops = {

tools/testing/selftests/iommu/iommufd.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2799,6 +2799,7 @@ TEST_F(iommufd_viommu, viommu_alloc_with_data)
27992799
struct iommu_viommu_selftest data = {
28002800
.in_data = 0xbeef,
28012801
};
2802+
uint32_t *test;
28022803

28032804
if (!self->device_id)
28042805
SKIP(return, "Skipping test for variant no_viommu");
@@ -2807,6 +2808,24 @@ TEST_F(iommufd_viommu, viommu_alloc_with_data)
28072808
IOMMU_VIOMMU_TYPE_SELFTEST, &data, sizeof(data),
28082809
&self->viommu_id);
28092810
ASSERT_EQ(data.out_data, data.in_data);
2811+
2812+
/* Negative mmap tests -- offset and length cannot be changed */
2813+
test_err_mmap(ENXIO, data.out_mmap_length,
2814+
data.out_mmap_offset + PAGE_SIZE);
2815+
test_err_mmap(ENXIO, data.out_mmap_length,
2816+
data.out_mmap_offset + PAGE_SIZE * 2);
2817+
test_err_mmap(ENXIO, data.out_mmap_length / 2, data.out_mmap_offset);
2818+
test_err_mmap(ENXIO, data.out_mmap_length * 2, data.out_mmap_offset);
2819+
2820+
/* Now do a correct mmap for a loopback test */
2821+
test = mmap(NULL, data.out_mmap_length, PROT_READ | PROT_WRITE,
2822+
MAP_SHARED, self->fd, data.out_mmap_offset);
2823+
ASSERT_NE(MAP_FAILED, test);
2824+
ASSERT_EQ(data.in_data, *test);
2825+
2826+
/* The owner of the mmap region should be blocked */
2827+
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, self->viommu_id));
2828+
munmap(test, data.out_mmap_length);
28102829
}
28112830

28122831
TEST_F(iommufd_viommu, vdevice_alloc)

tools/testing/selftests/iommu/iommufd_utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ static unsigned long PAGE_SIZE;
5656
#define offsetofend(TYPE, MEMBER) \
5757
(offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER))
5858

59+
#define test_err_mmap(_errno, length, offset) \
60+
EXPECT_ERRNO(_errno, (long)mmap(NULL, length, PROT_READ | PROT_WRITE, \
61+
MAP_SHARED, self->fd, offset))
62+
5963
static inline void *memfd_mmap(size_t length, int prot, int flags, int *mfd_p)
6064
{
6165
int mfd_flags = (flags & MAP_HUGETLB) ? MFD_HUGETLB : 0;

0 commit comments

Comments
 (0)