public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
@ 2026-03-07  0:17 Nicolin Chen
  2026-03-12 13:51 ` Will Deacon
  0 siblings, 1 reply; 7+ messages in thread
From: Nicolin Chen @ 2026-03-07  0:17 UTC (permalink / raw)
  To: will
  Cc: robin.murphy, joro, jgg, praan, mmarrid, kees, Alexander.Grest,
	baolu.lu, smostafa, linux-arm-kernel, iommu, linux-kernel, bbiber,
	skaestle

From: Malak Marrid <mmarrid@nvidia.com>

When a device is switching away from a domain, either through a detach or a
replace operation, it must drain its IOPF queue that only contains the page
requests for the old domain.

Currently, the IOPF infrastructure is used by master->stall_enabled. So the
stalled transaction for the old domain should be resumed/terminated. Fix it
properly.

Fixes: cfea71aea921 ("iommu/arm-smmu-v3: Put iopf enablement in the domain attach path")
Cc: stable@vger.kernel.org
Co-developed-by: Barak Biber <bbiber@nvidia.com>
Signed-off-by: Barak Biber <bbiber@nvidia.com>
Co-developed-by: Stefan Kaestle <skaestle@nvidia.com>
Signed-off-by: Stefan Kaestle <skaestle@nvidia.com>
Signed-off-by: Malak Marrid <mmarrid@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f0783..2176ee8bec767 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2843,6 +2843,12 @@ static int arm_smmu_enable_iopf(struct arm_smmu_master *master,
 	if (master->iopf_refcount) {
 		master->iopf_refcount++;
 		master_domain->using_iopf = true;
+		/*
+		 * If the device is already on the IOPF queue (domain replace),
+		 * drain in-flight fault handlers so nothing will hold the old
+		 * domain when the core switches the attach handle.
+		 */
+		iopf_queue_flush_dev(master->dev);
 		return 0;
 	}
 
@@ -2866,8 +2872,11 @@ static void arm_smmu_disable_iopf(struct arm_smmu_master *master,
 		return;
 
 	master->iopf_refcount--;
-	if (master->iopf_refcount == 0)
+	if (master->iopf_refcount == 0) {
+		/* Drain in-flight fault handlers before removing device */
+		iopf_queue_flush_dev(master->dev);
 		iopf_queue_remove_device(master->smmu->evtq.iopf, master->dev);
+	}
 }
 
 static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
-- 
2.43.0


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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-07  0:17 [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers Nicolin Chen
@ 2026-03-12 13:51 ` Will Deacon
  2026-03-12 14:25   ` Jason Gunthorpe
  0 siblings, 1 reply; 7+ messages in thread
From: Will Deacon @ 2026-03-12 13:51 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: robin.murphy, joro, jgg, praan, mmarrid, kees, Alexander.Grest,
	baolu.lu, smostafa, linux-arm-kernel, iommu, linux-kernel, bbiber,
	skaestle

On Fri, Mar 06, 2026 at 04:17:23PM -0800, Nicolin Chen wrote:
> From: Malak Marrid <mmarrid@nvidia.com>
> 
> When a device is switching away from a domain, either through a detach or a
> replace operation, it must drain its IOPF queue that only contains the page
> requests for the old domain.
> 
> Currently, the IOPF infrastructure is used by master->stall_enabled. So the
> stalled transaction for the old domain should be resumed/terminated. Fix it
> properly.
> 
> Fixes: cfea71aea921 ("iommu/arm-smmu-v3: Put iopf enablement in the domain attach path")
> Cc: stable@vger.kernel.org
> Co-developed-by: Barak Biber <bbiber@nvidia.com>
> Signed-off-by: Barak Biber <bbiber@nvidia.com>
> Co-developed-by: Stefan Kaestle <skaestle@nvidia.com>
> Signed-off-by: Stefan Kaestle <skaestle@nvidia.com>
> Signed-off-by: Malak Marrid <mmarrid@nvidia.com>
> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 4d00d796f0783..2176ee8bec767 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -2843,6 +2843,12 @@ static int arm_smmu_enable_iopf(struct arm_smmu_master *master,
>  	if (master->iopf_refcount) {
>  		master->iopf_refcount++;
>  		master_domain->using_iopf = true;
> +		/*
> +		 * If the device is already on the IOPF queue (domain replace),
> +		 * drain in-flight fault handlers so nothing will hold the old
> +		 * domain when the core switches the attach handle.
> +		 */
> +		iopf_queue_flush_dev(master->dev);

So this drains the iopf workqueue, but don't you still have a race with
the hardware generating a fault on the old domain and then that only
showing up once you've switched to the new one? What is the actual
problem you're trying to solve with this patch?

>  		return 0;
>  	}
>  
> @@ -2866,8 +2872,11 @@ static void arm_smmu_disable_iopf(struct arm_smmu_master *master,
>  		return;
>  
>  	master->iopf_refcount--;
> -	if (master->iopf_refcount == 0)
> +	if (master->iopf_refcount == 0) {
> +		/* Drain in-flight fault handlers before removing device */
> +		iopf_queue_flush_dev(master->dev);
>  		iopf_queue_remove_device(master->smmu->evtq.iopf, master->dev);

Why doesn't iopf_queue_remove_device() handle the draining? Is there a
case where you _don't_ want to drain the faults on the disable path?

Will

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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-12 13:51 ` Will Deacon
@ 2026-03-12 14:25   ` Jason Gunthorpe
  2026-03-24 14:04     ` Will Deacon
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Gunthorpe @ 2026-03-12 14:25 UTC (permalink / raw)
  To: Will Deacon, Lu Baolu, Kevin Tian
  Cc: Nicolin Chen, robin.murphy, joro, praan, mmarrid, kees,
	Alexander.Grest, baolu.lu, smostafa, linux-arm-kernel, iommu,
	linux-kernel, bbiber, skaestle

