iommufd/selftest: Refactor dirty bitmap tests

Rework the functions that test and set the bitmaps to receive a new
parameter (the pte_page_size) that reflects the expected PTE size in the
page tables. The same scheme is still used i.e. even bits are dirty and
odd page indexes aren't dirty. Here it just refactors to consider the size
of the PTE rather than hardcoded to IOMMU mock base page assumptions.

While at it, refactor dirty bitmap tests to use the idev_id created by the
fixture instead of creating a new one.

This is in preparation for doing tests with IOMMU hugepages where multiple
bits set as part of recording a whole hugepage as dirty and thus the
pte_page_size will vary depending on io hugepages or io base pages.

Link: https://lore.kernel.org/r/20240202133415.23819-6-joao.m.martins@oracle.com
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Joao Martins 2024-02-02 13:34:11 +00:00 committed by Jason Gunthorpe
parent 2780025e01
commit 407fc184f0
2 changed files with 36 additions and 31 deletions

View file

@ -1849,7 +1849,7 @@ TEST_F(iommufd_dirty_tracking, device_dirty_capability)
TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
{
uint32_t stddev_id;
uint32_t page_size = MOCK_PAGE_SIZE;
uint32_t hwpt_id;
uint32_t ioas_id;
@ -1859,34 +1859,31 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
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,
MOCK_APERTURE_START, self->page_size, page_size,
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,
MOCK_APERTURE_START, self->page_size, page_size,
self->bitmap + MOCK_PAGE_SIZE,
self->bitmap_size, 0, _metadata);
/* u64 unaligned bitmap */
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
MOCK_APERTURE_START, self->page_size,
self->bitmap + 0xff1,
self->bitmap_size, 0, _metadata);
MOCK_APERTURE_START, self->page_size, page_size,
self->bitmap + 0xff1, 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 page_size = MOCK_PAGE_SIZE;
uint32_t hwpt_id;
uint32_t ioas_id;
@ -1896,19 +1893,18 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
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,
MOCK_APERTURE_START, self->page_size, 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,
MOCK_APERTURE_START, self->page_size, page_size,
self->bitmap + MOCK_PAGE_SIZE,
self->bitmap_size,
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
@ -1916,13 +1912,11 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
/* u64 unaligned bitmap */
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
MOCK_APERTURE_START, self->page_size,
self->bitmap + 0xff1,
self->bitmap_size,
MOCK_APERTURE_START, self->page_size, page_size,
self->bitmap + 0xff1, self->bitmap_size,
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
_metadata);
test_ioctl_destroy(stddev_id);
test_ioctl_destroy(hwpt_id);
}

View file

@ -344,16 +344,19 @@ static int _test_cmd_mock_domain_set_dirty(int fd, __u32 hwpt_id, size_t length,
page_size, bitmap, nr))
static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
__u64 iova, size_t page_size, __u64 *bitmap,
__u64 iova, size_t page_size,
size_t pte_page_size, __u64 *bitmap,
__u64 bitmap_size, __u32 flags,
struct __test_metadata *_metadata)
{
unsigned long i, nbits = bitmap_size * BITS_PER_BYTE;
unsigned long nr = nbits / 2;
unsigned long npte = pte_page_size / page_size, pteset = 2 * npte;
unsigned long nbits = bitmap_size * BITS_PER_BYTE;
unsigned long j, i, nr = nbits / pteset ?: 1;
__u64 out_dirty = 0;
/* Mark all even bits as dirty in the mock domain */
for (i = 0; i < nbits; i += 2)
memset(bitmap, 0, bitmap_size);
for (i = 0; i < nbits; i += pteset)
set_bit(i, (unsigned long *)bitmap);
test_cmd_mock_domain_set_dirty(fd, hwpt_id, length, iova, page_size,
@ -365,8 +368,12 @@ static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap,
flags);
/* Beware ASSERT_EQ() is two statements -- braces are not redundant! */
for (i = 0; i < nbits; i++) {
ASSERT_EQ(!(i % 2), test_bit(i, (unsigned long *)bitmap));
for (i = 0; i < nbits; i += pteset) {
for (j = 0; j < pteset; j++) {
ASSERT_EQ(j < npte,
test_bit(i + j, (unsigned long *)bitmap));
}
ASSERT_EQ(!(i % pteset), test_bit(i, (unsigned long *)bitmap));
}
memset(bitmap, 0, bitmap_size);
@ -374,19 +381,23 @@ static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
flags);
/* It as read already -- expect all zeroes */
for (i = 0; i < nbits; i++) {
ASSERT_EQ(!(i % 2) && (flags &
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR),
test_bit(i, (unsigned long *)bitmap));
for (i = 0; i < nbits; i += pteset) {
for (j = 0; j < pteset; j++) {
ASSERT_EQ(
(j < npte) &&
(flags &
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR),
test_bit(i + j, (unsigned long *)bitmap));
}
}
return 0;
}
#define test_mock_dirty_bitmaps(hwpt_id, length, iova, page_size, bitmap, \
bitmap_size, flags, _metadata) \
#define test_mock_dirty_bitmaps(hwpt_id, length, iova, page_size, pte_size,\
bitmap, bitmap_size, flags, _metadata) \
ASSERT_EQ(0, _test_mock_dirty_bitmaps(self->fd, hwpt_id, length, iova, \
page_size, bitmap, bitmap_size, \
flags, _metadata))
page_size, pte_size, bitmap, \
bitmap_size, flags, _metadata))
static int _test_cmd_create_access(int fd, unsigned int ioas_id,
__u32 *access_id, unsigned int flags)