|
@@ -585,6 +585,10 @@ void math_state_restore(void)
|
|
struct thread_info *thread = current_thread_info();
|
|
struct thread_info *thread = current_thread_info();
|
|
struct task_struct *tsk = thread->task;
|
|
struct task_struct *tsk = thread->task;
|
|
|
|
|
|
|
|
+ /* We need a safe address that is cheap to find and that is already
|
|
|
|
+ in L1. We just brought in "thread->task", so use that */
|
|
|
|
+#define safe_address (thread->task)
|
|
|
|
+
|
|
if (!tsk_used_math(tsk)) {
|
|
if (!tsk_used_math(tsk)) {
|
|
local_irq_enable();
|
|
local_irq_enable();
|
|
/*
|
|
/*
|
|
@@ -602,6 +606,16 @@ void math_state_restore(void)
|
|
|
|
|
|
__thread_fpu_begin(thread);
|
|
__thread_fpu_begin(thread);
|
|
|
|
|
|
|
|
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
|
|
|
|
+ is pending. Clear the x87 state here by setting it to fixed
|
|
|
|
+ values. safe_address is a random variable that should be in L1 */
|
|
|
|
+ alternative_input(
|
|
|
|
+ ASM_NOP8 ASM_NOP2,
|
|
|
|
+ "emms\n\t" /* clear stack tags */
|
|
|
|
+ "fildl %P[addr]", /* set F?P to defined value */
|
|
|
|
+ X86_FEATURE_FXSAVE_LEAK,
|
|
|
|
+ [addr] "m" (safe_address));
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
|
|
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
|
|
*/
|
|
*/
|