On 8/23/2012 2:30 AM, Haojian Zhuang wrote:
Hi all,
I think that we have a memory mapping issue on ION carveout heap for v3.4+ kernel from android.
The scenario is User app + kernel driver (cpu) + kernel driver (dma) that all these three clients will access memory. And the memory is cacheable.
The .map_kernel() of carveout heap remaps the allocated memory buffer by ioremap().
In arm_ioremap(), we don't allow memory to be mapped. In order to make .map_kernel() working, we need to use memblock_alloc() & memblock_remove() to move the heap memory from system to reserved area. So the linear address of the memory buffer is removed from page table. And the new virtual address comes from .map_kernel() while kernel driver wants to access the buffer.
But ION use dma_sync_sg_for_devices() to flush cache that means they're using linear address from page. So they're using the NOT-EXISTED virtual address that is removed by memblock_remove().
The problem is more fundamental than that. In setting up the sg_list, Ion calls phys_to_page on the carved out memory. There's no guarantee in general that the page returned is valid at all so if addr is a physical address of memory carved out with memblock_remove, page_to_phys(phys_to_page(addr)) != addr.
Internally, we've gotten around this by using the dma_address field in the sg_list to indicate carved out memory. Obviously most APIs rely on sg_lists having a page so this isn't very generic.
Really this problem boils down to the question of should the dma APIs support memory removed with memblock_remove and if so, how?
Solution #1. .map_kernel() only returns the linear address. And there's a limitation of this solution, the heap should be always lying in low memory. So we needn't use any ioremap() and memblock_remove() any more.
How would you reserve a large block of lowmem without calling memblock_remove? The other issue is that if the memory is carved out for Ion, it can't be used for anything else. The lowmem is pretty much wasted if it's not being used constantly.
Also, if you actually want uncached carveout memory this won't work because you can't get an uncached mapping.
Solution #2. Use vmap() in .map_kernel().
vmap won't work because it relies on the page structures being valid.
How do you think about these two solutions?
Regards Haojian
Thanks, Laura