On Thu, Mar 12, 2026 at 01:51:26PM +0000, Will Deacon wrote:
> On Fri, Mar 06, 2026 at 04:17:23PM -0800, Nicolin Chen wrote:
> > From: Malak Marrid <mmarrid@nvidia.com>
> > 
> > When a device is switching away from a domain, either through a detach or a
> > replace operation, it must drain its IOPF queue that only contains the page
> > requests for the old domain.
> > 
> > Currently, the IOPF infrastructure is used by master->stall_enabled. So the
> > stalled transaction for the old domain should be resumed/terminated. Fix it
> > properly.
> > 
> > Fixes: cfea71aea921 ("iommu/arm-smmu-v3: Put iopf enablement in the domain attach path")
> > Cc: stable@vger.kernel.org
> > Co-developed-by: Barak Biber <bbiber@nvidia.com>
> > Signed-off-by: Barak Biber <bbiber@nvidia.com>
> > Co-developed-by: Stefan Kaestle <skaestle@nvidia.com>
> > Signed-off-by: Stefan Kaestle <skaestle@nvidia.com>
> > Signed-off-by: Malak Marrid <mmarrid@nvidia.com>
> > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> > ---
> >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > index 4d00d796f0783..2176ee8bec767 100644
> > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > @@ -2843,6 +2843,12 @@ static int arm_smmu_enable_iopf(struct arm_smmu_master *master,
> >  	if (master->iopf_refcount) {
> >  		master->iopf_refcount++;
> >  		master_domain->using_iopf = true;
> > +		/*
> > +		 * If the device is already on the IOPF queue (domain replace),
> > +		 * drain in-flight fault handlers so nothing will hold the old
> > +		 * domain when the core switches the attach handle.
> > +		 */
> > +		iopf_queue_flush_dev(master->dev);
> 
> So this drains the iopf workqueue, but don't you still have a race with
> the hardware generating a fault on the old domain and then that only
> showing up once you've switched to the new one? What is the actual
> problem you're trying to solve with this patch?

HW doesn't generate faults on domains, it calls
iommu_report_device_fault() which calls find_fault_handler() that
uses iommu_attach_handle_get() to find the domain. It then shoves the
domain pointer onto a WQ.

The ordering is supposed to be
 1) IOMMU HW starts using the new domain
 2) iommu_attach_handle_get() returns the new domain
 3) IOMMU driver flushes its own IRQs/queues that may be concurrently
    calling iommu_attach_handle_get()
 4) iopf_queue_flush_dev() to clear the iopf work queue
 5) domain is freed, no pointers in WQs or other threads

