x86, xsave: enable xsave/xrstor on cpus with xsave support
Enables xsave/xrstor by turning on cr4.osxsave on cpu's which have the xsave support. For now, features that OS supports/enabled are FP and SSE. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
a648bf4632
commit
dc1e35c6e9
10 changed files with 148 additions and 6 deletions
|
@ -38,7 +38,7 @@ obj-y += tsc.o io_delay.o rtc.o
|
||||||
|
|
||||||
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
|
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
|
||||||
obj-y += process.o
|
obj-y += process.o
|
||||||
obj-y += i387.o
|
obj-y += i387.o xsave.o
|
||||||
obj-y += ptrace.o
|
obj-y += ptrace.o
|
||||||
obj-y += ds.o
|
obj-y += ds.o
|
||||||
obj-$(CONFIG_X86_32) += tls.o
|
obj-$(CONFIG_X86_32) += tls.o
|
||||||
|
|
|
@ -712,6 +712,14 @@ void __cpuinit cpu_init(void)
|
||||||
current_thread_info()->status = 0;
|
current_thread_info()->status = 0;
|
||||||
clear_used_math();
|
clear_used_math();
|
||||||
mxcsr_feature_mask_init();
|
mxcsr_feature_mask_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boot processor to setup the FP and extended state context info.
|
||||||
|
*/
|
||||||
|
if (!smp_processor_id())
|
||||||
|
init_thread_xstate();
|
||||||
|
|
||||||
|
xsave_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
|
|
@ -61,6 +61,11 @@ void __init init_thread_xstate(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu_has_xsave) {
|
||||||
|
xsave_cntxt_init();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu_has_fxsr)
|
if (cpu_has_fxsr)
|
||||||
xstate_size = sizeof(struct i387_fxsave_struct);
|
xstate_size = sizeof(struct i387_fxsave_struct);
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
@ -83,6 +88,13 @@ void __cpuinit fpu_init(void)
|
||||||
|
|
||||||
write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
|
write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boot processor to setup the FP and extended state context info.
|
||||||
|
*/
|
||||||
|
if (!smp_processor_id())
|
||||||
|
init_thread_xstate();
|
||||||
|
xsave_init();
|
||||||
|
|
||||||
mxcsr_feature_mask_init();
|
mxcsr_feature_mask_init();
|
||||||
/* clean state in init */
|
/* clean state in init */
|
||||||
current_thread_info()->status = 0;
|
current_thread_info()->status = 0;
|
||||||
|
|
|
@ -1228,7 +1228,6 @@ void __init trap_init(void)
|
||||||
|
|
||||||
set_bit(SYSCALL_VECTOR, used_vectors);
|
set_bit(SYSCALL_VECTOR, used_vectors);
|
||||||
|
|
||||||
init_thread_xstate();
|
|
||||||
/*
|
/*
|
||||||
* Should be a barrier for any external CPU state:
|
* Should be a barrier for any external CPU state:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1172,10 +1172,6 @@ void __init trap_init(void)
|
||||||
#ifdef CONFIG_IA32_EMULATION
|
#ifdef CONFIG_IA32_EMULATION
|
||||||
set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
|
set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
* initialize the per thread extended state:
|
|
||||||
*/
|
|
||||||
init_thread_xstate();
|
|
||||||
/*
|
/*
|
||||||
* Should be a barrier for any external CPU state:
|
* Should be a barrier for any external CPU state:
|
||||||
*/
|
*/
|
||||||
|
|
87
arch/x86/kernel/xsave.c
Normal file
87
arch/x86/kernel/xsave.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* xsave/xrstor support.
|
||||||
|
*
|
||||||
|
* Author: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||||
|
*/
|
||||||
|
#include <linux/bootmem.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
|
#include <asm/i387.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported feature mask by the CPU and the kernel.
|
||||||
|
*/
|
||||||
|
unsigned int pcntxt_hmask, pcntxt_lmask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Represents init state for the supported extended state.
|
||||||
|
*/
|
||||||
|
struct xsave_struct *init_xstate_buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable the extended processor state save/restore feature
|
||||||
|
*/
|
||||||
|
void __cpuinit xsave_init(void)
|
||||||
|
{
|
||||||
|
if (!cpu_has_xsave)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_in_cr4(X86_CR4_OSXSAVE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable all the features that the HW is capable of
|
||||||
|
* and the Linux kernel is aware of.
|
||||||
|
*
|
||||||
|
* xsetbv();
|
||||||
|
*/
|
||||||
|
asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0),
|
||||||
|
"a" (pcntxt_lmask), "d" (pcntxt_hmask));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup the xstate image representing the init state
|
||||||
|
*/
|
||||||
|
void setup_xstate_init(void)
|
||||||
|
{
|
||||||
|
init_xstate_buf = alloc_bootmem(xstate_size);
|
||||||
|
init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable and initialize the xsave feature.
|
||||||
|
*/
|
||||||
|
void __init xsave_cntxt_init(void)
|
||||||
|
{
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
pcntxt_lmask = eax;
|
||||||
|
pcntxt_hmask = edx;
|
||||||
|
|
||||||
|
if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) {
|
||||||
|
printk(KERN_ERR "FP/SSE not shown under xsave features %x\n",
|
||||||
|
pcntxt_lmask);
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for now OS knows only about FP/SSE
|
||||||
|
*/
|
||||||
|
pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK;
|
||||||
|
pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK;
|
||||||
|
|
||||||
|
xsave_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recompute the context size for enabled features
|
||||||
|
*/
|
||||||
|
cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
xstate_size = ebx;
|
||||||
|
|
||||||
|
setup_xstate_init();
|
||||||
|
|
||||||
|
printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, "
|
||||||
|
"cntxt size 0x%x\n",
|
||||||
|
(pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size);
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
#include <asm/sigcontext.h>
|
#include <asm/sigcontext.h>
|
||||||
#include <asm/user.h>
|
#include <asm/user.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/xsave.h>
|
||||||
|
|
||||||
extern void fpu_init(void);
|
extern void fpu_init(void);
|
||||||
extern void mxcsr_feature_mask_init(void);
|
extern void mxcsr_feature_mask_init(void);
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
|
#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
|
||||||
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
|
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
|
||||||
#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
|
#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
|
||||||
|
#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* x86-64 Task Priority Register, CR8
|
* x86-64 Task Priority Register, CR8
|
||||||
|
|
|
@ -346,6 +346,18 @@ struct i387_soft_struct {
|
||||||
u32 entry_eip;
|
u32 entry_eip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xsave_hdr_struct {
|
||||||
|
u64 xstate_bv;
|
||||||
|
u64 reserved1[2];
|
||||||
|
u64 reserved2[5];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct xsave_struct {
|
||||||
|
struct i387_fxsave_struct i387;
|
||||||
|
struct xsave_hdr_struct xsave_hdr;
|
||||||
|
/* new processor state extensions will go here */
|
||||||
|
} __attribute__ ((packed, aligned (64)));
|
||||||
|
|
||||||
union thread_xstate {
|
union thread_xstate {
|
||||||
struct i387_fsave_struct fsave;
|
struct i387_fsave_struct fsave;
|
||||||
struct i387_fxsave_struct fxsave;
|
struct i387_fxsave_struct fxsave;
|
||||||
|
|
26
include/asm-x86/xsave.h
Normal file
26
include/asm-x86/xsave.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef __ASM_X86_XSAVE_H
|
||||||
|
#define __ASM_X86_XSAVE_H
|
||||||
|
|
||||||
|
#include <asm/processor.h>
|
||||||
|
#include <asm/i387.h>
|
||||||
|
|
||||||
|
#define XSTATE_FP 0x1
|
||||||
|
#define XSTATE_SSE 0x2
|
||||||
|
|
||||||
|
#define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE)
|
||||||
|
|
||||||
|
#define FXSAVE_SIZE 512
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the features that the OS can handle currently.
|
||||||
|
*/
|
||||||
|
#define XCNTXT_LMASK (XSTATE_FP | XSTATE_SSE)
|
||||||
|
#define XCNTXT_HMASK 0x0
|
||||||
|
|
||||||
|
extern unsigned int xstate_size, pcntxt_hmask, pcntxt_lmask;
|
||||||
|
extern struct xsave_struct *init_xstate_buf;
|
||||||
|
|
||||||
|
extern void xsave_cntxt_init(void);
|
||||||
|
extern void xsave_init(void);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue