All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/10] iommufd/{iova_bitmap,selftest}: Fix dirty hugepages tracking and selftests
@ 2024-06-21 18:42 Joao Martins
  2024-06-21 18:42 ` [PATCH v1 01/10] iommufd/selftest: Fix dirty bitmap tests with u8 bitmaps Joao Martins
                   ` (11 more replies)
  0 siblings, 12 replies; 27+ messages in thread
From: Joao Martins @ 2024-06-21 18:42 UTC (permalink / raw)
  To: iommu
  Cc: Jason Gunthorpe, Kevin Tian, Suravee Suthikulpanit, Lu Baolu,
	Joao Martins, Avihai Horon, Alex Williamson,
	Shameerali Kolothum Thodi

Hey,

This series purpose is to address what I thought was a complete fix[0].  It
also fixes arm64 64k base page cases that are broken right now with tiny
bitmap sizes (<= 128K IOVA ranges). It also makes selftest read_and_clear()
better iommu drivers and cover new bitmap sizes.

I go in details in the patch 9 but essentially over tons of live migrations
I find out two leftover issues that I failed to fix in my previous
series. The dirty case that that crosses iterations was indeed fixed by
[1], but it's the non dirty that was still generating issues:

a) Essentially, lack of alignment in iterations begin/end leads to checking
two times the same IOPTE for dirty bits reintroducing the 'partial
hugepage' check edge case. Though on big bitmaps (for a 1TB case which is
32MB bitmaps) the time taken pinning iterations can lead for the IOPTE
being dirty in the second time it is checked which makes it miss part of
the dirty page to be sent on the migration stream.

b) when we hit this hugepage represented across iterations we start
checking IOVAs being dirty slightly offsetted leading to set the wrong bits
when we find something dirty later on. This is only visible in >64G iova
ranges and PAGE_SIZE unaligned bitmaps.

The series is organized as:

* Patches 1-3: Fixes the 64k arm64 broken selftests and introduces two
more edge cases to cover the equivalent in 4k base pages.

* Patch 4: Fix selftest to match better the current iommu dirty
trackers, which was hiding the brokeness of (b) above. I have used the snip
below[*] to make sure all is passed, but I don't add it because testing
 >=64G takes longer than the selftests timeout tolerates. Furthermore this
is only relevant with the fixed window scheme which I remove in this series
and make it dynamic.

* Patches 5-10: Patches to prep for patch 9, that leads into removing
ithe partial hugepage represented across iterations that is self-induced.
upper layers not knowing what page size is for a given IOVA maps, but more
importantly because IOVA bitmaps deal with fixed 64G range passed into
read_and_clear(). To avoid further issues with this fixed scheme I redid
the fix and make it dynamic the iteration scheme i.e. pin the next 64G and
repin it everytime a dirty-size can't fit into the mapped pages without
requiring callers needing to work in a limited IOVA range (aka we can pass
read_and_clear() the whole thing and we pin the needed bitmap pages).
Additionally, because non dirty IOVA ranges don't need to get anything
pinned, it makes non-dirty cases very cheap as a bonus. I couldn't find a
measurable difference between dynamic vs fixed pinning, so I've removed it
in patch 10. It also makes the code simpler to follow & easier to maintain.
If folks agree with the approach I've taken here I can remove the callers
of iova_bitmap_for_each() in a follow-up cleanup series.

This series survives 1700 migrations of guests with applications doing RDMA
(which is roughly 3-days spent migration back and forth between hosts).
Additionally like the series in [1] I used a set of changes/tool to
exercise some dirty tracking tests but with real iommu drivers. Finally
tested >=64G IOMMU page sizes using this tool but with device-dax memory
(to generate >=64G contiguous RAM) to tackle the case of patch 9 when
iova_bitmap_set() gets called with enourmous page sizes that surprasse or
is equal to the maximum pin set of 64G.

Comments, review as usual appreciated.

	Joao

Joao Martins (10):
  iommufd/selftest: Fix dirty bitmap tests with u8 bitmaps
  iommufd/selftest: Fix iommufd_test_dirty() to handle <u8 bitmaps
  iommufd/selftest: Add tests for <= u8 bitmap sizes
  iommufd/selftest: Do not record head iova to better match iommu drivers
  iommufd/iova_bitmap: Check iova_bitmap_done() after set ahead
  iommufd/iova_bitmap: Cache mapped length in iova_bitmap_map struct
  iommufd/iova_bitmap: Move initial pinning to iova_bitmap_for_each()
  iommufd/iova_bitmap: Consolidate iova_bitmap_set exit conditionals
  iommufd/iova_bitmap: Dynamic pinning on iova_bitmap_set()
  iommufd/iova_bitmap: Remove iterator logic

 drivers/iommu/iommufd/iova_bitmap.c           | 124 +++++++-----------
 drivers/iommu/iommufd/selftest.c              |   6 +-
 tools/testing/selftests/iommu/iommufd.c       |  28 +++-
 tools/testing/selftests/iommu/iommufd_utils.h |   6 +-
 4 files changed, 79 insertions(+), 85 deletions(-)

[0] https://lore.kernel.org/linux-iommu/6b90f949-48da-4cb3-ad9a-ed54f1351a9a@oracle.com/
[1] https://lore.kernel.org/linux-iommu/20240202133415.23819-1-joao.m.martins@oracle.com/

[*] Adds 72G test and adds the offset=0x1 which exercises both (b)

diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h
index e854d3f67205..171d3e437356 100644
--- a/drivers/iommu/iommufd/iommufd_test.h
+++ b/drivers/iommu/iommufd/iommufd_test.h
@@ -26,7 +26,7 @@ enum {

 enum {
        MOCK_APERTURE_START = 1UL << 24,
-       MOCK_APERTURE_LAST = (1UL << 31) - 1,
+       MOCK_APERTURE_LAST = (1UL << 37) - 1,
 };

 enum {
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 61189215e1ab..61770e31e66a 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -1841,6 +1841,13 @@ FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty256M_huge)
        .hugepages = true,
 };

+FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty72G_huge)
+{
+       /* 2304K bitmap (72G IOVA range) */
+       .buffer_size = 72 * 1024UL * 1024UL * 1024UL,
+       .hugepages = true,
+};
+
 TEST_F(iommufd_dirty_tracking, enforce_dirty)
 {
        uint32_t ioas_id, stddev_id, idev_id;
@@ -1898,7 +1905,7 @@ TEST_F(iommufd_dirty_tracking, device_dirty_capability)
        test_ioctl_destroy(hwpt_id);
 }
-TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
+TEST_F_TIMEOUT(iommufd_dirty_tracking, get_dirty_bitmap, 4095)
 {
        uint32_t page_size = MOCK_PAGE_SIZE;
        uint32_t hwpt_id;
@@ -1932,10 +1939,16 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
                                self->bitmap + 0xff1, self->bitmap_size, 0,
                                _metadata);

+       /* broken non-dirty page cross iterations (>= 64G tests) */
+       test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
+                               MOCK_APERTURE_START, self->page_size, page_size,
+                               self->bitmap + 0x1, self->bitmap_size, 0,
+                               _metadata);
+
        test_ioctl_destroy(hwpt_id);
 }

-TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
+TEST_F_TIMEOUT(iommufd_dirty_tracking, get_dirty_bitmap_no_clear, 4095)
 {
        uint32_t page_size = MOCK_PAGE_SIZE;
        uint32_t hwpt_id;
@@ -1967,13 +1980,20 @@ TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
                                IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
                                _metadata);

-       /* u64 unaligned bitmap */
+       /* u8 unaligned bitmap */
        test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
                                MOCK_APERTURE_START, self->page_size, page_size,
                                self->bitmap + 0xff1, self->bitmap_size,
                                IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
                                _metadata);

+       /* broken non-dirty page cross iterations (>= 64G tests) */
+       test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
+                               MOCK_APERTURE_START, self->page_size, page_size,
+                               self->bitmap + 0x1, self->bitmap_size,
+                               IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
+                               _metadata);
+
        test_ioctl_destroy(hwpt_id);
 }

-- 
2.17.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2024-06-26 13:44 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-21 18:42 [PATCH v1 00/10] iommufd/{iova_bitmap,selftest}: Fix dirty hugepages tracking and selftests Joao Martins
2024-06-21 18:42 ` [PATCH v1 01/10] iommufd/selftest: Fix dirty bitmap tests with u8 bitmaps Joao Martins
2024-06-21 18:42 ` [PATCH v1 02/10] iommufd/selftest: Fix iommufd_test_dirty() to handle <u8 bitmaps Joao Martins
2024-06-21 18:42 ` [PATCH v1 03/10] iommufd/selftest: Add tests for <= u8 bitmap sizes Joao Martins
2024-06-25  3:33   ` Tian, Kevin
2024-06-25 11:04     ` Joao Martins
2024-06-26  2:33       ` Tian, Kevin
2024-06-26 10:13         ` Joao Martins
2024-06-21 18:42 ` [PATCH v1 04/10] iommufd/selftest: Do not record head iova to better match iommu drivers Joao Martins
2024-06-25  3:35   ` Tian, Kevin
2024-06-25 11:11     ` Joao Martins
2024-06-26  2:35       ` Tian, Kevin
2024-06-21 18:42 ` [PATCH v1 05/10] iommufd/iova_bitmap: Check iova_bitmap_done() after set ahead Joao Martins
2024-06-21 18:42 ` [PATCH v1 06/10] iommufd/iova_bitmap: Cache mapped length in iova_bitmap_map struct Joao Martins
2024-06-21 18:42 ` [PATCH v1 07/10] iommufd/iova_bitmap: Move initial pinning to iova_bitmap_for_each() Joao Martins
2024-06-21 18:42 ` [PATCH v1 08/10] iommufd/iova_bitmap: Consolidate iova_bitmap_set exit conditionals Joao Martins
2024-06-21 18:42 ` [PATCH v1 09/10] iommufd/iova_bitmap: Dynamic pinning on iova_bitmap_set() Joao Martins
2024-06-25  3:38   ` Tian, Kevin
2024-06-25 11:13     ` Joao Martins
2024-06-25 12:27       ` Jason Gunthorpe
2024-06-25 15:27         ` Joao Martins
2024-06-25 15:31           ` Jason Gunthorpe
2024-06-25 16:52             ` Joao Martins
2024-06-21 18:42 ` [PATCH v1 10/10] iommufd/iova_bitmap: Remove iterator logic Joao Martins
2024-06-25  3:39 ` [PATCH v1 00/10] iommufd/{iova_bitmap,selftest}: Fix dirty hugepages tracking and selftests Tian, Kevin
2024-06-26 13:41 ` Jason Gunthorpe
2024-06-26 13:43   ` Joao Martins

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.