So the naked iopf_queue_flush_dev() doesn't seem right, I'd expect a
synchronize_irq() (is that right for threaded IRQs?) too as the
threaded IRQ is concurrently calling iommu_attach_handle_get().

Next, something has gone wrong with the ordering of the xarray stores
in iommu_replace_device_pasid(), it doesn't follow the above since the
store for replace is after attach and flushing. Not sure how that
happened, I remember pointing this ordering out at various times..

Maybe we need to add a dedicated driver callback that does 
#3 and have the core do #4 internally. The driver shouldn't disable
its iopf during attach, it should happen in the flush handler.

> > @@ -2866,8 +2872,11 @@ static void arm_smmu_disable_iopf(struct arm_smmu_master *master,
> >  		return;
> >  
> >  	master->iopf_refcount--;
> > -	if (master->iopf_refcount == 0)
> > +	if (master->iopf_refcount == 0) {
> > +		/* Drain in-flight fault handlers before removing device */
> > +		iopf_queue_flush_dev(master->dev);
> >  		iopf_queue_remove_device(master->smmu->evtq.iopf, master->dev);
> 
> Why doesn't iopf_queue_remove_device() handle the draining? Is there a
> case where you _don't_ want to drain the faults on the disable path?

Because it isn't needed, this hunk is redundant.

We never disable iopf on a master that currently has an attached iopf
capable domain. When the domain was changed all the required flushing
should have been done - there should be exactly one
iopf_queue_flush_dev() inside a driver and it must be inside the
attach flow.

Jason

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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-12 14:25   ` Jason Gunthorpe
@ 2026-03-24 14:04     ` Will Deacon
  2026-03-24 14:17       ` Jason Gunthorpe
  0 siblings, 1 reply; 7+ messages in thread
From: Will Deacon @ 2026-03-24 14:04 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Lu Baolu, Kevin Tian, Nicolin Chen, robin.murphy, joro, praan,
	mmarrid, kees, Alexander.Grest, smostafa, linux-arm-kernel, iommu,
	linux-kernel, bbiber, skaestle

On Thu, Mar 12, 2026 at 11:25:09AM -0300, Jason Gunthorpe wrote:
> On Thu, Mar 12, 2026 at 01:51:26PM +0000, Will Deacon wrote:
> > On Fri, Mar 06, 2026 at 04:17:23PM -0800, Nicolin Chen wrote:
> > > From: Malak Marrid <mmarrid@nvidia.com>
> > > 
> > > When a device is switching away from a domain, either through a detach or a
> > > replace operation, it must drain its IOPF queue that only contains the page
> > > requests for the old domain.
> > > 
> > > Currently, the IOPF infrastructure is used by master->stall_enabled. So the
> > > stalled transaction for the old domain should be resumed/terminated. Fix it
> > > properly.
> > > 
> > > Fixes: cfea71aea921 ("iommu/arm-smmu-v3: Put iopf enablement in the domain attach path")
> > > Cc: stable@vger.kernel.org
> > > Co-developed-by: Barak Biber <bbiber@nvidia.com>
> > > Signed-off-by: Barak Biber <bbiber@nvidia.com>
> > > Co-developed-by: Stefan Kaestle <skaestle@nvidia.com>
> > > Signed-off-by: Stefan Kaestle <skaestle@nvidia.com>
> > > Signed-off-by: Malak Marrid <mmarrid@nvidia.com>
> > > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> > > ---
> > >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ++++++++++-
> > >  1 file changed, 10 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > > index 4d00d796f0783..2176ee8bec767 100644
> > > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > > @@ -2843,6 +2843,12 @@ static int arm_smmu_enable_iopf(struct arm_smmu_master *master,
> > >  	if (master->iopf_refcount) {
> > >  		master->iopf_refcount++;
> > >  		master_domain->using_iopf = true;
> > > +		/*
> > > +		 * If the device is already on the IOPF queue (domain replace),
> > > +		 * drain in-flight fault handlers so nothing will hold the old
> > > +		 * domain when the core switches the attach handle.
> > > +		 */
> > > +		iopf_queue_flush_dev(master->dev);
> > 
> > So this drains the iopf workqueue, but don't you still have a race with
> > the hardware generating a fault on the old domain and then that only
> > showing up once you've switched to the new one? What is the actual
> > problem you're trying to solve with this patch?
> 
> HW doesn't generate faults on domains, it calls
> iommu_report_device_fault() which calls find_fault_handler() that
> uses iommu_attach_handle_get() to find the domain. It then shoves the
> domain pointer onto a WQ.

Sorry, that was sloppy terminology on my part. I'm trying to reason about
faults that are generated by accesses that were translated with the
page-tables of the old domain being reported once we think we are using
the new domain.

> The ordering is supposed to be
>  1) IOMMU HW starts using the new domain
>  2) iommu_attach_handle_get() returns the new domain
>  3) IOMMU driver flushes its own IRQs/queues that may be concurrently
>     calling iommu_attach_handle_get()

Does that mean we should kick the evtq thread? I'm not sure what this
means for the priq.

>  4) iopf_queue_flush_dev() to clear the iopf work queue
>  5) domain is freed, no pointers in WQs or other threads
> 
> So the naked iopf_queue_flush_dev() doesn't seem right, I'd expect a
> synchronize_irq() (is that right for threaded IRQs?) too as the
> threaded IRQ is concurrently calling iommu_attach_handle_get().

I don't think we can rely on the IRQ being taken, though, so presumably
we have to kick the irq thread manually and see what's actually sitting
in the event queue after the CMD_SYNC?

Will

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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-24 14:04     ` Will Deacon
@ 2026-03-24 14:17       ` Jason Gunthorpe
  2026-03-24 14:35         ` Will Deacon
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Gunthorpe @ 2026-03-24 14:17 UTC (permalink / raw)
  To: Will Deacon
  Cc: Lu Baolu, Kevin Tian, Nicolin Chen, robin.murphy, joro, praan,
	mmarrid, kees, Alexander.Grest, smostafa, linux-arm-kernel, iommu,
	linux-kernel, bbiber, skaestle

On Tue, Mar 24, 2026 at 02:04:03PM +0000, Will Deacon wrote:
> Sorry, that was sloppy terminology on my part. I'm trying to reason about
> faults that are generated by accesses that were translated with the
> page-tables of the old domain being reported once we think we are using
> the new domain.

It doesn't matter.

If a concurrent fault is resolving on the old domain and it completes
after the STE is in the new domain the device will restart and if the
IOVA is still non-present it will refault. This is normal and fine.

If it is resolving on the new domain and the new domain has a present
PTE so the PRI is spurious then the fault handler should NOP it and
restart the device.

> > The ordering is supposed to be
> >  1) IOMMU HW starts using the new domain
> >  2) iommu_attach_handle_get() returns the new domain
> >  3) IOMMU driver flushes its own IRQs/queues that may be concurrently
> >     calling iommu_attach_handle_get()
> 
> Does that mean we should kick the evtq thread? I'm not sure what this
> means for the priq.

