@ -43,6 +43,13 @@ static unsigned int xstate_offsets[XFEATURE_MAX] = { [ 0 ... XFEATURE_MAX - 1] =
static unsigned int xstate_sizes [ XFEATURE_MAX ] = { [ 0 . . . XFEATURE_MAX - 1 ] = - 1 } ;
static unsigned int xstate_sizes [ XFEATURE_MAX ] = { [ 0 . . . XFEATURE_MAX - 1 ] = - 1 } ;
static unsigned int xstate_comp_offsets [ sizeof ( xfeatures_mask ) * 8 ] ;
static unsigned int xstate_comp_offsets [ sizeof ( xfeatures_mask ) * 8 ] ;
/*
* The XSAVE area of kernel can be in standard or compacted format ;
* it is always in standard format for user mode . This is the user
* mode standard format size used for signal and ptrace frames .
*/
unsigned int fpu_user_xstate_size ;
/*
/*
* Clear all of the X86_FEATURE_ * bits that are unavailable
* Clear all of the X86_FEATURE_ * bits that are unavailable
* when the CPU has no XSAVE support .
* when the CPU has no XSAVE support .
@ -171,7 +178,7 @@ void fpstate_sanitize_xstate(struct fpu *fpu)
*/
*/
while ( xfeatures ) {
while ( xfeatures ) {
if ( xfeatures & 0x1 ) {
if ( xfeatures & 0x1 ) {
int offset = xstate_offsets [ feature_bit ] ;
int offset = xstate_comp_ offsets [ feature_bit ] ;
int size = xstate_sizes [ feature_bit ] ;
int size = xstate_sizes [ feature_bit ] ;
memcpy ( ( void * ) fx + offset ,
memcpy ( ( void * ) fx + offset ,
@ -533,8 +540,9 @@ static void do_extra_xstate_size_checks(void)
XSTATE_WARN_ON ( paranoid_xstate_size ! = xstate_size ) ;
XSTATE_WARN_ON ( paranoid_xstate_size ! = xstate_size ) ;
}
}
/*
/*
* Calculate total size of enabled xstates in XCR0 / xfeatures_mask .
* Get total size of enabled xstates in XCR0 / xfeatures_mask .
*
*
* Note the SDM ' s wording here . " sub-function 0 " only enumerates
* Note the SDM ' s wording here . " sub-function 0 " only enumerates
* the size of the * user * states . If we use it to size a buffer
* the size of the * user * states . If we use it to size a buffer
@ -544,34 +552,33 @@ static void do_extra_xstate_size_checks(void)
* Note that we do not currently set any bits on IA32_XSS so
* Note that we do not currently set any bits on IA32_XSS so
* ' XCR0 | IA32_XSS = = XCR0 ' for now .
* ' XCR0 | IA32_XSS = = XCR0 ' for now .
*/
*/
static unsigned int __init calculate_xstate _size( void )
static unsigned int __init get_xsaves _size( void )
{
{
unsigned int eax , ebx , ecx , edx ;
unsigned int eax , ebx , ecx , edx ;
unsigned int calculated_xstate_size ;
/*
* - CPUID function 0 DH , sub - function 1 :
* EBX enumerates the size ( in bytes ) required by
* the XSAVES instruction for an XSAVE area
* containing all the state components
* corresponding to bits currently set in
* XCR0 | IA32_XSS .
*/
cpuid_count ( XSTATE_CPUID , 1 , & eax , & ebx , & ecx , & edx ) ;
return ebx ;
}
if ( ! boot_cpu_has ( X86_FEATURE_XSAVES ) ) {
static unsigned int __init get_xsave_size ( void )
/*
{
* - CPUID function 0 DH , sub - function 0 :
unsigned int eax , ebx , ecx , edx ;
* EBX enumerates the size ( in bytes ) required by
/*
* the XSAVE instruction for an XSAVE area
* - CPUID function 0 DH , sub - function 0 :
* containing all the * user * state components
* EBX enumerates the size ( in bytes ) required by
* corresponding to bits currently set in XCR0 .
* the XSAVE instruction for an XSAVE area
*/
* containing all the * user * state components
cpuid_count ( XSTATE_CPUID , 0 , & eax , & ebx , & ecx , & edx ) ;
* corresponding to bits currently set in XCR0 .
calculated_xstate_size = ebx ;
*/
} else {
cpuid_count ( XSTATE_CPUID , 0 , & eax , & ebx , & ecx , & edx ) ;
/*
return ebx ;
* - CPUID function 0 DH , sub - function 1 :
* EBX enumerates the size ( in bytes ) required by
* the XSAVES instruction for an XSAVE area
* containing all the state components
* corresponding to bits currently set in
* XCR0 | IA32_XSS .
*/
cpuid_count ( XSTATE_CPUID , 1 , & eax , & ebx , & ecx , & edx ) ;
calculated_xstate_size = ebx ;
}
return calculated_xstate_size ;
}
}
/*
/*
@ -591,7 +598,15 @@ static bool is_supported_xstate_size(unsigned int test_xstate_size)
static int init_xstate_size ( void )
static int init_xstate_size ( void )
{
{
/* Recompute the context size for enabled features: */
/* Recompute the context size for enabled features: */
unsigned int possible_xstate_size = calculate_xstate_size ( ) ;
unsigned int possible_xstate_size ;
unsigned int xsave_size ;
xsave_size = get_xsave_size ( ) ;
if ( boot_cpu_has ( X86_FEATURE_XSAVES ) )
possible_xstate_size = get_xsaves_size ( ) ;
else
possible_xstate_size = xsave_size ;
/* Ensure we have the space to store all enabled: */
/* Ensure we have the space to store all enabled: */
if ( ! is_supported_xstate_size ( possible_xstate_size ) )
if ( ! is_supported_xstate_size ( possible_xstate_size ) )
@ -603,6 +618,11 @@ static int init_xstate_size(void)
*/
*/
xstate_size = possible_xstate_size ;
xstate_size = possible_xstate_size ;
do_extra_xstate_size_checks ( ) ;
do_extra_xstate_size_checks ( ) ;
/*
* User space is always in standard format .
*/
fpu_user_xstate_size = xsave_size ;
return 0 ;
return 0 ;
}
}