Commit c154660b authored by Nicolin Chen's avatar Nicolin Chen Committed by Jason Gunthorpe
Browse files

iommufd/selftest: Add IOMMU_TEST_OP_ACCESS_REPLACE_IOAS coverage

Add a new IOMMU_TEST_OP_ACCESS_REPLACE_IOAS to allow replacing the
access->ioas, corresponding to the iommufd_access_replace() helper.

Then add replace coverage as a part of user_copy test case, which
basically repeats the copy test after replacing the old ioas with a new
one.

Link: https://lore.kernel.org/r/a4897f93d41c34b972213243b8dbf4c3832842e4.1690523699.git.nicolinc@nvidia.com


Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 70c16123
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ enum {
	IOMMU_TEST_OP_ACCESS_RW,
	IOMMU_TEST_OP_SET_TEMP_MEMORY_LIMIT,
	IOMMU_TEST_OP_MOCK_DOMAIN_REPLACE,
	IOMMU_TEST_OP_ACCESS_REPLACE_IOAS,
};

enum {
@@ -91,6 +92,9 @@ struct iommu_test_cmd {
		struct {
			__u32 limit;
		} memory_limit;
		struct {
			__u32 ioas_id;
		} access_replace_ioas;
	};
	__u32 last;
};
+19 −0
Original line number Diff line number Diff line
@@ -785,6 +785,22 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
	return rc;
}

static int iommufd_test_access_replace_ioas(struct iommufd_ucmd *ucmd,
					    unsigned int access_id,
					    unsigned int ioas_id)
{
	struct selftest_access *staccess;
	int rc;

	staccess = iommufd_access_get(access_id);
	if (IS_ERR(staccess))
		return PTR_ERR(staccess);

	rc = iommufd_access_replace(staccess->access, ioas_id);
	fput(staccess->file);
	return rc;
}

/* Check that the pages in a page array match the pages in the user VA */
static int iommufd_test_check_pages(void __user *uptr, struct page **pages,
				    size_t npages)
@@ -1000,6 +1016,9 @@ int iommufd_test(struct iommufd_ucmd *ucmd)
	case IOMMU_TEST_OP_CREATE_ACCESS:
		return iommufd_test_create_access(ucmd, cmd->id,
						  cmd->create_access.flags);
	case IOMMU_TEST_OP_ACCESS_REPLACE_IOAS:
		return iommufd_test_access_replace_ioas(
			ucmd, cmd->id, cmd->access_replace_ioas.ioas_id);
	case IOMMU_TEST_OP_ACCESS_PAGES:
		return iommufd_test_access_pages(
			ucmd, cmd->id, cmd->access_pages.iova,
+27 −2
Original line number Diff line number Diff line
@@ -1283,7 +1283,13 @@ TEST_F(iommufd_mock_domain, user_copy)
		.dst_iova = MOCK_APERTURE_START,
		.length = BUFFER_SIZE,
	};
	unsigned int ioas_id;
	struct iommu_ioas_unmap unmap_cmd = {
		.size = sizeof(unmap_cmd),
		.ioas_id = self->ioas_id,
		.iova = MOCK_APERTURE_START,
		.length = BUFFER_SIZE,
	};
	unsigned int new_ioas_id, ioas_id;

	/* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
	test_ioctl_ioas_alloc(&ioas_id);
@@ -1301,11 +1307,30 @@ TEST_F(iommufd_mock_domain, user_copy)
	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
	check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);

	/* Now replace the ioas with a new one */
	test_ioctl_ioas_alloc(&new_ioas_id);
	test_ioctl_ioas_map_id(new_ioas_id, buffer, BUFFER_SIZE,
			       &copy_cmd.src_iova);
	test_cmd_access_replace_ioas(access_cmd.id, new_ioas_id);

	/* Destroy the old ioas and cleanup copied mapping */
	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_UNMAP, &unmap_cmd));
	test_ioctl_destroy(ioas_id);

	/* Then run the same test again with the new ioas */
	access_cmd.access_pages.iova = copy_cmd.src_iova;
	ASSERT_EQ(0,
		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
			&access_cmd));
	copy_cmd.src_ioas_id = new_ioas_id;
	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
	check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);

	test_cmd_destroy_access_pages(
		access_cmd.id, access_cmd.access_pages.out_access_pages_id);
	test_cmd_destroy_access(access_cmd.id);

	test_ioctl_destroy(ioas_id);
	test_ioctl_destroy(new_ioas_id);
}

TEST_F(iommufd_mock_domain, replace)
+19 −0
Original line number Diff line number Diff line
@@ -119,6 +119,25 @@ static int _test_cmd_hwpt_alloc(int fd, __u32 device_id, __u32 pt_id,
#define test_cmd_hwpt_alloc(device_id, pt_id, hwpt_id) \
	ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, hwpt_id))

static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
					 unsigned int ioas_id)
{
	struct iommu_test_cmd cmd = {
		.size = sizeof(cmd),
		.op = IOMMU_TEST_OP_ACCESS_REPLACE_IOAS,
		.id = access_id,
		.access_replace_ioas = { .ioas_id = ioas_id },
	};
	int ret;

	ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
	if (ret)
		return ret;
	return 0;
}
#define test_cmd_access_replace_ioas(access_id, ioas_id) \
	ASSERT_EQ(0, _test_cmd_access_replace_ioas(self->fd, access_id, ioas_id))

static int _test_cmd_create_access(int fd, unsigned int ioas_id,
				   __u32 *access_id, unsigned int flags)
{