Skip to content

Commit 7c17e48

Browse files
committed
Merge branch 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Peter Anvin. This includes the resume-time FPU corruption fix from the chromeos guys, marked for stable. * 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, fpu: Avoid FPU lazy restore after suspend x86-32: Unbreak booting on some 486 clones x86, kvm: Remove incorrect redundant assembly constraint
2 parents 8fdd78e + 644c154 commit 7c17e48

File tree

4 files changed

+22
-10
lines changed

4 files changed

+22
-10
lines changed

arch/x86/include/asm/fpu-internal.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,17 @@ static inline void drop_init_fpu(struct task_struct *tsk)
399399
typedef struct { int preload; } fpu_switch_t;
400400

401401
/*
402-
* FIXME! We could do a totally lazy restore, but we need to
403-
* add a per-cpu "this was the task that last touched the FPU
404-
* on this CPU" variable, and the task needs to have a "I last
405-
* touched the FPU on this CPU" and check them.
402+
* Must be run with preemption disabled: this clears the fpu_owner_task,
403+
* on this CPU.
406404
*
407-
* We don't do that yet, so "fpu_lazy_restore()" always returns
408-
* false, but some day..
405+
* This will disable any lazy FPU state restore of the current FPU state,
406+
* but if the current thread owns the FPU, it will still be saved by.
409407
*/
408+
static inline void __cpu_disable_lazy_restore(unsigned int cpu)
409+
{
410+
per_cpu(fpu_owner_task, cpu) = NULL;
411+
}
412+
410413
static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
411414
{
412415
return new == this_cpu_read_stable(fpu_owner_task) &&

arch/x86/kernel/head_32.S

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,8 @@ default_entry:
292292
* be using the global pages.
293293
*
294294
* NOTE! If we are on a 486 we may have no cr4 at all!
295-
* Specifically, cr4 exists if and only if CPUID exists,
296-
* which in turn exists if and only if EFLAGS.ID exists.
295+
* Specifically, cr4 exists if and only if CPUID exists
296+
* and has flags other than the FPU flag set.
297297
*/
298298
movl $X86_EFLAGS_ID,%ecx
299299
pushl %ecx
@@ -308,6 +308,11 @@ default_entry:
308308
testl %ecx,%eax
309309
jz 6f # No ID flag = no CPUID = no CR4
310310

311+
movl $1,%eax
312+
cpuid
313+
andl $~1,%edx # Ignore CPUID.FPU
314+
jz 6f # No flags or only CPUID.FPU = no CR4
315+
311316
movl pa(mmu_cr4_features),%eax
312317
movl %eax,%cr4
313318

arch/x86/kernel/smpboot.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
#include <asm/mwait.h>
6969
#include <asm/apic.h>
7070
#include <asm/io_apic.h>
71+
#include <asm/i387.h>
72+
#include <asm/fpu-internal.h>
7173
#include <asm/setup.h>
7274
#include <asm/uv/uv.h>
7375
#include <linux/mc146818rtc.h>
@@ -818,6 +820,9 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
818820

819821
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
820822

823+
/* the FPU context is blank, nobody can own it */
824+
__cpu_disable_lazy_restore(cpu);
825+
821826
err = do_boot_cpu(apicid, cpu, tidle);
822827
if (err) {
823828
pr_debug("do_boot_cpu failed %d\n", err);

arch/x86/kvm/emulate.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,7 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
426426
_ASM_EXTABLE(1b, 3b) \
427427
: "=m" ((ctxt)->eflags), "=&r" (_tmp), \
428428
"+a" (*rax), "+d" (*rdx), "+qm"(_ex) \
429-
: "i" (EFLAGS_MASK), "m" ((ctxt)->src.val), \
430-
"a" (*rax), "d" (*rdx)); \
429+
: "i" (EFLAGS_MASK), "m" ((ctxt)->src.val)); \
431430
} while (0)
432431

433432
/* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */

0 commit comments

Comments
 (0)