Skip to content
  • David S. Miller's avatar
    sparc64: Guard against flushing openfirmware mappings. · 4ca9a237
    David S. Miller authored
    Based almost entirely upon a patch by Christopher Alexander Tobias
    Schulze.
    
    In commit db64fe02
    
     ("mm: rewrite vmap
    layer") lazy VMAP tlb flushing was added to the vmalloc layer.  This
    causes problems on sparc64.
    
    Sparc64 has two VMAP mapped regions and they are not contiguous with
    eachother.  First we have the malloc mapping area, then another
    unrelated region, then the vmalloc region.
    
    This "another unrelated region" is where the firmware is mapped.
    
    If the lazy TLB flushing logic in the vmalloc code triggers after
    we've had both a module unload and a vfree or similar, it will pass an
    address range that goes from somewhere inside the malloc region to
    somewhere inside the vmalloc region, and thus covering the
    openfirmware area entirely.
    
    The sparc64 kernel learns about openfirmware's dynamic mappings in
    this region early in the boot, and then services TLB misses in this
    area.  But openfirmware has some locked TLB entries which are not
    mentioned in those dynamic mappings and we should thus not disturb
    them.
    
    These huge lazy TLB flush ranges causes those openfirmware locked TLB
    entries to be removed, resulting in all kinds of problems including
    hard hangs and crashes during reboot/reset.
    
    Besides causing problems like this, such huge TLB flush ranges are
    also incredibly inefficient.  A plea has been made with the author of
    the VMAP lazy TLB flushing code, but for now we'll put a safety guard
    into our flush_tlb_kernel_range() implementation.
    
    Since the implementation has become non-trivial, stop defining it as a
    macro and instead make it a function in a C source file.
    
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    4ca9a237