diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-05-02 13:27:13 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:13 -0400 |
commit | 3dc494e86d1c93afd4c66385f270899dbfae483d (patch) | |
tree | 6583b57492dc91ef7cc6c23a233f7d5bb95bb5f6 /arch/i386 | |
parent | 45876233605c268e929a7875081e129debe34bdc (diff) |
[PATCH] i386: PARAVIRT: Add pagetable accessors to pack and unpack pagetable entries
Add a set of accessors to pack, unpack and modify page table entries
(at all levels). This allows a paravirt implementation to control the
contents of pgd/pmd/pte entries. For example, Xen uses this to
convert the (pseudo-)physical address into a machine address when
populating a pagetable entry, and converting back to pphys address
when an entry is read.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/paravirt.c | 84 | ||||
-rw-r--r-- | arch/i386/kernel/vmi.c | 6 |
2 files changed, 15 insertions, 75 deletions
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index 3fdbd1f62379..cba7a15ce1b0 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c | |||
@@ -117,78 +117,6 @@ static void native_flush_tlb_single(u32 addr) | |||
117 | __native_flush_tlb_single(addr); | 117 | __native_flush_tlb_single(addr); |
118 | } | 118 | } |
119 | 119 | ||
120 | #ifndef CONFIG_X86_PAE | ||
121 | static void native_set_pte(pte_t *ptep, pte_t pteval) | ||
122 | { | ||
123 | *ptep = pteval; | ||
124 | } | ||
125 | |||
126 | static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval) | ||
127 | { | ||
128 | *ptep = pteval; | ||
129 | } | ||
130 | |||
131 | static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval) | ||
132 | { | ||
133 | *pmdp = pmdval; | ||
134 | } | ||
135 | |||
136 | #else /* CONFIG_X86_PAE */ | ||
137 | |||
138 | static void native_set_pte(pte_t *ptep, pte_t pte) | ||
139 | { | ||
140 | ptep->pte_high = pte.pte_high; | ||
141 | smp_wmb(); | ||
142 | ptep->pte_low = pte.pte_low; | ||
143 | } | ||
144 | |||
145 | static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte) | ||
146 | { | ||
147 | ptep->pte_high = pte.pte_high; | ||
148 | smp_wmb(); | ||
149 | ptep->pte_low = pte.pte_low; | ||
150 | } | ||
151 | |||
152 | static void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) | ||
153 | { | ||
154 | ptep->pte_low = 0; | ||
155 | smp_wmb(); | ||
156 | ptep->pte_high = pte.pte_high; | ||
157 | smp_wmb(); | ||
158 | ptep->pte_low = pte.pte_low; | ||
159 | } | ||
160 | |||
161 | static void native_set_pte_atomic(pte_t *ptep, pte_t pteval) | ||
162 | { | ||
163 | set_64bit((unsigned long long *)ptep,pte_val(pteval)); | ||
164 | } | ||
165 | |||
166 | static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval) | ||
167 | { | ||
168 | set_64bit((unsigned long long *)pmdp,pmd_val(pmdval)); | ||
169 | } | ||
170 | |||
171 | static void native_set_pud(pud_t *pudp, pud_t pudval) | ||
172 | { | ||
173 | *pudp = pudval; | ||
174 | } | ||
175 | |||
176 | static void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
177 | { | ||
178 | ptep->pte_low = 0; | ||
179 | smp_wmb(); | ||
180 | ptep->pte_high = 0; | ||
181 | } | ||
182 | |||
183 | static void native_pmd_clear(pmd_t *pmd) | ||
184 | { | ||
185 | u32 *tmp = (u32 *)pmd; | ||
186 | *tmp = 0; | ||
187 | smp_wmb(); | ||
188 | *(tmp + 1) = 0; | ||
189 | } | ||
190 | #endif /* CONFIG_X86_PAE */ | ||
191 | |||
192 | /* These are in entry.S */ | 120 | /* These are in entry.S */ |
193 | extern void native_iret(void); | 121 | extern void native_iret(void); |
194 | extern void native_irq_enable_sysexit(void); | 122 | extern void native_irq_enable_sysexit(void); |
@@ -282,14 +210,26 @@ struct paravirt_ops paravirt_ops = { | |||
282 | .set_pmd = native_set_pmd, | 210 | .set_pmd = native_set_pmd, |
283 | .pte_update = paravirt_nop, | 211 | .pte_update = paravirt_nop, |
284 | .pte_update_defer = paravirt_nop, | 212 | .pte_update_defer = paravirt_nop, |
213 | |||
214 | .ptep_get_and_clear = native_ptep_get_and_clear, | ||
215 | |||
285 | #ifdef CONFIG_X86_PAE | 216 | #ifdef CONFIG_X86_PAE |
286 | .set_pte_atomic = native_set_pte_atomic, | 217 | .set_pte_atomic = native_set_pte_atomic, |
287 | .set_pte_present = native_set_pte_present, | 218 | .set_pte_present = native_set_pte_present, |
288 | .set_pud = native_set_pud, | 219 | .set_pud = native_set_pud, |
289 | .pte_clear = native_pte_clear, | 220 | .pte_clear = native_pte_clear, |
290 | .pmd_clear = native_pmd_clear, | 221 | .pmd_clear = native_pmd_clear, |
222 | |||
223 | .pmd_val = native_pmd_val, | ||
224 | .make_pmd = native_make_pmd, | ||
291 | #endif | 225 | #endif |
292 | 226 | ||
227 | .pte_val = native_pte_val, | ||
228 | .pgd_val = native_pgd_val, | ||
229 | |||
230 | .make_pte = native_make_pte, | ||
231 | .make_pgd = native_make_pgd, | ||
232 | |||
293 | .irq_enable_sysexit = native_irq_enable_sysexit, | 233 | .irq_enable_sysexit = native_irq_enable_sysexit, |
294 | .iret = native_iret, | 234 | .iret = native_iret, |
295 | 235 | ||
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c index 8f3bac473450..ea77d93f59dd 100644 --- a/arch/i386/kernel/vmi.c +++ b/arch/i386/kernel/vmi.c | |||
@@ -443,13 +443,13 @@ static void vmi_release_pd(u32 pfn) | |||
443 | ((level) | (is_current_as(mm, user) ? \ | 443 | ((level) | (is_current_as(mm, user) ? \ |
444 | (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0)) | 444 | (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0)) |
445 | 445 | ||
446 | static void vmi_update_pte(struct mm_struct *mm, u32 addr, pte_t *ptep) | 446 | static void vmi_update_pte(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
447 | { | 447 | { |
448 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); | 448 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); |
449 | vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); | 449 | vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); |
450 | } | 450 | } |
451 | 451 | ||
452 | static void vmi_update_pte_defer(struct mm_struct *mm, u32 addr, pte_t *ptep) | 452 | static void vmi_update_pte_defer(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
453 | { | 453 | { |
454 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); | 454 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); |
455 | vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0)); | 455 | vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0)); |
@@ -462,7 +462,7 @@ static void vmi_set_pte(pte_t *ptep, pte_t pte) | |||
462 | vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT); | 462 | vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT); |
463 | } | 463 | } |
464 | 464 | ||
465 | static void vmi_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte) | 465 | static void vmi_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) |
466 | { | 466 | { |
467 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); | 467 | vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); |
468 | vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); | 468 | vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); |