Re: [PATCH] kernel: dma: let dma use vmalloc area

From: Robin Murphy
Date: Mon Nov 27 2023 - 06:25:02 EST


On 2023-11-27 8:56 am, Zhaoyang Huang wrote:
On Mon, Nov 27, 2023 at 3:14 PM Christoph Hellwig <hch@xxxxxx> wrote:

On Mon, Nov 27, 2023 at 11:09:30AM +0800, zhaoyang.huang wrote:
From: Zhaoyang Huang <zhaoyang.huang@xxxxxxxxxx>

memremap within dma_init_coherent_memory will map the given phys_addr
into vmalloc area if the pa is not found during iterating iomem_resources,
which conflict the rejection of vmalloc area in dma_map_single_attrs.

I can't parse this sentence.
Sorry for the confusion, please find below codes for more information.
dma_init_coherent_memory
memremap
addr = ioremap_wt(offset, size);
What I mean is addr is a vmalloc address, which is implicitly mapped
by dma's framework and not be aware of to the driver.

IMO, it is find to let all valid virtual address be valid for DMA as the
user will keep corresponding RAM safe for transfer.

No, vmalloc address can't be passed to map_single. You need to pass
the page to dma_map_page, and explicitly mange cache consistency
using the invalidate_kernel_vmap_range and flush_kernel_vmap_range
helpers.
Please correct me if I am wrong. According to my understanding, cache
consistency could be solved inside dma_map_page via either
dma_direct_map_page(swio/arch_sync_dma_for_device) or ops->map_page.
The original thought of rejecting vmalloc is that this pa is not safe
as this mapping could go in any time. What I am suggesting is to let
this kind of va be enrolled.

No, the point is that dma_map_single() uses virt_to_page(), and virt_to_page() is definitely not valid for vmalloc addresses. At worst it may blow up in itself with an out-of-bounds dereference; at best it's going to return a completely bogus page pointer which may then make dma_map_page() fall over.

Thanks,
Robin.


static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
/* DMA must never operate on areas that might be remapped. */
if (dev_WARN_ONCE(dev, is_vmalloc_addr(ptr),
"rejecting DMA map of vmalloc memory\n"))
return DMA_MAPPING_ERROR;