diff mbox series

[v3,1/3] iommu/arm-smmu: Add support for driver IOMMU fault handlers

Message ID 20210225175135.91922-2-jcrouse@codeaurora.org
State Accepted
Commit f8f934c180f629bb927a04fd90d6a16ef1a94073
Headers show
Series [v3,1/3] iommu/arm-smmu: Add support for driver IOMMU fault handlers | expand

Commit Message

Jordan Crouse Feb. 25, 2021, 5:51 p.m. UTC
Call report_iommu_fault() to allow upper-level drivers to register their
own fault handlers.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---

 drivers/iommu/arm/arm-smmu/arm-smmu.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Comments

Robin Murphy March 2, 2021, 12:17 p.m. UTC | #1
On 2021-02-25 17:51, Jordan Crouse wrote:
> Call report_iommu_fault() to allow upper-level drivers to register their
> own fault handlers.
> 
> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
> ---
> 
>   drivers/iommu/arm/arm-smmu/arm-smmu.c | 9 +++++++--
>   1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index d8c6bfde6a61..0f3a9b5f3284 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -408,6 +408,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
>   	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
>   	struct arm_smmu_device *smmu = smmu_domain->smmu;
>   	int idx = smmu_domain->cfg.cbndx;
> +	int ret;
>   
>   	fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
>   	if (!(fsr & ARM_SMMU_FSR_FAULT))
> @@ -417,8 +418,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
>   	iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
>   	cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
>   
> -	dev_err_ratelimited(smmu->dev,
> -	"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
> +	ret = report_iommu_fault(domain, dev, iova,

Beware that "dev" here is not a struct device, so this isn't right. I'm 
not entirely sure what we *should* be passing here, since we can't 
easily attribute a context fault to a specific client device, and 
passing the IOMMU device seems a bit dubious too, so maybe just NULL?

Robin.

> +		fsynr & ARM_SMMU_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +
> +	if (ret == -ENOSYS)
> +		dev_err_ratelimited(smmu->dev,
> +		"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
>   			    fsr, iova, fsynr, cbfrsynra, idx);
>   
>   	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);
>
Jordan Crouse March 2, 2021, 3:54 p.m. UTC | #2
On Tue, Mar 02, 2021 at 12:17:24PM +0000, Robin Murphy wrote:
> On 2021-02-25 17:51, Jordan Crouse wrote:

> > Call report_iommu_fault() to allow upper-level drivers to register their

> > own fault handlers.

> > 

> > Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>

> > ---

> > 

> >   drivers/iommu/arm/arm-smmu/arm-smmu.c | 9 +++++++--

> >   1 file changed, 7 insertions(+), 2 deletions(-)

> > 

> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > index d8c6bfde6a61..0f3a9b5f3284 100644

> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > @@ -408,6 +408,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)

> >   	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);

> >   	struct arm_smmu_device *smmu = smmu_domain->smmu;

> >   	int idx = smmu_domain->cfg.cbndx;

> > +	int ret;

> >   	fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);

> >   	if (!(fsr & ARM_SMMU_FSR_FAULT))

> > @@ -417,8 +418,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)

> >   	iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);

> >   	cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));

> > -	dev_err_ratelimited(smmu->dev,

> > -	"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",

> > +	ret = report_iommu_fault(domain, dev, iova,

> 

> Beware that "dev" here is not a struct device, so this isn't right. I'm not

> entirely sure what we *should* be passing here, since we can't easily

> attribute a context fault to a specific client device, and passing the IOMMU

> device seems a bit dubious too, so maybe just NULL?


Agreed. The GPU doesn't use it and I doubt anything else would either since the
SMMU device is opaque to the leaf driver.

Jordan

> Robin.

> 

> > +		fsynr & ARM_SMMU_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);

> > +

> > +	if (ret == -ENOSYS)

> > +		dev_err_ratelimited(smmu->dev,

> > +		"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",

> >   			    fsr, iova, fsynr, cbfrsynra, idx);

> >   	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);

> > 

> _______________________________________________

> iommu mailing list

> iommu@lists.linux-foundation.org

> https://lists.linuxfoundation.org/mailman/listinfo/iommu
Rob Clark May 11, 2021, 6:59 p.m. UTC | #3
On Tue, Mar 2, 2021 at 7:54 AM Jordan Crouse <jordan@cosmicpenguin.net> wrote:
>

> On Tue, Mar 02, 2021 at 12:17:24PM +0000, Robin Murphy wrote:

> > On 2021-02-25 17:51, Jordan Crouse wrote:

> > > Call report_iommu_fault() to allow upper-level drivers to register their

> > > own fault handlers.

> > >

> > > Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>

> > > ---

> > >

> > >   drivers/iommu/arm/arm-smmu/arm-smmu.c | 9 +++++++--

> > >   1 file changed, 7 insertions(+), 2 deletions(-)

> > >

> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > > index d8c6bfde6a61..0f3a9b5f3284 100644

> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c

> > > @@ -408,6 +408,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)

> > >     struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);

> > >     struct arm_smmu_device *smmu = smmu_domain->smmu;

> > >     int idx = smmu_domain->cfg.cbndx;

> > > +   int ret;

> > >     fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);

> > >     if (!(fsr & ARM_SMMU_FSR_FAULT))

> > > @@ -417,8 +418,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)

> > >     iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);

> > >     cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));

> > > -   dev_err_ratelimited(smmu->dev,

> > > -   "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",

> > > +   ret = report_iommu_fault(domain, dev, iova,

> >

> > Beware that "dev" here is not a struct device, so this isn't right. I'm not

> > entirely sure what we *should* be passing here, since we can't easily

> > attribute a context fault to a specific client device, and passing the IOMMU

> > device seems a bit dubious too, so maybe just NULL?

>

> Agreed. The GPU doesn't use it and I doubt anything else would either since the

> SMMU device is opaque to the leaf driver.


Looks like other iommu drivers use a fun mix of attached device (for
ones that can make assumptions about one device per domain) and the
iommu dev ptr.. probably NULL is the right answer..

BR,
-R

> Jordan

>

> > Robin.

> >

> > > +           fsynr & ARM_SMMU_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);

> > > +

> > > +   if (ret == -ENOSYS)

> > > +           dev_err_ratelimited(smmu->dev,

> > > +           "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",

> > >                         fsr, iova, fsynr, cbfrsynra, idx);

> > >     arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);

> > >

> > _______________________________________________

> > iommu mailing list

> > iommu@lists.linux-foundation.org

> > https://lists.linuxfoundation.org/mailman/listinfo/iommu

> _______________________________________________

> iommu mailing list

> iommu@lists.linux-foundation.org

> https://lists.linuxfoundation.org/mailman/listinfo/iommu
diff mbox series

Patch

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..0f3a9b5f3284 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -408,6 +408,7 @@  static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	int idx = smmu_domain->cfg.cbndx;
+	int ret;
 
 	fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
 	if (!(fsr & ARM_SMMU_FSR_FAULT))
@@ -417,8 +418,12 @@  static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 	iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
 	cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
 
-	dev_err_ratelimited(smmu->dev,
-	"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
+	ret = report_iommu_fault(domain, dev, iova,
+		fsynr & ARM_SMMU_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+
+	if (ret == -ENOSYS)
+		dev_err_ratelimited(smmu->dev,
+		"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
 			    fsr, iova, fsynr, cbfrsynra, idx);
 
 	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);