• Linus Torvalds's avatar
    mremap: properly flush TLB before releasing the page · eb66ae03
    Linus Torvalds authored
    Jann Horn points out that our TLB flushing was subtly wrong for the
    mremap() case.  What makes mremap() special is that we don't follow the
    usual "add page to list of pages to be freed, then flush tlb, and then
    free pages".  No, mremap() obviously just _moves_ the page from one page
    table location to another.
    
    That matters, because mremap() thus doesn't directly control the
    lifetime of the moved page with a freelist: instead, the lifetime of the
    page is controlled by the page table locking, that serializes access to
    the entry.
    
    As a result, we need to flush the TLB not just before releasing the lock
    for the source location (to avoid any concurrent accesses to the entry),
    but also before we release the destination page table lock (to avoid the
    TLB being flushed after somebody else has already done something to that
    page).
    
    This also makes the whole "need_flush" logic unnecessary, since we now
    always end up flushing the TLB for every valid entry.
    Reported-and-tested-by: default avatarJann Horn <jannh@google.com>
    Acked-by: default avatarWill Deacon <will.deacon@arm.com>
    Tested-by: default avatarIngo Molnar <mingo@kernel.org>
    Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    eb66ae03
mremap.c 16.8 KB