The locking issue is around iommu_attach_handle_get(), so any
thread/irq concurrently calling that has to be fenced. That's it. We
don't have to expedite or synchronize with concurrent PRI at all.

> I don't think we can rely on the IRQ being taken, though, so presumably
> we have to kick the irq thread manually and see what's actually sitting
> in the event queue after the CMD_SYNC?

Er, I thought the iommu_attach_handle_get() was in a threaded irq? If
it is in a WQ then yeah more is needed.

Jason

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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-24 14:17       ` Jason Gunthorpe
@ 2026-03-24 14:35         ` Will Deacon
  2026-03-24 18:53           ` Jason Gunthorpe
  0 siblings, 1 reply; 7+ messages in thread
From: Will Deacon @ 2026-03-24 14:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Lu Baolu, Kevin Tian, Nicolin Chen, robin.murphy, joro, praan,
	mmarrid, kees, Alexander.Grest, smostafa, linux-arm-kernel, iommu,
	linux-kernel, bbiber, skaestle

On Tue, Mar 24, 2026 at 11:17:16AM -0300, Jason Gunthorpe wrote:
> On Tue, Mar 24, 2026 at 02:04:03PM +0000, Will Deacon wrote:
> > Sorry, that was sloppy terminology on my part. I'm trying to reason about
> > faults that are generated by accesses that were translated with the
> > page-tables of the old domain being reported once we think we are using
> > the new domain.
> 
> It doesn't matter.
> 
> If a concurrent fault is resolving on the old domain and it completes
> after the STE is in the new domain the device will restart and if the
> IOVA is still non-present it will refault. This is normal and fine.
> 
> If it is resolving on the new domain and the new domain has a present
> PTE so the PRI is spurious then the fault handler should NOP it and
> restart the device.

Hmm, I can see that working out if both domains expect faults, but if
I'm switching to a domain without a handler wouldn't I be better off
draining the outstanding faults generated on the old domain first?
Otherwise, won't we see a bunch of noise from the eventq thread as
it dumps unexpected events to the console?

Will

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

* Re: [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers
  2026-03-24 14:35         ` Will Deacon
