2008-07-29 10:29:19 -07:00
/*
* xsave / xrstor support .
*
* Author : Suresh Siddha < suresh . b . siddha @ intel . com >
*/
# include <linux/compat.h>
2014-05-29 11:12:43 -07:00
# include <linux/cpu.h>
2015-04-30 08:53:18 +02:00
2015-04-24 02:46:00 +02:00
# include <asm/fpu/api.h>
2015-04-24 02:54:44 +02:00
# include <asm/fpu/internal.h>
2015-04-30 08:45:02 +02:00
# include <asm/fpu/signal.h>
2015-04-30 08:53:18 +02:00
# include <asm/fpu/regset.h>
2015-04-30 12:45:38 +02:00
2014-10-24 15:58:07 -07:00
# include <asm/tlbflush.h>
2008-07-29 10:29:19 -07:00
2015-04-28 08:51:17 +02:00
static const char * xfeature_names [ ] =
{
" x87 floating point registers " ,
" SSE registers " ,
" AVX registers " ,
" MPX bounds registers " ,
" MPX CSR " ,
" AVX-512 opmask " ,
" AVX-512 Hi256 " ,
" AVX-512 ZMM_Hi256 " ,
" unknown xstate feature " ,
} ;
2008-07-29 10:29:19 -07:00
/*
2015-04-24 09:20:33 +02:00
* Mask of xstate features supported by the CPU and the kernel :
2008-07-29 10:29:19 -07:00
*/
2015-04-28 08:51:17 +02:00
u64 xfeatures_mask __read_mostly ;
2008-07-29 10:29:19 -07:00
2015-04-25 05:04:41 +02:00
static unsigned int xstate_offsets [ XFEATURES_NR_MAX ] , xstate_sizes [ XFEATURES_NR_MAX ] ;
2015-04-24 09:20:33 +02:00
static unsigned int xstate_comp_offsets [ sizeof ( xfeatures_mask ) * 8 ] ;
2015-04-24 09:23:59 +02:00
/* The number of supported xfeatures in xfeatures_mask: */
static unsigned int xfeatures_nr ;
2010-07-19 16:05:48 -07:00
2015-04-28 08:51:17 +02:00
/*
* Return whether the system supports a given xfeature .
*
* Also return the name of the ( most advanced ) feature that the caller requested :
*/
int cpu_has_xfeatures ( u64 xfeatures_needed , const char * * feature_name )
{
u64 xfeatures_missing = xfeatures_needed & ~ xfeatures_mask ;
if ( unlikely ( feature_name ) ) {
long xfeature_idx , max_idx ;
u64 xfeatures_print ;
/*
* So we use FLS here to be able to print the most advanced
* feature that was requested but is missing . So if a driver
* asks about " XSTATE_SSE | XSTATE_YMM " we ' ll print the
* missing AVX feature - this is the most informative message
* to users :
*/
if ( xfeatures_missing )
xfeatures_print = xfeatures_missing ;
else
xfeatures_print = xfeatures_needed ;
xfeature_idx = fls64 ( xfeatures_print ) - 1 ;
max_idx = ARRAY_SIZE ( xfeature_names ) - 1 ;
xfeature_idx = min ( xfeature_idx , max_idx ) ;
* feature_name = xfeature_names [ xfeature_idx ] ;
}
if ( xfeatures_missing )
return 0 ;
return 1 ;
}
EXPORT_SYMBOL_GPL ( cpu_has_xfeatures ) ;
2010-07-19 16:05:49 -07:00
/*
2015-05-01 09:59:04 +02:00
* When executing XSAVEOPT ( or other optimized XSAVE instructions ) , if
* a processor implementation detects that an FPU state component is still
* ( or is again ) in its initialized state , it may clear the corresponding
* bit in the header . xfeatures field , and can skip the writeout of registers
* to the corresponding memory layout .
2015-04-24 11:32:59 +02:00
*
* This means that when the bit is zero , the state component might still contain
* some previous - non - initialized register state .
*
* Before writing xstate information to user - space we sanitize those components ,
* to always ensure that the memory layout of a feature will be in the init state
* if the corresponding header bit is zero . This is to ensure that user - space doesn ' t
* see some stale state in the memory layout during signal handling , debugging etc .
2010-07-19 16:05:49 -07:00
*/
2015-04-28 11:25:02 +02:00
void fpstate_sanitize_xstate ( struct fpu * fpu )
2010-07-19 16:05:49 -07:00
{
2015-04-30 17:15:32 +02:00
struct fxregs_state * fx = & fpu - > state . fxsave ;
2015-04-24 11:32:59 +02:00
int feature_bit ;
2015-04-24 10:19:47 +02:00
u64 xfeatures ;
2010-07-19 16:05:49 -07:00
2015-04-28 11:17:55 +02:00
if ( ! use_xsaveopt ( ) )
2010-07-19 16:05:49 -07:00
return ;
2015-04-28 11:25:02 +02:00
xfeatures = fpu - > state . xsave . header . xfeatures ;
2010-07-19 16:05:49 -07:00
/*
* None of the feature bits are in init state . So nothing else
2011-03-17 16:24:16 -03:00
* to do for us , as the memory layout is up to date .
2010-07-19 16:05:49 -07:00
*/
2015-04-24 10:19:47 +02:00
if ( ( xfeatures & xfeatures_mask ) = = xfeatures_mask )
2010-07-19 16:05:49 -07:00
return ;
/*
* FP is in init state
*/
2015-04-24 10:19:47 +02:00
if ( ! ( xfeatures & XSTATE_FP ) ) {
2010-07-19 16:05:49 -07:00
fx - > cwd = 0x37f ;
fx - > swd = 0 ;
fx - > twd = 0 ;
fx - > fop = 0 ;
fx - > rip = 0 ;
fx - > rdp = 0 ;
memset ( & fx - > st_space [ 0 ] , 0 , 128 ) ;
}
/*
* SSE is in init state
*/
2015-04-24 10:19:47 +02:00
if ( ! ( xfeatures & XSTATE_SSE ) )
2010-07-19 16:05:49 -07:00
memset ( & fx - > xmm_space [ 0 ] , 0 , 256 ) ;
2015-04-24 11:32:59 +02:00
/*
* First two features are FPU and SSE , which above we handled
* in a special way already :
*/
feature_bit = 0x2 ;
2015-04-24 10:19:47 +02:00
xfeatures = ( xfeatures_mask & ~ xfeatures ) > > 2 ;
2010-07-19 16:05:49 -07:00
/*
2015-04-24 11:32:59 +02:00
* Update all the remaining memory layouts according to their
* standard xstate layout , if their header bit is in the init
* state :
2010-07-19 16:05:49 -07:00
*/
2015-04-24 10:19:47 +02:00
while ( xfeatures ) {
if ( xfeatures & 0x1 ) {
2010-07-19 16:05:49 -07:00
int offset = xstate_offsets [ feature_bit ] ;
int size = xstate_sizes [ feature_bit ] ;
2015-04-24 11:32:59 +02:00
memcpy ( ( void * ) fx + offset ,
2015-04-30 11:07:06 +02:00
( void * ) & init_fpstate . xsave + offset ,
2010-07-19 16:05:49 -07:00
size ) ;
}
2015-04-24 10:19:47 +02:00
xfeatures > > = 1 ;
2010-07-19 16:05:49 -07:00
feature_bit + + ;
}
}
2008-07-29 10:29:19 -07:00
/*
2015-04-25 06:26:36 +02:00
* Enable the extended processor state save / restore feature .
* Called once per CPU onlining .
2008-07-29 10:29:19 -07:00
*/
2015-04-25 06:26:36 +02:00
void fpu__init_cpu_xstate ( void )
2008-07-29 10:29:19 -07:00
{
2015-04-25 06:41:07 +02:00
if ( ! cpu_has_xsave | | ! xfeatures_mask )
2015-04-25 06:26:36 +02:00
return ;
2014-10-24 15:58:07 -07:00
cr4_set_bits ( X86_CR4_OSXSAVE ) ;
2015-04-24 09:20:33 +02:00
xsetbv ( XCR_XFEATURE_ENABLED_MASK , xfeatures_mask ) ;
2008-07-29 10:29:19 -07:00
}
2010-07-19 16:05:48 -07:00
/*
x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end
The current xstate code in setup_xstate_features() assumes that
the first zero bit means the end of xfeatures - but that is not
so, the SDM clearly states that an arbitrary set of xfeatures
might be enabled - and it is also clear from the description
of the compaction feature that holes are possible:
"13-6 Vol. 1MANAGING STATE USING THE XSAVE FEATURE SET
[...]
Compacted format. Each state component i (i ≥ 2) is located at a byte
offset from the base address of the XSAVE area based on the XCOMP_BV
field in the XSAVE header:
— If XCOMP_BV[i] = 0, state component i is not in the XSAVE area.
— If XCOMP_BV[i] = 1, the following items apply:
• If XCOMP_BV[j] = 0 for every j, 2 ≤ j < i, state component i is
located at a byte offset 576 from the base address of the XSAVE
area. (This item applies if i is the first bit set in bits 62:2 of
the XCOMP_BV; it implies that state component i is located at the
beginning of the extended region.)
• Otherwise, let j, 2 ≤ j < i, be the greatest value such that
XCOMP_BV[j] = 1. Then state component i is located at a byte offset
X from the location of state component j, where X is the number of
bytes required for state component j as enumerated in
CPUID.(EAX=0DH,ECX=j):EAX. (This item implies that state component i
immediately follows the preceding state component whose bit is set
in XCOMP_BV.)"
So don't assume that the first zero xfeatures bit means the end of
all xfeatures - iterate through all of them.
I'm not aware of hardware that triggers this currently.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-05-04 07:37:47 +02:00
* Record the offsets and sizes of various xstates contained
* in the XSAVE state memory layout .
*
* ( Note that certain features might be non - present , for them
* we ' ll have 0 offset and 0 size . )
2010-07-19 16:05:48 -07:00
*/
2010-07-21 19:03:56 +02:00
static void __init setup_xstate_features ( void )
2010-07-19 16:05:48 -07:00
{
x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end
The current xstate code in setup_xstate_features() assumes that
the first zero bit means the end of xfeatures - but that is not
so, the SDM clearly states that an arbitrary set of xfeatures
might be enabled - and it is also clear from the description
of the compaction feature that holes are possible:
"13-6 Vol. 1MANAGING STATE USING THE XSAVE FEATURE SET
[...]
Compacted format. Each state component i (i ≥ 2) is located at a byte
offset from the base address of the XSAVE area based on the XCOMP_BV
field in the XSAVE header:
— If XCOMP_BV[i] = 0, state component i is not in the XSAVE area.
— If XCOMP_BV[i] = 1, the following items apply:
• If XCOMP_BV[j] = 0 for every j, 2 ≤ j < i, state component i is
located at a byte offset 576 from the base address of the XSAVE
area. (This item applies if i is the first bit set in bits 62:2 of
the XCOMP_BV; it implies that state component i is located at the
beginning of the extended region.)
• Otherwise, let j, 2 ≤ j < i, be the greatest value such that
XCOMP_BV[j] = 1. Then state component i is located at a byte offset
X from the location of state component j, where X is the number of
bytes required for state component j as enumerated in
CPUID.(EAX=0DH,ECX=j):EAX. (This item implies that state component i
immediately follows the preceding state component whose bit is set
in XCOMP_BV.)"
So don't assume that the first zero xfeatures bit means the end of
all xfeatures - iterate through all of them.
I'm not aware of hardware that triggers this currently.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-05-04 07:37:47 +02:00
u32 eax , ebx , ecx , edx , leaf ;
2010-07-19 16:05:48 -07:00
2015-04-24 09:23:59 +02:00
xfeatures_nr = fls64 ( xfeatures_mask ) ;
2010-07-19 16:05:48 -07:00
x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end
The current xstate code in setup_xstate_features() assumes that
the first zero bit means the end of xfeatures - but that is not
so, the SDM clearly states that an arbitrary set of xfeatures
might be enabled - and it is also clear from the description
of the compaction feature that holes are possible:
"13-6 Vol. 1MANAGING STATE USING THE XSAVE FEATURE SET
[...]
Compacted format. Each state component i (i ≥ 2) is located at a byte
offset from the base address of the XSAVE area based on the XCOMP_BV
field in the XSAVE header:
— If XCOMP_BV[i] = 0, state component i is not in the XSAVE area.
— If XCOMP_BV[i] = 1, the following items apply:
• If XCOMP_BV[j] = 0 for every j, 2 ≤ j < i, state component i is
located at a byte offset 576 from the base address of the XSAVE
area. (This item applies if i is the first bit set in bits 62:2 of
the XCOMP_BV; it implies that state component i is located at the
beginning of the extended region.)
• Otherwise, let j, 2 ≤ j < i, be the greatest value such that
XCOMP_BV[j] = 1. Then state component i is located at a byte offset
X from the location of state component j, where X is the number of
bytes required for state component j as enumerated in
CPUID.(EAX=0DH,ECX=j):EAX. (This item implies that state component i
immediately follows the preceding state component whose bit is set
in XCOMP_BV.)"
So don't assume that the first zero xfeatures bit means the end of
all xfeatures - iterate through all of them.
I'm not aware of hardware that triggers this currently.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-05-04 07:37:47 +02:00
for ( leaf = 2 ; leaf < xfeatures_nr ; leaf + + ) {
2010-07-21 19:03:54 +02:00
cpuid_count ( XSTATE_CPUID , leaf , & eax , & ebx , & ecx , & edx ) ;
2010-07-19 16:05:48 -07:00
xstate_offsets [ leaf ] = ebx ;
xstate_sizes [ leaf ] = eax ;
x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end
The current xstate code in setup_xstate_features() assumes that
the first zero bit means the end of xfeatures - but that is not
so, the SDM clearly states that an arbitrary set of xfeatures
might be enabled - and it is also clear from the description
of the compaction feature that holes are possible:
"13-6 Vol. 1MANAGING STATE USING THE XSAVE FEATURE SET
[...]
Compacted format. Each state component i (i ≥ 2) is located at a byte
offset from the base address of the XSAVE area based on the XCOMP_BV
field in the XSAVE header:
— If XCOMP_BV[i] = 0, state component i is not in the XSAVE area.
— If XCOMP_BV[i] = 1, the following items apply:
• If XCOMP_BV[j] = 0 for every j, 2 ≤ j < i, state component i is
located at a byte offset 576 from the base address of the XSAVE
area. (This item applies if i is the first bit set in bits 62:2 of
the XCOMP_BV; it implies that state component i is located at the
beginning of the extended region.)
• Otherwise, let j, 2 ≤ j < i, be the greatest value such that
XCOMP_BV[j] = 1. Then state component i is located at a byte offset
X from the location of state component j, where X is the number of
bytes required for state component j as enumerated in
CPUID.(EAX=0DH,ECX=j):EAX. (This item implies that state component i
immediately follows the preceding state component whose bit is set
in XCOMP_BV.)"
So don't assume that the first zero xfeatures bit means the end of
all xfeatures - iterate through all of them.
I'm not aware of hardware that triggers this currently.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-05-04 07:37:47 +02:00
printk ( KERN_INFO " x86/fpu: xstate_offset[%d]: %04x, xstate_sizes[%d]: %04x \n " , leaf , ebx , leaf , eax ) ;
2010-07-19 16:05:48 -07:00
leaf + + ;
x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end
The current xstate code in setup_xstate_features() assumes that
the first zero bit means the end of xfeatures - but that is not
so, the SDM clearly states that an arbitrary set of xfeatures
might be enabled - and it is also clear from the description
of the compaction feature that holes are possible:
"13-6 Vol. 1MANAGING STATE USING THE XSAVE FEATURE SET
[...]
Compacted format. Each state component i (i ≥ 2) is located at a byte
offset from the base address of the XSAVE area based on the XCOMP_BV
field in the XSAVE header:
— If XCOMP_BV[i] = 0, state component i is not in the XSAVE area.
— If XCOMP_BV[i] = 1, the following items apply:
• If XCOMP_BV[j] = 0 for every j, 2 ≤ j < i, state component i is
located at a byte offset 576 from the base address of the XSAVE
area. (This item applies if i is the first bit set in bits 62:2 of
the XCOMP_BV; it implies that state component i is located at the
beginning of the extended region.)
• Otherwise, let j, 2 ≤ j < i, be the greatest value such that
XCOMP_BV[j] = 1. Then state component i is located at a byte offset
X from the location of state component j, where X is the number of
bytes required for state component j as enumerated in
CPUID.(EAX=0DH,ECX=j):EAX. (This item implies that state component i
immediately follows the preceding state component whose bit is set
in XCOMP_BV.)"
So don't assume that the first zero xfeatures bit means the end of
all xfeatures - iterate through all of them.
I'm not aware of hardware that triggers this currently.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-05-04 07:37:47 +02:00
}
2010-07-19 16:05:48 -07:00
}
2015-05-04 09:52:42 +02:00
static void __init print_xstate_feature ( u64 xstate_mask )
2015-04-24 08:48:01 +02:00
{
2015-04-28 09:17:26 +02:00
const char * feature_name ;
2015-04-24 08:48:01 +02:00
2015-04-28 09:17:26 +02:00
if ( cpu_has_xfeatures ( xstate_mask , & feature_name ) )
pr_info ( " x86/fpu: Supporting XSAVE feature 0x%02Lx: '%s' \n " , xstate_mask , feature_name ) ;
2015-04-24 08:48:01 +02:00
}
/*
* Print out all the supported xstate features :
*/
2015-05-04 09:52:42 +02:00
static void __init print_xstate_features ( void )
2015-04-24 08:48:01 +02:00
{
2015-04-28 09:17:26 +02:00
print_xstate_feature ( XSTATE_FP ) ;
print_xstate_feature ( XSTATE_SSE ) ;
print_xstate_feature ( XSTATE_YMM ) ;
print_xstate_feature ( XSTATE_BNDREGS ) ;
print_xstate_feature ( XSTATE_BNDCSR ) ;
print_xstate_feature ( XSTATE_OPMASK ) ;
print_xstate_feature ( XSTATE_ZMM_Hi256 ) ;
print_xstate_feature ( XSTATE_Hi16_ZMM ) ;
2015-04-24 08:48:01 +02:00
}
2014-05-29 11:12:44 -07:00
/*
* This function sets up offsets and sizes of all extended states in
* xsave area . This supports both standard format and compacted format
* of the xsave aread .
*/
2015-05-04 09:52:42 +02:00
static void __init setup_xstate_comp ( void )
2014-05-29 11:12:44 -07:00
{
2015-04-24 09:20:33 +02:00
unsigned int xstate_comp_sizes [ sizeof ( xfeatures_mask ) * 8 ] ;
2014-05-29 11:12:44 -07:00
int i ;
2014-05-30 14:59:24 -07:00
/*
* The FP xstates and SSE xstates are legacy states . They are always
* in the fixed offsets in the xsave area in either compacted form
* or standard form .
*/
xstate_comp_offsets [ 0 ] = 0 ;
2015-04-30 17:15:32 +02:00
xstate_comp_offsets [ 1 ] = offsetof ( struct fxregs_state , xmm_space ) ;
2014-05-29 11:12:44 -07:00
if ( ! cpu_has_xsaves ) {
2015-04-24 09:23:59 +02:00
for ( i = 2 ; i < xfeatures_nr ; i + + ) {
2015-04-24 09:20:33 +02:00
if ( test_bit ( i , ( unsigned long * ) & xfeatures_mask ) ) {
2014-05-29 11:12:44 -07:00
xstate_comp_offsets [ i ] = xstate_offsets [ i ] ;
xstate_comp_sizes [ i ] = xstate_sizes [ i ] ;
}
}
return ;
}
xstate_comp_offsets [ 2 ] = FXSAVE_SIZE + XSAVE_HDR_SIZE ;
2015-04-24 09:23:59 +02:00
for ( i = 2 ; i < xfeatures_nr ; i + + ) {
2015-04-24 09:20:33 +02:00
if ( test_bit ( i , ( unsigned long * ) & xfeatures_mask ) )
2014-05-29 11:12:44 -07:00
xstate_comp_sizes [ i ] = xstate_sizes [ i ] ;
else
xstate_comp_sizes [ i ] = 0 ;
if ( i > 2 )
xstate_comp_offsets [ i ] = xstate_comp_offsets [ i - 1 ]
+ xstate_comp_sizes [ i - 1 ] ;
}
}
2008-07-29 10:29:19 -07:00
/*
* setup the xstate image representing the init state
*/
2015-05-04 09:52:42 +02:00
static void __init setup_init_fpu_buf ( void )
2008-07-29 10:29:19 -07:00
{
2015-05-05 11:34:49 +02:00
static int on_boot_cpu = 1 ;
WARN_ON_FPU ( ! on_boot_cpu ) ;
on_boot_cpu = 0 ;
2012-09-06 14:58:52 -07:00
if ( ! cpu_has_xsave )
return ;
setup_xstate_features ( ) ;
2015-04-24 08:48:01 +02:00
print_xstate_features ( ) ;
2010-07-19 16:05:48 -07:00
2014-05-29 11:12:42 -07:00
if ( cpu_has_xsaves ) {
2015-04-30 11:07:06 +02:00
init_fpstate . xsave . header . xcomp_bv = ( u64 ) 1 < < 63 | xfeatures_mask ;
init_fpstate . xsave . header . xfeatures = xfeatures_mask ;
2014-05-29 11:12:42 -07:00
}
2010-07-19 16:05:49 -07:00
/*
* Init all the features state with header_bv being 0x0
*/
2015-05-27 14:04:44 +02:00
copy_kernel_to_xregs_booting ( & init_fpstate . xsave ) ;
2015-04-22 15:08:34 +02:00
2010-07-19 16:05:49 -07:00
/*
* Dump the init state again . This is to identify the init state
* of any feature which is not represented by all zero ' s .
*/
2015-04-30 11:34:09 +02:00
copy_xregs_to_kernel_booting ( & init_fpstate . xsave ) ;
2008-07-29 10:29:19 -07:00
}
2014-05-29 11:12:43 -07:00
/*
2015-04-24 09:20:33 +02:00
* Calculate total size of enabled xstates in XCR0 / xfeatures_mask .
2014-05-29 11:12:43 -07:00
*/
static void __init init_xstate_size ( void )
{
unsigned int eax , ebx , ecx , edx ;
int i ;
if ( ! cpu_has_xsaves ) {
cpuid_count ( XSTATE_CPUID , 0 , & eax , & ebx , & ecx , & edx ) ;
xstate_size = ebx ;
return ;
}
xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE ;
for ( i = 2 ; i < 64 ; i + + ) {
2015-04-24 09:20:33 +02:00
if ( test_bit ( i , ( unsigned long * ) & xfeatures_mask ) ) {
2014-05-29 11:12:43 -07:00
cpuid_count ( XSTATE_CPUID , i , & eax , & ebx , & ecx , & edx ) ;
xstate_size + = eax ;
}
}
}
2008-07-29 10:29:19 -07:00
/*
* Enable and initialize the xsave feature .
2015-04-25 06:26:36 +02:00
* Called once per system bootup .
2008-07-29 10:29:19 -07:00
*/
2015-05-04 09:52:42 +02:00
void __init fpu__init_system_xstate ( void )
2008-07-29 10:29:19 -07:00
{
unsigned int eax , ebx , ecx , edx ;
2015-05-05 11:34:49 +02:00
static int on_boot_cpu = 1 ;
WARN_ON_FPU ( ! on_boot_cpu ) ;
on_boot_cpu = 0 ;
2008-07-29 10:29:19 -07:00
2015-04-25 06:47:24 +02:00
if ( ! cpu_has_xsave ) {
pr_info ( " x86/fpu: Legacy x87 FPU detected. \n " ) ;
return ;
}
2010-07-21 19:03:54 +02:00
if ( boot_cpu_data . cpuid_level < XSTATE_CPUID ) {
2015-05-05 11:34:49 +02:00
WARN_ON_FPU ( 1 ) ;
2010-07-21 19:03:54 +02:00
return ;
}
cpuid_count ( XSTATE_CPUID , 0 , & eax , & ebx , & ecx , & edx ) ;
2015-04-24 09:20:33 +02:00
xfeatures_mask = eax + ( ( u64 ) edx < < 32 ) ;
2008-07-29 10:29:19 -07:00
2015-04-24 09:20:33 +02:00
if ( ( xfeatures_mask & XSTATE_FPSSE ) ! = XSTATE_FPSSE ) {
pr_err ( " x86/fpu: FP/SSE not present amongst the CPU's xstate features: 0x%llx. \n " , xfeatures_mask ) ;
2008-07-29 10:29:19 -07:00
BUG ( ) ;
}
2015-05-24 09:58:12 +02:00
/* Support only the state known to the OS: */
2015-04-24 09:20:33 +02:00
xfeatures_mask = xfeatures_mask & XCNTXT_MASK ;
2010-07-21 19:03:53 +02:00
2015-04-25 06:26:36 +02:00
/* Enable xstate instructions to be able to continue with initialization: */
fpu__init_cpu_xstate ( ) ;
2008-07-29 10:29:19 -07:00
2015-05-24 09:58:12 +02:00
/* Recompute the context size for enabled features: */
2014-05-29 11:12:43 -07:00
init_xstate_size ( ) ;
2008-07-29 10:29:19 -07:00
2015-04-24 09:20:33 +02:00
update_regset_xstate_info ( xstate_size , xfeatures_mask ) ;
2015-04-30 12:45:38 +02:00
fpu__init_prepare_fx_sw_frame ( ) ;
2012-09-06 14:58:52 -07:00
setup_init_fpu_buf ( ) ;
2015-05-04 09:43:55 +02:00
setup_xstate_comp ( ) ;
2008-07-29 10:29:19 -07:00
2015-04-24 03:25:18 +02:00
pr_info ( " x86/fpu: Enabled xstate features 0x%llx, context size is 0x%x bytes, using '%s' format. \n " ,
2015-04-24 09:20:33 +02:00
xfeatures_mask ,
2015-04-24 03:25:18 +02:00
xstate_size ,
cpu_has_xsaves ? " compacted " : " standard " ) ;
2008-07-29 10:29:19 -07:00
}
2010-07-20 20:50:51 +02:00
2015-04-24 10:02:32 +02:00
/*
* Restore minimal FPU state after suspend :
*/
void fpu__resume_cpu ( void )
{
/*
* Restore XCR0 on xsave capable CPUs :
*/
if ( cpu_has_xsave )
xsetbv ( XCR_XFEATURE_ENABLED_MASK , xfeatures_mask ) ;
}
2014-05-29 11:12:44 -07:00
/*
* Given the xsave area and a state inside , this function returns the
* address of the state .
*
* This is the API that is called to get xstate address in either
* standard format or compacted format of xsave area .
*
2015-06-07 11:37:00 -07:00
* Note that if there is no data for the field in the xsave buffer
* this will return NULL .
*
2014-05-29 11:12:44 -07:00
* Inputs :
2015-06-07 11:37:00 -07:00
* xstate : the thread ' s storage area for all FPU data
* xstate_feature : state which is defined in xsave . h ( e . g .
* XSTATE_FP , XSTATE_SSE , etc . . . )
2014-05-29 11:12:44 -07:00
* Output :
2015-06-07 11:37:00 -07:00
* address of the state in the xsave area , or NULL if the
* field is not present in the xsave buffer .
2014-05-29 11:12:44 -07:00
*/
2015-06-07 11:37:00 -07:00
void * get_xsave_addr ( struct xregs_state * xsave , int xstate_feature )
2014-05-29 11:12:44 -07:00
{
2015-06-07 11:37:00 -07:00
int feature_nr = fls64 ( xstate_feature ) - 1 ;
/*
* Do we even * have * xsave state ?
*/
if ( ! boot_cpu_has ( X86_FEATURE_XSAVE ) )
return NULL ;
xsave = & current - > thread . fpu . state . xsave ;
/*
* We should not ever be requesting features that we
* have not enabled . Remember that pcntxt_mask is
* what we write to the XCR0 register .
*/
WARN_ONCE ( ! ( xfeatures_mask & xstate_feature ) ,
" get of unsupported state " ) ;
/*
* This assumes the last ' xsave * ' instruction to
* have requested that ' xstate_feature ' be saved .
* If it did not , we might be seeing and old value
* of the field in the buffer .
*
* This can happen because the last ' xsave ' did not
* request that this feature be saved ( unlikely )
* or because the " init optimization " caused it
* to not be saved .
*/
if ( ! ( xsave - > header . xfeatures & xstate_feature ) )
2014-05-29 11:12:44 -07:00
return NULL ;
2015-06-07 11:37:00 -07:00
return ( void * ) xsave + xstate_comp_offsets [ feature_nr ] ;
2014-05-29 11:12:44 -07:00
}
2014-11-24 10:57:42 +01:00
EXPORT_SYMBOL_GPL ( get_xsave_addr ) ;