diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-01-30 07:32:58 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:32:58 -0500 |
commit | 4891645e764d2e181b834509a689fcd12e890c10 (patch) | |
tree | f347227c2d5a5b112bca8fe76b149ccc5157ef84 /include | |
parent | 8405b122ad0dd75354b3bfed4de9a96514fd40cb (diff) |
x86: unify paravirt pagetable accessors
Put all the defines for mapping pagetable operations to their native
versions (for the non-paravirt case) into one place. Make the
corresponding changes to paravirt.h.
The tricky part here is that when a pagetable entry can't be updated
atomically (ie, 32-bit PAE), we need special handlers for pte_clear,
set_pte_atomic and set_pte_present. However, the other two modes
don't need special handling for these, and can use a common
set_pte(_at) path.
[ mingo@elte.hu: fixes ]
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.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/paravirt.h | 21 | ||||
-rw-r--r-- | include/asm-x86/pgtable-2level.h | 30 | ||||
-rw-r--r-- | include/asm-x86/pgtable-3level.h | 15 | ||||
-rw-r--r-- | include/asm-x86/pgtable.h | 63 | ||||
-rw-r--r-- | include/asm-x86/pgtable_64.h | 64 |
5 files changed, 121 insertions, 72 deletions
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 24385decbd47..4aa06b929e48 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h | |||
@@ -1039,6 +1039,27 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval) | |||
1039 | { | 1039 | { |
1040 | PVOP_VCALL2(pv_mmu_ops.set_pmd, pmdp, pmdval.pud.pgd.pgd); | 1040 | PVOP_VCALL2(pv_mmu_ops.set_pmd, pmdp, pmdval.pud.pgd.pgd); |
1041 | } | 1041 | } |
1042 | |||
1043 | static inline void pmd_clear(pmd_t *pmdp) | ||
1044 | { | ||
1045 | set_pmd(pmdp, __pmd(0)); | ||
1046 | } | ||
1047 | |||
1048 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
1049 | { | ||
1050 | set_pte_at(mm, addr, ptep, __pte(0)); | ||
1051 | } | ||
1052 | |||
1053 | static inline void set_pte_atomic(pte_t *ptep, pte_t pte) | ||
1054 | { | ||
1055 | set_pte(ptep, pte); | ||
1056 | } | ||
1057 | |||
1058 | static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, | ||
1059 | pte_t *ptep, pte_t pte) | ||
1060 | { | ||
1061 | set_pte(ptep, pte); | ||
1062 | } | ||
1042 | #endif /* CONFIG_X86_PAE */ | 1063 | #endif /* CONFIG_X86_PAE */ |
1043 | 1064 | ||
1044 | /* Lazy mode for batching updates / context switch */ | 1065 | /* Lazy mode for batching updates / context switch */ |
diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h index 65cdc8f9e3b3..ce486bdbbbb7 100644 --- a/include/asm-x86/pgtable-2level.h +++ b/include/asm-x86/pgtable-2level.h | |||
@@ -15,29 +15,31 @@ static inline void native_set_pte(pte_t *ptep , pte_t pte) | |||
15 | { | 15 | { |
16 | *ptep = pte; | 16 | *ptep = pte; |
17 | } | 17 | } |
18 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | 18 | |
19 | pte_t *ptep , pte_t pte) | ||
20 | { | ||
21 | native_set_pte(ptep, pte); | ||
22 | } | ||
23 | static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) | 19 | static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
24 | { | 20 | { |
25 | *pmdp = pmd; | 21 | *pmdp = pmd; |
26 | } | 22 | } |
27 | #ifndef CONFIG_PARAVIRT | ||
28 | #define set_pte(pteptr, pteval) native_set_pte(pteptr, pteval) | ||
29 | #define set_pte_at(mm,addr,ptep,pteval) native_set_pte_at(mm, addr, ptep, pteval) | ||
30 | #define set_pmd(pmdptr, pmdval) native_set_pmd(pmdptr, pmdval) | ||
31 | #endif | ||
32 | 23 | ||
33 | #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval) | 24 | static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) |
34 | #define set_pte_present(mm,addr,ptep,pteval) set_pte_at(mm,addr,ptep,pteval) | 25 | { |
26 | native_set_pte(ptep, pte); | ||
27 | } | ||
28 | |||
29 | static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr, | ||
30 | pte_t *ptep, pte_t pte) | ||
31 | { | ||
32 | native_set_pte(ptep, pte); | ||
33 | } | ||
35 | 34 | ||
36 | #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) | 35 | static inline void native_pmd_clear(pmd_t *pmdp) |
36 | { | ||
37 | native_set_pmd(pmdp, __pmd(0)); | ||
38 | } | ||
37 | 39 | ||
38 | static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp) | 40 | static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp) |
39 | { | 41 | { |
40 | *xp = __pte(0); | 42 | *xp = native_make_pte(0); |
41 | } | 43 | } |
42 | 44 | ||
43 | #ifdef CONFIG_SMP | 45 | #ifdef CONFIG_SMP |
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h index a123e687112f..5af7a44ed902 100644 --- a/include/asm-x86/pgtable-3level.h +++ b/include/asm-x86/pgtable-3level.h | |||
@@ -39,11 +39,6 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) | |||
39 | smp_wmb(); | 39 | smp_wmb(); |
40 | ptep->pte_low = pte.pte_low; | 40 | ptep->pte_low = pte.pte_low; |
41 | } | 41 | } |
42 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
43 | pte_t *ptep , pte_t pte) | ||
44 | { | ||
45 | native_set_pte(ptep, pte); | ||
46 | } | ||
47 | 42 | ||
48 | /* | 43 | /* |
49 | * Since this is only called on user PTEs, and the page fault handler | 44 | * Since this is only called on user PTEs, and the page fault handler |
@@ -94,16 +89,6 @@ static inline void native_pmd_clear(pmd_t *pmd) | |||
94 | *(tmp + 1) = 0; | 89 | *(tmp + 1) = 0; |
95 | } | 90 | } |
96 | 91 | ||
97 | #ifndef CONFIG_PARAVIRT | ||
98 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) | ||
99 | #define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte) | ||
100 | #define set_pte_present(mm, addr, ptep, pte) native_set_pte_present(mm, addr, ptep, pte) | ||
101 | #define set_pte_atomic(ptep, pte) native_set_pte_atomic(ptep, pte) | ||
102 | #define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd) | ||
103 | #define set_pud(pudp, pud) native_set_pud(pudp, pud) | ||
104 | #define pmd_clear(pmd) native_pmd_clear(pmd) | ||
105 | #endif | ||
106 | |||
107 | /* | 92 | /* |
108 | * Pentium-II erratum A13: in PAE mode we explicitly have to flush | 93 | * Pentium-II erratum A13: in PAE mode we explicitly have to flush |
109 | * the TLB via cr3 if the top-level pgd is changed... | 94 | * the TLB via cr3 if the top-level pgd is changed... |
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index eb14a70a4728..a1eeacdf9d8c 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
@@ -178,6 +178,39 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
178 | return __pte(val); | 178 | return __pte(val); |
179 | } | 179 | } |
180 | 180 | ||
181 | #ifdef CONFIG_PARAVIRT | ||
182 | #include <asm/paravirt.h> | ||
183 | #else /* !CONFIG_PARAVIRT */ | ||
184 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) | ||
185 | #define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte) | ||
186 | |||
187 | #define set_pte_present(mm, addr, ptep, pte) \ | ||
188 | native_set_pte_present(mm, addr, ptep, pte) | ||
189 | #define set_pte_atomic(ptep, pte) \ | ||
190 | native_set_pte_atomic(ptep, pte) | ||
191 | |||
192 | #define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd) | ||
193 | |||
194 | #ifndef __PAGETABLE_PUD_FOLDED | ||
195 | #define set_pgd(pgdp, pgd) native_set_pgd(pgdp, pgd) | ||
196 | #define pgd_clear(pgd) native_pgd_clear(pgd) | ||
197 | #endif | ||
198 | |||
199 | #ifndef set_pud | ||
200 | # define set_pud(pudp, pud) native_set_pud(pudp, pud) | ||
201 | #endif | ||
202 | |||
203 | #ifndef __PAGETABLE_PMD_FOLDED | ||
204 | #define pud_clear(pud) native_pud_clear(pud) | ||
205 | #endif | ||
206 | |||
207 | #define pte_clear(mm, addr, ptep) native_pte_clear(mm, addr, ptep) | ||
208 | #define pmd_clear(pmd) native_pmd_clear(pmd) | ||
209 | |||
210 | #define pte_update(mm, addr, ptep) do { } while (0) | ||
211 | #define pte_update_defer(mm, addr, ptep) do { } while (0) | ||
212 | #endif /* CONFIG_PARAVIRT */ | ||
213 | |||
181 | #endif /* __ASSEMBLY__ */ | 214 | #endif /* __ASSEMBLY__ */ |
182 | 215 | ||
183 | #ifdef CONFIG_X86_32 | 216 | #ifdef CONFIG_X86_32 |
@@ -188,6 +221,22 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
188 | 221 | ||
189 | #ifndef __ASSEMBLY__ | 222 | #ifndef __ASSEMBLY__ |
190 | 223 | ||
224 | /* local pte updates need not use xchg for locking */ | ||
225 | static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep) | ||
226 | { | ||
227 | pte_t res = *ptep; | ||
228 | |||
229 | /* Pure native function needs no input for mm, addr */ | ||
230 | native_pte_clear(NULL, 0, ptep); | ||
231 | return res; | ||
232 | } | ||
233 | |||
234 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
235 | pte_t *ptep , pte_t pte) | ||
236 | { | ||
237 | native_set_pte(ptep, pte); | ||
238 | } | ||
239 | |||
191 | #ifndef CONFIG_PARAVIRT | 240 | #ifndef CONFIG_PARAVIRT |
192 | /* | 241 | /* |
193 | * Rules for using pte_update - it must be called after any PTE update which | 242 | * Rules for using pte_update - it must be called after any PTE update which |
@@ -206,16 +255,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
206 | #define pte_update_defer(mm, addr, ptep) do { } while (0) | 255 | #define pte_update_defer(mm, addr, ptep) do { } while (0) |
207 | #endif | 256 | #endif |
208 | 257 | ||
209 | /* local pte updates need not use xchg for locking */ | ||
210 | static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep) | ||
211 | { | ||
212 | pte_t res = *ptep; | ||
213 | |||
214 | /* Pure native function needs no input for mm, addr */ | ||
215 | native_pte_clear(NULL, 0, ptep); | ||
216 | return res; | ||
217 | } | ||
218 | |||
219 | /* | 258 | /* |
220 | * We only update the dirty/accessed state if we set | 259 | * We only update the dirty/accessed state if we set |
221 | * the dirty bit by hand in the kernel, since the hardware | 260 | * the dirty bit by hand in the kernel, since the hardware |
@@ -287,10 +326,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
287 | pte_update(mm, addr, ptep); | 326 | pte_update(mm, addr, ptep); |
288 | } | 327 | } |
289 | 328 | ||
290 | #ifndef CONFIG_PARAVIRT | ||
291 | #define pte_clear(mm, addr, ptep) native_pte_clear(mm, addr, ptep) | ||
292 | #endif /* !CONFIG_PARAVIRT */ | ||
293 | |||
294 | #include <asm-generic/pgtable.h> | 329 | #include <asm-generic/pgtable.h> |
295 | #endif /* __ASSEMBLY__ */ | 330 | #endif /* __ASSEMBLY__ */ |
296 | 331 | ||
diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h index 435e17187eb6..29fdeb8111bb 100644 --- a/include/asm-x86/pgtable_64.h +++ b/include/asm-x86/pgtable_64.h | |||
@@ -63,51 +63,59 @@ extern void clear_kernel_mapping(unsigned long addr, unsigned long size); | |||
63 | #define pgd_none(x) (!pgd_val(x)) | 63 | #define pgd_none(x) (!pgd_val(x)) |
64 | #define pud_none(x) (!pud_val(x)) | 64 | #define pud_none(x) (!pud_val(x)) |
65 | 65 | ||
66 | static inline void set_pte(pte_t *dst, pte_t val) | 66 | struct mm_struct; |
67 | |||
68 | static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, | ||
69 | pte_t *ptep) | ||
67 | { | 70 | { |
68 | *dst = val; | 71 | *ptep = native_make_pte(0); |
69 | } | 72 | } |
70 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) | ||
71 | 73 | ||
72 | static inline void set_pmd(pmd_t *dst, pmd_t val) | 74 | static inline void native_set_pte(pte_t *ptep, pte_t pte) |
73 | { | 75 | { |
74 | *dst = val; | 76 | *ptep = pte; |
75 | } | 77 | } |
76 | 78 | ||
77 | static inline void set_pud(pud_t *dst, pud_t val) | 79 | static inline pte_t native_ptep_get_and_clear(pte_t *xp) |
78 | { | 80 | { |
79 | *dst = val; | 81 | #ifdef CONFIG_SMP |
82 | return native_make_pte(xchg(&xp->pte, 0)); | ||
83 | #else | ||
84 | /* native_local_ptep_get_and_clear, but duplicated because of cyclic dependency */ | ||
85 | pte_t ret = *xp; | ||
86 | native_pte_clear(NULL, 0, xp); | ||
87 | return ret; | ||
88 | #endif | ||
80 | } | 89 | } |
81 | 90 | ||
82 | static inline void pud_clear (pud_t *pud) | 91 | static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
83 | { | 92 | { |
84 | set_pud(pud, __pud(0)); | 93 | *pmdp = pmd; |
85 | } | 94 | } |
86 | 95 | ||
87 | static inline void set_pgd(pgd_t *dst, pgd_t val) | 96 | static inline void native_pmd_clear(pmd_t *pmd) |
88 | { | 97 | { |
89 | *dst = val; | 98 | native_set_pmd(pmd, native_make_pmd(0)); |
90 | } | 99 | } |
91 | 100 | ||
92 | static inline void pgd_clear (pgd_t * pgd) | 101 | static inline void native_set_pud(pud_t *pudp, pud_t pud) |
93 | { | 102 | { |
94 | set_pgd(pgd, __pgd(0)); | 103 | *pudp = pud; |
95 | } | 104 | } |
96 | 105 | ||
97 | #define native_ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0)) | 106 | static inline void native_pud_clear(pud_t *pud) |
107 | { | ||
108 | native_set_pud(pud, native_make_pud(0)); | ||
109 | } | ||
98 | 110 | ||
99 | struct mm_struct; | 111 | static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd) |
112 | { | ||
113 | *pgdp = pgd; | ||
114 | } | ||
100 | 115 | ||
101 | static inline pte_t native_ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) | 116 | static inline void native_pgd_clear(pgd_t * pgd) |
102 | { | 117 | { |
103 | pte_t pte; | 118 | native_set_pgd(pgd, native_make_pgd(0)); |
104 | if (full) { | ||
105 | pte = *ptep; | ||
106 | *ptep = __pte(0); | ||
107 | } else { | ||
108 | pte = native_ptep_get_and_clear(ptep); | ||
109 | } | ||
110 | return pte; | ||
111 | } | 119 | } |
112 | 120 | ||
113 | #define pte_same(a, b) ((a).pte == (b).pte) | 121 | #define pte_same(a, b) ((a).pte == (b).pte) |
@@ -151,7 +159,6 @@ static inline unsigned long pmd_bad(pmd_t pmd) | |||
151 | 159 | ||
152 | #define pte_none(x) (!pte_val(x)) | 160 | #define pte_none(x) (!pte_val(x)) |
153 | #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) | 161 | #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) |
154 | #define native_pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) | ||
155 | 162 | ||
156 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this right? */ | 163 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this right? */ |
157 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 164 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
@@ -196,7 +203,6 @@ static inline unsigned long pmd_bad(pmd_t pmd) | |||
196 | pmd_index(address)) | 203 | pmd_index(address)) |
197 | #define pmd_none(x) (!pmd_val(x)) | 204 | #define pmd_none(x) (!pmd_val(x)) |
198 | #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) | 205 | #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) |
199 | #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) | ||
200 | #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot))) | 206 | #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot))) |
201 | #define pmd_pfn(x) ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT) | 207 | #define pmd_pfn(x) ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT) |
202 | 208 | ||