Skip to content

Commit aff028a

Browse files
robclarkwilldeacon
authored andcommitted
iommu/io-pgtable-arm: Add way to debug pgtable walk
Add an io-pgtable method to walk the pgtable returning the raw PTEs that would be traversed for a given iova access. Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Mostafa Saleh <[email protected]> Link: https://lore.kernel.org/r/[email protected] [will: Removed 'arm_lpae_io_pgtable_walk_data::level' per Mostafa] Signed-off-by: Will Deacon <[email protected]>
1 parent d9e589e commit aff028a

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

drivers/iommu/io-pgtable-arm.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,28 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
754754
return iopte_to_paddr(d.pte, data) | iova;
755755
}
756756

757+
static int visit_pgtable_walk(struct io_pgtable_walk_data *walk_data, int lvl,
758+
arm_lpae_iopte *ptep, size_t size)
759+
{
760+
struct arm_lpae_io_pgtable_walk_data *data = walk_data->data;
761+
data->ptes[lvl] = *ptep;
762+
return 0;
763+
}
764+
765+
static int arm_lpae_pgtable_walk(struct io_pgtable_ops *ops, unsigned long iova,
766+
void *wd)
767+
{
768+
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
769+
struct io_pgtable_walk_data walk_data = {
770+
.data = wd,
771+
.visit = visit_pgtable_walk,
772+
.addr = iova,
773+
.end = iova + 1,
774+
};
775+
776+
return __arm_lpae_iopte_walk(data, &walk_data, data->pgd, data->start_level);
777+
}
778+
757779
static int io_pgtable_visit(struct arm_lpae_io_pgtable *data,
758780
struct io_pgtable_walk_data *walk_data,
759781
arm_lpae_iopte *ptep, int lvl)
@@ -929,6 +951,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
929951
.unmap_pages = arm_lpae_unmap_pages,
930952
.iova_to_phys = arm_lpae_iova_to_phys,
931953
.read_and_clear_dirty = arm_lpae_read_and_clear_dirty,
954+
.pgtable_walk = arm_lpae_pgtable_walk,
932955
};
933956

934957
return data;

include/linux/io-pgtable.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,22 @@ struct io_pgtable_cfg {
180180
};
181181
};
182182

183+
/**
184+
* struct arm_lpae_io_pgtable_walk_data - information from a pgtable walk
185+
*
186+
* @ptes: The recorded PTE values from the walk
187+
*/
188+
struct arm_lpae_io_pgtable_walk_data {
189+
u64 ptes[4];
190+
};
191+
183192
/**
184193
* struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
185194
*
186195
* @map_pages: Map a physically contiguous range of pages of the same size.
187196
* @unmap_pages: Unmap a range of virtually contiguous pages of the same size.
188197
* @iova_to_phys: Translate iova to physical address.
198+
* @pgtable_walk: (optional) Perform a page table walk for a given iova.
189199
*
190200
* These functions map directly onto the iommu_ops member functions with
191201
* the same names.
@@ -199,6 +209,7 @@ struct io_pgtable_ops {
199209
struct iommu_iotlb_gather *gather);
200210
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
201211
unsigned long iova);
212+
int (*pgtable_walk)(struct io_pgtable_ops *ops, unsigned long iova, void *wd);
202213
int (*read_and_clear_dirty)(struct io_pgtable_ops *ops,
203214
unsigned long iova, size_t size,
204215
unsigned long flags,

0 commit comments

Comments
 (0)