[PATCH 1/2] iommu/io-pgtable-arm: align next walk address to large page size

From: Seongjun Hong

Date: Mon Oct 26 2026 - 09:43:46 EST


Align down walk_data->addr before the increment by page size to prevent
the missing dirty pages on IOMMU_HWPT_GET_DIRTY_BITMAP ioctl.

As Commit e21952d72b47 ("iommufd/iova_bitmap: Ensure that iova_bitmap_set()
handles the full IOVA") mentioned, the requested iova range can begin in
the middle of the large page (e.g., 2MB page block). So incrementing walk
address by large page size (e.g., 2M) could bypass next dirty'd small pages.

Fixes: 4fe88fd8b4ae ("iommu/io-pgtable-arm: Add read_and_clear_dirty() support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Seongjun Hong <hsj0512@xxxxxxxxx>
---
drivers/iommu/io-pgtable-arm.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 476c0e25631a..01c3f9cd5d9c 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -821,7 +821,7 @@ static int io_pgtable_visit(struct arm_lpae_io_pgtable *data,
return ret;

if (iopte_leaf(pte, lvl, iop->fmt)) {
- walk_data->addr += size;
+ walk_data->addr = ALIGN_DOWN(walk_data->addr, size) + size;
return 0;
}

@@ -868,7 +868,9 @@ static int visit_dirty(struct io_pgtable_walk_data *walk_data, int lvl,
return 0;

if (iopte_writeable_dirty(*ptep)) {
- iommu_dirty_bitmap_record(dirty, walk_data->addr, size);
+ u64 iova = ALIGN_DOWN(walk_data->addr, size);
+
+ iommu_dirty_bitmap_record(dirty, iova, size);
if (!(walk_data->flags & IOMMU_DIRTY_NO_CLEAR))
iopte_set_writeable_clean(ptep);
}

--
2.43.0