-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux…
…/kernel/git/tip/tip Pull x86 mm changes from Ingo Molnar: "The main change in this cycle is the rework of the TLB range flushing code, to simplify, fix and consolidate the code. By Dave Hansen" * 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm: Set TLB flush tunable to sane value (33) x86/mm: New tunable for single vs full TLB flush x86/mm: Add tracepoints for TLB flushes x86/mm: Unify remote INVLPG code x86/mm: Fix missed global TLB flush stat x86/mm: Rip out complicated, out-of-date, buggy TLB flushing x86/mm: Clean up the TLB flushing code x86/smep: Be more informative when signalling an SMEP fault
- Loading branch information
Showing
11 changed files
with
193 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
When the kernel unmaps or modified the attributes of a range of | ||
memory, it has two choices: | ||
1. Flush the entire TLB with a two-instruction sequence. This is | ||
a quick operation, but it causes collateral damage: TLB entries | ||
from areas other than the one we are trying to flush will be | ||
destroyed and must be refilled later, at some cost. | ||
2. Use the invlpg instruction to invalidate a single page at a | ||
time. This could potentialy cost many more instructions, but | ||
it is a much more precise operation, causing no collateral | ||
damage to other TLB entries. | ||
|
||
Which method to do depends on a few things: | ||
1. The size of the flush being performed. A flush of the entire | ||
address space is obviously better performed by flushing the | ||
entire TLB than doing 2^48/PAGE_SIZE individual flushes. | ||
2. The contents of the TLB. If the TLB is empty, then there will | ||
be no collateral damage caused by doing the global flush, and | ||
all of the individual flush will have ended up being wasted | ||
work. | ||
3. The size of the TLB. The larger the TLB, the more collateral | ||
damage we do with a full flush. So, the larger the TLB, the | ||
more attrative an individual flush looks. Data and | ||
instructions have separate TLBs, as do different page sizes. | ||
4. The microarchitecture. The TLB has become a multi-level | ||
cache on modern CPUs, and the global flushes have become more | ||
expensive relative to single-page flushes. | ||
|
||
There is obviously no way the kernel can know all these things, | ||
especially the contents of the TLB during a given flush. The | ||
sizes of the flush will vary greatly depending on the workload as | ||
well. There is essentially no "right" point to choose. | ||
|
||
You may be doing too many individual invalidations if you see the | ||
invlpg instruction (or instructions _near_ it) show up high in | ||
profiles. If you believe that individual invalidations being | ||
called too often, you can lower the tunable: | ||
|
||
/sys/debug/kernel/x86/tlb_single_page_flush_ceiling | ||
|
||
This will cause us to do the global flush for more cases. | ||
Lowering it to 0 will disable the use of the individual flushes. | ||
Setting it to 1 is a very conservative setting and it should | ||
never need to be 0 under normal circumstances. | ||
|
||
Despite the fact that a single individual flush on x86 is | ||
guaranteed to flush a full 2MB [1], hugetlbfs always uses the full | ||
flushes. THP is treated exactly the same as normal memory. | ||
|
||
You might see invlpg inside of flush_tlb_mm_range() show up in | ||
profiles, or you can use the trace_tlb_flush() tracepoints. to | ||
determine how long the flush operations are taking. | ||
|
||
Essentially, you are balancing the cycles you spend doing invlpg | ||
with the cycles that you spend refilling the TLB later. | ||
|
||
You can measure how expensive TLB refills are by using | ||
performance counters and 'perf stat', like this: | ||
|
||
perf stat -e | ||
cpu/event=0x8,umask=0x84,name=dtlb_load_misses_walk_duration/, | ||
cpu/event=0x8,umask=0x82,name=dtlb_load_misses_walk_completed/, | ||
cpu/event=0x49,umask=0x4,name=dtlb_store_misses_walk_duration/, | ||
cpu/event=0x49,umask=0x2,name=dtlb_store_misses_walk_completed/, | ||
cpu/event=0x85,umask=0x4,name=itlb_misses_walk_duration/, | ||
cpu/event=0x85,umask=0x2,name=itlb_misses_walk_completed/ | ||
|
||
That works on an IvyBridge-era CPU (i5-3320M). Different CPUs | ||
may have differently-named counters, but they should at least | ||
be there in some form. You can use pmu-tools 'ocperf list' | ||
(https://github.com/andikleen/pmu-tools) to find the right | ||
counters for a given CPU. | ||
|
||
1. A footnote in Intel's SDM "4.10.4.2 Recommended Invalidation" | ||
says: "One execution of INVLPG is sufficient even for a page | ||
with size greater than 4 KBytes." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.