Highmem issues with MMC filesystem

Nicolas Pitre nico at fluxnic.net
Thu Mar 18 09:20:06 EDT 2010


On Thu, 18 Mar 2010, Russell King - ARM Linux wrote:

> On Thu, Mar 18, 2010 at 01:15:58PM +0200, saeed bishara wrote:
> > >> The only conclusion I came to so far is that ARMv5 where highmem works
> > >> just fine in all cases has VIVT cache whereas ARMv6 has VIPT cache.
> > >> And the problem with VIPT caches occurs when direct DMA is involved,
> > >> otherwise there is no problem if PIO or NFS is used.  Sprinkling some
> > >> flush_cache_all() in a few places makes things work, but this is not a
> > >> satisfactory solution.
> > >
> > > This sounds like the problem we had with the DMA API.  Since that's now
> > > fixed, there shouldn't be a problem with the latest (-rc) kernels, or
> > > a kernel with my old streaming DMA patches applied.
> > The failure happens also on 2.6.34.rc1,  as Nico said, it looks like
> > that buffers that are subject to DMA remain dirty, as I understand it,
> > for vipt nonaliasing cpu's, the kernel doesn't clean user space cache
> > lines. if I force kmap_atomic/kunmap_atomic to highmem pages that are
> > not mapped by the kernel (kmap_high_get returns null), then the issue
> > disappears.
> 
> In no case does the kernel ever clean user space cache lines for DMA;
> that's not the responsibility of the DMA API.

Let's forget about user space.  Even some kernel space memory is 
affected too.

The issue as I see it is that highmem pages being DMA'd to may be cached 
even when they're unmapped on VIPT machines.  And the DMA code performs 
L1 cache maintenance only on pages which are virtually mapped.

Contrary to VIVT caches which have to be flushed all the time, VIPT 
caches may avoid cache flushing in some cases, which may lead to some 
highmem pages not being mapped but still cached somehow.  But so far I 
just can't find how that could happen.

The only way a highmem page can be unmapped is through kunmap_atomic() 
where an explicit __cpuc_flush_dcache_area() is performed, or through 
flush_all_zero_pkmaps() where flush_cache_kmaps() translates into 
flush_cache_all().

So something allows for some highmem pages to escape cache flushing when 
unmapped.  But I can't find it.


Nicolas


More information about the linux-arm-kernel mailing list