2013-04-08 15:58:07

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 0/4] x86: FPU detection in C

From: Borislav Petkov <[email protected]>

Hi,

so this is the final result. Patches boot on every qemu cpu model and on
two baremetal configs here.

The three patches after yours are some small fixlets for issues I
spotted while testing.

Thanks.

Borislav Petkov (3):
x86: Fold-in trivial check_config function
x86, AMD: Correct {rd,wr}msr_amd_safe warnings
x86, CPU, AMD: Drop useless label

H. Peter Anvin (1):
x86: Get rid of ->hard_math and all the FPU asm fu

arch/x86/include/asm/fpu-internal.h | 2 --
arch/x86/include/asm/processor.h | 3 +-
arch/x86/kernel/asm-offsets_32.c | 1 -
arch/x86/kernel/cpu/amd.c | 17 +++++------
arch/x86/kernel/cpu/bugs.c | 48 ++++++++----------------------
arch/x86/kernel/cpu/common.c | 3 +-
arch/x86/kernel/cpu/cyrix.c | 2 +-
arch/x86/kernel/cpu/proc.c | 4 +--
arch/x86/kernel/head_32.S | 21 -------------
arch/x86/kernel/i387.c | 59 ++++++++++++++++++++++++++++++-------
arch/x86/kernel/xsave.c | 5 ++--
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
13 files changed, 78 insertions(+), 91 deletions(-)

--
1.8.2.135.g7b592fa


2013-04-08 15:58:08

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 2/4] x86: Fold-in trivial check_config function

From: Borislav Petkov <[email protected]>

Fold it into its single call site. No functionality change.

Signed-off-by: Borislav Petkov <[email protected]>
---
arch/x86/kernel/cpu/bugs.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index efa24c0b7c43..03445346ee0a 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -63,21 +63,6 @@ static void __init check_fpu(void)
}
}

-/*
- * Check whether we are able to run this kernel safely on SMP.
- *
- * - i386 is no longer supported.
- * - In order to run on anything without a TSC, we need to be
- * compiled for a i486.
- */
-
-static void __init check_config(void)
-{
- if (boot_cpu_data.x86 < 4)
- panic("Kernel requires i486+ for 'invlpg' and other features");
-}
-
-
void __init check_bugs(void)
{
identify_boot_cpu();
@@ -85,7 +70,17 @@ void __init check_bugs(void)
pr_info("CPU: ");
print_cpu_info(&boot_cpu_data);
#endif
- check_config();
+
+ /*
+ * Check whether we are able to run this kernel safely on SMP.
+ *
+ * - i386 is no longer supported.
+ * - In order to run on anything without a TSC, we need to be
+ * compiled for a i486.
+ */
+ if (boot_cpu_data.x86 < 4)
+ panic("Kernel requires i486+ for 'invlpg' and other features");
+
init_utsname()->machine[1] =
'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
alternative_instructions();
--
1.8.2.135.g7b592fa

2013-04-08 15:58:19

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 3/4] x86, AMD: Correct {rd,wr}msr_amd_safe warnings

From: Borislav Petkov <[email protected]>

The idea with those routines is to slowly phase them out and not call
them on anything else besides K8. They even have a check for that which,
when called too early, fails. Let me explain:

It gets the cpuinfo_x86 pointer from the per_cpu array and when this
happens for cpu0, before its boot_cpu_data has been copied back to the
per_cpu array in smp_store_boot_cpu_info(), we get an empty struct and
thus the check fails.

Use boot_cpu_data directly instead.

Signed-off-by: Borislav Petkov <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 9a2a71669c5d..cea02d703bca 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -20,11 +20,11 @@

static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };
int err;

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[1] = msr;
gprs[7] = 0x9c5a203a;
@@ -38,10 +38,10 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)

static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[0] = (u32)val;
gprs[1] = msr;
--
1.8.2.135.g7b592fa

2013-04-08 15:58:17

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 1/4] x86: Get rid of ->hard_math and all the FPU asm fu

From: "H. Peter Anvin" <[email protected]>

Reimplement FPU detection code in C and drop old, not-so-recommended
detection method in asm. Move all the relevant stuff into i387.c where
it conceptually belongs. Finally drop cpuinfo_x86.hard_math.

Signed-off-by: H. Peter Anvin <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
---
arch/x86/include/asm/fpu-internal.h | 2 --
arch/x86/include/asm/processor.h | 3 +-
arch/x86/kernel/asm-offsets_32.c | 1 -
arch/x86/kernel/cpu/bugs.c | 21 ++-----------
arch/x86/kernel/cpu/common.c | 3 +-
arch/x86/kernel/cpu/cyrix.c | 2 +-
arch/x86/kernel/cpu/proc.c | 4 +--
arch/x86/kernel/head_32.S | 21 -------------
arch/x86/kernel/i387.c | 59 ++++++++++++++++++++++++++++++-------
arch/x86/kernel/xsave.c | 5 ++--
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
12 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index e25cc33ec54d..fb808d71cd70 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -62,10 +62,8 @@ extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
#define xstateregs_active fpregs_active

#ifdef CONFIG_MATH_EMULATION
-# define HAVE_HWFP (boot_cpu_data.hard_math)
extern void finit_soft_fpu(struct i387_soft_struct *soft);
#else
-# define HAVE_HWFP 1
static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
#endif

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 22224b3b43bb..578f8b1d6910 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -89,9 +89,9 @@ struct cpuinfo_x86 {
char wp_works_ok; /* It doesn't on 386's */

/* Problems on some 486Dx4's and old 386's: */
- char hard_math;
char rfu;
char pad0;
+ char pad1;
#else
/* Number of 4K pages in DTLB/ITLB combined(in pages): */
int x86_tlbsize;
@@ -164,6 +164,7 @@ extern const struct seq_operations cpuinfo_op;
#define cache_line_size() (boot_cpu_data.x86_cache_alignment)

extern void cpu_detect(struct cpuinfo_x86 *c);
+extern void __cpuinit fpu_detect(struct cpuinfo_x86 *c);

extern void early_cpu_init(void);
extern void identify_boot_cpu(void);
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 85d98ab15cdc..a8ff7f936649 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -28,7 +28,6 @@ void foo(void)
OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
OFFSET(CPUINFO_x86_mask, cpuinfo_x86, x86_mask);
- OFFSET(CPUINFO_hard_math, cpuinfo_x86, hard_math);
OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index c59635ecbbb8..efa24c0b7c43 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -17,15 +17,6 @@
#include <asm/paravirt.h>
#include <asm/alternative.h>

-static int __init no_387(char *s)
-{
- boot_cpu_data.hard_math = 0;
- write_cr0(X86_CR0_TS | X86_CR0_EM | X86_CR0_MP | read_cr0());
- return 1;
-}
-
-__setup("no387", no_387);
-
static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0;

@@ -44,15 +35,6 @@ static void __init check_fpu(void)
{
s32 fdiv_bug;

- if (!boot_cpu_data.hard_math) {
-#ifndef CONFIG_MATH_EMULATION
- pr_emerg("No coprocessor found and no math emulation present\n");
- pr_emerg("Giving up\n");
- for (;;) ;
-#endif
- return;
- }
-
kernel_fpu_begin();

/*
@@ -112,5 +94,6 @@ void __init check_bugs(void)
* kernel_fpu_begin/end() in check_fpu() relies on the patched
* alternative instructions.
*/
- check_fpu();
+ if (cpu_has_fpu)
+ check_fpu();
}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22018f70a671..d4dd99350e9d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -711,10 +711,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
return;

cpu_detect(c);
-
get_cpu_vendor(c);
-
get_cpu_cap(c);
+ fpu_detect(c);

if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index d048d5ca43c1..7582f475b163 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -333,7 +333,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
switch (dir0_lsn) {
case 0xd: /* either a 486SLC or DLC w/o DEVID */
dir0_msn = 0;
- p = Cx486_name[(c->hard_math) ? 1 : 0];
+ p = Cx486_name[(cpu_has_fpu ? 1 : 0)];
break;

case 0xe: /* a 486S A step */
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 37a198bd48c8..aee6317b902f 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -37,8 +37,8 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
- c->hard_math ? "yes" : "no",
- c->hard_math ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
c->cpuid_level,
c->wp_works_ok ? "yes" : "no");
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 73afd11799ca..e65ddc62e113 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -444,7 +444,6 @@ is486:
orl %ecx,%eax
movl %eax,%cr0

- call check_x87
lgdt early_gdt_descr
lidt idt_descr
ljmp $(__KERNEL_CS),$1f
@@ -467,26 +466,6 @@ is486:
pushl $0 # fake return address for unwinder
jmp *(initial_code)

-/*
- * We depend on ET to be correct. This checks for 287/387.
- */
-check_x87:
- movb $0,X86_HARD_MATH
- clts
- fninit
- fstsw %ax
- cmpb $0,%al
- je 1f
- movl %cr0,%eax /* no coprocessor: have to set bits */
- xorl $4,%eax /* set EM */
- movl %eax,%cr0
- ret
- ALIGN
-1: movb $1,X86_HARD_MATH
- .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
- ret
-
-
#include "verify_cpu.S"

/*
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 245a71db401a..3a6455304c8d 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -135,7 +135,7 @@ static void __cpuinit init_thread_xstate(void)
* xsave_init().
*/

- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
/*
* Disable xsave as we do not support it if i387
* emulation is enabled.
@@ -162,6 +162,14 @@ void __cpuinit fpu_init(void)
unsigned long cr0;
unsigned long cr4_mask = 0;

+#ifndef CONFIG_MATH_EMULATION
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
+ pr_emerg("No FPU found and no math emulation present\n");
+ pr_emerg("Giving up\n");
+ for (;;)
+ asm volatile("hlt");
+ }
+#endif
if (cpu_has_fxsr)
cr4_mask |= X86_CR4_OSFXSR;
if (cpu_has_xmm)
@@ -171,7 +179,7 @@ void __cpuinit fpu_init(void)

cr0 = read_cr0();
cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
cr0 |= X86_CR0_EM;
write_cr0(cr0);

@@ -189,7 +197,7 @@ void __cpuinit fpu_init(void)

void fpu_finit(struct fpu *fpu)
{
- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
finit_soft_fpu(&fpu->state->soft);
return;
}
@@ -218,7 +226,7 @@ int init_fpu(struct task_struct *tsk)
int ret;

if (tsk_used_math(tsk)) {
- if (HAVE_HWFP && tsk == current)
+ if (static_cpu_has(X86_FEATURE_FPU) && tsk == current)
unlazy_fpu(tsk);
tsk->thread.fpu.last_cpu = ~0;
return 0;
@@ -515,14 +523,13 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
if (ret)
return ret;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.fpu.state->fsave, 0,
-1);
- }

sanitize_i387_state(target);

@@ -549,13 +556,13 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,

sanitize_i387_state(target);

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu.state->fsave, 0, -1);
- }
+ &target->thread.fpu.state->fsave, 0,
+ -1);

if (pos > 0 || count < sizeof(env))
convert_from_fxsr(&env, target);
@@ -596,3 +603,33 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
EXPORT_SYMBOL(dump_fpu);

#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
+
+static int __init no_387(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_FPU);
+ return 1;
+}
+
+__setup("no387", no_387);
+
+void __cpuinit fpu_detect(struct cpuinfo_x86 *c)
+{
+ unsigned long cr0;
+ u16 fsw, fcw;
+
+ fsw = fcw = 0xffff;
+
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
+ write_cr0(cr0);
+
+ asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+ : "+m" (fsw), "+m" (fcw));
+
+ if (fsw == 0 && (fcw & 0x103f) == 0x003f)
+ set_cpu_cap(c, X86_FEATURE_FPU);
+ else
+ clear_cpu_cap(c, X86_FEATURE_FPU);
+
+ /* The final cr0 value is set in fpu_init() */
+}
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index ada87a329edc..d6c28acdf99c 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -243,7 +243,7 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!access_ok(VERIFY_WRITE, buf, size))
return -EACCES;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(current, NULL, 0,
sizeof(struct user_i387_ia32_struct), NULL,
(struct _fpstate_ia32 __user *) buf) ? -1 : 1;
@@ -350,11 +350,10 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!used_math() && init_fpu(tsk))
return -1;

- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(current, NULL,
0, sizeof(struct user_i387_ia32_struct),
NULL, buf) != 0;
- }

if (use_xsave()) {
struct _fpx_sw_bytes fx_sw_user;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 1cbd89ca5569..d3f2ab39f364 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1409,7 +1409,7 @@ __init void lguest_init(void)
new_cpu_data.x86_capability[0] = cpuid_edx(1);

/* Math is always hard! */
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);

/* We don't have features. We have puppies! Puppies! */
#ifdef CONFIG_X86_MCE
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c8e1c7b95c3b..18833ffb2fbc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1463,7 +1463,7 @@ asmlinkage void __init xen_start_kernel(void)
#ifdef CONFIG_X86_32
/* set up basic CPUID stuff */
cpu_detect(&new_cpu_data);
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);
new_cpu_data.wp_works_ok = 1;
new_cpu_data.x86_capability[0] = cpuid_edx(1);
#endif
--
1.8.2.135.g7b592fa

2013-04-08 15:58:43

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 4/4] x86, CPU, AMD: Drop useless label

From: Borislav Petkov <[email protected]>

All we want to do is return from this function so stop jumping around
like a flea for no good reason.

Signed-off-by: Borislav Petkov <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index cea02d703bca..5013a48d1aff 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -192,11 +192,11 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
/* Athlon 660/661 is valid. */
if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
(c->x86_mask == 1)))
- goto valid_k7;
+ return;

/* Duron 670 is valid */
if ((c->x86_model == 7) && (c->x86_mask == 0))
- goto valid_k7;
+ return;

/*
* Athlon 662, Duron 671, and Athlon >model 7 have capability
@@ -209,7 +209,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
((c->x86_model == 7) && (c->x86_mask >= 1)) ||
(c->x86_model > 7))
if (cpu_has_mp)
- goto valid_k7;
+ return;

/* If we get here, not a certified SMP capable AMD system. */

@@ -220,9 +220,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: This combination of AMD"
" processors is not suitable for SMP.\n");
add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);
-
-valid_k7:
- ;
}

static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
--
1.8.2.135.g7b592fa

Subject: [tip:x86/cpu] x86: Get rid of ->hard_math and all the FPU asm fu

Commit-ID: c70293d0e3fef6b989cd8268027d410cf06ce384
Gitweb: http://git.kernel.org/tip/c70293d0e3fef6b989cd8268027d410cf06ce384
Author: H. Peter Anvin <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:43 +0200
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 8 Apr 2013 09:07:14 -0700

x86: Get rid of ->hard_math and all the FPU asm fu

Reimplement FPU detection code in C and drop old, not-so-recommended
detection method in asm. Move all the relevant stuff into i387.c where
it conceptually belongs. Finally drop cpuinfo_x86.hard_math.

[ hpa: huge thanks to Borislav for taking my original concept patch
and productizing it ]

Signed-off-by: H. Peter Anvin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Borislav Petkov <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/include/asm/fpu-internal.h | 2 --
arch/x86/include/asm/processor.h | 3 +-
arch/x86/kernel/asm-offsets_32.c | 1 -
arch/x86/kernel/cpu/bugs.c | 21 ++-----------
arch/x86/kernel/cpu/common.c | 3 +-
arch/x86/kernel/cpu/cyrix.c | 2 +-
arch/x86/kernel/cpu/proc.c | 4 +--
arch/x86/kernel/head_32.S | 21 -------------
arch/x86/kernel/i387.c | 59 ++++++++++++++++++++++++++++++-------
arch/x86/kernel/xsave.c | 5 ++--
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
12 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index e25cc33..fb808d7 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -62,10 +62,8 @@ extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
#define xstateregs_active fpregs_active

#ifdef CONFIG_MATH_EMULATION
-# define HAVE_HWFP (boot_cpu_data.hard_math)
extern void finit_soft_fpu(struct i387_soft_struct *soft);
#else
-# define HAVE_HWFP 1
static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
#endif

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 22224b3..578f8b1 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -89,9 +89,9 @@ struct cpuinfo_x86 {
char wp_works_ok; /* It doesn't on 386's */

/* Problems on some 486Dx4's and old 386's: */
- char hard_math;
char rfu;
char pad0;
+ char pad1;
#else
/* Number of 4K pages in DTLB/ITLB combined(in pages): */
int x86_tlbsize;
@@ -164,6 +164,7 @@ extern const struct seq_operations cpuinfo_op;
#define cache_line_size() (boot_cpu_data.x86_cache_alignment)

extern void cpu_detect(struct cpuinfo_x86 *c);
+extern void __cpuinit fpu_detect(struct cpuinfo_x86 *c);

extern void early_cpu_init(void);
extern void identify_boot_cpu(void);
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 85d98ab..a8ff7f9 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -28,7 +28,6 @@ void foo(void)
OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
OFFSET(CPUINFO_x86_mask, cpuinfo_x86, x86_mask);
- OFFSET(CPUINFO_hard_math, cpuinfo_x86, hard_math);
OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index c59635e..efa24c0 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -17,15 +17,6 @@
#include <asm/paravirt.h>
#include <asm/alternative.h>

-static int __init no_387(char *s)
-{
- boot_cpu_data.hard_math = 0;
- write_cr0(X86_CR0_TS | X86_CR0_EM | X86_CR0_MP | read_cr0());
- return 1;
-}
-
-__setup("no387", no_387);
-
static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0;

@@ -44,15 +35,6 @@ static void __init check_fpu(void)
{
s32 fdiv_bug;

- if (!boot_cpu_data.hard_math) {
-#ifndef CONFIG_MATH_EMULATION
- pr_emerg("No coprocessor found and no math emulation present\n");
- pr_emerg("Giving up\n");
- for (;;) ;
-#endif
- return;
- }
-
kernel_fpu_begin();

/*
@@ -112,5 +94,6 @@ void __init check_bugs(void)
* kernel_fpu_begin/end() in check_fpu() relies on the patched
* alternative instructions.
*/
- check_fpu();
+ if (cpu_has_fpu)
+ check_fpu();
}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22018f7..d4dd993 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -711,10 +711,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
return;

cpu_detect(c);
-
get_cpu_vendor(c);
-
get_cpu_cap(c);
+ fpu_detect(c);

if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index d048d5c..7582f47 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -333,7 +333,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
switch (dir0_lsn) {
case 0xd: /* either a 486SLC or DLC w/o DEVID */
dir0_msn = 0;
- p = Cx486_name[(c->hard_math) ? 1 : 0];
+ p = Cx486_name[(cpu_has_fpu ? 1 : 0)];
break;

case 0xe: /* a 486S A step */
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 37a198b..aee6317 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -37,8 +37,8 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
- c->hard_math ? "yes" : "no",
- c->hard_math ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
c->cpuid_level,
c->wp_works_ok ? "yes" : "no");
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 73afd11..e65ddc6 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -444,7 +444,6 @@ is486:
orl %ecx,%eax
movl %eax,%cr0

- call check_x87
lgdt early_gdt_descr
lidt idt_descr
ljmp $(__KERNEL_CS),$1f
@@ -467,26 +466,6 @@ is486:
pushl $0 # fake return address for unwinder
jmp *(initial_code)

-/*
- * We depend on ET to be correct. This checks for 287/387.
- */
-check_x87:
- movb $0,X86_HARD_MATH
- clts
- fninit
- fstsw %ax
- cmpb $0,%al
- je 1f
- movl %cr0,%eax /* no coprocessor: have to set bits */
- xorl $4,%eax /* set EM */
- movl %eax,%cr0
- ret
- ALIGN
-1: movb $1,X86_HARD_MATH
- .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
- ret
-
-
#include "verify_cpu.S"

/*
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 245a71d..3a64553 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -135,7 +135,7 @@ static void __cpuinit init_thread_xstate(void)
* xsave_init().
*/

- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
/*
* Disable xsave as we do not support it if i387
* emulation is enabled.
@@ -162,6 +162,14 @@ void __cpuinit fpu_init(void)
unsigned long cr0;
unsigned long cr4_mask = 0;

+#ifndef CONFIG_MATH_EMULATION
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
+ pr_emerg("No FPU found and no math emulation present\n");
+ pr_emerg("Giving up\n");
+ for (;;)
+ asm volatile("hlt");
+ }
+#endif
if (cpu_has_fxsr)
cr4_mask |= X86_CR4_OSFXSR;
if (cpu_has_xmm)
@@ -171,7 +179,7 @@ void __cpuinit fpu_init(void)

cr0 = read_cr0();
cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
cr0 |= X86_CR0_EM;
write_cr0(cr0);

@@ -189,7 +197,7 @@ void __cpuinit fpu_init(void)

void fpu_finit(struct fpu *fpu)
{
- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU)) {
finit_soft_fpu(&fpu->state->soft);
return;
}
@@ -218,7 +226,7 @@ int init_fpu(struct task_struct *tsk)
int ret;

if (tsk_used_math(tsk)) {
- if (HAVE_HWFP && tsk == current)
+ if (static_cpu_has(X86_FEATURE_FPU) && tsk == current)
unlazy_fpu(tsk);
tsk->thread.fpu.last_cpu = ~0;
return 0;
@@ -515,14 +523,13 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
if (ret)
return ret;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.fpu.state->fsave, 0,
-1);
- }

sanitize_i387_state(target);

@@ -549,13 +556,13 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,

sanitize_i387_state(target);

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu.state->fsave, 0, -1);
- }
+ &target->thread.fpu.state->fsave, 0,
+ -1);

if (pos > 0 || count < sizeof(env))
convert_from_fxsr(&env, target);
@@ -596,3 +603,33 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
EXPORT_SYMBOL(dump_fpu);

#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
+
+static int __init no_387(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_FPU);
+ return 1;
+}
+
+__setup("no387", no_387);
+
+void __cpuinit fpu_detect(struct cpuinfo_x86 *c)
+{
+ unsigned long cr0;
+ u16 fsw, fcw;
+
+ fsw = fcw = 0xffff;
+
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
+ write_cr0(cr0);
+
+ asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+ : "+m" (fsw), "+m" (fcw));
+
+ if (fsw == 0 && (fcw & 0x103f) == 0x003f)
+ set_cpu_cap(c, X86_FEATURE_FPU);
+ else
+ clear_cpu_cap(c, X86_FEATURE_FPU);
+
+ /* The final cr0 value is set in fpu_init() */
+}
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index ada87a3..d6c28ac 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -243,7 +243,7 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!access_ok(VERIFY_WRITE, buf, size))
return -EACCES;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(current, NULL, 0,
sizeof(struct user_i387_ia32_struct), NULL,
(struct _fpstate_ia32 __user *) buf) ? -1 : 1;
@@ -350,11 +350,10 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!used_math() && init_fpu(tsk))
return -1;

- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(current, NULL,
0, sizeof(struct user_i387_ia32_struct),
NULL, buf) != 0;
- }

if (use_xsave()) {
struct _fpx_sw_bytes fx_sw_user;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 1cbd89c..d3f2ab3 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1409,7 +1409,7 @@ __init void lguest_init(void)
new_cpu_data.x86_capability[0] = cpuid_edx(1);

/* Math is always hard! */
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);

/* We don't have features. We have puppies! Puppies! */
#ifdef CONFIG_X86_MCE
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c8e1c7b..18833ff 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1463,7 +1463,7 @@ asmlinkage void __init xen_start_kernel(void)
#ifdef CONFIG_X86_32
/* set up basic CPUID stuff */
cpu_detect(&new_cpu_data);
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);
new_cpu_data.wp_works_ok = 1;
new_cpu_data.x86_capability[0] = cpuid_edx(1);
#endif

Subject: [tip:x86/cpu] x86: Fold-in trivial check_config function

Commit-ID: e277a49385743dfa69a7adbb1ff19732d83d258c
Gitweb: http://git.kernel.org/tip/e277a49385743dfa69a7adbb1ff19732d83d258c
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:44 +0200
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 8 Apr 2013 09:07:17 -0700

