x86/fpu: Remove 'init_xstate_buf' bootmem allocation
[linux-2.6-block.git] / arch / x86 / kernel / fpu / init.c
CommitLineData
0c867537
IM
1/*
2 * x86 FPU boot time init code
3 */
78f7f1e5 4#include <asm/fpu/internal.h>
0c867537
IM
5#include <asm/tlbflush.h>
6
4d164092
IM
7/*
8 * Boot time CPU/FPU FDIV bug detection code:
9 */
10
11static double __initdata x = 4195835.0;
12static double __initdata y = 3145727.0;
13
14/*
15 * This used to check for exceptions..
16 * However, it turns out that to support that,
17 * the XMM trap handlers basically had to
18 * be buggy. So let's have a correct XMM trap
19 * handler, and forget about printing out
20 * some status at boot.
21 *
22 * We should really only care about bugs here
23 * anyway. Not features.
24 */
25static void __init check_fpu(void)
26{
27 s32 fdiv_bug;
28
29 kernel_fpu_begin();
30
31 /*
32 * trap_init() enabled FXSR and company _before_ testing for FP
33 * problems here.
34 *
35 * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
36 */
37 __asm__("fninit\n\t"
38 "fldl %1\n\t"
39 "fdivl %2\n\t"
40 "fmull %2\n\t"
41 "fldl %1\n\t"
42 "fsubp %%st,%%st(1)\n\t"
43 "fistpl %0\n\t"
44 "fwait\n\t"
45 "fninit"
46 : "=m" (*&fdiv_bug)
47 : "m" (*&x), "m" (*&y));
48
49 kernel_fpu_end();
50
51 if (fdiv_bug) {
52 set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
53 pr_warn("Hmm, FPU with FDIV bug\n");
54 }
55}
56
57void fpu__init_check_bugs(void)
58{
59 /*
60 * kernel_fpu_begin/end() in check_fpu() relies on the patched
61 * alternative instructions.
62 */
63 if (cpu_has_fpu)
64 check_fpu();
65}
66
67/*
68 * Boot time FPU feature detection code:
69 */
0c867537 70unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
91a8c2a5 71
0c867537
IM
72unsigned int xstate_size;
73EXPORT_SYMBOL_GPL(xstate_size);
0c867537
IM
74
75static void mxcsr_feature_mask_init(void)
76{
91a8c2a5 77 unsigned int mask = 0;
0c867537
IM
78
79 if (cpu_has_fxsr) {
91a8c2a5
IM
80 struct i387_fxsave_struct fx_tmp __aligned(32) = { };
81
82 asm volatile("fxsave %0" : "+m" (fx_tmp));
83
84 mask = fx_tmp.mxcsr_mask;
85
86 /*
87 * If zero then use the default features mask,
88 * which has all features set, except the
89 * denormals-are-zero feature bit:
90 */
0c867537
IM
91 if (mask == 0)
92 mask = 0x0000ffbf;
93 }
94 mxcsr_feature_mask &= mask;
95}
96
97static void fpstate_xstate_init_size(void)
98{
99 /*
100 * Note that xstate_size might be overwriten later during
101 * xsave_init().
102 */
103
104 if (!cpu_has_fpu) {
105 /*
106 * Disable xsave as we do not support it if i387
107 * emulation is enabled.
108 */
109 setup_clear_cpu_cap(X86_FEATURE_XSAVE);
110 setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
111 xstate_size = sizeof(struct i387_soft_struct);
6a133207
IM
112 } else {
113 if (cpu_has_fxsr)
114 xstate_size = sizeof(struct i387_fxsave_struct);
115 else
116 xstate_size = sizeof(struct i387_fsave_struct);
0c867537 117 }
0c867537
IM
118}
119
120/*
121 * Called on the boot CPU at bootup to set up the initial FPU state that
122 * is later cloned into all processes.
123 *
124 * Also called on secondary CPUs to set up the FPU state of their
125 * idle threads.
126 */
127void fpu__cpu_init(void)
128{
129 unsigned long cr0;
130 unsigned long cr4_mask = 0;
131
132#ifndef CONFIG_MATH_EMULATION
133 if (!cpu_has_fpu) {
134 pr_emerg("No FPU found and no math emulation present\n");
135 pr_emerg("Giving up\n");
136 for (;;)
137 asm volatile("hlt");
138 }
139#endif
140 if (cpu_has_fxsr)
141 cr4_mask |= X86_CR4_OSFXSR;
142 if (cpu_has_xmm)
143 cr4_mask |= X86_CR4_OSXMMEXCPT;
144 if (cr4_mask)
145 cr4_set_bits(cr4_mask);
146
147 cr0 = read_cr0();
148 cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
149 if (!cpu_has_fpu)
150 cr0 |= X86_CR0_EM;
151 write_cr0(cr0);
152
0c867537
IM
153
154 mxcsr_feature_mask_init();
155 xsave_init();
156 eager_fpu_init();
157}
146ed598
IM
158
159static int __init no_387(char *s)
160{
161 setup_clear_cpu_cap(X86_FEATURE_FPU);
162 return 1;
163}
164
165__setup("no387", no_387);
166
167/*
168 * Set the X86_FEATURE_FPU CPU-capability bit based on
169 * trying to execute an actual sequence of FPU instructions:
170 */
171void fpu__detect(struct cpuinfo_x86 *c)
172{
173 unsigned long cr0;
174 u16 fsw, fcw;
175
176 fsw = fcw = 0xffff;
177
178 cr0 = read_cr0();
179 cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
180 write_cr0(cr0);
181
182 asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
183 : "+m" (fsw), "+m" (fcw));
184
185 if (fsw == 0 && (fcw & 0x103f) == 0x003f)
186 set_cpu_cap(c, X86_FEATURE_FPU);
187 else
188 clear_cpu_cap(c, X86_FEATURE_FPU);
189
6a133207
IM
190 /* The final cr0 value is set later, in fpu_init() */
191
192 fpstate_xstate_init_size();
146ed598 193}