ion: map cma heap to user with vm_insert_page, not remap_pfn_range
remap_pfn_range takes any memory even if not backed by struct page.
All ion heaps are nowadays, which is why ion_heap_map_user does the
call like this (starting with a page, getting its pfn):
remap_pfn_range(vma, addr, page_to_pfn(page), len,
vma->vm_page_prot);
remap_pfn_range sets:
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
Because of VM_IO and VM_PFNMAP the mapped buffer can't be used by
the gasket driver. In user mmap is called, and the pointer is passed
all the way to gasket's user part, which ioctl's into
drivers/staging/gasket/gasket_page_table.c gasket_perform_mapping
to map the user pointer for DMA. Gasket needs the backing physical
page, and uses get_user_pages_fast for this. This fails because
mm/gup.c check_vma_flags
if (vm_flags & (VM_IO | VM_PFNMAP))
return -EFAULT;
This makes ION buffers allocated from the CMA heap unusable by
gasket without copying it to a virtual user address with
different vm_flags.
So we need a user mapping with different vm_flags, which can be
achieved with vm_insert_page. It requires caller to have struct
page to work with, which we do. For CMA this mapping is straight
forward as cma_alloc by definition allocates entire physically
contiguous pages. Scatter gather table thus only have one entry
per ION buffer from the CMA heap, see ion_cma_allocate.
Further details:
https://lkml.org/lkml/2006/3/16/170
BUG: 142164990
Change-Id: I434cbc4e89d86275850cada705253453c1e3f071
1 file changed