x86: Fold-in trivial check_config function

Fold it into its single call site. No functionality change.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/bugs.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index efa24c0..0344534 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -63,21 +63,6 @@ static void __init check_fpu(void)
}
}

-/*
- * Check whether we are able to run this kernel safely on SMP.
- *
- * - i386 is no longer supported.
- * - In order to run on anything without a TSC, we need to be
- * compiled for a i486.
- */
-
-static void __init check_config(void)
-{
- if (boot_cpu_data.x86 < 4)
- panic("Kernel requires i486+ for 'invlpg' and other features");
-}
-
-
void __init check_bugs(void)
{
identify_boot_cpu();
@@ -85,7 +70,17 @@ void __init check_bugs(void)
pr_info("CPU: ");
print_cpu_info(&boot_cpu_data);
#endif
- check_config();
+
+ /*
+ * Check whether we are able to run this kernel safely on SMP.
+ *
+ * - i386 is no longer supported.
+ * - In order to run on anything without a TSC, we need to be
+ * compiled for a i486.
+ */
+ if (boot_cpu_data.x86 < 4)
+ panic("Kernel requires i486+ for 'invlpg' and other features");
+
init_utsname()->machine[1] =
'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
alternative_instructions();

Subject: [tip:x86/cpu] x86, AMD: Correct {rd,wr}msr_amd_safe warnings

Commit-ID: 982f33db626e7b42f44e0d404ebb110bf139c18b
Gitweb: http://git.kernel.org/tip/982f33db626e7b42f44e0d404ebb110bf139c18b
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:45 +0200
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 8 Apr 2013 09:07:17 -0700

x86, AMD: Correct {rd,wr}msr_amd_safe warnings

The idea with those routines is to slowly phase them out and not call
them on anything else besides K8. They even have a check for that which,
when called too early, fails. Let me explain:

It gets the cpuinfo_x86 pointer from the per_cpu array and when this
happens for cpu0, before its boot_cpu_data has been copied back to the
per_cpu array in smp_store_boot_cpu_info(), we get an empty struct and
thus the check fails.

Use boot_cpu_data directly instead.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 9a2a716..cea02d7 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -20,11 +20,11 @@

static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };
int err;

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[1] = msr;
gprs[7] = 0x9c5a203a;
@@ -38,10 +38,10 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)

static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[0] = (u32)val;
gprs[1] = msr;

Subject: [tip:x86/cpu] x86, CPU, AMD: Drop useless label

Commit-ID: 042c16f14161fb569fd1a60b908c5196109052da
Gitweb: http://git.kernel.org/tip/042c16f14161fb569fd1a60b908c5196109052da
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:46 +0200
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 8 Apr 2013 09:07:18 -0700

x86, CPU, AMD: Drop useless label

All we want to do is return from this function so stop jumping around
like a flea for no good reason.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index cea02d7..5013a48 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -192,11 +192,11 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
/* Athlon 660/661 is valid. */
if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
(c->x86_mask == 1)))
- goto valid_k7;
+ return;

/* Duron 670 is valid */
if ((c->x86_model == 7) && (c->x86_mask == 0))
- goto valid_k7;
+ return;

/*
* Athlon 662, Duron 671, and Athlon >model 7 have capability
@@ -209,7 +209,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
((c->x86_model == 7) && (c->x86_mask >= 1)) ||
(c->x86_model > 7))
if (cpu_has_mp)
- goto valid_k7;
+ return;

/* If we get here, not a certified SMP capable AMD system. */

@@ -220,9 +220,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: This combination of AMD"
" processors is not suitable for SMP.\n");
add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);
-
-valid_k7:
- ;
}

static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)

2013-04-10 11:08:49

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C


I think this series broke FPU emulation, crashing in early boot:

[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] __ex_table already sorted, skipping sort
[ 0.000000] Initializing CPU#0
[ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 0.000000] IP: [<b10fa063>] kmem_cache_alloc+0x13/0x130
[ 0.000000] *pde = 00000000
[ 0.000000] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
[ 0.000000] Modules linked in:
[ 0.000000] Pid: 0, comm: swapper Not tainted 3.9.0-rc6+ #221907
[ 0.000000] EIP: 0060:[<b10fa063>] EFLAGS: 00210046 CPU: 0
[ 0.000000] EIP is at kmem_cache_alloc+0x13/0x130
[ 0.000000] EAX: 00000000 EBX: b156dfa0 ECX: 0000007b EDX: 000000d0
[ 0.000000] ESI: effd09c0 EDI: 00000000 EBP: b1563ea4 ESP: b1563e78
[ 0.000000] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 0.000000] CR0: 80050037 CR2: 00000000 CR3: 015fa000 CR4: 00000690
[ 0.000000] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 0.000000] DR6: ffff0ff0 DR7: 00000400
[ 0.000000] Process swapper (pid: 0, ti=b1562000 task=b156dfa0 task.ti=b1562000)
[ 0.000000] Stack:
[ 0.000000] 3b9aca00 00000000 b1563e8c b11cfb0c 000000d0 b1563eb8 b10277d2 b1706040
[ 0.000000] b156dfa0 effd09c0 b13ed7a0 b1563eb0 b1008827 b1563f44 b1563f3c b132fa45
[ 0.000000] b1563ed8 b1027c80 00000000 00000000 b1706062 00000001 b1563ee0 00200046
[ 0.000000] Call Trace:
[ 0.000000] [<b11cfb0c>] ? sprintf+0x1c/0x20
[ 0.000000] [<b10277d2>] ? print_time.part.5+0x82/0xc0
[ 0.000000] [<b13ed7a0>] ? do_debug+0x150/0x150
[ 0.000000] [<b1008827>] init_fpu+0x67/0xa0
[ 0.000000] [<b132fa45>] math_emulate+0x695/0xc40
[ 0.000000] [<b1027c80>] ? print_prefix+0x60/0xa0
[ 0.000000] [<b13ef9f8>] ? sub_preempt_count+0x8/0x80
[ 0.000000] [<b13ef9f8>] ? sub_preempt_count+0x8/0x80
[ 0.000000] [<b1028719>] ? wake_up_klogd+0x49/0x70
[ 0.000000] [<b1028aa5>] ? console_unlock+0x365/0x4c0
[ 0.000000] [<b13ed7a0>] ? do_debug+0x150/0x150
[ 0.000000] [<b13ed7de>] do_device_not_available+0x3e/0x80
[ 0.000000] [<b13ed17c>] error_code+0x6c/0x74
[ 0.000000] [<b13de90c>] ? fpu_init+0x80/0xf5
[ 0.000000] [<b13e0960>] cpu_init+0x2b0/0x2b8
[ 0.000000] [<b15a6355>] trap_init+0x243/0x24b
[ 0.000000] [<b15a48ba>] start_kernel+0x1b1/0x363
[ 0.000000] [<b15a453e>] ? repair_env_string+0x51/0x51
[ 0.000000] [<b15a4382>] i386_start_kernel+0x12c/0x12f
[ 0.000000] Code: 0c 89 f0 e8 50 f4 ff ff 5b 5e 5d c3 8d b6 00 00 00 00 8d bf 00 00 00 00 55 89 e5 57 56 53 83 ec 20 e8 c2 90 2f 00 89 c7 89 55 e4 <8b> 07 64 03 05 94 d6 5e b1 8b 58 04 8b 00 85 c0 89 45 ec 74 76
[ 0.000000] EIP: [<b10fa063>] kmem_cache_alloc+0x13/0x130 SS:ESP 0068:b1563e78
[ 0.000000] CR2: 0000000000000000
[ 0.000000] ---[ end trace a7919e7f17c0a725 ]---
[ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
[ 0.000000] Rebooting in 1 seconds..Press any key to enter the menu

Config attached.

Thanks,

Ingo


Attachments:
(No filename) (3.08 kB)
.config (70.73 kB)
Download all attachments

2013-04-10 12:24:16

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C

On Wed, Apr 10, 2013 at 01:08:40PM +0200, Ingo Molnar wrote:
> Config attached.

How do you even build this? I tried tip:x86/cpu but it fails here:

drivers/misc/lkdtm.c: In function ‘recursive_loop.constprop.3’:
drivers/misc/lkdtm.c:276:1: warning: the frame size of 1028 bytes is larger than 1024 bytes [-Wframe-larger-than=]
In file included from /w/kernel/linux-2.6/arch/x86/include/asm/uaccess.h:537:0,
from include/linux/uaccess.h:5,
from include/linux/highmem.h:8,
from include/linux/pagemap.h:10,
from fs/binfmt_misc.c:27:
/w/kernel/linux-2.6/arch/x86/include/asm/uaccess_32.h: In function ‘parse_command.part.2’:
/w/kernel/linux-2.6/arch/x86/include/asm/uaccess_32.h:211:26: error: call to ‘copy_from_user_overflow’ declared with attribute error: copy_from_user() buffer size is not provably correct
make[1]: *** [fs/binfmt_misc.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [fs] Error 2
make: *** Waiting for unfinished jobs....

because of CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-10 12:25:32

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C


* Borislav Petkov <[email protected]> wrote:

> On Wed, Apr 10, 2013 at 01:08:40PM +0200, Ingo Molnar wrote:
> > Config attached.
>
> How do you even build this? I tried tip:x86/cpu but it fails here:
>
> drivers/misc/lkdtm.c: In function ???recursive_loop.constprop.3???:
> drivers/misc/lkdtm.c:276:1: warning: the frame size of 1028 bytes is larger than 1024 bytes [-Wframe-larger-than=]
> In file included from /w/kernel/linux-2.6/arch/x86/include/asm/uaccess.h:537:0,
> from include/linux/uaccess.h:5,
> from include/linux/highmem.h:8,
> from include/linux/pagemap.h:10,
> from fs/binfmt_misc.c:27:
> /w/kernel/linux-2.6/arch/x86/include/asm/uaccess_32.h: In function ???parse_command.part.2???:
> /w/kernel/linux-2.6/arch/x86/include/asm/uaccess_32.h:211:26: error: call to ???copy_from_user_overflow??? declared with attribute error: copy_from_user() buffer size is not provably correct
> make[1]: *** [fs/binfmt_misc.o] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [fs] Error 2
> make: *** Waiting for unfinished jobs....
>
> because of CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y.

In my builds I disable that. So I'd suggest to disable that bit in the .config and
retry.

Thanks,

Ingo

2013-04-10 13:32:56

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C

(let's test the reply-to-all settings now :-))

On Wed, Apr 10, 2013 at 02:25:27PM +0200, Ingo Molnar wrote:
> In my builds I disable that. So I'd suggest to disable that bit in the
> .config and retry.

Yep, did that and was able to reproduce the issue in qemu. At a first
glance, it looks like we're calling kmalloc too early but I need to
verify this is actually the case. Stay tuned.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-10 15:36:55

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C

On 04/10/2013 06:32 AM, Borislav Petkov wrote:
> (let's test the reply-to-all settings now :-))
>
> On Wed, Apr 10, 2013 at 02:25:27PM +0200, Ingo Molnar wrote:
>> In my builds I disable that. So I'd suggest to disable that bit in the
>> .config and retry.
>
> Yep, did that and was able to reproduce the issue in qemu. At a first
> glance, it looks like we're calling kmalloc too early but I need to
> verify this is actually the case. Stay tuned.
>

OK, this thread took off in another direction but you're still looking
at this, right?

-hpa

2013-04-10 16:11:29

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH 0/4] x86: FPU detection in C

On Wed, Apr 10, 2013 at 08:35:43AM -0700, H. Peter Anvin wrote:
> OK, this thread took off in another direction but you're still looking
> at this, right?

Yep, and I think I have the rootcause, let's start (oops below for
info).

When the oops happens, we're on the following path:

start_kernel
|-> trap_init
|-> cpu_init
|-> fpu_init

and down that path we do mxcsr_feature_mask_init() at some point which does

b13cf456: 0f ae 05 80 54 58 b1 fxsave 0xb1585480

This causes an #NM for the first time since we have CR0.EM set. We enter
the handler do_device_not_available which calls into math_emulate()
because we have CONFIG_MATH_EMULATION on.

It, in the beginning, does init_fpu(current) which does fpu_alloc, which in
turn, does kmem_cache_alloc(task_xstate_cachep...

Since we have SLUB on in this particular .config, we go to
slab_alloc_node() in slub.c and the following code (cf. the Code section
below):

kmem_cache_alloc:
pushl %ebp #
movl %esp, %ebp #,
pushl %edi #
pushl %esi #
pushl %ebx #
subl $32, %esp #,
call mcount
movl %eax, %edi # s, s
movl %edx, -28(%ebp) # gfpflags, %sfp
.L825:
movl (%edi), %eax # s_3(D)->cpu_slab, tcp_ptr__ <---
#APP
# 2341 "mm/slub.c" 1
add %fs:this_cpu_off, %eax # this_cpu_off, tcp_ptr__
# 0 "" 2
#NO_APP

and %edi, is of course, 0.

Finally, this happens because we haven't initialized task_xstate_cachep.

We still do the initialization albeit a bit further down in the same
function:

start_kernel
|-> fork_init(totalram_pages)
|-> arch_task_cache_init

This, however, is *after* trap_init -> Boom.

Provided I haven't made a mistake, this is the problem we're seeing.

[ 0.000000] Initializing CPU#0
[ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 0.000000] IP: [<b10fa893>] kmem_cache_alloc+0x13/0x130
[ 0.000000] *pde = 00000000
[ 0.000000] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
[ 0.000000] Modules linked in:
[ 0.000000] Pid: 0, comm: swapper Not tainted 3.9.0-rc5+ #2
[ 0.000000] EIP: 0060:[<b10fa893>] EFLAGS: 00210046 CPU: 0
[ 0.000000] EIP is at kmem_cache_alloc+0x13/0x130
[ 0.000000] EAX: 00000000 EBX: b1557fa0 ECX: 0000007b EDX: 000000d0
[ 0.000000] ESI: f77df9a0 EDI: 00000000 EBP: b154dea4 ESP: b154de78
[ 0.000000] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 0.000000] CR0: 80050037 CR2: 00000000 CR3: 015e8000 CR4: 00000290
[ 0.000000] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 0.000000] DR6: ffff0ff0 DR7: 00000400
[ 0.000000] Process swapper (pid: 0, ti=b154c000 task=b1557fa0 task.ti=b154c000)
[ 0.000000] Stack:
[ 0.000000] 3b9aca00 00000000 b154de8c b11d033c 000000d0 b154deb8 b1028952 b16f4040
[ 0.000000] b1557fa0 f77df9a0 b13de290 b154deb0 b1009897 b154df44 b154df3c b1320715
[ 0.000000] b154ded8 b1028e00 00000000 00000000 b16f4062 00000001 b154dee0 00200046
[ 0.000000] Call Trace:
[ 0.000000] [<b11d033c>] ? sprintf+0x1c/0x20
[ 0.000000] [<b1028952>] ? print_time.part.5+0x82/0xc0
[ 0.000000] [<b13de290>] ? do_debug+0x150/0x150
[ 0.000000] [<b1009897>] init_fpu+0x67/0xa0
[ 0.000000] [<b1320715>] math_emulate+0x695/0xc40
[ 0.000000] [<b1028e00>] ? print_prefix+0x60/0xa0
[ 0.000000] [<b13e04e8>] ? sub_preempt_count+0x8/0x80
[ 0.000000] [<b13e04e8>] ? sub_preempt_count+0x8/0x80
[ 0.000000] [<b1029899>] ? wake_up_klogd+0x49/0x70
[ 0.000000] [<b1029c25>] ? console_unlock+0x365/0x4c0
[ 0.000000] [<b13de290>] ? do_debug+0x150/0x150
[ 0.000000] [<b13de2ce>] do_device_not_available+0x3e/0x80
[ 0.000000] [<b13ddc6c>] error_code+0x6c/0x74
[ 0.000000] [<b13cf456>] ? fpu_init+0x80/0xf5
[ 0.000000] [<b13d14b1>] cpu_init+0x2b0/0x2b8
[ 0.000000] [<b1594335>] trap_init+0x243/0x24b
[ 0.000000] [<b159289f>] start_kernel+0x1a2/0x34f
[ 0.000000] [<b1592532>] ? repair_env_string+0x51/0x51
[ 0.000000] [<b1592376>] i386_start_kernel+0x12c/0x12f
[ 0.000000] Code: 0c 89 f0 e8 50 f4 ff ff 5b 5e 5d c3 8d b6 00 00 00 00 8d bf 00 00 00 00 55 89 e5 57 56 53 83 ec 20 e8 72 93 2e 00 89 c7 89 55 e4 <8b> 07 64 03 05 94 b6 5d b1 8b 58 04 8b 00 85 c0 89 45 ec 74 76
[ 0.000000] EIP: [<b10fa893>] kmem_cache_alloc+0x13/0x130 SS:ESP 0068:b154de78
[ 0.000000] CR2: 0000000000000000
[ 0.000000] ---[ end trace a7919e7f17c0a725 ]---
[ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task!

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-10 21:29:57

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH] x86, FPU: Fix FPU initialization

On Wed, Apr 10, 2013 at 06:11:22PM +0200, Borislav Petkov wrote:
> On Wed, Apr 10, 2013 at 08:35:43AM -0700, H. Peter Anvin wrote:
> > OK, this thread took off in another direction but you're still looking
> > at this, right?
>
> Yep, and I think I have the rootcause, let's start (oops below for
> info).

