Commit dc751d41 authored by Joao Martins's avatar Joao Martins Committed by Jason Zeng
Browse files

iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR flag

mainline inclusion
from mainline-v6.7-rc1
commit 0795b305da8902e7d092f90bf9a1a2c98f34b1db
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I8Y6AM
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?0795b305da8902e7d092f90bf9a1a2c98f34b1db

--------------------------------

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.

Intel-SIG: 0795b305da89 iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR flag
Backport IOMMUFD Dirty Tracking

Link: https://lore.kernel.org/r/20231024135109.73787-19-joao.m.martins@oracle.com


Signed-off-by: default avatarJoao Martins <joao.m.martins@oracle.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
[ jz: amend commit log ]
Signed-off-by: default avatarJason Zeng <jason.zeng@intel.com>
parent 82fe01e5
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -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)) {
			/* Clear dirty */
			if (!(flags & IOMMU_DIRTY_NO_CLEAR)) {
				unsigned long val;

			/* Clear dirty */
				val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
			old = xa_store(&mock->pfns, cur / MOCK_IO_PAGE_SIZE,
				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);
		}
+36 −2
Original line number Diff line number Diff line
@@ -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);
+16 −10
Original line number Diff line number Diff line
@@ -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)