@ 2026-03-24 18:53           ` Jason Gunthorpe
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Gunthorpe @ 2026-03-24 18:53 UTC (permalink / raw)
  To: Will Deacon
  Cc: Lu Baolu, Kevin Tian, Nicolin Chen, robin.murphy, joro, praan,
	mmarrid, kees, Alexander.Grest, smostafa, linux-arm-kernel, iommu,
	linux-kernel, bbiber, skaestle

On Tue, Mar 24, 2026 at 02:35:14PM +0000, Will Deacon wrote:
> On Tue, Mar 24, 2026 at 11:17:16AM -0300, Jason Gunthorpe wrote:
> > On Tue, Mar 24, 2026 at 02:04:03PM +0000, Will Deacon wrote:
> > > Sorry, that was sloppy terminology on my part. I'm trying to reason about
> > > faults that are generated by accesses that were translated with the
> > > page-tables of the old domain being reported once we think we are using
> > > the new domain.
> > 
> > It doesn't matter.
> > 
> > If a concurrent fault is resolving on the old domain and it completes
> > after the STE is in the new domain the device will restart and if the
> > IOVA is still non-present it will refault. This is normal and fine.
> > 
> > If it is resolving on the new domain and the new domain has a present
> > PTE so the PRI is spurious then the fault handler should NOP it and
> > restart the device.
> 
> Hmm, I can see that working out if both domains expect faults, but if
> I'm switching to a domain without a handler 

iommu_report_device_fault() still handles the event and generates an
error ack.

> wouldn't I be better off draining the outstanding faults generated
> on the old domain first?  Otherwise, won't we see a bunch of noise
> from the eventq thread as it dumps unexpected events to the console?

Yes, it does look like since iommu_report_device_fault() handles it
but returns an error code we will get a print.

You'd need to double flush the the event queue. We always have to
flush after changing the group->domain since that is preventing a UAF

Then you'd have to flush before changing the group->domain to avoid
the prints if faulting is being disabled.

IDK, may not be worth worrying about or maybe we should just remove
the prints..

Jason

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

end of thread, other threads:[~2026-03-24 18:54 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-07  0:17 [PATCH rc] iommu/arm-smmu-v3: Drain in-flight fault handlers Nicolin Chen
2026-03-12 13:51 ` Will Deacon
2026-03-12 14:25   ` Jason Gunthorpe
2026-03-24 14:04     ` Will Deacon
2026-03-24 14:17       ` Jason Gunthorpe
2026-03-24 14:35         ` Will Deacon
2026-03-24 18:53           ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox