diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/process_64.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 14 |
3 files changed, 16 insertions, 22 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 86974c72d0d0..01b115d86770 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -211,15 +211,6 @@ static inline void fpu_fxsave(struct fpu *fpu) | |||
| 211 | 211 | ||
| 212 | #endif /* CONFIG_X86_64 */ | 212 | #endif /* CONFIG_X86_64 */ |
| 213 | 213 | ||
| 214 | /* We need a safe address that is cheap to find and that is already | ||
| 215 | in L1 during context switch. The best choices are unfortunately | ||
| 216 | different for UP and SMP */ | ||
| 217 | #ifdef CONFIG_SMP | ||
| 218 | #define safe_address (__per_cpu_offset[0]) | ||
| 219 | #else | ||
| 220 | #define safe_address (__get_cpu_var(kernel_cpustat).cpustat[CPUTIME_USER]) | ||
| 221 | #endif | ||
| 222 | |||
| 223 | /* | 214 | /* |
| 224 | * These must be called with preempt disabled | 215 | * These must be called with preempt disabled |
| 225 | */ | 216 | */ |
| @@ -243,16 +234,6 @@ static inline void fpu_save_init(struct fpu *fpu) | |||
| 243 | 234 | ||
| 244 | if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) | 235 | if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) |
| 245 | asm volatile("fnclex"); | 236 | asm volatile("fnclex"); |
| 246 | |||
| 247 | /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception | ||
| 248 | is pending. Clear the x87 state here by setting it to fixed | ||
| 249 | values. safe_address is a random variable that should be in L1 */ | ||
| 250 | alternative_input( | ||
| 251 | ASM_NOP8 ASM_NOP2, | ||
| 252 | "emms\n\t" /* clear stack tags */ | ||
| 253 | "fildl %P[addr]", /* set F?P to defined value */ | ||
| 254 | X86_FEATURE_FXSAVE_LEAK, | ||
| 255 | [addr] "m" (safe_address)); | ||
| 256 | } | 237 | } |
| 257 | 238 | ||
| 258 | static inline void __save_init_fpu(struct task_struct *tsk) | 239 | static inline void __save_init_fpu(struct task_struct *tsk) |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 992b4e542bc3..753e803f7197 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -387,6 +387,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 387 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 387 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
| 388 | unsigned fsindex, gsindex; | 388 | unsigned fsindex, gsindex; |
| 389 | 389 | ||
| 390 | __unlazy_fpu(prev_p); | ||
| 391 | |||
| 390 | /* | 392 | /* |
| 391 | * Reload esp0, LDT and the page table pointer: | 393 | * Reload esp0, LDT and the page table pointer: |
| 392 | */ | 394 | */ |
| @@ -415,9 +417,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 415 | 417 | ||
| 416 | load_TLS(next, cpu); | 418 | load_TLS(next, cpu); |
| 417 | 419 | ||
| 418 | /* Must be after DS reload */ | ||
| 419 | __unlazy_fpu(prev_p); | ||
| 420 | |||
| 421 | /* | 420 | /* |
| 422 | * Leave lazy mode, flushing any hypercalls made here. | 421 | * Leave lazy mode, flushing any hypercalls made here. |
| 423 | * This must be done before restoring TLS segments so | 422 | * This must be done before restoring TLS segments so |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 5afe824c66e5..4d42300dcd2c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -585,6 +585,10 @@ void math_state_restore(void) | |||
| 585 | struct thread_info *thread = current_thread_info(); | 585 | struct thread_info *thread = current_thread_info(); |
| 586 | struct task_struct *tsk = thread->task; | 586 | struct task_struct *tsk = thread->task; |
| 587 | 587 | ||
| 588 | /* We need a safe address that is cheap to find and that is already | ||
| 589 | in L1. We just brought in "thread->task", so use that */ | ||
| 590 | #define safe_address (thread->task) | ||
| 591 | |||
| 588 | if (!tsk_used_math(tsk)) { | 592 | if (!tsk_used_math(tsk)) { |
| 589 | local_irq_enable(); | 593 | local_irq_enable(); |
| 590 | /* | 594 | /* |
| @@ -602,6 +606,16 @@ void math_state_restore(void) | |||
| 602 | 606 | ||
| 603 | __thread_fpu_begin(thread); | 607 | __thread_fpu_begin(thread); |
| 604 | 608 | ||
| 609 | /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception | ||
| 610 | is pending. Clear the x87 state here by setting it to fixed | ||
| 611 | values. safe_address is a random variable that should be in L1 */ | ||
| 612 | alternative_input( | ||
| 613 | ASM_NOP8 ASM_NOP2, | ||
| 614 | "emms\n\t" /* clear stack tags */ | ||
| 615 | "fildl %P[addr]", /* set F?P to defined value */ | ||
| 616 | X86_FEATURE_FXSAVE_LEAK, | ||
| 617 | [addr] "m" (safe_address)); | ||
| 618 | |||
| 605 | /* | 619 | /* |
| 606 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | 620 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. |
| 607 | */ | 621 | */ |
