iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR flag
authorJoao Martins <joao.m.martins@oracle.com>
Tue, 24 Oct 2023 13:51:09 +0000 (14:51 +0100)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 24 Oct 2023 14:58:44 +0000 (11:58 -0300)
Change test_mock_dirty_bitmaps() to pass a flag where it specifies the flag
under test. The test does the same thing as the GET_DIRTY_BITMAP regular
test. Except that it tests whether the dirtied bits are fetched all the
same a second time, as opposed to observing them cleared.

Link: https://lore.kernel.org/r/20231024135109.73787-19-joao.m.martins@oracle.com
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/iommufd/selftest.c
tools/testing/selftests/iommu/iommufd.c
tools/testing/selftests/iommu/iommufd_utils.h

index 0eb01d1f9df874560a9b3e31788dbea48870b1f6..d8551c9d5b6ce67c8c460399603fe99a9bcd7b2f 100644 (file)
@@ -193,13 +193,16 @@ static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
 
                ent = xa_load(&mock->pfns, cur / MOCK_IO_PAGE_SIZE);
                if (ent && (xa_to_value(ent) & MOCK_PFN_DIRTY_IOVA)) {
-                       unsigned long val;
-
                        /* Clear dirty */
-                       val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
-                       old = xa_store(&mock->pfns, cur / MOCK_IO_PAGE_SIZE,
-                                      xa_mk_value(val), GFP_KERNEL);
-                       WARN_ON_ONCE(ent != old);
+                       if (!(flags & IOMMU_DIRTY_NO_CLEAR)) {
+                               unsigned long val;
+
+                               val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
+                               old = xa_store(&mock->pfns,
+                                              cur / MOCK_IO_PAGE_SIZE,
+                                              xa_mk_value(val), GFP_KERNEL);
+                               WARN_ON_ONCE(ent != old);
+                       }
                        iommu_dirty_bitmap_record(dirty, cur,
                                                  MOCK_IO_PAGE_SIZE);
                }
index f4f8bd17ae67019700434220e1bcb2708ab985dc..76a4351e3434c188a3bba50e8686aeb059b59141 100644 (file)
@@ -1598,13 +1598,47 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
 
        test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
                                MOCK_APERTURE_START, self->page_size,
-                               self->bitmap, self->bitmap_size, _metadata);
+                               self->bitmap, self->bitmap_size, 0, _metadata);
 
        /* PAGE_SIZE unaligned bitmap */
        test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
                                MOCK_APERTURE_START, self->page_size,
                                self->bitmap + MOCK_PAGE_SIZE,
-                               self->bitmap_size, _metadata);
+                               self->bitmap_size, 0, _metadata);
+
+       test_ioctl_destroy(stddev_id);
+       test_ioctl_destroy(hwpt_id);
+}
+
+TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
+{
+       uint32_t stddev_id;
+       uint32_t hwpt_id;
+       uint32_t ioas_id;
+
+       test_ioctl_ioas_alloc(&ioas_id);
+       test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
+                                    variant->buffer_size, MOCK_APERTURE_START);
+
+       test_cmd_hwpt_alloc(self->idev_id, ioas_id,
+                           IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
+       test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
+
+       test_cmd_set_dirty_tracking(hwpt_id, true);
+
+       test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
+                               MOCK_APERTURE_START, self->page_size,
+                               self->bitmap, self->bitmap_size,
+                               IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
+                               _metadata);
+
+       /* Unaligned bitmap */
+       test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
+                               MOCK_APERTURE_START, self->page_size,
+                               self->bitmap + MOCK_PAGE_SIZE,
+                               self->bitmap_size,
+                               IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
+                               _metadata);
 
        test_ioctl_destroy(stddev_id);
        test_ioctl_destroy(hwpt_id);
index 2410d06f5a340884e70e51169da9e6597a207e54..e263bf80a977d35a3ee2161b0a84e3e737a7a056 100644 (file)
@@ -217,11 +217,12 @@ static int _test_cmd_set_dirty_tracking(int fd, __u32 hwpt_id, bool enabled)
 
 static int _test_cmd_get_dirty_bitmap(int fd, __u32 hwpt_id, size_t length,
                                      __u64 iova, size_t page_size,
-                                     __u64 *bitmap)
+                                     __u64 *bitmap, __u32 flags)
 {
        struct iommu_hwpt_get_dirty_bitmap cmd = {
                .size = sizeof(cmd),
                .hwpt_id = hwpt_id,
+               .flags = flags,
                .iova = iova,
                .length = length,
                .page_size = page_size,
@@ -236,9 +237,9 @@ static int _test_cmd_get_dirty_bitmap(int fd, __u32 hwpt_id, size_t length,
 }
 
 #define test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size,    \
-                                 bitmap)                                  \
+                                 bitmap, flags)                           \
        ASSERT_EQ(0, _test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, \
-                                               page_size, bitmap))
+                                               page_size, bitmap, flags))
 
 static int _test_cmd_mock_domain_set_dirty(int fd, __u32 hwpt_id, size_t length,
                                           __u64 iova, size_t page_size,
@@ -273,7 +274,7 @@ static int _test_cmd_mock_domain_set_dirty(int fd, __u32 hwpt_id, size_t length,
 
 static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
                                    __u64 iova, size_t page_size, __u64 *bitmap,
-                                   __u64 bitmap_size,
+                                   __u64 bitmap_size, __u32 flags,
                                    struct __test_metadata *_metadata)
 {
        unsigned long i, count, nbits = bitmap_size * BITS_PER_BYTE;
@@ -292,25 +293,30 @@ static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
 
        /* Expect all even bits as dirty in the user bitmap */
        memset(bitmap, 0, bitmap_size);
-       test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap);
+       test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap,
+                                 flags);
        for (count = 0, i = 0; i < nbits; count += !(i % 2), i++)
                ASSERT_EQ(!(i % 2), test_bit(i, (unsigned long *)bitmap));
        ASSERT_EQ(count, out_dirty);
 
        memset(bitmap, 0, bitmap_size);
-       test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap);
+       test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap,
+                                 flags);
 
        /* It as read already -- expect all zeroes */
-       for (i = 0; i < nbits; i++)
-               ASSERT_EQ(0, test_bit(i, (unsigned long *)bitmap));
+       for (i = 0; i < nbits; i++) {
+               ASSERT_EQ(!(i % 2) && (flags &
+                                      IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR),
+                         test_bit(i, (unsigned long *)bitmap));
+       }
 
        return 0;
 }
 #define test_mock_dirty_bitmaps(hwpt_id, length, iova, page_size, bitmap,      \
-                               bitmap_size, _metadata)                        \
+                               bitmap_size, flags, _metadata)                 \
        ASSERT_EQ(0, _test_mock_dirty_bitmaps(self->fd, hwpt_id, length, iova, \
                                              page_size, bitmap, bitmap_size,  \
-                                             _metadata))
+                                             flags, _metadata))
 
 static int _test_cmd_create_access(int fd, unsigned int ioas_id,
                                   __u32 *access_id, unsigned int flags)