• Nitin Gupta's avatar
    ARM: force dcache flush if dcache_dirty bit set · 787b2faa
    Nitin Gupta authored
    On ARM, update_mmu_cache() does dcache flush for a page only if
    it has a kernel mapping (page_mapping(page) != NULL). The correct
    behavior would be to force the flush based on dcache_dirty bit only.
    
    One of the cases where present logic would be a problem is when
    a RAM based block device[1] is used as a swap disk. In this case,
    we would have in-memory data corruption as shown in steps below:
    
    do_swap_page()
    {
        - Allocate a new page (if not already in swap cache)
        - Issue read from swap disk
            - Block driver issues flush_dcache_page()
            - flush_dcache_page() simply sets PG_dcache_dirty bit and does not
              actually issue a flush since this page has no user space mapping yet.
        - Now, if swap disk is almost full, this newly read page is removed
          from swap cache and corrsponding swap slot is freed.
        - Map this page anonymously in user space.
        - update_mmu_cache()
            - Since this page does not have kernel mapping (its not in page/swap
              cache and is mapped anonymously), it does not issue dcache flush
              even if dcache_dirty bit is set by flush_dcache_page() above.
    
        <user now gets stale data since dcache was never flushed>
    }
    
    Same problem exists on mips too.
    
    [1] example:
     - brd (RAM based block device)
     - ramzswap (RAM based compressed swap device)
    Signed-off-by: default avatarNitin Gupta <ngupta@vflare.org>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    787b2faa
fault-armv.c 5.56 KB