Skip to content

Commit 280d7a1

Browse files
committed
Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fpu updates from Ingo Molnar: "The main changes relate to fixes between (lack of) CPUID and FPU detection that should only affect old or weird CPUs, by Andy Lutomirski" * 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/fpu: Fix the "Giving up, no FPU found" test x86/fpu: Fix CPUID-less FPU detection x86/fpu: Fix "x86/fpu: Legacy x87 FPU detected" message x86/cpu: Re-apply forced caps every time CPU caps are re-read x86/cpu: Factor out application of forced CPU caps x86/cpu: Add X86_FEATURE_CPUID x86/fpu/xstate: Move XSAVES state init to a function
2 parents 8a9365a + 9729017 commit 280d7a1

File tree

6 files changed

+57
-35
lines changed

6 files changed

+57
-35
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
101101
#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
102102
#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
103-
/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
103+
#define X86_FEATURE_CPUID ( 3*32+25) /* CPU has CPUID instruction itself */
104104
#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
105105
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
106106
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ extern void fpstate_init_soft(struct swregs_state *soft);
8787
#else
8888
static inline void fpstate_init_soft(struct swregs_state *soft) {}
8989
#endif
90+
91+
static inline void fpstate_init_xstate(struct xregs_state *xsave)
92+
{
93+
/*
94+
* XRSTORS requires these bits set in xcomp_bv, or it will
95+
* trigger #GP:
96+
*/
97+
xsave->header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | xfeatures_mask;
98+
}
99+
90100
static inline void fpstate_init_fxstate(struct fxregs_state *fx)
91101
{
92102
fx->cwd = 0x37f;

arch/x86/kernel/cpu/common.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,16 @@ void cpu_detect(struct cpuinfo_x86 *c)
659659
}
660660
}
661661

662+
static void apply_forced_caps(struct cpuinfo_x86 *c)
663+
{
664+
int i;
665+
666+
for (i = 0; i < NCAPINTS; i++) {
667+
c->x86_capability[i] &= ~cpu_caps_cleared[i];
668+
c->x86_capability[i] |= cpu_caps_set[i];
669+
}
670+
}
671+
662672
void get_cpu_cap(struct cpuinfo_x86 *c)
663673
{
664674
u32 eax, ebx, ecx, edx;
@@ -752,6 +762,13 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
752762
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
753763

754764
init_scattered_cpuid_features(c);
765+
766+
/*
767+
* Clear/Set all flags overridden by options, after probe.
768+
* This needs to happen each time we re-probe, which may happen
769+
* several times during CPU initialization.
770+
*/
771+
apply_forced_caps(c);
755772
}
756773

757774
static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
@@ -805,14 +822,12 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
805822
memset(&c->x86_capability, 0, sizeof c->x86_capability);
806823
c->extended_cpuid_level = 0;
807824

808-
if (!have_cpuid_p())
809-
identify_cpu_without_cpuid(c);
810-
811825
/* cyrix could have cpuid enabled via c_identify()*/
812826
if (have_cpuid_p()) {
813827
cpu_detect(c);
814828
get_cpu_vendor(c);
815829
get_cpu_cap(c);
830+
setup_force_cpu_cap(X86_FEATURE_CPUID);
816831

817832
if (this_cpu->c_early_init)
818833
this_cpu->c_early_init(c);
@@ -822,6 +837,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
822837

823838
if (this_cpu->c_bsp_init)
824839
this_cpu->c_bsp_init(c);
840+
} else {
841+
identify_cpu_without_cpuid(c);
842+
setup_clear_cpu_cap(X86_FEATURE_CPUID);
825843
}
826844

827845
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
@@ -1039,10 +1057,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
10391057
this_cpu->c_identify(c);
10401058

10411059
/* Clear/Set all flags overridden by options, after probe */
1042-
for (i = 0; i < NCAPINTS; i++) {
1043-
c->x86_capability[i] &= ~cpu_caps_cleared[i];
1044-
c->x86_capability[i] |= cpu_caps_set[i];
1045-
}
1060+
apply_forced_caps(c);
10461061

