aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-01-30 07:34:11 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:34:11 -0500
commitfa28ba21cec24d3fa1279bcae7e5d5ff6224635a (patch)
treedda47a7faa85428753691a50f49b0404f78ea0ec /include
parentf212ec4b7b4d84290f12c9c0416cdea283bf5f40 (diff)
x86: defer cr3 reload when doing pud_clear()
PAE mode requires that we reload cr3 in order to guarantee that changes to the pgd will be noticed by the processor. This means that in principle pud_clear needs to reload cr3 every time. However, because reloading cr3 implies a tlb flush, we want to avoid it where possible. pud_clear() is only used in a couple of places: - in free_pmd_range(), when pulling down a range of process address space, and - huge_pmd_unshare() In both cases, the calling code will do a a tlb flush anyway, so there's no need to do it within pud_clear(). In free_pmd_range(), the pud_clear is immediately followed by pmd_free_tlb(); we can hook that to make the mmu_gather do an unconditional full flush to make sure cr3 gets reloaded. In huge_pmd_unshare, it is followed by flush_tlb_range, which always results in a full cr3-reload tlb flush. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Andi Kleen <ak@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: William Irwin <wli@holomorphy.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include')
-rw-r--r--include/asm-x86/pgalloc_32.h7
-rw-r--r--include/asm-x86/pgtable-3level.h21
2 files changed, 22 insertions, 6 deletions
diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
index 0caa37a9a25f..10c2b452e64c 100644
--- a/include/asm-x86/pgalloc_32.h
+++ b/include/asm-x86/pgalloc_32.h
@@ -74,6 +74,13 @@ static inline void pmd_free(pmd_t *pmd)
74 74
75static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) 75static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
76{ 76{
77 /* This is called just after the pmd has been detached from
78 the pgd, which requires a full tlb flush to be recognized
79 by the CPU. Rather than incurring multiple tlb flushes
80 while the address space is being pulled down, make the tlb
81 gathering machinery do a full flush when we're done. */
82 tlb->fullmm = 1;
83
77 paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); 84 paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
78 tlb_remove_page(tlb, virt_to_page(pmd)); 85 tlb_remove_page(tlb, virt_to_page(pmd));
79} 86}
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
index ed4c6f0e57ec..a195c3e757b9 100644
--- a/include/asm-x86/pgtable-3level.h
+++ b/include/asm-x86/pgtable-3level.h
@@ -96,14 +96,23 @@ static inline void pud_clear(pud_t *pudp)
96 set_pud(pudp, __pud(0)); 96 set_pud(pudp, __pud(0));
97 97
98 /* 98 /*
99 * Pentium-II erratum A13: in PAE mode we explicitly have to flush 99 * In principle we need to do a cr3 reload here to make sure
100 * the TLB via cr3 if the top-level pgd is changed... 100 * the processor recognizes the changed pgd. In practice, all
101 * the places where pud_clear() gets called are followed by
102 * full tlb flushes anyway, so we can defer the cost here.
101 * 103 *
102 * XXX I don't think we need to worry about this here, since 104 * Specifically:
103 * when clearing the pud, the calling code needs to flush the 105 *
104 * tlb anyway. But do it now for safety's sake. - jsgf 106 * mm/memory.c:free_pmd_range() - immediately after the
107 * pud_clear() it does a pmd_free_tlb(). We change the
108 * mmu_gather structure to do a full tlb flush (which has the
109 * effect of reloading cr3) when the pagetable free is
110 * complete.
111 *
112 * arch/x86/mm/hugetlbpage.c:huge_pmd_unshare() - the call to
113 * this is followed by a flush_tlb_range, which on x86 does a
114 * full tlb flush.
105 */ 115 */
106 write_cr3(read_cr3());
107} 116}
108 117
109#define pud_page(pud) \ 118#define pud_page(pud) \