Re: [PATCH 1/2] dma-direct: Validate DMA mask against canonical DMA addresses

Jason Gunthorpe
2026-01-20T15:43:31Z

On Tue, Jan 20, 2026 at 08:55:43PM +0530, Aneesh Kumar K.V wrote:
> > The check in dma_direct_supported() is checking if the device's HW
> > capability can contain the range of dma_addr_t's the DMA API will
> > generate. Since it above is generating dma_addr_t's with the
> > PROT_NS_SHARED set, it is correct to check it against the mask.
> >
> > If the IOVA does not contain PROT_NS_SHARED then I would expect all of
> > the above to be removed too?
> >
> > Can you please explain what the probem is better?
>
> There is no specific problem identified. The motivation for this change
> is to ensure that the trusted device mask check is accurate.

Well, don't break untrusted in the process, and please explain
motivation in commit messages in future. Why things are being changed
is very important information.

> > I just had a long talk with our internal people about this very
> > subject and they were adament that the ARM design had the T=0 SMMU S2
> > configured so that the IOVA starts at PROT_NS_SHARED, not 0. I am
> > against this, I think it is a bad choice, and this patch is showing
> > exactly why :)
> >
> > IMHO you should map the T=0 S2 so that the IOVA starts at 0 and we
> > don't add PROT_NS_SHARED to the IOVA anyhwere.
>
> But how will we support a trusted device access to both shared and
> private memory? Commit 7d953a06241624ee2efb172d037a4168978f4147 goes
> into some details w.r.t why PROT_NS_SHARED was added to dma_addr_t.

The IO translation path used by trusted and untrusted devices are
completely different. You don't need a T=0 device to have the same S2
as a T=1 device. The commit doesn't explain anything, it is just
documenting the poor S2 conventions that CCA already adopted.

What should be done is that the T=0 untrusted translation path, which
can *never* access private memory anyhow, simply puts what the CPU
sees as the PROT_NS_SHARED region starting at IOVA 0. This path is
setup by the host VMM (ie qemu) and HW can support whatever
translation you want. There is no use case to ever not set
PROT_NS_SHARED for T=1 DMA so why break so many real devices by
requiring this useless bit?

The T=1 trusted translation path should have the RMM setup the S2 so
it mirrors the CPU S2 with the private memory at 0 and the shared
starting at PROT_NS_SHARED. An address width limited device would then
be unable to access shared memory without bouncing through private
memory with SWIOTLB, but it can probably access all the private
memory. The existing SWIOTLB address limit bouncing machinery is
designed to mitigate exactly this condition so it can be used to
bounce buffer from private memory to shared if that use case ever
comes up.

Given this little mistake has already happened I'd suggest that the
VMM/qemu be changed to double map the same T=0 space to both 0 and
PROT_NS_SHARED, and have a discovery bit in the guest that it is
allowed to use 0 based IOVA for T=0 DMA.

Then you can fixuup the DMA API calls so that:
1) If an old VMM continue to use PROT_NS_SHARED for T=0 and continue
to check it against the DMA limit, de-supporting address width
limited HW
2) If a new VMM drop PROT_NS_SHARED for T=0 and check it. Since
everything must use SWIOTLB ensure that SWIOTLB allocated addresses
within the device support range, as it already is able to do.
3) For a T=1 device assume it will not DMA to shared memory, we don't
have any way to describe that in the DMA API right now. Check the
native physical address against the limit and SWIOTLB bounce to
private memory for outside the limit.

This way CCA would work on alot more actual HW :\

Jason