diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-23 15:48:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-23 15:48:17 -0400 |
commit | ee5c2ab09b79d3aba3515a3eae7c5cf1e2cbc569 (patch) | |
tree | 45896aa3ae1071c089f969cdce72d83125ed459a | |
parent | f6837bfa6506892e889ec79d8ab29931b4468826 (diff) | |
parent | ebb9cfe20fe167f29960a5e913193a684fac50bf (diff) |
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
xen: don't drop NX bit
xen: mask unwanted pte bits in __supported_pte_mask
xen: Use wmb instead of rmb in xen_evtchn_do_upcall().
x86: fix NULL pointer deref in __switch_to
-rw-r--r-- | arch/x86/xen/enlighten.c | 5 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 56 | ||||
-rw-r--r-- | arch/x86/xen/xen-head.S | 2 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 15 | ||||
-rw-r--r-- | drivers/xen/events.c | 2 |
5 files changed, 46 insertions, 34 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c8a56e457d61..c048de34d6a1 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1228,6 +1228,11 @@ asmlinkage void __init xen_start_kernel(void) | |||
1228 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) | 1228 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) |
1229 | pv_info.kernel_rpl = 0; | 1229 | pv_info.kernel_rpl = 0; |
1230 | 1230 | ||
1231 | /* Prevent unwanted bits from being set in PTEs. */ | ||
1232 | __supported_pte_mask &= ~_PAGE_GLOBAL; | ||
1233 | if (!is_initial_xendomain()) | ||
1234 | __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); | ||
1235 | |||
1231 | /* set the limit of our address space */ | 1236 | /* set the limit of our address space */ |
1232 | xen_reserve_top(); | 1237 | xen_reserve_top(); |
1233 | 1238 | ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3525ef523a74..265601d5a6ae 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -179,48 +179,54 @@ out: | |||
179 | preempt_enable(); | 179 | preempt_enable(); |
180 | } | 180 | } |
181 | 181 | ||
182 | pteval_t xen_pte_val(pte_t pte) | 182 | /* Assume pteval_t is equivalent to all the other *val_t types. */ |
183 | static pteval_t pte_mfn_to_pfn(pteval_t val) | ||
183 | { | 184 | { |
184 | pteval_t ret = pte.pte; | 185 | if (val & _PAGE_PRESENT) { |
186 | unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT; | ||
187 | pteval_t flags = val & ~PTE_MASK; | ||
188 | val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags; | ||
189 | } | ||
190 | |||
191 | return val; | ||
192 | } | ||
193 | |||
194 | static pteval_t pte_pfn_to_mfn(pteval_t val) | ||
195 | { | ||
196 | if (val & _PAGE_PRESENT) { | ||
197 | unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT; | ||
198 | pteval_t flags = val & ~PTE_MASK; | ||
199 | val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags; | ||
200 | } | ||
185 | 201 | ||
186 | if (ret & _PAGE_PRESENT) | 202 | return val; |
187 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | 203 | } |
188 | 204 | ||
189 | return ret; | 205 | pteval_t xen_pte_val(pte_t pte) |
206 | { | ||
207 | return pte_mfn_to_pfn(pte.pte); | ||
190 | } | 208 | } |
191 | 209 | ||
192 | pgdval_t xen_pgd_val(pgd_t pgd) | 210 | pgdval_t xen_pgd_val(pgd_t pgd) |
193 | { | 211 | { |
194 | pgdval_t ret = pgd.pgd; | 212 | return pte_mfn_to_pfn(pgd.pgd); |
195 | if (ret & _PAGE_PRESENT) | ||
196 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | ||
197 | return ret; | ||
198 | } | 213 | } |
199 | 214 | ||
200 | pte_t xen_make_pte(pteval_t pte) | 215 | pte_t xen_make_pte(pteval_t pte) |
201 | { | 216 | { |
202 | if (pte & _PAGE_PRESENT) { | 217 | pte = pte_pfn_to_mfn(pte); |
203 | pte = phys_to_machine(XPADDR(pte)).maddr; | 218 | return native_make_pte(pte); |
204 | pte &= ~(_PAGE_PCD | _PAGE_PWT); | ||
205 | } | ||
206 | |||
207 | return (pte_t){ .pte = pte }; | ||
208 | } | 219 | } |
209 | 220 | ||
210 | pgd_t xen_make_pgd(pgdval_t pgd) | 221 | pgd_t xen_make_pgd(pgdval_t pgd) |
211 | { | 222 | { |
212 | if (pgd & _PAGE_PRESENT) | 223 | pgd = pte_pfn_to_mfn(pgd); |
213 | pgd = phys_to_machine(XPADDR(pgd)).maddr; | 224 | return native_make_pgd(pgd); |
214 | |||
215 | return (pgd_t){ pgd }; | ||
216 | } | 225 | } |
217 | 226 | ||
218 | pmdval_t xen_pmd_val(pmd_t pmd) | 227 | pmdval_t xen_pmd_val(pmd_t pmd) |
219 | { | 228 | { |
220 | pmdval_t ret = native_pmd_val(pmd); | 229 | return pte_mfn_to_pfn(pmd.pmd); |
221 | if (ret & _PAGE_PRESENT) | ||
222 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | ||
223 | return ret; | ||
224 | } | 230 | } |
225 | #ifdef CONFIG_X86_PAE | 231 | #ifdef CONFIG_X86_PAE |
226 | void xen_set_pud(pud_t *ptr, pud_t val) | 232 | void xen_set_pud(pud_t *ptr, pud_t val) |
@@ -267,9 +273,7 @@ void xen_pmd_clear(pmd_t *pmdp) | |||
267 | 273 | ||
268 | pmd_t xen_make_pmd(pmdval_t pmd) | 274 | pmd_t xen_make_pmd(pmdval_t pmd) |
269 | { | 275 | { |
270 | if (pmd & _PAGE_PRESENT) | 276 | pmd = pte_pfn_to_mfn(pmd); |
271 | pmd = phys_to_machine(XPADDR(pmd)).maddr; | ||
272 | |||
273 | return native_make_pmd(pmd); | 277 | return native_make_pmd(pmd); |
274 | } | 278 | } |
275 | #else /* !PAE */ | 279 | #else /* !PAE */ |
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 288d587ce73c..3175e973fd0d 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S | |||
@@ -17,7 +17,7 @@ ENTRY(startup_xen) | |||
17 | 17 | ||
18 | __FINIT | 18 | __FINIT |
19 | 19 | ||
20 | .pushsection .bss.page_aligned | 20 | .pushsection .text |
21 | .align PAGE_SIZE_asm | 21 | .align PAGE_SIZE_asm |
22 | ENTRY(hypercall_page) | 22 | ENTRY(hypercall_page) |
23 | .skip 0x1000 | 23 | .skip 0x1000 |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 5126d5d9ea0e..2e554a4ab337 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
@@ -176,7 +176,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) | |||
176 | * we set it now, so we can trap and pass that trap to the Guest if it | 176 | * we set it now, so we can trap and pass that trap to the Guest if it |
177 | * uses the FPU. */ | 177 | * uses the FPU. */ |
178 | if (cpu->ts) | 178 | if (cpu->ts) |
179 | lguest_set_ts(); | 179 | unlazy_fpu(current); |
180 | 180 | ||
181 | /* SYSENTER is an optimized way of doing system calls. We can't allow | 181 | /* SYSENTER is an optimized way of doing system calls. We can't allow |
182 | * it because it always jumps to privilege level 0. A normal Guest | 182 | * it because it always jumps to privilege level 0. A normal Guest |
@@ -196,6 +196,10 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) | |||
196 | * trap made the switcher code come back, and an error code which some | 196 | * trap made the switcher code come back, and an error code which some |
197 | * traps set. */ | 197 | * traps set. */ |
198 | 198 | ||
199 | /* Restore SYSENTER if it's supposed to be on. */ | ||
200 | if (boot_cpu_has(X86_FEATURE_SEP)) | ||
201 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); | ||
202 | |||
199 | /* If the Guest page faulted, then the cr2 register will tell us the | 203 | /* If the Guest page faulted, then the cr2 register will tell us the |
200 | * bad virtual address. We have to grab this now, because once we | 204 | * bad virtual address. We have to grab this now, because once we |
201 | * re-enable interrupts an interrupt could fault and thus overwrite | 205 | * re-enable interrupts an interrupt could fault and thus overwrite |
@@ -203,13 +207,12 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) | |||
203 | if (cpu->regs->trapnum == 14) | 207 | if (cpu->regs->trapnum == 14) |
204 | cpu->arch.last_pagefault = read_cr2(); | 208 | cpu->arch.last_pagefault = read_cr2(); |
205 | /* Similarly, if we took a trap because the Guest used the FPU, | 209 | /* Similarly, if we took a trap because the Guest used the FPU, |
206 | * we have to restore the FPU it expects to see. */ | 210 | * we have to restore the FPU it expects to see. |
211 | * math_state_restore() may sleep and we may even move off to | ||
212 | * a different CPU. So all the critical stuff should be done | ||
213 | * before this. */ | ||
207 | else if (cpu->regs->trapnum == 7) | 214 | else if (cpu->regs->trapnum == 7) |
208 | math_state_restore(); | 215 | math_state_restore(); |
209 | |||
210 | /* Restore SYSENTER if it's supposed to be on. */ | ||
211 | if (boot_cpu_has(X86_FEATURE_SEP)) | ||
212 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); | ||
213 | } | 216 | } |
214 | 217 | ||
215 | /*H:130 Now we've examined the hypercall code; our Guest can make requests. | 218 | /*H:130 Now we've examined the hypercall code; our Guest can make requests. |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 4f0f22b020ea..76e5b7386af9 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -529,7 +529,7 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) | |||
529 | 529 | ||
530 | #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ | 530 | #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ |
531 | /* Clear master flag /before/ clearing selector flag. */ | 531 | /* Clear master flag /before/ clearing selector flag. */ |
532 | rmb(); | 532 | wmb(); |
533 | #endif | 533 | #endif |
534 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); | 534 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); |
535 | while (pending_words != 0) { | 535 | while (pending_words != 0) { |