2006-10-03 21:01:26 +00:00
|
|
|
/* include/asm-generic/tlb.h
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Generic TLB shootdown code
|
|
|
|
*
|
|
|
|
* Copyright 2001 Red Hat, Inc.
|
|
|
|
* Based on code from mm/memory.c Copyright Linus Torvalds and others.
|
|
|
|
*
|
2015-11-16 10:08:45 +00:00
|
|
|
* Copyright 2011 Red Hat, Inc., Peter Zijlstra
|
2011-05-25 00:11:45 +00:00
|
|
|
*
|
2005-04-16 22:20:36 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*/
|
|
|
|
#ifndef _ASM_GENERIC__TLB_H
|
|
|
|
#define _ASM_GENERIC__TLB_H
|
|
|
|
|
2018-08-23 08:47:09 +00:00
|
|
|
#include <linux/mmu_notifier.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/swap.h>
|
2008-01-31 21:05:48 +00:00
|
|
|
#include <asm/pgalloc.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
|
2018-08-24 12:28:28 +00:00
|
|
|
#ifdef CONFIG_MMU
|
|
|
|
|
2018-09-04 08:43:14 +00:00
|
|
|
/*
|
|
|
|
* Generic MMU-gather implementation.
|
|
|
|
*
|
|
|
|
* The mmu_gather data structure is used by the mm code to implement the
|
|
|
|
* correct and efficient ordering of freeing pages and TLB invalidations.
|
|
|
|
*
|
|
|
|
* This correct ordering is:
|
|
|
|
*
|
|
|
|
* 1) unhook page
|
|
|
|
* 2) TLB invalidate page
|
|
|
|
* 3) free page
|
|
|
|
*
|
|
|
|
* That is, we must never free a page before we have ensured there are no live
|
|
|
|
* translations left to it. Otherwise it might be possible to observe (or
|
|
|
|
* worse, change) the page content after it has been reused.
|
|
|
|
*
|
|
|
|
* The mmu_gather API consists of:
|
|
|
|
*
|
|
|
|
* - tlb_gather_mmu() / tlb_finish_mmu(); start and finish a mmu_gather
|
|
|
|
*
|
|
|
|
* Finish in particular will issue a (final) TLB invalidate and free
|
|
|
|
* all (remaining) queued pages.
|
|
|
|
*
|
|
|
|
* - tlb_start_vma() / tlb_end_vma(); marks the start / end of a VMA
|
|
|
|
*
|
|
|
|
* Defaults to flushing at tlb_end_vma() to reset the range; helps when
|
|
|
|
* there's large holes between the VMAs.
|
|
|
|
*
|
|
|
|
* - tlb_remove_page() / __tlb_remove_page()
|
|
|
|
* - tlb_remove_page_size() / __tlb_remove_page_size()
|
|
|
|
*
|
|
|
|
* __tlb_remove_page_size() is the basic primitive that queues a page for
|
|
|
|
* freeing. __tlb_remove_page() assumes PAGE_SIZE. Both will return a
|
|
|
|
* boolean indicating if the queue is (now) full and a call to
|
|
|
|
* tlb_flush_mmu() is required.
|
|
|
|
*
|
|
|
|
* tlb_remove_page() and tlb_remove_page_size() imply the call to
|
|
|
|
* tlb_flush_mmu() when required and has no return value.
|
|
|
|
*
|
|
|
|
* - tlb_remove_check_page_size_change()
|
|
|
|
*
|
|
|
|
* call before __tlb_remove_page*() to set the current page-size; implies a
|
|
|
|
* possible tlb_flush_mmu() call.
|
|
|
|
*
|
|
|
|
* - tlb_flush_mmu() / tlb_flush_mmu_tlbonly() / tlb_flush_mmu_free()
|
|
|
|
*
|
|
|
|
* tlb_flush_mmu_tlbonly() - does the TLB invalidate (and resets
|
|
|
|
* related state, like the range)
|
|
|
|
*
|
|
|
|
* tlb_flush_mmu_free() - frees the queued pages; make absolutely
|
|
|
|
* sure no additional tlb_remove_page()
|
|
|
|
* calls happen between _tlbonly() and this.
|
|
|
|
*
|
|
|
|
* tlb_flush_mmu() - the above two calls.
|
|
|
|
*
|
|
|
|
* - mmu_gather::fullmm
|
|
|
|
*
|
|
|
|
* A flag set by tlb_gather_mmu() to indicate we're going to free
|
|
|
|
* the entire mm; this allows a number of optimizations.
|
|
|
|
*
|
|
|
|
* - We can ignore tlb_{start,end}_vma(); because we don't
|
|
|
|
* care about ranges. Everything will be shot down.
|
|
|
|
*
|
|
|
|
* - (RISC) architectures that use ASIDs can cycle to a new ASID
|
|
|
|
* and delay the invalidation until ASID space runs out.
|
|
|
|
*
|
|
|
|
* - mmu_gather::need_flush_all
|
|
|
|
*
|
|
|
|
* A flag that can be set by the arch code if it wants to force
|
|
|
|
* flush the entire TLB irrespective of the range. For instance
|
|
|
|
* x86-PAE needs this when changing top-level entries.
|
|
|
|
*
|
|
|
|
* And requires the architecture to provide and implement tlb_flush().
|
|
|
|
*
|
|
|
|
* tlb_flush() may, in addition to the above mentioned mmu_gather fields, make
|
|
|
|
* use of:
|
|
|
|
*
|
|
|
|
* - mmu_gather::start / mmu_gather::end
|
|
|
|
*
|
|
|
|
* which provides the range that needs to be flushed to cover the pages to
|
|
|
|
* be freed.
|
|
|
|
*
|
|
|
|
* - mmu_gather::freed_tables
|
|
|
|
*
|
|
|
|
* set when we freed page table pages
|
|
|
|
*
|
|
|
|
* - tlb_get_unmap_shift() / tlb_get_unmap_size()
|
|
|
|
*
|
|
|
|
* returns the smallest TLB entry size unmapped in this range
|
|
|
|
*
|
|
|
|
* Additionally there are a few opt-in features:
|
|
|
|
*
|
|
|
|
* HAVE_RCU_TABLE_FREE
|
|
|
|
*
|
|
|
|
* This provides tlb_remove_table(), to be used instead of tlb_remove_page()
|
|
|
|
* for page directores (__p*_free_tlb()). This provides separate freeing of
|
|
|
|
* the page-table pages themselves in a semi-RCU fashion (see comment below).
|
|
|
|
* Useful if your architecture doesn't use IPIs for remote TLB invalidates
|
|
|
|
* and therefore doesn't naturally serialize with software page-table walkers.
|
|
|
|
*
|
|
|
|
* When used, an architecture is expected to provide __tlb_remove_table()
|
|
|
|
* which does the actual freeing of these pages.
|
|
|
|
*
|
|
|
|
* HAVE_RCU_TABLE_INVALIDATE
|
|
|
|
*
|
|
|
|
* This makes HAVE_RCU_TABLE_FREE call tlb_flush_mmu_tlbonly() before freeing
|
|
|
|
* the page-table pages. Required if you use HAVE_RCU_TABLE_FREE and your
|
|
|
|
* architecture uses the Linux page-tables natively.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#define HAVE_GENERIC_MMU_GATHER
|
|
|
|
|
2011-05-25 00:12:00 +00:00
|
|
|
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
|
|
|
|
/*
|
|
|
|
* Semi RCU freeing of the page directories.
|
|
|
|
*
|
|
|
|
* This is needed by some architectures to implement software pagetable walkers.
|
|
|
|
*
|
|
|
|
* gup_fast() and other software pagetable walkers do a lockless page-table
|
|
|
|
* walk and therefore needs some synchronization with the freeing of the page
|
|
|
|
* directories. The chosen means to accomplish that is by disabling IRQs over
|
|
|
|
* the walk.
|
|
|
|
*
|
|
|
|
* Architectures that use IPIs to flush TLBs will then automagically DTRT,
|
|
|
|
* since we unlink the page, flush TLBs, free the page. Since the disabling of
|
|
|
|
* IRQs delays the completion of the TLB flush we can never observe an already
|
|
|
|
* freed page.
|
|
|
|
*
|
|
|
|
* Architectures that do not have this (PPC) need to delay the freeing by some
|
|
|
|
* other means, this is that means.
|
|
|
|
*
|
|
|
|
* What we do is batch the freed directory pages (tables) and RCU free them.
|
|
|
|
* We use the sched RCU variant, as that guarantees that IRQ/preempt disabling
|
|
|
|
* holds off grace periods.
|
|
|
|
*
|
|
|
|
* However, in order to batch these pages we need to allocate storage, this
|
|
|
|
* allocation is deep inside the MM code and can thus easily fail on memory
|
|
|
|
* pressure. To guarantee progress we fall back to single table freeing, see
|
|
|
|
* the implementation of tlb_remove_table_one().
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
struct mmu_table_batch {
|
|
|
|
struct rcu_head rcu;
|
|
|
|
unsigned int nr;
|
|
|
|
void *tables[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_TABLE_BATCH \
|
|
|
|
((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
|
|
|
|
|
|
|
|
extern void tlb_table_flush(struct mmu_gather *tlb);
|
|
|
|
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-05-25 00:11:45 +00:00
|
|
|
/*
|
|
|
|
* If we can't allocate a page to make a big batch of page pointers
|
|
|
|
* to work on, then just handle a few from the on-stack structure.
|
|
|
|
*/
|
|
|
|
#define MMU_GATHER_BUNDLE 8
|
|
|
|
|
2011-05-25 00:12:01 +00:00
|
|
|
struct mmu_gather_batch {
|
|
|
|
struct mmu_gather_batch *next;
|
|
|
|
unsigned int nr;
|
|
|
|
unsigned int max;
|
|
|
|
struct page *pages[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_GATHER_BATCH \
|
|
|
|
((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *))
|
|
|
|
|
2013-01-04 23:35:12 +00:00
|
|
|
/*
|
|
|
|
* Limit the maximum number of mmu_gather batches to reduce a risk of soft
|
|
|
|
* lockups for non-preemptible kernels on huge machines when a lot of memory
|
|
|
|
* is zapped during unmapping.
|
|
|
|
* 10K pages freed at once should be safe even without a preemption point.
|
|
|
|
*/
|
|
|
|
#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH)
|
|
|
|
|
2018-09-04 08:43:14 +00:00
|
|
|
/*
|
|
|
|
* struct mmu_gather is an opaque type used by the mm code for passing around
|
2005-10-30 01:16:01 +00:00
|
|
|
* any data needed by arch specific code for tlb_remove_page.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
struct mmu_gather {
|
|
|
|
struct mm_struct *mm;
|
2018-09-04 08:43:14 +00:00
|
|
|
|
2011-05-25 00:12:00 +00:00
|
|
|
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
|
|
|
|
struct mmu_table_batch *batch;
|
|
|
|
#endif
|
2018-09-04 08:43:14 +00:00
|
|
|
|
2012-06-28 01:02:21 +00:00
|
|
|
unsigned long start;
|
|
|
|
unsigned long end;
|
2018-08-23 19:27:25 +00:00
|
|
|
/*
|
|
|
|
* we are in the middle of an operation to clear
|
|
|
|
* a full mm and can make some optimizations
|
|
|
|
*/
|
|
|
|
unsigned int fullmm : 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we have performed an operation which
|
|
|
|
* requires a complete flush of the tlb
|
|
|
|
*/
|
|
|
|
unsigned int need_flush_all : 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we have removed page directories
|
|
|
|
*/
|
|
|
|
unsigned int freed_tables : 1;
|
2011-05-25 00:12:01 +00:00
|
|
|
|
2018-08-23 20:01:46 +00:00
|
|
|
/*
|
|
|
|
* at which levels have we cleared entries?
|
|
|
|
*/
|
|
|
|
unsigned int cleared_ptes : 1;
|
|
|
|
unsigned int cleared_pmds : 1;
|
|
|
|
unsigned int cleared_puds : 1;
|
|
|
|
unsigned int cleared_p4ds : 1;
|
|
|
|
|
2011-05-25 00:12:01 +00:00
|
|
|
struct mmu_gather_batch *active;
|
|
|
|
struct mmu_gather_batch local;
|
|
|
|
struct page *__pages[MMU_GATHER_BUNDLE];
|
2013-01-04 23:35:12 +00:00
|
|
|
unsigned int batch_count;
|
2016-07-26 22:24:12 +00:00
|
|
|
int page_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2017-08-10 22:24:05 +00:00
|
|
|
void arch_tlb_gather_mmu(struct mmu_gather *tlb,
|
|
|
|
struct mm_struct *mm, unsigned long start, unsigned long end);
|
2011-05-25 00:12:14 +00:00
|
|
|
void tlb_flush_mmu(struct mmu_gather *tlb);
|
2017-08-10 22:24:05 +00:00
|
|
|
void arch_tlb_finish_mmu(struct mmu_gather *tlb,
|
mm: fix MADV_[FREE|DONTNEED] TLB flush miss problem
Nadav reported parallel MADV_DONTNEED on same range has a stale TLB
problem and Mel fixed it[1] and found same problem on MADV_FREE[2].
Quote from Mel Gorman:
"The race in question is CPU 0 running madv_free and updating some PTEs
while CPU 1 is also running madv_free and looking at the same PTEs.
CPU 1 may have writable TLB entries for a page but fail the pte_dirty
check (because CPU 0 has updated it already) and potentially fail to
flush.
Hence, when madv_free on CPU 1 returns, there are still potentially
writable TLB entries and the underlying PTE is still present so that a
subsequent write does not necessarily propagate the dirty bit to the
underlying PTE any more. Reclaim at some unknown time at the future
may then see that the PTE is still clean and discard the page even
though a write has happened in the meantime. I think this is possible
but I could have missed some protection in madv_free that prevents it
happening."
This patch aims for solving both problems all at once and is ready for
other problem with KSM, MADV_FREE and soft-dirty story[3].
TLB batch API(tlb_[gather|finish]_mmu] uses [inc|dec]_tlb_flush_pending
and mmu_tlb_flush_pending so that when tlb_finish_mmu is called, we can
catch there are parallel threads going on. In that case, forcefully,
flush TLB to prevent for user to access memory via stale TLB entry
although it fail to gather page table entry.
I confirmed this patch works with [4] test program Nadav gave so this
patch supersedes "mm: Always flush VMA ranges affected by zap_page_range
v2" in current mmotm.
NOTE:
This patch modifies arch-specific TLB gathering interface(x86, ia64,
s390, sh, um). It seems most of architecture are straightforward but
s390 need to be careful because tlb_flush_mmu works only if
mm->context.flush_mm is set to non-zero which happens only a pte entry
really is cleared by ptep_get_and_clear and friends. However, this
problem never changes the pte entries but need to flush to prevent
memory access from stale tlb.
[1] http://lkml.kernel.org/r/20170725101230.5v7gvnjmcnkzzql3@techsingularity.net
[2] http://lkml.kernel.org/r/20170725100722.2dxnmgypmwnrfawp@suse.de
[3] http://lkml.kernel.org/r/BD3A0EBE-ECF4-41D4-87FA-C755EA9AB6BD@gmail.com
[4] https://patchwork.kernel.org/patch/9861621/
[minchan@kernel.org: decrease tlb flush pending count in tlb_finish_mmu]
Link: http://lkml.kernel.org/r/20170808080821.GA31730@bbox
Link: http://lkml.kernel.org/r/20170802000818.4760-7-namit@vmware.com
Signed-off-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Nadav Amit <namit@vmware.com>
Reported-by: Nadav Amit <namit@vmware.com>
Reported-by: Mel Gorman <mgorman@techsingularity.net>
Acked-by: Mel Gorman <mgorman@techsingularity.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Nadav Amit <nadav.amit@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-08-10 22:24:12 +00:00
|
|
|
unsigned long start, unsigned long end, bool force);
|
2018-09-03 14:07:36 +00:00
|
|
|
void tlb_flush_mmu_free(struct mmu_gather *tlb);
|
2016-07-26 22:24:12 +00:00
|
|
|
extern bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page,
|
|
|
|
int page_size);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-10-29 10:03:09 +00:00
|
|
|
static inline void __tlb_adjust_range(struct mmu_gather *tlb,
|
2016-12-13 00:42:34 +00:00
|
|
|
unsigned long address,
|
|
|
|
unsigned int range_size)
|
2014-10-29 10:03:09 +00:00
|
|
|
{
|
|
|
|
tlb->start = min(tlb->start, address);
|
2016-12-13 00:42:34 +00:00
|
|
|
tlb->end = max(tlb->end, address + range_size);
|
2014-10-29 10:03:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __tlb_reset_range(struct mmu_gather *tlb)
|
|
|
|
{
|
2015-01-12 19:10:55 +00:00
|
|
|
if (tlb->fullmm) {
|
|
|
|
tlb->start = tlb->end = ~0;
|
|
|
|
} else {
|
|
|
|
tlb->start = TASK_SIZE;
|
|
|
|
tlb->end = 0;
|
|
|
|
}
|
2018-08-23 19:27:25 +00:00
|
|
|
tlb->freed_tables = 0;
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->cleared_ptes = 0;
|
|
|
|
tlb->cleared_pmds = 0;
|
|
|
|
tlb->cleared_puds = 0;
|
|
|
|
tlb->cleared_p4ds = 0;
|
2014-10-29 10:03:09 +00:00
|
|
|
}
|
|
|
|
|
2018-08-23 08:47:09 +00:00
|
|
|
static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
|
|
|
|
{
|
|
|
|
if (!tlb->end)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tlb_flush(tlb);
|
|
|
|
mmu_notifier_invalidate_range(tlb->mm, tlb->start, tlb->end);
|
|
|
|
__tlb_reset_range(tlb);
|
|
|
|
}
|
|
|
|
|
2016-07-26 22:24:12 +00:00
|
|
|
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
|
|
|
|
struct page *page, int page_size)
|
|
|
|
{
|
2016-12-13 00:42:43 +00:00
|
|
|
if (__tlb_remove_page_size(tlb, page, page_size))
|
2016-07-26 22:24:12 +00:00
|
|
|
tlb_flush_mmu(tlb);
|
|
|
|
}
|
|
|
|
|
2016-12-13 00:42:43 +00:00
|
|
|
static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
|
2016-07-26 22:24:12 +00:00
|
|
|
{
|
|
|
|
return __tlb_remove_page_size(tlb, page, PAGE_SIZE);
|
|
|
|
}
|
|
|
|
|
2016-07-26 22:24:09 +00:00
|
|
|
/* tlb_remove_page
|
|
|
|
* Similar to __tlb_remove_page but will call tlb_flush_mmu() itself when
|
|
|
|
* required.
|
|
|
|
*/
|
|
|
|
static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
|
|
|
|
{
|
2016-07-26 22:24:12 +00:00
|
|
|
return tlb_remove_page_size(tlb, page, PAGE_SIZE);
|
2016-07-26 22:24:09 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 00:42:40 +00:00
|
|
|
#ifndef tlb_remove_check_page_size_change
|
|
|
|
#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
|
|
|
|
static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
|
|
|
|
unsigned int page_size)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We don't care about page size change, just update
|
|
|
|
* mmu_gather page size here so that debug checks
|
|
|
|
* doesn't throw false warning.
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_DEBUG_VM
|
|
|
|
tlb->page_size = page_size;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-08-23 20:01:46 +00:00
|
|
|
static inline unsigned long tlb_get_unmap_shift(struct mmu_gather *tlb)
|
|
|
|
{
|
|
|
|
if (tlb->cleared_ptes)
|
|
|
|
return PAGE_SHIFT;
|
|
|
|
if (tlb->cleared_pmds)
|
|
|
|
return PMD_SHIFT;
|
|
|
|
if (tlb->cleared_puds)
|
|
|
|
return PUD_SHIFT;
|
|
|
|
if (tlb->cleared_p4ds)
|
|
|
|
return P4D_SHIFT;
|
|
|
|
|
|
|
|
return PAGE_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned long tlb_get_unmap_size(struct mmu_gather *tlb)
|
|
|
|
{
|
|
|
|
return 1UL << tlb_get_unmap_shift(tlb);
|
|
|
|
}
|
|
|
|
|
2014-10-29 10:03:09 +00:00
|
|
|
/*
|
|
|
|
* In the case of tlb vma handling, we can optimise these away in the
|
|
|
|
* case where we're doing a full MM flush. When we're doing a munmap,
|
|
|
|
* the vmas are adjusted to only cover the region to be torn down.
|
|
|
|
*/
|
|
|
|
#ifndef tlb_start_vma
|
|
|
|
#define tlb_start_vma(tlb, vma) do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define __tlb_end_vma(tlb, vma) \
|
|
|
|
do { \
|
2018-08-23 08:47:09 +00:00
|
|
|
if (!tlb->fullmm) \
|
|
|
|
tlb_flush_mmu_tlbonly(tlb); \
|
2014-10-29 10:03:09 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#ifndef tlb_end_vma
|
|
|
|
#define tlb_end_vma __tlb_end_vma
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __tlb_remove_tlb_entry
|
|
|
|
#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
|
|
|
|
*
|
2014-10-29 10:03:09 +00:00
|
|
|
* Record the fact that pte's were really unmapped by updating the range,
|
|
|
|
* so we can later optimise away the tlb invalidate. This helps when
|
|
|
|
* userspace is unmapping already-unmapped pages, which happens quite a lot.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
#define tlb_remove_tlb_entry(tlb, ptep, address) \
|
|
|
|
do { \
|
2016-12-13 00:42:34 +00:00
|
|
|
__tlb_adjust_range(tlb, address, PAGE_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->cleared_ptes = 1; \
|
2005-04-16 22:20:36 +00:00
|
|
|
__tlb_remove_tlb_entry(tlb, ptep, address); \
|
|
|
|
} while (0)
|
|
|
|
|
2018-08-23 20:01:46 +00:00
|
|
|
#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
|
|
|
|
do { \
|
|
|
|
unsigned long _sz = huge_page_size(h); \
|
|
|
|
__tlb_adjust_range(tlb, address, _sz); \
|
|
|
|
if (_sz == PMD_SIZE) \
|
|
|
|
tlb->cleared_pmds = 1; \
|
|
|
|
else if (_sz == PUD_SIZE) \
|
|
|
|
tlb->cleared_puds = 1; \
|
|
|
|
__tlb_remove_tlb_entry(tlb, ptep, address); \
|
2016-12-13 00:42:37 +00:00
|
|
|
} while (0)
|
|
|
|
|
2012-01-13 01:19:16 +00:00
|
|
|
/**
|
|
|
|
* tlb_remove_pmd_tlb_entry - remember a pmd mapping for later tlb invalidation
|
|
|
|
* This is a nop so far, because only x86 needs it.
|
|
|
|
*/
|
|
|
|
#ifndef __tlb_remove_pmd_tlb_entry
|
|
|
|
#define __tlb_remove_pmd_tlb_entry(tlb, pmdp, address) do {} while (0)
|
|
|
|
#endif
|
|
|
|
|
2016-12-13 00:42:34 +00:00
|
|
|
#define tlb_remove_pmd_tlb_entry(tlb, pmdp, address) \
|
|
|
|
do { \
|
|
|
|
__tlb_adjust_range(tlb, address, HPAGE_PMD_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->cleared_pmds = 1; \
|
2016-12-13 00:42:34 +00:00
|
|
|
__tlb_remove_pmd_tlb_entry(tlb, pmdp, address); \
|
2012-01-13 01:19:16 +00:00
|
|
|
} while (0)
|
|
|
|
|
2017-02-24 22:57:02 +00:00
|
|
|
/**
|
|
|
|
* tlb_remove_pud_tlb_entry - remember a pud mapping for later tlb
|
|
|
|
* invalidation. This is a nop so far, because only x86 needs it.
|
|
|
|
*/
|
|
|
|
#ifndef __tlb_remove_pud_tlb_entry
|
|
|
|
#define __tlb_remove_pud_tlb_entry(tlb, pudp, address) do {} while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define tlb_remove_pud_tlb_entry(tlb, pudp, address) \
|
|
|
|
do { \
|
|
|
|
__tlb_adjust_range(tlb, address, HPAGE_PUD_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->cleared_puds = 1; \
|
2017-02-24 22:57:02 +00:00
|
|
|
__tlb_remove_pud_tlb_entry(tlb, pudp, address); \
|
|
|
|
} while (0)
|
|
|
|
|
2016-12-13 00:42:34 +00:00
|
|
|
/*
|
|
|
|
* For things like page tables caches (ie caching addresses "inside" the
|
|
|
|
* page tables, like x86 does), for legacy reasons, flushing an
|
|
|
|
* individual page had better flush the page table caches behind it. This
|
|
|
|
* is definitely how x86 works, for example. And if you have an
|
|
|
|
* architected non-legacy page table cache (which I'm not aware of
|
|
|
|
* anybody actually doing), you're going to have some architecturally
|
|
|
|
* explicit flushing for that, likely *separate* from a regular TLB entry
|
|
|
|
* flush, and thus you'd need more than just some range expansion..
|
|
|
|
*
|
|
|
|
* So if we ever find an architecture
|
|
|
|
* that would want something that odd, I think it is up to that
|
|
|
|
* architecture to do its own odd thing, not cause pain for others
|
|
|
|
* http://lkml.kernel.org/r/CA+55aFzBggoXtNXQeng5d_mRoDnaMBE5Y+URs+PHR67nUpMtaw@mail.gmail.com
|
|
|
|
*
|
|
|
|
* For now w.r.t page table cache, mark the range_size as PAGE_SIZE
|
|
|
|
*/
|
|
|
|
|
2018-07-13 23:59:03 +00:00
|
|
|
#ifndef pte_free_tlb
|
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
Upcoming paches to support the new 64-bit "BookE" powerpc architecture
will need to have the virtual address corresponding to PTE page when
freeing it, due to the way the HW table walker works.
Basically, the TLB can be loaded with "large" pages that cover the whole
virtual space (well, sort-of, half of it actually) represented by a PTE
page, and which contain an "indirect" bit indicating that this TLB entry
RPN points to an array of PTEs from which the TLB can then create direct
entries. Thus, in order to invalidate those when PTE pages are deleted,
we need the virtual address to pass to tlbilx or tlbivax instructions.
The old trick of sticking it somewhere in the PTE page struct page sucks
too much, the address is almost readily available in all call sites and
almost everybody implemets these as macros, so we may as well add the
argument everywhere. I added it to the pmd and pud variants for consistency.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Howells <dhowells@redhat.com> [MN10300 & FRV]
Acked-by: Nick Piggin <npiggin@suse.de>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [s390]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-07-22 05:44:28 +00:00
|
|
|
#define pte_free_tlb(tlb, ptep, address) \
|
2005-04-16 22:20:36 +00:00
|
|
|
do { \
|
2016-12-13 00:42:34 +00:00
|
|
|
__tlb_adjust_range(tlb, address, PAGE_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->freed_tables = 1; \
|
|
|
|
tlb->cleared_pmds = 1; \
|
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
Upcoming paches to support the new 64-bit "BookE" powerpc architecture
will need to have the virtual address corresponding to PTE page when
freeing it, due to the way the HW table walker works.
Basically, the TLB can be loaded with "large" pages that cover the whole
virtual space (well, sort-of, half of it actually) represented by a PTE
page, and which contain an "indirect" bit indicating that this TLB entry
RPN points to an array of PTEs from which the TLB can then create direct
entries. Thus, in order to invalidate those when PTE pages are deleted,
we need the virtual address to pass to tlbilx or tlbivax instructions.
The old trick of sticking it somewhere in the PTE page struct page sucks
too much, the address is almost readily available in all call sites and
almost everybody implemets these as macros, so we may as well add the
argument everywhere. I added it to the pmd and pud variants for consistency.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Howells <dhowells@redhat.com> [MN10300 & FRV]
Acked-by: Nick Piggin <npiggin@suse.de>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [s390]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-07-22 05:44:28 +00:00
|
|
|
__pte_free_tlb(tlb, ptep, address); \
|
2005-04-16 22:20:36 +00:00
|
|
|
} while (0)
|
2018-07-13 23:59:03 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-07-13 23:59:03 +00:00
|
|
|
#ifndef pmd_free_tlb
|
2017-03-09 14:24:06 +00:00
|
|
|
#define pmd_free_tlb(tlb, pmdp, address) \
|
|
|
|
do { \
|
2018-08-23 19:27:25 +00:00
|
|
|
__tlb_adjust_range(tlb, address, PAGE_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->freed_tables = 1; \
|
|
|
|
tlb->cleared_puds = 1; \
|
2017-03-09 14:24:06 +00:00
|
|
|
__pmd_free_tlb(tlb, pmdp, address); \
|
|
|
|
} while (0)
|
2018-07-13 23:59:03 +00:00
|
|
|
#endif
|
2017-03-09 14:24:06 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#ifndef __ARCH_HAS_4LEVEL_HACK
|
2018-07-13 23:59:03 +00:00
|
|
|
#ifndef pud_free_tlb
|
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
Upcoming paches to support the new 64-bit "BookE" powerpc architecture
will need to have the virtual address corresponding to PTE page when
freeing it, due to the way the HW table walker works.
Basically, the TLB can be loaded with "large" pages that cover the whole
virtual space (well, sort-of, half of it actually) represented by a PTE
page, and which contain an "indirect" bit indicating that this TLB entry
RPN points to an array of PTEs from which the TLB can then create direct
entries. Thus, in order to invalidate those when PTE pages are deleted,
we need the virtual address to pass to tlbilx or tlbivax instructions.
The old trick of sticking it somewhere in the PTE page struct page sucks
too much, the address is almost readily available in all call sites and
almost everybody implemets these as macros, so we may as well add the
argument everywhere. I added it to the pmd and pud variants for consistency.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Howells <dhowells@redhat.com> [MN10300 & FRV]
Acked-by: Nick Piggin <npiggin@suse.de>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [s390]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-07-22 05:44:28 +00:00
|
|
|
#define pud_free_tlb(tlb, pudp, address) \
|
2005-04-16 22:20:36 +00:00
|
|
|
do { \
|
2016-12-13 00:42:34 +00:00
|
|
|
__tlb_adjust_range(tlb, address, PAGE_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->freed_tables = 1; \
|
|
|
|
tlb->cleared_p4ds = 1; \
|
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
mm: Pass virtual address to [__]p{te,ud,md}_free_tlb()
Upcoming paches to support the new 64-bit "BookE" powerpc architecture
will need to have the virtual address corresponding to PTE page when
freeing it, due to the way the HW table walker works.
Basically, the TLB can be loaded with "large" pages that cover the whole
virtual space (well, sort-of, half of it actually) represented by a PTE
page, and which contain an "indirect" bit indicating that this TLB entry
RPN points to an array of PTEs from which the TLB can then create direct
entries. Thus, in order to invalidate those when PTE pages are deleted,
we need the virtual address to pass to tlbilx or tlbivax instructions.
The old trick of sticking it somewhere in the PTE page struct page sucks
too much, the address is almost readily available in all call sites and
almost everybody implemets these as macros, so we may as well add the
argument everywhere. I added it to the pmd and pud variants for consistency.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Howells <dhowells@redhat.com> [MN10300 & FRV]
Acked-by: Nick Piggin <npiggin@suse.de>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [s390]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-07-22 05:44:28 +00:00
|
|
|
__pud_free_tlb(tlb, pudp, address); \
|
2005-04-16 22:20:36 +00:00
|
|
|
} while (0)
|
|
|
|
#endif
|
2018-07-13 23:59:03 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2017-03-09 14:24:06 +00:00
|
|
|
#ifndef __ARCH_HAS_5LEVEL_HACK
|
2018-07-13 23:59:03 +00:00
|
|
|
#ifndef p4d_free_tlb
|
2017-03-09 14:24:06 +00:00
|
|
|
#define p4d_free_tlb(tlb, pudp, address) \
|
2005-04-16 22:20:36 +00:00
|
|
|
do { \
|
2018-08-23 19:27:25 +00:00
|
|
|
__tlb_adjust_range(tlb, address, PAGE_SIZE); \
|
2018-08-23 20:01:46 +00:00
|
|
|
tlb->freed_tables = 1; \
|
2017-03-09 14:24:06 +00:00
|
|
|
__p4d_free_tlb(tlb, pudp, address); \
|
2005-04-16 22:20:36 +00:00
|
|
|
} while (0)
|
2017-03-09 14:24:06 +00:00
|
|
|
#endif
|
2018-07-13 23:59:03 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-08-24 12:28:28 +00:00
|
|
|
#endif /* CONFIG_MMU */
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#define tlb_migrate_finish(mm) do {} while (0)
|
|
|
|
|
|
|
|
#endif /* _ASM_GENERIC__TLB_H */
|