On Mon, 9 Mar 2026 10:33:10 +0100
Christian König <[email protected]> wrote:

> On 3/6/26 15:55, Boris Brezillon wrote:
> > On Fri, 6 Mar 2026 13:54:15 +0100
> > Christian König <[email protected]> wrote:
> >   
> >> On 3/6/26 13:36, Philipp Stanner wrote:  
> >>>>>> (which
> >>>>>> is the thing that would be attached to the HW ringbuf. The
> >>>>>> reason is: we don't want to leave unsignalled fences behind,
> >>>>>>    
> >>>>>
> >>>>> Not only do we not "want to", we actually *cannot*. We have to
> >>>>> make sure all fences are signaled because only this way the C
> >>>>> backend plus RCU can protect also the Rust code against UAF.
> >>>>>    
> >>>>>>  and if the HW ring is
> >>>>>> gone, there's nothing that can signal it. Mind explaining why
> >>>>>> you think this shouldn't be done, because I originally
> >>>>>> interpreted your suggestion as exactly the opposite.    
> >>>>>
> >>>>> I also don't get it. All fences must always get signaled, that's
> >>>>> one of the most fundamental fence rules. Thus, if the last
> >>>>> accessor to a fence drops, you do want to signal it with
> >>>>> -ECANCELED    
> >>>>
> >>>> All fences must always signal because the HW operation must
> >>>> always complete or be terminated by a timeout.
> >>>>
> >>>> If a fence signals only because it runs out of scope than that
> >>>> means that you have a huge potential for data corruption and that
> >>>> is even worse than not signaling a fence.
> >>>>
> >>>> In other words not signaling a fence can leave the system in a
> >>>> deadlock state, but signaling it incorrectly usually results in
> >>>> random data corruption.    
> >>>
> >>> It all stands and falls with the question whether a fence can drop
> >>> by accident in Rust, or if it will only ever drop when the hw-ring
> >>> is closed.
> >>>
> >>> What do you believe is the right thing to do when a driver
> >>> unloads? 
> >>
> >> Do a dma_fence_wait() to make sure that all HW operations have
> >> completed and all fences signaled.
> >>  
> >>> Ideally we could design it in a way that the driver closes its
> >>> rings, the pending fences drop and get signaled with ECANCELED.
> >>>  
> >>
> >> No, exactly that is a really bad idea.
> >>
> >> Just do it the other way around, use the dma_fence to wait for the
> >> HW operation to be completed.  
> > 
> > But in practice you don't just wait for the HW to finish most of the
> > time. You instruct the HW to stop processing stuff, and then wait
> > for it to acknowledge that it indeed stopped.  
> 
> And how does the HW acknowledged that it has indeed stopped? Maybe by
> sending an interrupt which signals a DMA-fence?

Yes, it's likely something like a _STATUS register update reflecting
the new HW state, plus an interrupt to wake the CPU up. The decision to
poll the status register or go the async-way is up to the driver.

> 
> The point here is that all acknowledgement from the HW that a DMA
> operation was indeed stopped, independent if it's the normal
> operation completed use case or if it's the I have aborted use case,
> *must* always take the same HW and SW path.
> 
> It is *not* sufficient that you do something like busy waiting for a
> bit in a register to flip in the abortion path and for a DMA memory
> write in the normal completion path.

I'm assuming the DMA_OP_COMPLETE is also a register update of some
sort. But let's assume it's not, then sure, we need to make sure the
operation is either complete (event received through the IRQ handler),
or the DMA engine is fully stopped. Doesn't really matter which path is
doing this check, as long as it's done.

> 
> That's why MMU/VM inside a device is usually not sufficient to
> prevent freed memory from being written to. You need an IOMMU for
> that, e.g. close to the CPU/memory and without caches behind the HW
> path.

Either that, or you need a way to preempt DMA engine operations and
have them cancelled before they make it to the bus, plus wait for the
non-cancellable ones. And it doesn't really matter how the HW works,
because my point is not that we need to enforce how the SW can ensure
the HW is done processing the stuff (that's very HW specific), just
that there needs to be a way to do this SW <-> HW synchronization, and
it's the driver responsibility to ensure that ultimately. My second
point was that, once the HW block is considered idle, there might be
operations that were never dequeued because they were cancelled before
the HW got to it, and for those, we'll never get HW events. We just have
to walk the list and manually signal fences. That's the step I was
suggesting to automate through the auto-signal-on-drop approach, but we
can automate it through an explicit DriverFenceTimeline::cancel_all()
method, I guess.

Reply via email to