10471062
#ifdef CONFIG_X86_64
10481063
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
@@ -1103,10 +1118,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
11031118
* Clear/Set all flags overridden by options, need do it
11041119
* before following smp all cpus cap AND.
11051120
*/
1106-
for (i = 0; i < NCAPINTS; i++) {
1107-
c->x86_capability[i] &= ~cpu_caps_cleared[i];
1108-
c->x86_capability[i] |= cpu_caps_set[i];
1109-
}
1121+
apply_forced_caps(c);
11101122

11111123
/*
11121124
* On SMP, boot_cpu_data holds the common feature set between

arch/x86/kernel/fpu/core.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <asm/fpu/regset.h>
1010
#include <asm/fpu/signal.h>
1111
#include <asm/fpu/types.h>
12-
#include <asm/fpu/xstate.h>
1312
#include <asm/traps.h>
1413

1514
#include <linux/hardirq.h>
@@ -179,14 +178,8 @@ void fpstate_init(union fpregs_state *state)
179178

180179
memset(state, 0, fpu_kernel_xstate_size);
181180

182-
/*
183-
* XRSTORS requires that this bit is set in xcomp_bv, or
184-
* it will #GP. Make sure it is replaced after the memset().
185-
*/
186181
if (static_cpu_has(X86_FEATURE_XSAVES))
187-
state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
188-
xfeatures_mask;
189-
182+
fpstate_init_xstate(&state->xsave);
190183
if (static_cpu_has(X86_FEATURE_FXSR))
191184
fpstate_init_fxstate(&state->fxsave);
192185
else

arch/x86/kernel/fpu/init.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,7 @@ void fpu__init_cpu(void)
4848
fpu__init_cpu_xstate();
4949
}
5050

51-
/*
52-
* The earliest FPU detection code.
53-
*
54-
* Set the X86_FEATURE_FPU CPU-capability bit based on
55-
* trying to execute an actual sequence of FPU instructions:
56-
*/
57-
static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
51+
static bool fpu__probe_without_cpuid(void)
5852
{
5953
unsigned long cr0;
6054
u16 fsw, fcw;
@@ -65,18 +59,25 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
6559
cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
6660
write_cr0(cr0);
6761

68-
if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
69-
asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
70-
: "+m" (fsw), "+m" (fcw));
62+
asm volatile("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
63+
64+
pr_info("x86/fpu: Probing for FPU: FSW=0x%04hx FCW=0x%04hx\n", fsw, fcw);
7165

72-
if (fsw == 0 && (fcw & 0x103f) == 0x003f)
73-
set_cpu_cap(c, X86_FEATURE_FPU);
66+
return fsw == 0 && (fcw & 0x103f) == 0x003f;
67+
}
68+
69+
static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
70+
{
71+
if (!boot_cpu_has(X86_FEATURE_CPUID) &&
72+
!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
73+
if (fpu__probe_without_cpuid())
74+
setup_force_cpu_cap(X86_FEATURE_FPU);
7475
else
75-
clear_cpu_cap(c, X86_FEATURE_FPU);
76+
setup_clear_cpu_cap(X86_FEATURE_FPU);
7677
}
7778

7879
#ifndef CONFIG_MATH_EMULATION
79-
if (!boot_cpu_has(X86_FEATURE_FPU)) {
80+
if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_FPU)) {
8081
pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n");
8182
for (;;)
8283
asm volatile("hlt");

arch/x86/kernel/fpu/xstate.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,14 @@ void __init fpu__init_system_xstate(void)
706706
WARN_ON_FPU(!on_boot_cpu);
707707
on_boot_cpu = 0;
708708

709+
if (!boot_cpu_has(X86_FEATURE_FPU)) {
710+
pr_info("x86/fpu: No FPU detected\n");
711+
return;
712+
}
713+
709714
if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
710-
pr_info("x86/fpu: Legacy x87 FPU detected.\n");
715+
pr_info("x86/fpu: x87 FPU will use %s\n",
716+
boot_cpu_has(X86_FEATURE_FXSR) ? "FXSAVE" : "FSAVE");
711717
return;
712718
}
713719

0 commit comments

Comments
 (0)