2012-09-21 12:43:10 -07:00
/*
* Supervisor Mode Access Prevention support
*
* Copyright ( C ) 2012 Intel Corporation
* Author : H . Peter Anvin < hpa @ linux . intel . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; version 2
* of the License .
*/
# ifndef _ASM_X86_SMAP_H
# define _ASM_X86_SMAP_H
# include <linux/stringify.h>
# include <asm/nops.h>
2016-01-26 22:12:04 +01:00
# include <asm/cpufeatures.h>
2012-09-21 12:43:10 -07:00
/* "Raw" instruction opcodes */
# define __ASM_CLAC .byte 0x0f,0x01,0xca
# define __ASM_STAC .byte 0x0f,0x01,0xcb
# ifdef __ASSEMBLY__
# include <asm/alternative-asm.h>
# ifdef CONFIG_X86_SMAP
2015-01-15 09:17:12 +01:00
# define ASM_CLAC \
ALTERNATIVE " " , __stringify ( __ASM_CLAC ) , X86_FEATURE_SMAP
# define ASM_STAC \
ALTERNATIVE " " , __stringify ( __ASM_STAC ) , X86_FEATURE_SMAP
2012-09-21 12:43:10 -07:00
# else /* CONFIG_X86_SMAP */
# define ASM_CLAC
# define ASM_STAC
# endif /* CONFIG_X86_SMAP */
# else /* __ASSEMBLY__ */
# include <asm/alternative.h>
# ifdef CONFIG_X86_SMAP
2012-09-21 12:43:12 -07:00
static __always_inline void clac ( void )
2012-09-21 12:43:10 -07:00
{
/* Note: a barrier is implicit in alternative() */
2015-01-15 09:17:12 +01:00
alternative ( " " , __stringify ( __ASM_CLAC ) , X86_FEATURE_SMAP ) ;
2012-09-21 12:43:10 -07:00
}
2012-09-21 12:43:12 -07:00
static __always_inline void stac ( void )
2012-09-21 12:43:10 -07:00
{
/* Note: a barrier is implicit in alternative() */
2015-01-15 09:17:12 +01:00
alternative ( " " , __stringify ( __ASM_STAC ) , X86_FEATURE_SMAP ) ;
2012-09-21 12:43:10 -07:00
}
2019-04-03 09:39:48 +02:00
static __always_inline unsigned long smap_save ( void )
{
unsigned long flags ;
asm volatile ( ALTERNATIVE ( " " , " pushf; pop %0; " __stringify ( __ASM_CLAC ) ,
X86_FEATURE_SMAP )
: " =rm " ( flags ) : : " memory " , " cc " ) ;
return flags ;
}
static __always_inline void smap_restore ( unsigned long flags )
{
asm volatile ( ALTERNATIVE ( " " , " push %0; popf " , X86_FEATURE_SMAP )
: : " g " ( flags ) : " memory " , " cc " ) ;
}
2012-09-21 12:43:10 -07:00
/* These macros can be used in asm() statements */
# define ASM_CLAC \
2015-01-15 09:17:12 +01:00
ALTERNATIVE ( " " , __stringify ( __ASM_CLAC ) , X86_FEATURE_SMAP )
2012-09-21 12:43:10 -07:00
# define ASM_STAC \
2015-01-15 09:17:12 +01:00
ALTERNATIVE ( " " , __stringify ( __ASM_STAC ) , X86_FEATURE_SMAP )
2012-09-21 12:43:10 -07:00
# else /* CONFIG_X86_SMAP */
static inline void clac ( void ) { }
static inline void stac ( void ) { }
2019-04-03 09:39:48 +02:00
static inline unsigned long smap_save ( void ) { return 0 ; }
static inline void smap_restore ( unsigned long flags ) { }
2012-09-21 12:43:10 -07:00
# define ASM_CLAC
# define ASM_STAC
# endif /* CONFIG_X86_SMAP */
# endif /* __ASSEMBLY__ */
# endif /* _ASM_X86_SMAP_H */