From: Ingo Molnar Date: Wed, 22 Apr 2015 08:53:34 +0000 (+0200) Subject: x86/fpu: Split out the boot time FPU init code into fpu/init.c X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=0c8675379048f36c76ad3a46519310ee2d626b2f;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git x86/fpu: Split out the boot time FPU init code into fpu/init.c Move boot time FPU initialization code into init.c, to better isolate it into its own domain. Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar --- diff --git a/arch/x86/kernel/fpu/Makefile b/arch/x86/kernel/fpu/Makefile index 89fd66a4b3a1..50464a716b87 100644 --- a/arch/x86/kernel/fpu/Makefile +++ b/arch/x86/kernel/fpu/Makefile @@ -2,4 +2,4 @@ # Build rules for the FPU support code: # -obj-y += core.o xsave.o +obj-y += init.o core.o xsave.o diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 01101553c6c1..9866a580952f 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -139,94 +139,6 @@ void fpu__save(struct task_struct *tsk) } EXPORT_SYMBOL_GPL(fpu__save); -unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; -unsigned int xstate_size; -EXPORT_SYMBOL_GPL(xstate_size); -static struct i387_fxsave_struct fx_scratch; - -static void mxcsr_feature_mask_init(void) -{ - unsigned long mask = 0; - - if (cpu_has_fxsr) { - memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); - asm volatile("fxsave %0" : "+m" (fx_scratch)); - mask = fx_scratch.mxcsr_mask; - if (mask == 0) - mask = 0x0000ffbf; - } - mxcsr_feature_mask &= mask; -} - -static void fpstate_xstate_init_size(void) -{ - /* - * Note that xstate_size might be overwriten later during - * xsave_init(). - */ - - if (!cpu_has_fpu) { - /* - * Disable xsave as we do not support it if i387 - * emulation is enabled. - */ - setup_clear_cpu_cap(X86_FEATURE_XSAVE); - setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); - xstate_size = sizeof(struct i387_soft_struct); - return; - } - - if (cpu_has_fxsr) - xstate_size = sizeof(struct i387_fxsave_struct); - else - xstate_size = sizeof(struct i387_fsave_struct); -} - -/* - * Called on the boot CPU at bootup to set up the initial FPU state that - * is later cloned into all processes. - * - * Also called on secondary CPUs to set up the FPU state of their - * idle threads. - */ -void fpu__cpu_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) - cr4_mask |= X86_CR4_OSXMMEXCPT; - if (cr4_mask) - cr4_set_bits(cr4_mask); - - cr0 = read_cr0(); - cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ - if (!cpu_has_fpu) - cr0 |= X86_CR0_EM; - write_cr0(cr0); - - /* - * fpstate_xstate_init_size() is only called once, to avoid overriding - * 'xstate_size' during (secondary CPU) bootup or during CPU hotplug. - */ - if (xstate_size == 0) - fpstate_xstate_init_size(); - - mxcsr_feature_mask_init(); - xsave_init(); - eager_fpu_init(); -} - void fpstate_init(struct fpu *fpu) { if (!cpu_has_fpu) { diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c new file mode 100644 index 000000000000..0a666298abbd --- /dev/null +++ b/arch/x86/kernel/fpu/init.c @@ -0,0 +1,93 @@ +/* + * x86 FPU boot time init code + */ +#include +#include + +unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; +unsigned int xstate_size; +EXPORT_SYMBOL_GPL(xstate_size); +static struct i387_fxsave_struct fx_scratch; + +static void mxcsr_feature_mask_init(void) +{ + unsigned long mask = 0; + + if (cpu_has_fxsr) { + memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); + asm volatile("fxsave %0" : "+m" (fx_scratch)); + mask = fx_scratch.mxcsr_mask; + if (mask == 0) + mask = 0x0000ffbf; + } + mxcsr_feature_mask &= mask; +} + +static void fpstate_xstate_init_size(void) +{ + /* + * Note that xstate_size might be overwriten later during + * xsave_init(). + */ + + if (!cpu_has_fpu) { + /* + * Disable xsave as we do not support it if i387 + * emulation is enabled. + */ + setup_clear_cpu_cap(X86_FEATURE_XSAVE); + setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); + xstate_size = sizeof(struct i387_soft_struct); + return; + } + + if (cpu_has_fxsr) + xstate_size = sizeof(struct i387_fxsave_struct); + else + xstate_size = sizeof(struct i387_fsave_struct); +} + +/* + * Called on the boot CPU at bootup to set up the initial FPU state that + * is later cloned into all processes. + * + * Also called on secondary CPUs to set up the FPU state of their + * idle threads. + */ +void fpu__cpu_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) + cr4_mask |= X86_CR4_OSXMMEXCPT; + if (cr4_mask) + cr4_set_bits(cr4_mask); + + cr0 = read_cr0(); + cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ + if (!cpu_has_fpu) + cr0 |= X86_CR0_EM; + write_cr0(cr0); + + /* + * fpstate_xstate_init_size() is only called once, to avoid overriding + * 'xstate_size' during (secondary CPU) bootup or during CPU hotplug. + */ + if (xstate_size == 0) + fpstate_xstate_init_size(); + + mxcsr_feature_mask_init(); + xsave_init(); + eager_fpu_init(); +}