Over the years, LWN has also looked at ARM'sspecial memory managementchallenges. Recent ARM CPUs are, like those implementing otherarchitectures, becoming more complex in order to improve performance. SoARM processors can now do speculative prefetching of memory contents insurprising ways. This prefetching works well on cached memory, but should notbe used on memory that has been marked as uncached. An additionalcomplication comes from the fact that virtual memory systemscan have more than one mapping for a given range of memory, and caching isa feature of the mapping, not the memory itself. So one might well wonderwhat happens if different mappings have different caching attributes. Onrecent ARM processor designs, what happens is officially undefined; inpractice, it can mean problems like corrupted memory, machine checks, orsimple hangs. As it happens, kernel developers normally go out of theirway to avoid that kind of behavior.
The current CMA mechanism is used as an allocator behinddma_alloc_coherent(), which creates a cache-coherent DMA buffer.In the absence of bus-snooping hardware that is able to notice when a DMAtransfer changes memory, "cache-coherent" is likely to mean simply"uncached." So CMA must, on such systems, create an uncached range ofmemory to hand back to the requesting driver. That is easily done, and allshould be well...at least, unless there happens to be another mapping tothe same memory with different caching attributes.
Unfortunately, conflicting mappings can come about easily on a Linuxsystem. One of the first things the kernel does as it boots is to create a"linear mapping" which provides kernel-space virtual addresses for most orall of the memory present in the system. The kernel cannot manipulatememory directly without such a mapping; putting as much of memory aspossible into a persistent mapping thus makes sense. On a 32-bit system,just under 1GB of memory can be mapped this way (64-bit systems can alwaysmap all of memory and will be able to do so for quite some time yet). Thiskernel-mapped memory is called "low memory"; almost all allocations ofmemory for the kernel's use come from the low memory area. Naturally, lowmemory is mapped with caching enabled; to do otherwise would destroy the performance ofthe system. If a region of low memory is turned into a DMA buffer with anuncached mapping, the system will have two conflicting mappings for thesame memory and will have moved into "undefined behavior" territory.
These conflicting mappings are the reason behind ARM maintainer RussellKing's strong opposition to the merging ofCMA in its current form. He believes that the code is unsafe on ARMsystems; it should not, he says, be merged until the mapping problem hasbeen solved.The interesting thing is that the existing DMA API has the same problem onARM; dma_alloc_coherent() uses vanilla alloc_pages() toobtain a buffer, then changes the caching attributes before giving thebuffer back to the caller. The addition of CMA does not make ARM's DMA APIany more or less safe than it was before; it just perpetuates an existingproblem.
Russell has a patch pending for 3.1 which addresses this problemby setting aside a chunk of memory which is never mapped into the kernel'saddress space. With this memory pool available, coherent DMA mappings canbe set up without endangering the operation of the system.The whole reason CMA exists, though, is to provide large, contiguousbuffers without the need to set aside memory; Russell's approach thusdefeats the entire purpose. The pressures which have led to the creationof CMA will not go away anytime soon, so it seems that another solution isneeded. Arnd Bergmann has outlined twopossibilities, neither of which is entirely pleasant:
......
Please access the below link to view the full content.
Original link: http://lwn.net/Articles/449925/