[PATCH v3 09/19] iommufd/selftest: Test IOMMU_HWPT_SET_DIRTY

Joao Martins
2023-09-23T01:27:56Z

Change mock_domain to supporting dirty tracking and add tests to exercise
the new SET_DIRTY API in the iommufd_dirty_tracking selftest fixture.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
---
drivers/iommu/iommufd/selftest.c | 17 +++++++++++++++
tools/testing/selftests/iommu/iommufd.c | 15 +++++++++++++
tools/testing/selftests/iommu/iommufd_utils.h | 21 +++++++++++++++++++
3 files changed, 53 insertions(+)

diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 4cf5a2b859e7..507ada06d5ad 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -24,6 +24,7 @@ static struct platform_device *selftest_iommu_dev;
size_t iommufd_test_memory_limit = 65536;

enum {
+ MOCK_DIRTY_TRACK = 1,
MOCK_IO_PAGE_SIZE = PAGE_SIZE / 2,

/*
@@ -86,6 +87,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
}

struct mock_iommu_domain {
+ unsigned long flags;
struct iommu_domain domain;
struct xarray pfns;
};
@@ -156,6 +158,21 @@ static void *mock_domain_hw_info(struct device *dev, u32 *length, u32 *type)
static int mock_domain_set_dirty_tracking(struct iommu_domain *domain,
bool enable)
{
+ struct mock_iommu_domain *mock =
+ container_of(domain, struct mock_iommu_domain, domain);
+ unsigned long flags = mock->flags;
+
+ if (enable && !domain->dirty_ops)
+ return -EINVAL;
+
+ /* No change? */
+ if (!(enable ^ !!(flags & MOCK_DIRTY_TRACK)))
+ return 0;
+
+ flags = (enable ?
+ flags | MOCK_DIRTY_TRACK : flags & ~MOCK_DIRTY_TRACK);
+
+ mock->flags = flags;
return 0;
}

diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 71ad12867da6..dba173d1dd02 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -1479,6 +1479,21 @@ TEST_F(iommufd_dirty_tracking, enforce_dirty)
test_ioctl_destroy(stddev_id);
}

+TEST_F(iommufd_dirty_tracking, set_dirty)
+{
+ uint32_t stddev_id;
+ uint32_t hwpt_id;
+
+ test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
+ IOMMU_HWPT_ALLOC_ENFORCE_DIRTY, &hwpt_id);
+ test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
+ test_cmd_set_dirty(hwpt_id, true);
+ test_cmd_set_dirty(hwpt_id, false);
+
+ test_ioctl_destroy(stddev_id);
+ test_ioctl_destroy(hwpt_id);
+}
+
/* VFIO compatibility IOCTLs */

TEST_F(iommufd, simple_ioctls)
diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h
index 930edfe693c7..1626e2efbfb1 100644
--- a/tools/testing/selftests/iommu/iommufd_utils.h
+++ b/tools/testing/selftests/iommu/iommufd_utils.h
@@ -177,9 +177,30 @@ static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
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_set_dirty(int fd, __u32 hwpt_id, bool enabled)
+{
+ struct iommu_hwpt_set_dirty cmd = {
+ .size = sizeof(cmd),
+ .flags = enabled ? IOMMU_DIRTY_TRACKING_ENABLED :
+ IOMMU_DIRTY_TRACKING_DISABLED,
+ .hwpt_id = hwpt_id,
+ };
+ int ret;
+
+ ret = ioctl(fd, IOMMU_HWPT_SET_DIRTY, &cmd);
+ if (ret)
+ return -errno;
+ return 0;
+}
+
+#define test_cmd_set_dirty(hwpt_id, enabled) \
+ ASSERT_EQ(0, _test_cmd_set_dirty(self->fd, hwpt_id, enabled))
+
static int _test_cmd_create_access(int fd, unsigned int ioas_id,
__u32 *access_id, unsigned int flags)
{
--
2.17.2