linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/2] io-pgtable-arm + drm/msm: Extend iova fault debugging
@ 2024-06-26 20:40 Rob Clark
  2024-06-26 20:40 ` [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk Rob Clark
  0 siblings, 1 reply; 5+ messages in thread
From: Rob Clark @ 2024-06-26 20:40 UTC (permalink / raw)
  To: iommu
  Cc: linux-arm-msm, Will Deacon, Robin Murphy, Rob Clark,
	Boris Brezillon, open list:DRM DRIVER for Qualcomm Adreno GPUs,
	open list:DRM DRIVER for Qualcomm Adreno GPUs, Jason Gunthorpe,
	Joao Martins, Joerg Roedel, Konrad Dybcio,
	moderated list:ARM SMMU DRIVERS, open list,
	open list:POWER MANAGEMENT CORE, Lu Baolu, Marijn Suijten,
	Rafael J. Wysocki, Sean Paul

From: Rob Clark <robdclark@chromium.org>

This series extends io-pgtable-arm with a method to retrieve the page
table entries traversed in the process of address translation, and then
beefs up drm/msm gpu devcore dump to include this (and additional info)
in the devcore dump.

This is a respin of https://patchwork.freedesktop.org/series/94968/
(minus a patch that was already merged)

v2: Fix an armv7/32b build error in the last patch
v3: Incorperate Will Deacon's suggestion to make the interface
    callback based.
v4: Actually wire up the callback
v5: Drop the callback approach

Rob Clark (2):
  iommu/io-pgtable-arm: Add way to debug pgtable walk
  drm/msm: Extend gpu devcore dumps with pgtbl info

 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 ++++++++
 drivers/gpu/drm/msm/msm_gpu.c           |  9 +++++++
 drivers/gpu/drm/msm/msm_gpu.h           |  8 ++++++
 drivers/gpu/drm/msm/msm_iommu.c         | 25 ++++++++++++++++++
 drivers/gpu/drm/msm/msm_mmu.h           |  3 ++-
 drivers/iommu/io-pgtable-arm.c          | 34 ++++++++++++++++++-------
 include/linux/io-pgtable.h              | 16 ++++++++++++
 7 files changed, 95 insertions(+), 10 deletions(-)

-- 
2.45.2



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

* [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk
  2024-06-26 20:40 [PATCH v5 0/2] io-pgtable-arm + drm/msm: Extend iova fault debugging Rob Clark
@ 2024-06-26 20:40 ` Rob Clark
  2024-07-03 15:02   ` Will Deacon
  0 siblings, 1 reply; 5+ messages in thread
From: Rob Clark @ 2024-06-26 20:40 UTC (permalink / raw)
  To: iommu
  Cc: linux-arm-msm, Will Deacon, Robin Murphy, Rob Clark, Joerg Roedel,
	Jason Gunthorpe, Steven Price, Boris Brezillon, Kevin Tian,
	Joao Martins, moderated list:ARM SMMU DRIVERS, open list

From: Rob Clark <robdclark@chromium.org>

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 <robdclark@chromium.org>
---
 drivers/iommu/io-pgtable-arm.c | 34 +++++++++++++++++++++++++---------
 include/linux/io-pgtable.h     | 16 ++++++++++++++++
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 3d23b924cec1..24bbfd9a8874 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -690,8 +690,8 @@ static size_t arm_lpae_unmap_pages(struct io_pgtable_ops *ops, unsigned long iov
 				data->start_level, ptep);
 }
 
-static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
-					 unsigned long iova)
+static int arm_lpae_pgtable_walk(struct io_pgtable_ops *ops, unsigned long iova,
+				 struct io_pgtable_walk_data *wd)
 {
 	struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
 	arm_lpae_iopte pte, *ptep = data->pgd;
@@ -700,7 +700,7 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
 	do {
 		/* Valid IOPTE pointer? */
 		if (!ptep)
-			return 0;
+			return -ENOENT;
 
 		/* Grab the IOPTE we're interested in */
 		ptep += ARM_LPAE_LVL_IDX(iova, lvl, data);
@@ -708,22 +708,37 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
 
 		/* Valid entry? */
 		if (!pte)
-			return 0;
+			return -ENOENT;
 
-		/* Leaf entry? */
+		wd->ptes[wd->level++] = pte;
+
+		/* Leaf entry?  If so, we've found the translation */
 		if (iopte_leaf(pte, lvl, data->iop.fmt))
-			goto found_translation;
+			return 0;
 
 		/* Take it to the next level */
 		ptep = iopte_deref(pte, data);
 	} while (++lvl < ARM_LPAE_MAX_LEVELS);
 
 	/* Ran out of page tables to walk */
-	return 0;
+	return -ENOENT;
+}
+
+static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
+					 unsigned long iova)
+{
+	struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
+	struct io_pgtable_walk_data wd = {};
+	int ret, lvl;
+
+	ret = arm_lpae_pgtable_walk(ops, iova, &wd);
+	if (ret)
+		return 0;
+
+	lvl = wd.level + data->start_level;
 
-found_translation:
 	iova &= (ARM_LPAE_BLOCK_SIZE(lvl, data) - 1);
-	return iopte_to_paddr(pte, data) | iova;
+	return iopte_to_paddr(wd.ptes[wd.level - 1], data) | iova;
 }
 
 static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
@@ -804,6 +819,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
 		.map_pages	= arm_lpae_map_pages,
 		.unmap_pages	= arm_lpae_unmap_pages,
 		.iova_to_phys	= arm_lpae_iova_to_phys,
+		.pgtable_walk	= arm_lpae_pgtable_walk,
 	};
 
 	return data;
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 86cf1f7ae389..4d696724c7da 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -171,12 +171,26 @@ struct io_pgtable_cfg {
 	};
 };
 
+/**
+ * struct io_pgtable_walk_data - information from a pgtable walk
+ *
+ * @ptes:     The recorded PTE values from the walk
+ * @level:    The level of the last PTE
+ *
+ * @level also specifies the last valid index in @ptes
+ */
+struct io_pgtable_walk_data {
+	u64 ptes[4];
+	int level;
+};
+
 /**
  * struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
  *
  * @map_pages:    Map a physically contiguous range of pages of the same size.
  * @unmap_pages:  Unmap a range of virtually contiguous pages of the same size.
  * @iova_to_phys: Translate iova to physical address.
+ * @pgtable_walk: (optional) Perform a page table walk for a given iova.
  *
  * These functions map directly onto the iommu_ops member functions with
  * the same names.
@@ -190,6 +204,8 @@ struct io_pgtable_ops {
 			      struct iommu_iotlb_gather *gather);
 	phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
 				    unsigned long iova);
+	int (*pgtable_walk)(struct io_pgtable_ops *ops, unsigned long iova,
+			    struct io_pgtable_walk_data *wd);
 	int (*read_and_clear_dirty)(struct io_pgtable_ops *ops,
 				    unsigned long iova, size_t size,
 				    unsigned long flags,
-- 
2.45.2



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

* Re: [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk
  2024-06-26 20:40 ` [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk Rob Clark
@ 2024-07-03 15:02   ` Will Deacon
  2024-07-03 16:18     ` Rob Clark
  0 siblings, 1 reply; 5+ messages in thread
From: Will Deacon @ 2024-07-03 15:02 UTC (permalink / raw)
  To: Rob Clark
  Cc: iommu, linux-arm-msm, Robin Murphy, Rob Clark, Joerg Roedel,
	Jason Gunthorpe, Steven Price, Boris Brezillon, Kevin Tian,
	Joao Martins, moderated list:ARM SMMU DRIVERS, open list

Hi Rob,

On Wed, Jun 26, 2024 at 01:40:26PM -0700, Rob Clark wrote:
> From: Rob Clark <robdclark@chromium.org>
> 
> 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 <robdclark@chromium.org>
> ---
>  drivers/iommu/io-pgtable-arm.c | 34 +++++++++++++++++++++++++---------
>  include/linux/io-pgtable.h     | 16 ++++++++++++++++
>  2 files changed, 41 insertions(+), 9 deletions(-)

Non-technical question, but with patch 2/2 being drm-specific, how do
you plan to get this merged this once it's finalised? I can take this
part via the IOMMU tree?

> +static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
> +					 unsigned long iova)
> +{
> +	struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
> +	struct io_pgtable_walk_data wd = {};
> +	int ret, lvl;
> +
> +	ret = arm_lpae_pgtable_walk(ops, iova, &wd);
> +	if (ret)
> +		return 0;
> +
> +	lvl = wd.level + data->start_level;

nit, but the level is architectural so I think we should initialise
wd.level to data->start_level instead.

>  
> -found_translation:
>  	iova &= (ARM_LPAE_BLOCK_SIZE(lvl, data) - 1);
> -	return iopte_to_paddr(pte, data) | iova;
> +	return iopte_to_paddr(wd.ptes[wd.level - 1], data) | iova;
>  }
>  
>  static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
> @@ -804,6 +819,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
>  		.map_pages	= arm_lpae_map_pages,
>  		.unmap_pages	= arm_lpae_unmap_pages,
>  		.iova_to_phys	= arm_lpae_iova_to_phys,
> +		.pgtable_walk	= arm_lpae_pgtable_walk,
>  	};
>  
>  	return data;
> diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
> index 86cf1f7ae389..4d696724c7da 100644
> --- a/include/linux/io-pgtable.h
> +++ b/include/linux/io-pgtable.h
> @@ -171,12 +171,26 @@ struct io_pgtable_cfg {
>  	};
>  };
>  
> +/**
> + * struct io_pgtable_walk_data - information from a pgtable walk
> + *
> + * @ptes:     The recorded PTE values from the walk
> + * @level:    The level of the last PTE
> + *
> + * @level also specifies the last valid index in @ptes
> + */
> +struct io_pgtable_walk_data {
> +	u64 ptes[4];
> +	int level;
> +};

