Re: [PATCH 2/2] arm: use swiotlb for bounce buffer on LPAE configs

From: Christoph Hellwig
Date: Thu Jan 09 2020 - 09:49:24 EST


On Wed, Jan 08, 2020 at 03:20:07PM +0000, Robin Murphy wrote:
>> The problem - I think - is that the DMA_BIT_MASK(32) from
>> dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)) is treated as physical
>> address along the call path so the dma_pfn_offset is applied to it and
>> the check will fail, saying that DMA_BIT_MASK(32) can not be supported.
>
> But that's the thing - in isolation, that is entirely correct. Considering
> ZONE_DMA32 for simplicity, in general the zone is expected to cover the
> physical address range 0x0000_0000 - 0xffff_ffff (because DMA offsets are
> relatively rare), and a device with a dma_pfn_offset of more than
> (0x1_0000_0000 >> PAGE_SHIFT) *cannot* support that range with any mask,
> because the DMA address itself would have to be negative.

Note that ZONE_DMA32 is irrelevant in this particular case, as we are
talking about arm32. But with ZONE_DMA instead this roughly makes sense.

> The problem is that platforms with esoteric memory maps have no right thing
> to do. If the base of RAM is at at 0x1_0000_0000 or higher, the "correct"
> ZONE_DMA32 would be empty while ZONE_NORMAL above it would not, and last
> time I looked that makes the page allocator break badly. So the standard
> bodge on such platforms is to make ZONE_DMA32 cover not the first 4GB of
> *PA space*, but the first 4GB of *RAM*, wherever that happens to be. That
> then brings different problems - now the page allocator is happy and
> successfully returns GFP_DMA32 allocations from the range 0x8_0000_0000 -
> 0x8_ffff_ffff that are utterly useless to 32-bit devices with zero
> dma_pfn_offset - see the AMD Seattle SoC for the prime example of that. If
> on the other hand all devices are guaranteed to have a dma_pfn_offset that
> puts the base of RAM at DMA address 0 then GFP_DMA32 allocations do end up
> working as expected, but now the original assumption of where ZONE_DMA32
> actually is is broken, so generic code unaware of the
> platform/architecture-specific bodge will be misled - that's the case
> you're running into.
>
> Having thought this far, if there's a non-hacky way to reach in and grab
> ZONE_DMA{32} such that dma_direct_supported() could use zone_end_pfn()
> instead of trying to assume either way, that might be the most robust
> general solution.

zone_dma_bits is our somewhat ugly way to try to poke into this
information, although the way it is done right now sucks pretty badly.

The patch I sent to Peter in December was trying to convey that
information in a way similar to what the arm32 legacy dma code does, but
it didn't work, so I'll need to find some time to sit down and figure out
why.