RE: [PATCH v5 10/13] iommufd/selftest: Add vIOMMU coverage for IOMMU_HWPT_INVALIDATE ioctl

2024-10-29 Thread Tian, Kevin
> From: Nicolin Chen 
> Sent: Saturday, October 26, 2024 7:51 AM
> 
> Add a viommu_cache test function to cover vIOMMU invalidations using the
> updated IOMMU_HWPT_INVALIDATE ioctl, which now allows passing in a
> vIOMMU
> via its hwpt_id field.
> 
> Signed-off-by: Nicolin Chen 

Reviewed-by: Kevin Tian 



[PATCH v5 10/13] iommufd/selftest: Add vIOMMU coverage for IOMMU_HWPT_INVALIDATE ioctl

2024-10-25 Thread Nicolin Chen
Add a viommu_cache test function to cover vIOMMU invalidations using the
updated IOMMU_HWPT_INVALIDATE ioctl, which now allows passing in a vIOMMU
via its hwpt_id field.

Signed-off-by: Nicolin Chen 
---
 tools/testing/selftests/iommu/iommufd_utils.h |  32 
 tools/testing/selftests/iommu/iommufd.c   | 173 ++
 2 files changed, 205 insertions(+)

diff --git a/tools/testing/selftests/iommu/iommufd_utils.h 
b/tools/testing/selftests/iommu/iommufd_utils.h
index 3ae6cb5eed7d..aa458c80ad30 100644
--- a/tools/testing/selftests/iommu/iommufd_utils.h
+++ b/tools/testing/selftests/iommu/iommufd_utils.h
@@ -289,6 +289,38 @@ static int _test_cmd_hwpt_invalidate(int fd, __u32 
hwpt_id, void *reqs,
 data_type, lreq, nreqs));   \
})
 
+static int _test_cmd_viommu_invalidate(int fd, __u32 viommu_id, void *reqs,
+  uint32_t data_type, uint32_t lreq,
+  uint32_t *nreqs)
+{
+   struct iommu_hwpt_invalidate cmd = {
+   .size = sizeof(cmd),
+   .hwpt_id = viommu_id,
+   .data_type = data_type,
+   .data_uptr = (uint64_t)reqs,
+   .entry_len = lreq,
+   .entry_num = *nreqs,
+   };
+   int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
+   *nreqs = cmd.entry_num;
+   return rc;
+}
+
+#define test_cmd_viommu_invalidate(viommu, reqs, lreq, nreqs)  
\
+   ({ \
+   ASSERT_EQ(0,   \
+ _test_cmd_viommu_invalidate(self->fd, viommu, reqs,  \
+   IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, \
+   lreq, nreqs)); \
+   })
+#define test_err_viommu_invalidate(_errno, viommu_id, reqs, data_type, lreq,   
\
+nreqs)\
+   ({ \
+   EXPECT_ERRNO(_errno, _test_cmd_viommu_invalidate(  \
+self->fd, viommu_id, reqs,\
+data_type, lreq, nreqs)); \
+   })
+
 static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
 unsigned int ioas_id)
 {
diff --git a/tools/testing/selftests/iommu/iommufd.c 
b/tools/testing/selftests/iommu/iommufd.c
index ff0181e5db48..9a7d4b9c44f6 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -2498,4 +2498,177 @@ TEST_F(iommufd_viommu, vdevice_alloc)
}
 }
 
+TEST_F(iommufd_viommu, vdevice_cache)
+{
+   struct iommu_viommu_invalidate_selftest inv_reqs[2] = {};
+   uint32_t viommu_id = self->viommu_id;
+   uint32_t dev_id = self->device_id;
+   uint32_t vdev_id = 0;
+   uint32_t num_inv;
+
+   if (dev_id) {
+   test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
+
+   test_cmd_dev_check_cache_all(dev_id,
+IOMMU_TEST_DEV_CACHE_DEFAULT);
+
+   /* Check data_type by passing zero-length array */
+   num_inv = 0;
+   test_cmd_viommu_invalidate(viommu_id, inv_reqs,
+  sizeof(*inv_reqs), &num_inv);
+   assert(!num_inv);
+
+   /* Negative test: Invalid data_type */
+   num_inv = 1;
+   test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
+  
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID,
+  sizeof(*inv_reqs), &num_inv);
+   assert(!num_inv);
+
+   /* Negative test: structure size sanity */
+   num_inv = 1;
+   test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
+  
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
+  sizeof(*inv_reqs) + 1, &num_inv);
+   assert(!num_inv);
+
+   num_inv = 1;
+   test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
+  
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
+  1, &num_inv);
+   assert(!num_inv);
+
+   /* Negative test: invalid flag is passed */
+   num_inv = 1;
+   inv_reqs[0].flags = 0x;
+   inv_reqs[0].vdev_id = 0x99;
+   test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
+  
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
+  sizeof(*inv_reqs),