I wonder if we can do better than hardcoding the '4' here? I wouldn't be
surprised if this doesn't work, but could we do something along the
lines of:

struct io_pgtable_walk_data {
	int level;
	int num_levels;
	u64 ptes[] __counted_by(num_levels);
};

and then have the Arm (LPAE)-specific code wrap that in a private
structure:

struct arm_lpae_io_pgtable_walk_data {
	struct io_pgtable_walk_data data;
	u64 ptes[ARM_LPAE_MAX_LEVELS];
};

which is used by the walker?

Will


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

* Re: [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk
  2024-07-03 15:02   ` Will Deacon
@ 2024-07-03 16:18     ` Rob Clark
  2024-07-09 18:20       ` Jason Gunthorpe
  0 siblings, 1 reply; 5+ messages in thread
From: Rob Clark @ 2024-07-03 16:18 UTC (permalink / raw)
  To: Will Deacon
  Cc: iommu, linux-arm-msm, Robin Murphy, Rob Clark, Joerg Roedel,
	Jason Gunthorpe, Steven Price, Boris Brezillon, Kevin Tian,
	Joao Martins, moderated list:ARM SMMU DRIVERS, open list

On Wed, Jul 3, 2024 at 8:02 AM Will Deacon <will@kernel.org> wrote:
>
> Hi Rob,
>
> On Wed, Jun 26, 2024 at 01:40:26PM -0700, Rob Clark wrote:
> > From: Rob Clark <robdclark@chromium.org>
> >
> > 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 <robdclark@chromium.org>
> > ---
> >  drivers/iommu/io-pgtable-arm.c | 34 +++++++++++++++++++++++++---------
> >  include/linux/io-pgtable.h     | 16 ++++++++++++++++
> >  2 files changed, 41 insertions(+), 9 deletions(-)
>
> Non-technical question, but with patch 2/2 being drm-specific, how do
> you plan to get this merged this once it's finalised? I can take this
> part via the IOMMU tree?

I guess if need be, I could merge the drm part only after the iommu
part lands.  We've lived with an earlier iteration of these series as
downstream patches in the CrOS kernel for this long, it isn't the end
of the world if it takes a bit longer

> > +static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
> > +                                      unsigned long iova)
> > +{
> > +     struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
> > +     struct io_pgtable_walk_data wd = {};
> > +     int ret, lvl;
> > +
> > +     ret = arm_lpae_pgtable_walk(ops, iova, &wd);
> > +     if (ret)
> > +             return 0;
> > +
> > +     lvl = wd.level + data->start_level;
>
> nit, but the level is architectural so I think we should initialise
> wd.level to data->start_level instead.

Hmm, I wanted to use wd.level to get the index of the last entry in
wd.ptes.  Perhaps I should just call it something other than 'level'
instead?

> >
> > -found_translation:
> >       iova &= (ARM_LPAE_BLOCK_SIZE(lvl, data) - 1);
> > -     return iopte_to_paddr(pte, data) | iova;
> > +     return iopte_to_paddr(wd.ptes[wd.level - 1], data) | iova;
> >  }
> >
> >  static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
> > @@ -804,6 +819,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
> >               .map_pages      = arm_lpae_map_pages,
> >               .unmap_pages    = arm_lpae_unmap_pages,
> >               .iova_to_phys   = arm_lpae_iova_to_phys,
> > +             .pgtable_walk   = arm_lpae_pgtable_walk,
> >       };
> >
> >       return data;
> > diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
> > index 86cf1f7ae389..4d696724c7da 100644
> > --- a/include/linux/io-pgtable.h
> > +++ b/include/linux/io-pgtable.h
> > @@ -171,12 +171,26 @@ struct io_pgtable_cfg {
> >       };
> >  };
> >
> > +/**
> > + * struct io_pgtable_walk_data - information from a pgtable walk
> > + *
> > + * @ptes:     The recorded PTE values from the walk
> > + * @level:    The level of the last PTE
> > + *
> > + * @level also specifies the last valid index in @ptes
> > + */
> > +struct io_pgtable_walk_data {
> > +     u64 ptes[4];
> > +     int level;
> > +};
>
> I wonder if we can do better than hardcoding the '4' here? I wouldn't be
> surprised if this doesn't work, but could we do something along the
> lines of:
>
> struct io_pgtable_walk_data {
>         int level;
>         int num_levels;
>         u64 ptes[] __counted_by(num_levels);
> };
>
> and then have the Arm (LPAE)-specific code wrap that in a private
> structure:
>
> struct arm_lpae_io_pgtable_walk_data {
>         struct io_pgtable_walk_data data;
>         u64 ptes[ARM_LPAE_MAX_LEVELS];
> };
>
> which is used by the walker?

I guess we could just make the walk_data fxn ptr arg a void* and
rename io_pgtable_walk_data -> io_lpae_pgtable_walk_data?  I'm not
sure how hard to try to make this interface generic when I think it is
probably only going to be used by code that knows what pgtable format
is used.  It's kinda the same question about what type to use for the
pte.  Maybe the answer is just "it's pgtable format dependent"?

BR,
-R


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

* Re: [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk
  2024-07-03 16:18     ` Rob Clark
@ 2024-07-09 18:20       ` Jason Gunthorpe
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2024-07-09 18:20 UTC (permalink / raw)
  To: Rob Clark
  Cc: Will Deacon, iommu, linux-arm-msm, Robin Murphy, Rob Clark,
	Joerg Roedel, Steven Price, Boris Brezillon, Kevin Tian,
	Joao Martins, moderated list:ARM SMMU DRIVERS, open list

On Wed, Jul 03, 2024 at 09:18:43AM -0700, Rob Clark wrote:
> On Wed, Jul 3, 2024 at 8:02 AM Will Deacon <will@kernel.org> wrote:
> >
> > Hi Rob,
> >
> > On Wed, Jun 26, 2024 at 01:40:26PM -0700, Rob Clark wrote:
> > > From: Rob Clark <robdclark@chromium.org>
> > >
> > > 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 <robdclark@chromium.org>
> > > ---
> > >  drivers/iommu/io-pgtable-arm.c | 34 +++++++++++++++++++++++++---------
> > >  include/linux/io-pgtable.h     | 16 ++++++++++++++++
> > >  2 files changed, 41 insertions(+), 9 deletions(-)
> >
> > Non-technical question, but with patch 2/2 being drm-specific, how do
> > you plan to get this merged this once it's finalised? I can take this
> > part via the IOMMU tree?
> 
> I guess if need be, I could merge the drm part only after the iommu
> part lands.  We've lived with an earlier iteration of these series as
> downstream patches in the CrOS kernel for this long, it isn't the end
> of the world if it takes a bit longer

We should try not to split series up, there are too many cases where
the other parts don't make it and we end up with some cruft.

This is only two patches, get iommu or DRM to ack their parts and send
it through one tree.

Jason


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

end of thread, other threads:[~2024-07-09 18:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-26 20:40 [PATCH v5 0/2] io-pgtable-arm + drm/msm: Extend iova fault debugging Rob Clark
2024-06-26 20:40 ` [PATCH v5 1/2] iommu/io-pgtable-arm: Add way to debug pgtable walk Rob Clark
2024-07-03 15:02   ` Will Deacon
2024-07-03 16:18     ` Rob Clark
2024-07-09 18:20       ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).