aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86
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
commit6194ba6ff6ccf8d5c54c857600843c67aa82c407 (patch)
tree657dd9f452b252260fcf59959c0586920b8fe4c3 /include/asm-x86
parentfd40d6e3188b12c59696d6cb4a6f26333814d66f (diff)
x86: don't special-case pmd allocations as much
In x86 PAE mode, stop treating pmds as a special case. Previously they were always allocated and freed with the pgd. The modifies the code to be the same as 64-bit mode, where they are allocated on demand. This is a step on the way to unifying 32/64-bit pagetable allocation as much as possible. There is a complicating wart, however. When you install a new reference to a pmd in the pgd, the processor isn't guaranteed to see it unless you reload cr3. Since reloading cr3 also has the side-effect of flushing the tlb, this is an expense that we want to avoid whereever possible. This patch simply avoids reloading cr3 unless the update is to the current pagetable. Later patches will optimise this further. 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/asm-x86')
-rw-r--r--include/asm-x86/pgalloc_32.h22
-rw-r--r--include/asm-x86/pgtable-3level.h39
-rw-r--r--include/asm-x86/pgtable_32.h3
3 files changed, 47 insertions, 17 deletions
diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
index 3482c3427897..0caa37a9a25f 100644
--- a/include/asm-x86/pgalloc_32.h
+++ b/include/asm-x86/pgalloc_32.h
@@ -63,21 +63,35 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
63 */ 63 */
64static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 64static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
65{ 65{
66 BUG(); 66 return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
67 return (pmd_t *)2;
68} 67}
69 68
70static inline void pmd_free(pmd_t *pmd) 69static inline void pmd_free(pmd_t *pmd)
71{ 70{
71 BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
72 free_page((unsigned long)pmd);
72} 73}
73 74
74static 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)
75{ 76{
77 paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
78 tlb_remove_page(tlb, virt_to_page(pmd));
76} 79}
77 80
78static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 81static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
79{ 82{
80 BUG(); 83 paravirt_alloc_pd(mm, __pa(pmd) >> PAGE_SHIFT);
84
85 /* Note: almost everything apart from _PAGE_PRESENT is
86 reserved at the pmd (PDPT) level. */
87 set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
88
89 /*
90 * Pentium-II erratum A13: in PAE mode we explicitly have to flush
91 * the TLB via cr3 if the top-level pgd is changed...
92 */
93 if (mm == current->active_mm)
94 write_cr3(read_cr3());
81} 95}
82#endif /* CONFIG_X86_PAE */ 96#endif /* CONFIG_X86_PAE */
83 97
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
index 62a1ffbc8784..ed4c6f0e57ec 100644
--- a/include/asm-x86/pgtable-3level.h
+++ b/include/asm-x86/pgtable-3level.h
@@ -15,9 +15,19 @@
15#define pgd_ERROR(e) \ 15#define pgd_ERROR(e) \
16 printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) 16 printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
17 17
18#define pud_none(pud) 0 18
19#define pud_bad(pud) 0 19static inline int pud_none(pud_t pud)
20#define pud_present(pud) 1 20{
21 return pud_val(pud) == 0;
22}
23static inline int pud_bad(pud_t pud)
24{
25 return (pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
26}
27static inline int pud_present(pud_t pud)
28{
29 return pud_val(pud) & _PAGE_PRESENT;
30}
21 31
22/* Rules for using set_pte: the pte being assigned *must* be 32/* Rules for using set_pte: the pte being assigned *must* be
23 * either not present or in a state where the hardware will 33 * either not present or in a state where the hardware will
@@ -58,7 +68,7 @@ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
58} 68}
59static inline void native_set_pud(pud_t *pudp, pud_t pud) 69static inline void native_set_pud(pud_t *pudp, pud_t pud)
60{ 70{
61 *pudp = pud; 71 set_64bit((unsigned long long *)(pudp),native_pud_val(pud));
62} 72}
63 73
64/* 74/*
@@ -81,13 +91,20 @@ static inline void native_pmd_clear(pmd_t *pmd)
81 *(tmp + 1) = 0; 91 *(tmp + 1) = 0;
82} 92}
83 93
84/* 94static inline void pud_clear(pud_t *pudp)
85 * Pentium-II erratum A13: in PAE mode we explicitly have to flush 95{
86 * the TLB via cr3 if the top-level pgd is changed... 96 set_pud(pudp, __pud(0));
87 * We do not let the generic code free and clear pgd entries due to 97
88 * this erratum. 98 /*
89 */ 99 * Pentium-II erratum A13: in PAE mode we explicitly have to flush
90static inline void pud_clear (pud_t * pud) { } 100 * the TLB via cr3 if the top-level pgd is changed...
101 *
102 * XXX I don't think we need to worry about this here, since
103 * when clearing the pud, the calling code needs to flush the
104 * tlb anyway. But do it now for safety's sake. - jsgf
105 */
106 write_cr3(read_cr3());
107}
91 108
92#define pud_page(pud) \ 109#define pud_page(pud) \
93((struct page *) __va(pud_val(pud) & PAGE_MASK)) 110((struct page *) __va(pud_val(pud) & PAGE_MASK))
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
index ca7b150ca8b7..7b61cb5989b0 100644
--- a/include/asm-x86/pgtable_32.h
+++ b/include/asm-x86/pgtable_32.h
@@ -31,8 +31,7 @@ extern spinlock_t pgd_lock;
31extern struct page *pgd_list; 31extern struct page *pgd_list;
32void check_pgt_cache(void); 32void check_pgt_cache(void);
33 33
34void pmd_ctor(struct kmem_cache *, void *); 34static inline void pgtable_cache_init(void) {}
35void pgtable_cache_init(void);
36void paging_init(void); 35void paging_init(void);
37 36
38 37