• Nicolas Pitre's avatar
    ARM: 5687/1: fix an oops with highmem · 13f96d8f
    Nicolas Pitre authored
    In xdr_partial_copy_from_skb() there is that sequence:
    
    		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
    		[...]
    		flush_dcache_page(*ppage);
    		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
    
    Mixing flush_dcache_page() and kmap_atomic() is a bit odd,
    especially since kunmap_atomic() must deal with cache issues
    already.  OTOH the non-highmem case must use flush_dcache_page()
    as kunmap_atomic() becomes a no op with no cache maintenance.
    
    Problem is that with highmem the implementation of kmap_atomic()
    doesn't set page->virtual, and page_address(page) returns 0 in
    that case. Here flush_dcache_page() calls __flush_dcache_page()
    which calls __cpuc_flush_dcache_page(page_address(page)) resulting
    in a kernel oops.
    
    None of the kmap_atomic() implementations uses set_page_address().
    Hence we can assume page_address() is always expected to return 0 in
    that case. Let's conditionally call __cpuc_flush_dcache_page() only
    when the page address is non zero, and perform that test only when
    highmem is configured.
    Signed-off-by: default avatarNicolas Pitre <nico@marvell.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    13f96d8f
flush.c 7.07 KB