• Nicolas Pitre's avatar
    ARM: 6007/1: fix highmem with VIPT cache and DMA · 7e5a69e8
    Nicolas Pitre authored
    The VIVT cache of a highmem page is always flushed before the page
    is unmapped.  This cache flush is explicit through flush_cache_kmaps()
    in flush_all_zero_pkmaps(), or through __cpuc_flush_dcache_area() in
    kunmap_atomic().  There is also an implicit flush of those highmem pages
    that were part of a process that just terminated making those pages free
    as the whole VIVT cache has to be flushed on every task switch. Hence
    unmapped highmem pages need no cache maintenance in that case.
    
    However unmapped pages may still be cached with a VIPT cache because the
    cache is tagged with physical addresses.  There is no need for a whole
    cache flush during task switching for that reason, and despite the
    explicit cache flushes in flush_all_zero_pkmaps() and kunmap_atomic(),
    some highmem pages that were mapped in user space end up still cached
    even when they become unmapped.
    
    So, we do have to perform cache maintenance on those unmapped highmem
    pages in the context of DMA when using a VIPT cache.  Unfortunately,
    it is not possible to perform that cache maintenance using physical
    addresses as all the L1 cache maintenance coprocessor functions accept
    virtual addresses only.  Therefore we have no choice but to set up a
    temporary virtual mapping for that purpose.
    
    And of course the explicit cache flushing when unmapping a highmem page
    on a system with a VIPT cache now can go, which should increase
    performance.
    
    While at it, because the code in __flush_dcache_page() has to be modified
    anyway, let's also make sure the mapped highmem pages are pinned with
    kmap_high_get() for the duration of the cache maintenance operation.
    Because kunmap() does unmap highmem pages lazily, it was reported by
    Gary King <GKing@nvidia.com> that those pages ended up being unmapped
    during cache maintenance on SMP causing segmentation faults.
    Signed-off-by: default avatarNicolas Pitre <nico@marvell.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    7e5a69e8
highmem.c 5.43 KB