Ok, here's a fix which boots fine here in qemu. Ingo, it would be cool
if you gave it a run to verify.

Thanks.

--
>From 2263430417dd8de1a5fef4b2c40127e681fdc1ab Mon Sep 17 00:00:00 2001
From: Borislav Petkov <[email protected]>
Date: Wed, 10 Apr 2013 21:37:03 +0200
Subject: [PATCH] x86, FPU: Fix FPU initialization

c70293d0e3fe ("x86: Get rid of ->hard_math and all the FPU asm
fu") converted the FPU detection code to C. Yours truly, in his
overzealousness, used static_cpu_has() too early, before alternatives
have run, leading to the checks in fpu_init() to fail and fpu_init() to
set CR0.EM.

This, in turn, lead to an early NULL ptr due to
a chicken-and-an-egg issue (full details here:
http://lkml.kernel.org/r/[email protected]).

Fix it back to the normal CPU feature checks.

Signed-off-by: Borislav Petkov <[email protected]>
---
arch/x86/kernel/i387.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 3a6455304c8d..b0928898bf54 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -163,7 +163,7 @@ void __cpuinit fpu_init(void)
unsigned long cr4_mask = 0;

#ifndef CONFIG_MATH_EMULATION
- if (!static_cpu_has(X86_FEATURE_FPU)) {
+ if (!cpu_has_fpu) {
pr_emerg("No FPU found and no math emulation present\n");
pr_emerg("Giving up\n");
for (;;)
@@ -179,7 +179,7 @@ void __cpuinit fpu_init(void)

cr0 = read_cr0();
cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
- if (!static_cpu_has(X86_FEATURE_FPU))
+ if (!cpu_has_fpu)
cr0 |= X86_CR0_EM;
write_cr0(cr0);

--
1.8.2.135.g7b592fa


--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-11 12:10:01

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> On Wed, Apr 10, 2013 at 06:11:22PM +0200, Borislav Petkov wrote:
> > On Wed, Apr 10, 2013 at 08:35:43AM -0700, H. Peter Anvin wrote:
> > > OK, this thread took off in another direction but you're still looking
> > > at this, right?
> >
> > Yep, and I think I have the rootcause, let's start (oops below for
> > info).
>
> Ok, here's a fix which boots fine here in qemu. Ingo, it would be cool
> if you gave it a run to verify.

Even with this applied, the attached config is still unhappy and crashes/locks up
during user-space init, see the crashlog attached below.

The config has MATH_EMULATION=y, so I suspect it's the same problem category.

(I'll keep tip:x86/cpu excluded from tip:master so that others are not affected by
this bug.)

Thanks,

Ingo

INIT: version 2.86 booting
[ 14.723352] mount (55) used greatest stack depth: 5820 bytes left
[ 14.723352] mount (55) used greatest stack depth: 5820 bytes left
[ 15.187354] awk (64) used greatest stack depth: 5816 bytes left
[ 15.187354] awk (64) used greatest stack depth: 5816 bytes left
Welcome to [ 15.327059] gzip (70) used greatest stack depth: 5576 bytes left
[ 15.327059] gzip (70) used greatest stack depth: 5576 bytes left
Fedora Core
Press 'I' to enter interactive startup.
modprobe: FATAL: Could not load /lib/modules/3.9.0-rc6+/modules.dep: No such file or directory

[ 15.921486] BUG: unable to handle kernel [ 15.921486] BUG: unable to handle kernel paging requestpaging request at 0000407a
at 0000407a
[ 15.921486] IP:[ 15.921486] IP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00
[<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00
[ 15.921486] *pde = 00000000 [ 15.921486] *pde = 00000000

[ 15.921486] Oops: 0002 [#1] [ 15.921486] Oops: 0002 [#1] SMP SMP

[ 15.921486] Modules linked in:[ 15.921486] Modules linked in:

[ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E
[ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E
[ 15.921486] EIP: 0060:[<41071ab0>] EFLAGS: 00013002 CPU: 0
[ 15.921486] EIP: 0060:[<41071ab0>] EFLAGS: 00013002 CPU: 0
[ 15.921486] EIP is at __lock_acquire.isra.19+0x3e0/0xb00
[ 15.921486] EIP is at __lock_acquire.isra.19+0x3e0/0xb00
[ 15.921486] EAX: 7e917f94 EBX: 00003f76 ECX: 00000000 EDX: 00000000
[ 15.921486] EAX: 7e917f94 EBX: 00003f76 ECX: 00000000 EDX: 00000000
[ 15.921486] ESI: 00000000 EDI: 7e9469c0 EBP: 7e9cfed8 ESP: 7e9cfe88
[ 15.921486] ESI: 00000000 EDI: 7e9469c0 EBP: 7e9cfed8 ESP: 7e9cfe88
[ 15.921486] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 15.921486] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 15.921486] CR0: 8005003b CR2: 0000407a CR3: 01768000 CR4: 00000690
[ 15.921486] CR0: 8005003b CR2: 0000407a CR3: 01768000 CR4: 00000690
[ 15.921486] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 15.921486] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 15.921486] DR6: ffff0ff0 DR7: 00000400
[ 15.921486] DR6: ffff0ff0 DR7: 00000400
[ 15.921486] Process hwclock (pid: 73, ti=7e9ce000 task=7e9469c0 task.ti=7e9ce000)
[ 15.921486] Process hwclock (pid: 73, ti=7e9ce000 task=7e9469c0 task.ti=7e9ce000)
[ 15.921486] Stack:
[ 15.921486] Stack:
[ 15.921486] 00000003[ 15.921486] 00000003 b4fe9c00 b4fe9c00 00000003 00000003 00000001 00000001 7e999500 7e999500 00000000 00000000 7e999d00 7e999d00 7e995340 7e995340

[ 15.921486] 00003002[ 15.921486] 00003002 7e8e8920 7e8e8920 7e9c0207 7e9c0207 80100008 80100008 7e999500 7e999500 7e9c0207 7e9c0207 7e946d24 7e946d24 7e946d20 7e946d20

[ 15.921486] 7e917f94[ 15.921486] 7e917f94 00000000 00000000 7e9469c0 7e9469c0 00003246 00003246 7e9cff00 7e9cff00 4107264d 4107264d 00000000 00000000 00000000 00000000

[ 15.921486] Call Trace:
[ 15.921486] Call Trace:
[ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
[ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
[ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] exit_fs+0x35/0x70
[ 15.921486] [<41109905>] exit_fs+0x35/0x70
[ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
[ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
[ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
[ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
[ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
[ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
[ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
[ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
[ 15.921486] Code:[ 15.921486] Code: 00 00 83 83 3d 3d c0 c0 14 14 d0 d0 41 41 00 00 0f 0f 85 85 18 18 05 05 00 00 00 00 ba ba 34 34 03 03 00 00 00 00 b8 b8 cb cb e0 e0 4e 4e 41 41 e8 e8 ee ee 74 74 fb fb ff ff e9 e9 04 04 05 05 00 00 00 00 85 85 db db 0f 0f 84 84 fc fc 04 04 00 00 00 00 90 90 <3e> <3e> ff ff 83 83 04 04 01 01 00 00 00 00 a1 a1 48 48 48 48 77 77 41 41 8b 8b b7 b7 5c 5c 03 03 00 00 00 00 85 85 c0 c0 0f 0f

[ 15.921486] EIP: [<41071ab0>] [ 15.921486] EIP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00__lock_acquire.isra.19+0x3e0/0xb00 SS:ESP 0068:7e9cfe88
SS:ESP 0068:7e9cfe88
[ 15.921486] CR2: 000000000000407a
[ 15.921486] CR2: 000000000000407a
[ 15.921486] ---[ end trace 630c66e4c0c7a4b4 ]---
[ 15.921486] ---[ end trace 630c66e4c0c7a4b4 ]---
[ 15.921486] Fixing recursive fault but reboot is needed!
[ 15.921486] Fixing recursive fault but reboot is needed!
[ 15.921486] BUG: scheduling while atomic: hwclock/73/0x00000003
[ 15.921486] BUG: scheduling while atomic: hwclock/73/0x00000003
[ 15.921486] INFO: lockdep is turned off.
[ 15.921486] INFO: lockdep is turned off.
[ 15.921486] Modules linked in:[ 15.921486] Modules linked in:

[ 15.921486] Pid: 73, comm: hwclock Tainted: G D W 3.9.0-rc6+ #222032
[ 15.921486] Pid: 73, comm: hwclock Tainted: G D W 3.9.0-rc6+ #222032
[ 15.921486] Call Trace:
[ 15.921486] Call Trace:
[ 15.921486] [<413d73d0>] __schedule_bug+0x54/0x66
[ 15.921486] [<413d73d0>] __schedule_bug+0x54/0x66
[ 15.921486] [<413dd6f4>] __schedule+0x64/0x720
[ 15.921486] [<413dd6f4>] __schedule+0x64/0x720
[ 15.921486] [<413d6f42>] ? printk+0x48/0x4a
[ 15.921486] [<413d6f42>] ? printk+0x48/0x4a
[ 15.921486] [<413de06d>] schedule+0x4d/0x50
[ 15.921486] [<413de06d>] schedule+0x4d/0x50
[ 15.921486] [<4102db77>] do_exit+0xc7/0x850
[ 15.921486] [<4102db77>] do_exit+0xc7/0x850
[ 15.921486] [<4102bffe>] ? kmsg_dump+0xde/0x110
[ 15.921486] [<4102bffe>] ? kmsg_dump+0xde/0x110
[ 15.921486] [<4102c012>] ? kmsg_dump+0xf2/0x110
[ 15.921486] [<4102c012>] ? kmsg_dump+0xf2/0x110
[ 15.921486] [<4102bf3c>] ? kmsg_dump+0x1c/0x110
[ 15.921486] [<4102bf3c>] ? kmsg_dump+0x1c/0x110
[ 15.921486] [<413e0417>] oops_end+0x87/0x90
[ 15.921486] [<413e0417>] oops_end+0x87/0x90
[ 15.921486] [<413d6921>] no_context+0x17a/0x182
[ 15.921486] [<413d6921>] no_context+0x17a/0x182
[ 15.921486] [<413d6a46>] __bad_area_nosemaphore+0x11d/0x125
[ 15.921486] [<413d6a46>] __bad_area_nosemaphore+0x11d/0x125
[ 15.921486] [<4105387d>] ? sched_clock_local+0x1d/0x160
[ 15.921486] [<4105387d>] ? sched_clock_local+0x1d/0x160
[ 15.921486] [<413e2990>] ? __do_page_fault+0x4c0/0x4c0
[ 15.921486] [<413e2990>] ? __do_page_fault+0x4c0/0x4c0
[ 15.921486] [<413d6a60>] bad_area_nosemaphore+0x12/0x14
[ 15.921486] [<413d6a60>] bad_area_nosemaphore+0x12/0x14
[ 15.921486] [<413e2916>] __do_page_fault+0x446/0x4c0
[ 15.921486] [<413e2916>] __do_page_fault+0x446/0x4c0
[ 15.921486] [<41053bb7>] ? sched_clock_cpu+0x137/0x170
[ 15.921486] [<41053bb7>] ? sched_clock_cpu+0x137/0x170
[ 15.921486] [<4105387d>] ? sched_clock_local+0x1d/0x160
[ 15.921486] [<4105387d>] ? sched_clock_local+0x1d/0x160
[ 15.921486] [<413e2990>] ? __do_page_fault+0x4c0/0x4c0
[ 15.921486] [<413e2990>] ? __do_page_fault+0x4c0/0x4c0
[ 15.921486] [<413e2998>] do_page_fault+0x8/0x10
[ 15.921486] [<413e2998>] do_page_fault+0x8/0x10
[ 15.921486] [<413dfd1f>] error_code+0x67/0x6c
[ 15.921486] [<413dfd1f>] error_code+0x67/0x6c
[ 15.921486] [<41071ab0>] ? __lock_acquire.isra.19+0x3e0/0xb00
[ 15.921486] [<41071ab0>] ? __lock_acquire.isra.19+0x3e0/0xb00
[ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
[ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
[ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
[ 15.921486] [<41109905>] exit_fs+0x35/0x70
[ 15.921486] [<41109905>] exit_fs+0x35/0x70
[ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
[ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
[ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
[ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
[ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
[ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
[ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
[ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
[ 37.139621] CPA self-test:
[ 37.139621] CPA self-test:
[ 37.139621] 4k 4080 large 252 gb 0 x 4332[40000000-7ffef000] miss 0
[ 37.139621] 4k 4080 large 252 gb 0 x 4332[40000000-7ffef000] miss 0
[ 37.169620] 4k 206832 large 54 gb 0 x 206886[40000000-7ffef000] miss 0
[ 37.169620] 4k 206832 large 54 gb 0 x 206886[40000000-7ffef000] miss 0
[ 37.189616] 4k 206832 large 54 gb 0 x 206886[40000000-7ffef000] miss 0
[ 37.189616] 4k 206832 large 54 gb 0 x 206886[40000000-7ffef000] miss 0
[ 37.199944] ok.
[ 37.199944] ok.


Attachments:
(No filename) (9.82 kB)
config (85.03 kB)
Download all attachments

2013-04-11 14:23:40

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Thu, Apr 11, 2013 at 02:09:52PM +0200, Ingo Molnar wrote:
> Even with this applied, the attached config is still unhappy and
> crashes/locks up during user-space init, see the crashlog attached
> below.
>
> The config has MATH_EMULATION=y, so I suspect it's the same problem
> category.
>
> (I'll keep tip:x86/cpu excluded from tip:master so that others are not
> affected by this bug.)

Right,

of course, I can't trigger it here :(

Let's see:

> INIT: version 2.86 booting
> [ 14.723352] mount (55) used greatest stack depth: 5820 bytes left
> [ 14.723352] mount (55) used greatest stack depth: 5820 bytes left

Don't you just hate the repeated lines? :-)

> [ 15.187354] awk (64) used greatest stack depth: 5816 bytes left
> [ 15.187354] awk (64) used greatest stack depth: 5816 bytes left
> Welcome to [ 15.327059] gzip (70) used greatest stack depth: 5576 bytes left
> [ 15.327059] gzip (70) used greatest stack depth: 5576 bytes left
> Fedora Core
> Press 'I' to enter interactive startup.
> modprobe: FATAL: Could not load /lib/modules/3.9.0-rc6+/modules.dep: No such file or directory
>
> [ 15.921486] BUG: unable to handle kernel [ 15.921486] BUG: unable to handle kernel paging requestpaging request at 0000407a
> at 0000407a
> [ 15.921486] IP:[ 15.921486] IP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00
> [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00
> [ 15.921486] *pde = 00000000 [ 15.921486] *pde = 00000000
>
> [ 15.921486] Oops: 0002 [#1] [ 15.921486] Oops: 0002 [#1] SMP SMP
>
> [ 15.921486] Modules linked in:[ 15.921486] Modules linked in:
>
> [ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E
> [ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E

Ok, so you're running a M686 32-bit kernel on an Athlon 64?

Also, what exactly is that kernel: 3.9.0-rc6+? tip:x86/cpu is
v3.9-rc5-11-g3019653a5758

> [ 15.921486] EIP: 0060:[<41071ab0>] EFLAGS: 00013002 CPU: 0
> [ 15.921486] EIP: 0060:[<41071ab0>] EFLAGS: 00013002 CPU: 0
> [ 15.921486] EIP is at __lock_acquire.isra.19+0x3e0/0xb00
> [ 15.921486] EIP is at __lock_acquire.isra.19+0x3e0/0xb00
> [ 15.921486] EAX: 7e917f94 EBX: 00003f76 ECX: 00000000 EDX: 00000000
> [ 15.921486] EAX: 7e917f94 EBX: 00003f76 ECX: 00000000 EDX: 00000000
> [ 15.921486] ESI: 00000000 EDI: 7e9469c0 EBP: 7e9cfed8 ESP: 7e9cfe88
> [ 15.921486] ESI: 00000000 EDI: 7e9469c0 EBP: 7e9cfed8 ESP: 7e9cfe88
> [ 15.921486] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> [ 15.921486] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> [ 15.921486] CR0: 8005003b CR2: 0000407a CR3: 01768000 CR4: 00000690
> [ 15.921486] CR0: 8005003b CR2: 0000407a CR3: 01768000 CR4: 00000690
> [ 15.921486] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> [ 15.921486] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> [ 15.921486] DR6: ffff0ff0 DR7: 00000400
> [ 15.921486] DR6: ffff0ff0 DR7: 00000400
> [ 15.921486] Process hwclock (pid: 73, ti=7e9ce000 task=7e9469c0 task.ti=7e9ce000)
> [ 15.921486] Process hwclock (pid: 73, ti=7e9ce000 task=7e9469c0 task.ti=7e9ce000)
> [ 15.921486] Stack:
> [ 15.921486] Stack:
> [ 15.921486] 00000003[ 15.921486] 00000003 b4fe9c00 b4fe9c00 00000003 00000003 00000001 00000001 7e999500 7e999500 00000000 00000000 7e999d00 7e999d00 7e995340 7e995340
>
> [ 15.921486] 00003002[ 15.921486] 00003002 7e8e8920 7e8e8920 7e9c0207 7e9c0207 80100008 80100008 7e999500 7e999500 7e9c0207 7e9c0207 7e946d24 7e946d24 7e946d20 7e946d20
>
> [ 15.921486] 7e917f94[ 15.921486] 7e917f94 00000000 00000000 7e9469c0 7e9469c0 00003246 00003246 7e9cff00 7e9cff00 4107264d 4107264d 00000000 00000000 00000000 00000000
>
> [ 15.921486] Call Trace:
> [ 15.921486] Call Trace:
> [ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
> [ 15.921486] [<4107264d>] lock_acquire+0x5d/0x80
> [ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
> [ 15.921486] [<41109905>] ? exit_fs+0x35/0x70

Right, so I can't see how exit_fs grabbing a bunch of locks could be
related to MATH_EMULATION. I'm not saying it can't - I just don't see it
from the trace.

> [ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
> [ 15.921486] [<413deba1>] _raw_spin_lock+0x41/0x70
> [ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
> [ 15.921486] [<41109905>] ? exit_fs+0x35/0x70
> [ 15.921486] [<41109905>] exit_fs+0x35/0x70
> [ 15.921486] [<41109905>] exit_fs+0x35/0x70
> [ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
> [ 15.921486] [<4102ddab>] do_exit+0x2fb/0x850
> [ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
> [ 15.921486] [<4102e48c>] do_group_exit+0x6c/0xb0
> [ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
> [ 15.921486] [<4102e4e3>] sys_exit_group+0x13/0x20
> [ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
> [ 15.921486] [<413e4f05>] sysenter_do_call+0x12/0x31
> [ 15.921486] Code:[ 15.921486] Code: 00 00 83 83 3d 3d c0 c0 14 14 d0 d0 41 41 00 00 0f 0f 85 85 18 18 05 05 00 00 00 00 ba ba 34 34 03 03 00 00 00 00 b8 b8 cb cb e0 e0 4e 4e 41 41 e8 e8 ee ee 74 74 fb fb ff ff e9 e9 04 04 05 05 00 00 00 00 85 85 db db 0f 0f 84 84 fc fc 04 04 00 00 00 00 90 90 <3e> <3e> ff ff 83 83 04 04 01 01 00 00 00 00 a1 a1 48 48 48 48 77 77 41 41 8b 8b b7 b7 5c 5c 03 03 00 00 00 00 85 85 c0 c0 0f 0f
>
> [ 15.921486] EIP: [<41071ab0>] [ 15.921486] EIP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00__lock_acquire.isra.19+0x3e0/0xb00 SS:ESP 0068:7e9cfe88
> SS:ESP 0068:7e9cfe88
> [ 15.921486] CR2: 000000000000407a
> [ 15.921486] CR2: 000000000000407a
> [ 15.921486] ---[ end trace 630c66e4c0c7a4b4 ]---
> [ 15.921486] ---[ end trace 630c66e4c0c7a4b4 ]---

Ok, so I can't trigger this in kvm. What happens here is that the guest
simply reboots.

Can you please checkout tip:x86/cpu to the commit before the FPU patch,
i.e. before this one:

commit c70293d0e3fef6b989cd8268027d410cf06ce384
Author: H. Peter Anvin <[email protected]>
Date: Mon Apr 8 17:57:43 2013 +0200

x86: Get rid of ->hard_math and all the FPU asm fu

and see whether it still triggers or not.

That would give us some triage insights on what's going on.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-11 19:27:13

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On 04/11/2013 05:09 AM, Ingo Molnar wrote:
>
> Even with this applied, the attached config is still unhappy and crashes/locks up
> during user-space init, see the crashlog attached below.
>
> The config has MATH_EMULATION=y, so I suspect it's the same problem category.
>

What host is this?

-hpa

2013-04-11 20:23:36

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Thu, Apr 11, 2013 at 12:26:09PM -0700, H. Peter Anvin wrote:
> What host is this?

Judging by the DMI string in the oops:

> [ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E

it is an ASUS board with a K8 on it - probably Ingo's old K8 which
triggers all kinds of crap off an on.

8-)

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-12 05:32:39

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> On Thu, Apr 11, 2013 at 12:26:09PM -0700, H. Peter Anvin wrote:
> > What host is this?
>
> Judging by the DMI string in the oops:
>
> > [ 15.921486] Pid: 73, comm: hwclock Tainted: G W 3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E
>
> it is an ASUS board with a K8 on it - probably Ingo's old K8 which
> triggers all kinds of crap off an on.
>
> 8-)

Yep, with Fedora Core 8, and totally unchanged userspace, booting randconfigs of
the latest -tip:master tree. This box has booted up over a million Linux kernels
in the past 4+ years, so when it shows new types of sickness then in 99.9% of the
cases it's something about the kernel.

The lockup went away after excluding x86/cpu. I'll try more testing as time
permits.

Thanks,

Ingo

2013-04-12 05:35:49

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

I used to have one of these but have it away when cleaning out my study... no space.

Ingo Molnar <[email protected]> wrote:

>
>* Borislav Petkov <[email protected]> wrote:
>
>> On Thu, Apr 11, 2013 at 12:26:09PM -0700, H. Peter Anvin wrote:
>> > What host is this?
>>
>> Judging by the DMI string in the oops:
>>
>> > [ 15.921486] Pid: 73, comm: hwclock Tainted: G W
>3.9.0-rc6+ #222032 System manufacturer System Product Name/A8N-E
>>
>> it is an ASUS board with a K8 on it - probably Ingo's old K8 which
>> triggers all kinds of crap off an on.
>>
>> 8-)
>
>Yep, with Fedora Core 8, and totally unchanged userspace, booting
>randconfigs of
>the latest -tip:master tree. This box has booted up over a million
>Linux kernels
>in the past 4+ years, so when it shows new types of sickness then in
>99.9% of the
>cases it's something about the kernel.
>
>The lockup went away after excluding x86/cpu. I'll try more testing as
>time
>permits.
>
>Thanks,
>
> Ingo

--
Sent from my mobile phone. Please excuse brevity and lack of formatting.

2013-04-12 09:47:31

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Thu, Apr 11, 2013 at 10:34:48PM -0700, H. Peter Anvin wrote:
> >The lockup went away after excluding x86/cpu. I'll try more testing
> >as time permits.

Right,

so tip:x86/cpu has all in all 11 patches. Maybe a quick bisect?

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-12 11:26:36

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Fri, Apr 12, 2013 at 11:47:24AM +0200, Borislav Petkov wrote:
> On Thu, Apr 11, 2013 at 10:34:48PM -0700, H. Peter Anvin wrote:
> > >The lockup went away after excluding x86/cpu. I'll try more testing
> > >as time permits.
>
> Right,
>
> so tip:x86/cpu has all in all 11 patches. Maybe a quick bisect?

Ok, some more info. decodecoding your "Code:" section gives this (yep,
all the instruction bytes were repeated so I could've made a mistake
there while removing the duplicates):

[ 15.921486] Code: 00 83 3d c0 14 d0 41 00 0f 85 18 05 00 00 ba 34 03 00 00 b8 cb e0 4e 41 e8 ee 74 fb ff e9 04 05 00 00 85 db 0f 84 fc 04 00 00 90 <3e> ff 83 04 01 00 00 a1 48 48 77 41 8b b7 5c 03 00 00 85 c0 0f
All code
========
0: 00 83 3d c0 14 d0 add %al,-0x2feb3fc3(%rbx)
6: 41 00 0f add %cl,(%r15)
9: 85 18 test %ebx,(%rax)
b: 05 00 00 ba 34 add $0x34ba0000,%eax
10: 03 00 add (%rax),%eax
12: 00 b8 cb e0 4e 41 add %bh,0x414ee0cb(%rax)
18: e8 ee 74 fb ff callq 0xfffffffffffb750b
1d: e9 04 05 00 00 jmpq 0x526
22: 85 db test %ebx,%ebx
24: 0f 84 fc 04 00 00 je 0x526
2a: 90 nop
2b:* 3e ff 83 04 01 00 00 incl %ds:0x104(%rbx) <-- trapping instruction
32: a1 48 48 77 41 8b b7 movabs 0x35cb78b41774848,%eax
39: 5c 03
3b: 00 00 add %al,(%rax)
3d: 85 c0 test %eax,%eax
3f:

Now, if I look at __lock_acquire objdump here, I get:

2688: 31 c0 xor %eax,%eax
268a: e9 49 0b 00 00 jmp 31d8 <__lock_acquire+0xba6>
268f: 8b 4d c4 mov -0x3c(%ebp),%ecx
2692: 8b 44 91 04 mov 0x4(%ecx,%edx,4),%eax
2696: 85 c0 test %eax,%eax
2698: 75 0e jne 26a8 <__lock_acquire+0x76>
269a: 8b 45 c4 mov -0x3c(%ebp),%eax
269d: 31 c9 xor %ecx,%ecx
269f: e8 12 e5 ff ff call bb6 <register_lock_class>
26a4: 85 c0 test %eax,%eax
26a6: 74 e0 je 2688 <__lock_acquire+0x56>
26a8: ff 80 04 01 00 00 incl 0x104(%eax) <---
26ae: 8b 96 68 03 00 00 mov 0x368(%esi),%edx

which can be correlated with a lot of fuzz but the INC seems to look
the same and the offset within __lock_acquire is almost in the same
vicinity.

Which looks like this snippet here:

.L752:
movl -60(%ebp), %eax # %sfp,
xorl %ecx, %ecx #
call register_lock_class #
testl %eax, %eax # class
je .L970 #,
.L753:
#APP
# 95 "/w/kernel/linux-2.6/arch/x86/include/asm/atomic.h" 1
incl 260(%eax) # MEM[(struct atomic_t *)D.29327_54].counter <---
# 0 "" 2
#NO_APP

and this has to be:

/*
* Not cached?
*/
if (unlikely(!class)) {
class = register_lock_class(lock, subclass, 0);
if (!class)
return 0;
}
atomic_inc((atomic_t *)&class->ops); <---


So looking at the decode above, we have the class pointer in %ebx
(decodecode somehow can't differentiate between 32- and 64-bit code
dump, probably needs a flag or so) and it is 0x00003f76. Which doesn't
look like a valid kernel pointer to me.

And 0x00003f76 + 0x104 gives exactly 0x0000407a which is the address at
which we #PF:

[ 15.921486] BUG: unable to handle kernel paging request at 0000407a
[ 15.921486] IP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00

More hmmm...

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-15 10:09:05

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> And 0x00003f76 + 0x104 gives exactly 0x0000407a which is the address at
> which we #PF:
>
> [ 15.921486] BUG: unable to handle kernel paging request at 0000407a
> [ 15.921486] IP: [<41071ab0>] __lock_acquire.isra.19+0x3e0/0xb00
>
> More hmmm...

It gave me the impression of memory corruption - but impressions can deceive ;-)

Anyway, not sure I can test/bisect it this week - merge window preparations and
all that.

Thanks,

Ingo

2013-04-15 10:17:46

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Mon, Apr 15, 2013 at 12:08:58PM +0200, Ingo Molnar wrote:
> It gave me the impression of memory corruption - but impressions can
> deceive ;-)
>
> Anyway, not sure I can test/bisect it this week - merge window
> preparations and all that.

Ok, and also, in your oops, it said 3.9.0-rc6+ but tip:x86/cpu is
v3.9-rc5-11-g3019653a5758 so could it be a different kernel or some
strange interaction with some other code. I'll run your config with
tip:x86/cpu on my AMD box here to see whether I can repro on real hw.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-15 10:18:32

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> On Mon, Apr 15, 2013 at 12:08:58PM +0200, Ingo Molnar wrote:
> > It gave me the impression of memory corruption - but impressions can
> > deceive ;-)
> >
> > Anyway, not sure I can test/bisect it this week - merge window
> > preparations and all that.
>
> Ok, and also, in your oops, it said 3.9.0-rc6+ but tip:x86/cpu is
> v3.9-rc5-11-g3019653a5758 so could it be a different kernel or some strange
> interaction with some other code. [...]

It was tip:master with x86/cpu merged in freshly.

Thanks,

Ingo

2013-04-15 15:54:20

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Mon, Apr 15, 2013 at 12:18:25PM +0200, Ingo Molnar wrote:
> It was tip:master with x86/cpu merged in freshly.

Ok, some more observations. I can trigger some oops similar yours (I
haven't caught mine yet over serial or such) with latest tip/master +
tip:x86/cpu.

When I remove tip:x86/cpu, the machine boots fine so I probably can
say now that I can reproduce at least similar behavior to what you're
observing.

Anyway, I'll try to catch the oops and try to decipher it and do a
bisection. Will keep you posted.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-15 22:04:12

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Mon, Apr 15, 2013 at 05:54:15PM +0200, Borislav Petkov wrote:
> On Mon, Apr 15, 2013 at 12:18:25PM +0200, Ingo Molnar wrote:
> > It was tip:master with x86/cpu merged in freshly.
>
> Ok, some more observations. I can trigger some oops similar yours (I
> haven't caught mine yet over serial or such) with latest tip/master +
> tip:x86/cpu.

Ok, here's the deal - it looks like a corruption which causes a couple
of different backtraces with different functions in the call trace. I've
bisected tip:x86/cpu and the evildoers are:

commit 3019653a57585602690fd38679326e9337f7ed7f
Author: Borislav Petkov <[email protected]>
Date: Wed Apr 10 21:37:03 2013 +0200

x86/fpu: Fix FPU initialization

commit c70293d0e3fef6b989cd8268027d410cf06ce384
Author: H. Peter Anvin <[email protected]>
Date: Mon Apr 8 17:57:43 2013 +0200

x86: Get rid of ->hard_math and all the FPU asm fu


I'll venture a guess and say that if you revert those, your .config
would boot on your K8 too.

So, I'd propose we take those 2 out for more careful inspection and
fixing and the rest of tip:x86/cpu can go upstream in the upcoming merge
window. IMHO of course.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-16 09:25:33

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> On Mon, Apr 15, 2013 at 05:54:15PM +0200, Borislav Petkov wrote:
> > On Mon, Apr 15, 2013 at 12:18:25PM +0200, Ingo Molnar wrote:
> > > It was tip:master with x86/cpu merged in freshly.
> >
> > Ok, some more observations. I can trigger some oops similar yours (I
> > haven't caught mine yet over serial or such) with latest tip/master +
> > tip:x86/cpu.
>
> Ok, here's the deal - it looks like a corruption which causes a couple
> of different backtraces with different functions in the call trace. I've
> bisected tip:x86/cpu and the evildoers are:

Correct, 'late effects of memory corruption' was my first impression too, from the
crash pattern.

>
> commit 3019653a57585602690fd38679326e9337f7ed7f
> Author: Borislav Petkov <[email protected]>
> Date: Wed Apr 10 21:37:03 2013 +0200
>
> x86/fpu: Fix FPU initialization
>
> commit c70293d0e3fef6b989cd8268027d410cf06ce384
> Author: H. Peter Anvin <[email protected]>
> Date: Mon Apr 8 17:57:43 2013 +0200
>
> x86: Get rid of ->hard_math and all the FPU asm fu
>
>
> I'll venture a guess and say that if you revert those, your .config
> would boot on your K8 too.
>
> So, I'd propose we take those 2 out for more careful inspection and
> fixing and the rest of tip:x86/cpu can go upstream in the upcoming merge
> window. IMHO of course.

I've got limited extra capacity right now - but if Peter rebases tip:x86/cpu or
you send a pullable update of tip:x86/cpu I can stick it into -tip testing and
yell if it goes wrong.

Thanks,

Ingo

2013-04-16 09:48:56

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization

On Tue, Apr 16, 2013 at 11:25:28AM +0200, Ingo Molnar wrote:
> I've got limited extra capacity right now - but if Peter rebases
> tip:x86/cpu or you send a pullable update of tip:x86/cpu I can stick
> it into -tip testing and yell if it goes wrong.
>

Ok, I'll do that in a second.

Btw, another heads-up: you know how I'm regularly testing
Linus+tip/master - well, I started seeing some strange lockups on my
workstation with -rc7 + tip from two days ago. And the box wouldn't
resume properly, the last line it would print is:

"Disabling non-boot CPUs ..."

and then hang. I've backed-out tip/master and it seems to work so it has
to be some interaction caused by something in tip. I haven't been able
to put my finger on it though but I'll watch it and try to trigger it on
my other boxes.

Thanks.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-16 10:08:57

by Borislav Petkov

[permalink] [raw]
Subject: [GIT PULL] Rebase tip:x86/cpu

Hi,

here it is.

Original tip:x86/cpu tree state is this:

3019653a5758 x86/fpu: Fix FPU initialization
042c16f14161 x86, CPU, AMD: Drop useless label
982f33db626e x86, AMD: Correct {rd,wr}msr_amd_safe warnings
e277a4938574 x86: Fold-in trivial check_config function
c70293d0e3fe x86: Get rid of ->hard_math and all the FPU asm fu
7d7dc116e56c x86, cpu: Convert AMD Erratum 400
e6ee94d58dfd x86, cpu: Convert AMD Erratum 383
c5b41a67505c x86, cpu: Convert Cyrix coma bug detection
93a829e8e2c2 x86, cpu: Convert FDIV bug detection
e2604b49e8a8 x86, cpu: Convert F00F bug detection
65fc985b37dc x86, cpu: Expand cpufeature facility to include cpu bugs

and the rebased one is this:

1077c932db63 x86, CPU, AMD: Drop useless label
682469a5db6f x86, AMD: Correct {rd,wr}msr_amd_safe warnings
55a36b65ee71 x86: Fold-in trivial check_config function
7d7dc116e56c x86, cpu: Convert AMD Erratum 400
e6ee94d58dfd x86, cpu: Convert AMD Erratum 383
c5b41a67505c x86, cpu: Convert Cyrix coma bug detection
93a829e8e2c2 x86, cpu: Convert FDIV bug detection
e2604b49e8a8 x86, cpu: Convert F00F bug detection
65fc985b37dc x86, cpu: Expand cpufeature facility to include cpu bugs

Commits c70293d0e3fe and 3019653a5758 are gone and the three commits
in-between have received new commit ids. Those 6 before that are
unchanged, as their commit ids show.

Please pull,
thanks.

The following changes since commit 07961ac7c0ee8b546658717034fe692fd12eefa9:

Linux 3.9-rc5 (2013-03-31 15:12:43 -0700)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git tags/tip_x86_cpu_rebased

for you to fetch changes up to 1077c932db63ecc571c31df1c24d4a44e30928e5:

x86, CPU, AMD: Drop useless label (2013-04-16 11:50:51 +0200)

----------------------------------------------------------------
Rebase tip:x86/cpu to drop two patches which trigger a random corruption
on 32-bit.

----------------------------------------------------------------
Borislav Petkov (9):
x86, cpu: Expand cpufeature facility to include cpu bugs
x86, cpu: Convert F00F bug detection
x86, cpu: Convert FDIV bug detection
x86, cpu: Convert Cyrix coma bug detection
x86, cpu: Convert AMD Erratum 383
x86, cpu: Convert AMD Erratum 400
x86: Fold-in trivial check_config function
x86, AMD: Correct {rd,wr}msr_amd_safe warnings
x86, CPU, AMD: Drop useless label

arch/x86/include/asm/cpufeature.h | 19 +++++++++++++++++++
arch/x86/include/asm/processor.h | 25 +------------------------
arch/x86/kernel/alternative.c | 2 +-
arch/x86/kernel/cpu/amd.c | 48 +++++++++++++++++++++++++++++-------------------
arch/x86/kernel/cpu/bugs.c | 34 +++++++++++++++-------------------
arch/x86/kernel/cpu/common.c | 4 ++++
arch/x86/kernel/cpu/cyrix.c | 5 +++--
arch/x86/kernel/cpu/intel.c | 4 ++--
arch/x86/kernel/cpu/proc.c | 6 +++---
arch/x86/kernel/process.c | 2 +-
arch/x86/kernel/setup.c | 2 --
arch/x86/kvm/svm.c | 2 +-
arch/x86/mm/fault.c | 2 +-
13 files changed, 80 insertions(+), 75 deletions(-)

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

2013-04-16 11:33:56

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86, FPU: Fix FPU initialization


* Borislav Petkov <[email protected]> wrote:

> On Tue, Apr 16, 2013 at 11:25:28AM +0200, Ingo Molnar wrote:
> > I've got limited extra capacity right now - but if Peter rebases
> > tip:x86/cpu or you send a pullable update of tip:x86/cpu I can stick
> > it into -tip testing and yell if it goes wrong.
> >
>
> Ok, I'll do that in a second.
>
> Btw, another heads-up: you know how I'm regularly testing
> Linus+tip/master - well, I started seeing some strange lockups on my
> workstation with -rc7 + tip from two days ago. And the box wouldn't
> resume properly, the last line it would print is:
>
> "Disabling non-boot CPUs ..."
>
> and then hang. I've backed-out tip/master and it seems to work so it has
> to be some interaction caused by something in tip. I haven't been able
> to put my finger on it though but I'll watch it and try to trigger it on
> my other boxes.

Would be nice to pin that down ...

You are the first one to report this.

Thanks,

Ingo

2013-04-16 11:35:10

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL] Rebase tip:x86/cpu


* Borislav Petkov <[email protected]> wrote:

> Hi,
>
> here it is.
>
> Original tip:x86/cpu tree state is this:
>
> 3019653a5758 x86/fpu: Fix FPU initialization
> 042c16f14161 x86, CPU, AMD: Drop useless label
> 982f33db626e x86, AMD: Correct {rd,wr}msr_amd_safe warnings
> e277a4938574 x86: Fold-in trivial check_config function
> c70293d0e3fe x86: Get rid of ->hard_math and all the FPU asm fu
> 7d7dc116e56c x86, cpu: Convert AMD Erratum 400
> e6ee94d58dfd x86, cpu: Convert AMD Erratum 383
> c5b41a67505c x86, cpu: Convert Cyrix coma bug detection
> 93a829e8e2c2 x86, cpu: Convert FDIV bug detection
> e2604b49e8a8 x86, cpu: Convert F00F bug detection
> 65fc985b37dc x86, cpu: Expand cpufeature facility to include cpu bugs
>
> and the rebased one is this:
>
> 1077c932db63 x86, CPU, AMD: Drop useless label
> 682469a5db6f x86, AMD: Correct {rd,wr}msr_amd_safe warnings
> 55a36b65ee71 x86: Fold-in trivial check_config function
> 7d7dc116e56c x86, cpu: Convert AMD Erratum 400
> e6ee94d58dfd x86, cpu: Convert AMD Erratum 383
> c5b41a67505c x86, cpu: Convert Cyrix coma bug detection
> 93a829e8e2c2 x86, cpu: Convert FDIV bug detection
> e2604b49e8a8 x86, cpu: Convert F00F bug detection
> 65fc985b37dc x86, cpu: Expand cpufeature facility to include cpu bugs
>
> Commits c70293d0e3fe and 3019653a5758 are gone and the three commits
> in-between have received new commit ids. Those 6 before that are
> unchanged, as their commit ids show.

Thanks, I started testing this.

Ingo

Subject: [tip:x86/cpu] x86: Fold-in trivial check_config function

Commit-ID: 55a36b65ee7107d6bb557c96fd202c4e90164542
Gitweb: http://git.kernel.org/tip/55a36b65ee7107d6bb557c96fd202c4e90164542
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:44 +0200
Committer: Borislav Petkov <[email protected]>
CommitDate: Tue, 16 Apr 2013 11:50:50 +0200

x86: Fold-in trivial check_config function

Fold it into its single call site. No functionality change.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/bugs.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index c59635e..4112be9 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -81,21 +81,6 @@ static void __init check_fpu(void)
}
}

-/*
- * Check whether we are able to run this kernel safely on SMP.
- *
- * - i386 is no longer supported.
- * - In order to run on anything without a TSC, we need to be
- * compiled for a i486.
- */
-
-static void __init check_config(void)
-{
- if (boot_cpu_data.x86 < 4)
- panic("Kernel requires i486+ for 'invlpg' and other features");
-}
-
-
void __init check_bugs(void)
{
identify_boot_cpu();
@@ -103,7 +88,17 @@ void __init check_bugs(void)
pr_info("CPU: ");
print_cpu_info(&boot_cpu_data);
#endif
- check_config();
+
+ /*
+ * Check whether we are able to run this kernel safely on SMP.
+ *
+ * - i386 is no longer supported.
+ * - In order to run on anything without a TSC, we need to be
+ * compiled for a i486.
+ */
+ if (boot_cpu_data.x86 < 4)
+ panic("Kernel requires i486+ for 'invlpg' and other features");
+
init_utsname()->machine[1] =
'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
alternative_instructions();

Subject: [tip:x86/cpu] x86, AMD: Correct {rd,wr}msr_amd_safe warnings

Commit-ID: 682469a5db6fade318a72406935b5000186e5643
Gitweb: http://git.kernel.org/tip/682469a5db6fade318a72406935b5000186e5643
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:45 +0200
Committer: Borislav Petkov <[email protected]>
CommitDate: Tue, 16 Apr 2013 11:50:51 +0200

x86, AMD: Correct {rd,wr}msr_amd_safe warnings

The idea with those routines is to slowly phase them out and not call
them on anything else besides K8. They even have a check for that which,
when called too early, fails. Let me explain:

It gets the cpuinfo_x86 pointer from the per_cpu array and when this
happens for cpu0, before its boot_cpu_data has been copied back to the
per_cpu array in smp_store_boot_cpu_info(), we get an empty struct and
thus the check fails.

Use boot_cpu_data directly instead.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 9a2a716..cea02d7 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -20,11 +20,11 @@

static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };
int err;

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[1] = msr;
gprs[7] = 0x9c5a203a;
@@ -38,10 +38,10 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)

static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
{
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
u32 gprs[8] = { 0 };

- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
+ "%s should only be used on K8!\n", __func__);

gprs[0] = (u32)val;
gprs[1] = msr;

Subject: [tip:x86/cpu] x86, CPU, AMD: Drop useless label

Commit-ID: 1077c932db63ecc571c31df1c24d4a44e30928e5
Gitweb: http://git.kernel.org/tip/1077c932db63ecc571c31df1c24d4a44e30928e5
Author: Borislav Petkov <[email protected]>
AuthorDate: Mon, 8 Apr 2013 17:57:46 +0200
Committer: Borislav Petkov <[email protected]>
CommitDate: Tue, 16 Apr 2013 11:50:51 +0200

x86, CPU, AMD: Drop useless label

All we want to do is return from this function so stop jumping around
like a flea for no good reason.

Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/kernel/cpu/amd.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index cea02d7..5013a48 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -192,11 +192,11 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
/* Athlon 660/661 is valid. */
if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
(c->x86_mask == 1)))
- goto valid_k7;
+ return;

/* Duron 670 is valid */
if ((c->x86_model == 7) && (c->x86_mask == 0))
- goto valid_k7;
+ return;

/*
* Athlon 662, Duron 671, and Athlon >model 7 have capability
@@ -209,7 +209,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
((c->x86_model == 7) && (c->x86_mask >= 1)) ||
(c->x86_model > 7))
if (cpu_has_mp)
- goto valid_k7;
+ return;

/* If we get here, not a certified SMP capable AMD system. */

@@ -220,9 +220,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: This combination of AMD"
" processors is not suitable for SMP.\n");
add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);
-
-valid_k7:
- ;
}

static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)

Subject: [tip:x86/fpu] x86: Get rid of ->hard_math and all the FPU asm fu

Commit-ID: 60e019eb37a8d989031ad47ae9810453536f3127
Gitweb: http://git.kernel.org/tip/60e019eb37a8d989031ad47ae9810453536f3127
Author: H. Peter Anvin <[email protected]>
AuthorDate: Mon, 29 Apr 2013 16:04:20 +0200
Committer: H. Peter Anvin <[email protected]>
CommitDate: Thu, 6 Jun 2013 14:32:04 -0700

x86: Get rid of ->hard_math and all the FPU asm fu

Reimplement FPU detection code in C and drop old, not-so-recommended
detection method in asm. Move all the relevant stuff into i387.c where
it conceptually belongs. Finally drop cpuinfo_x86.hard_math.

[ hpa: huge thanks to Borislav for taking my original concept patch
and productizing it ]

[ Boris, note to self: do not use static_cpu_has before alternatives! ]

Signed-off-by: H. Peter Anvin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Borislav Petkov <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/include/asm/fpu-internal.h | 2 --
arch/x86/include/asm/processor.h | 3 +-
arch/x86/kernel/asm-offsets_32.c | 1 -
arch/x86/kernel/cpu/bugs.c | 21 ++-----------
arch/x86/kernel/cpu/common.c | 3 +-
arch/x86/kernel/cpu/cyrix.c | 2 +-
arch/x86/kernel/cpu/proc.c | 4 +--
arch/x86/kernel/head_32.S | 21 -------------
arch/x86/kernel/i387.c | 59 ++++++++++++++++++++++++++++++-------
arch/x86/kernel/xsave.c | 5 ++--
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
12 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index e25cc33..fb808d7 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -62,10 +62,8 @@ extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
#define xstateregs_active fpregs_active

#ifdef CONFIG_MATH_EMULATION
-# define HAVE_HWFP (boot_cpu_data.hard_math)
extern void finit_soft_fpu(struct i387_soft_struct *soft);
#else
-# define HAVE_HWFP 1
static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
#endif

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 22224b3..578f8b1 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -89,9 +89,9 @@ struct cpuinfo_x86 {
char wp_works_ok; /* It doesn't on 386's */

/* Problems on some 486Dx4's and old 386's: */
- char hard_math;
char rfu;
char pad0;
+ char pad1;
#else
/* Number of 4K pages in DTLB/ITLB combined(in pages): */
int x86_tlbsize;
@@ -164,6 +164,7 @@ extern const struct seq_operations cpuinfo_op;
#define cache_line_size() (boot_cpu_data.x86_cache_alignment)

extern void cpu_detect(struct cpuinfo_x86 *c);
+extern void __cpuinit fpu_detect(struct cpuinfo_x86 *c);

extern void early_cpu_init(void);
extern void identify_boot_cpu(void);
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 0ef4bba..d67c4be 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -28,7 +28,6 @@ void foo(void)
OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
OFFSET(CPUINFO_x86_mask, cpuinfo_x86, x86_mask);
- OFFSET(CPUINFO_hard_math, cpuinfo_x86, hard_math);
OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 4112be9..0344534 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -17,15 +17,6 @@
#include <asm/paravirt.h>
#include <asm/alternative.h>

-static int __init no_387(char *s)
-{
- boot_cpu_data.hard_math = 0;
- write_cr0(X86_CR0_TS | X86_CR0_EM | X86_CR0_MP | read_cr0());
- return 1;
-}
-
-__setup("no387", no_387);
-
static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0;

@@ -44,15 +35,6 @@ static void __init check_fpu(void)
{
s32 fdiv_bug;

- if (!boot_cpu_data.hard_math) {
-#ifndef CONFIG_MATH_EMULATION
- pr_emerg("No coprocessor found and no math emulation present\n");
- pr_emerg("Giving up\n");
- for (;;) ;
-#endif
- return;
- }
-
kernel_fpu_begin();

/*
@@ -107,5 +89,6 @@ void __init check_bugs(void)
* kernel_fpu_begin/end() in check_fpu() relies on the patched
* alternative instructions.
*/
- check_fpu();
+ if (cpu_has_fpu)
+ check_fpu();
}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22018f7..d4dd993 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -711,10 +711,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
return;

cpu_detect(c);
-
get_cpu_vendor(c);
-
get_cpu_cap(c);
+ fpu_detect(c);

if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index d048d5c..7582f47 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -333,7 +333,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
switch (dir0_lsn) {
case 0xd: /* either a 486SLC or DLC w/o DEVID */
dir0_msn = 0;
- p = Cx486_name[(c->hard_math) ? 1 : 0];
+ p = Cx486_name[(cpu_has_fpu ? 1 : 0)];
break;

case 0xe: /* a 486S A step */
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 37a198b..aee6317 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -37,8 +37,8 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
- c->hard_math ? "yes" : "no",
- c->hard_math ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
+ static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
c->cpuid_level,
c->wp_works_ok ? "yes" : "no");
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 73afd11..e65ddc6 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -444,7 +444,6 @@ is486:
orl %ecx,%eax
movl %eax,%cr0

- call check_x87
lgdt early_gdt_descr
lidt idt_descr
ljmp $(__KERNEL_CS),$1f
@@ -467,26 +466,6 @@ is486:
pushl $0 # fake return address for unwinder
jmp *(initial_code)

-/*
- * We depend on ET to be correct. This checks for 287/387.
- */
-check_x87:
- movb $0,X86_HARD_MATH
- clts
- fninit
- fstsw %ax
- cmpb $0,%al
- je 1f
- movl %cr0,%eax /* no coprocessor: have to set bits */
- xorl $4,%eax /* set EM */
- movl %eax,%cr0
- ret
- ALIGN
-1: movb $1,X86_HARD_MATH
- .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
- ret
-
-
#include "verify_cpu.S"

/*
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index cb33909..b627746 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -131,7 +131,7 @@ static void __cpuinit init_thread_xstate(void)
* xsave_init().
*/

- if (!HAVE_HWFP) {
+ if (!cpu_has_fpu) {
/*
* Disable xsave as we do not support it if i387
* emulation is enabled.
@@ -158,6 +158,14 @@ void __cpuinit fpu_init(void)
unsigned long cr0;
unsigned long cr4_mask = 0;

+#ifndef CONFIG_MATH_EMULATION
+ if (!cpu_has_fpu) {
+ pr_emerg("No FPU found and no math emulation present\n");
+ pr_emerg("Giving up\n");
+ for (;;)
+ asm volatile("hlt");
+ }
+#endif
if (cpu_has_fxsr)
cr4_mask |= X86_CR4_OSFXSR;
if (cpu_has_xmm)
@@ -167,7 +175,7 @@ void __cpuinit fpu_init(void)

cr0 = read_cr0();
cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
- if (!HAVE_HWFP)
+ if (!cpu_has_fpu)
cr0 |= X86_CR0_EM;
write_cr0(cr0);

@@ -185,7 +193,7 @@ void __cpuinit fpu_init(void)

void fpu_finit(struct fpu *fpu)
{
- if (!HAVE_HWFP) {
+ if (!cpu_has_fpu) {
finit_soft_fpu(&fpu->state->soft);
return;
}
@@ -214,7 +222,7 @@ int init_fpu(struct task_struct *tsk)
int ret;

if (tsk_used_math(tsk)) {
- if (HAVE_HWFP && tsk == current)
+ if (cpu_has_fpu && tsk == current)
unlazy_fpu(tsk);
tsk->thread.fpu.last_cpu = ~0;
return 0;
@@ -511,14 +519,13 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
if (ret)
return ret;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.fpu.state->fsave, 0,
-1);
- }

sanitize_i387_state(target);

@@ -545,13 +552,13 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,

sanitize_i387_state(target);

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);

- if (!cpu_has_fxsr) {
+ if (!cpu_has_fxsr)
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu.state->fsave, 0, -1);
- }
+ &target->thread.fpu.state->fsave, 0,
+ -1);

if (pos > 0 || count < sizeof(env))
convert_from_fxsr(&env, target);
@@ -592,3 +599,33 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
EXPORT_SYMBOL(dump_fpu);

#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
+
+static int __init no_387(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_FPU);
+ return 1;
+}
+
+__setup("no387", no_387);
+
+void __cpuinit fpu_detect(struct cpuinfo_x86 *c)
+{
+ unsigned long cr0;
+ u16 fsw, fcw;
+
+ fsw = fcw = 0xffff;
+
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
+ write_cr0(cr0);
+
+ asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+ : "+m" (fsw), "+m" (fcw));
+
+ if (fsw == 0 && (fcw & 0x103f) == 0x003f)
+ set_cpu_cap(c, X86_FEATURE_FPU);
+ else
+ clear_cpu_cap(c, X86_FEATURE_FPU);
+
+ /* The final cr0 value is set in fpu_init() */
+}
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index ada87a3..d6c28ac 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -243,7 +243,7 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!access_ok(VERIFY_WRITE, buf, size))
return -EACCES;

- if (!HAVE_HWFP)
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(current, NULL, 0,
sizeof(struct user_i387_ia32_struct), NULL,
(struct _fpstate_ia32 __user *) buf) ? -1 : 1;
@@ -350,11 +350,10 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
if (!used_math() && init_fpu(tsk))
return -1;

- if (!HAVE_HWFP) {
+ if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_set(current, NULL,
0, sizeof(struct user_i387_ia32_struct),
NULL, buf) != 0;
- }

if (use_xsave()) {
struct _fpx_sw_bytes fx_sw_user;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 7114c63..d482bca 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1410,7 +1410,7 @@ __init void lguest_init(void)
new_cpu_data.x86_capability[0] = cpuid_edx(1);

/* Math is always hard! */
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);

/* We don't have features. We have puppies! Puppies! */
#ifdef CONFIG_X86_MCE
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a492be2..2fa02bc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1557,7 +1557,7 @@ asmlinkage void __init xen_start_kernel(void)
#ifdef CONFIG_X86_32
/* set up basic CPUID stuff */
cpu_detect(&new_cpu_data);
- new_cpu_data.hard_math = 1;
+ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);
new_cpu_data.wp_works_ok = 1;
new_cpu_data.x86_capability[0] = cpuid_edx(1);
#endif