xref: /openbmc/linux/arch/x86/include/asm/smap.h (revision 51ae4a2d)
151ae4a2dSH. Peter Anvin /*
251ae4a2dSH. Peter Anvin  * Supervisor Mode Access Prevention support
351ae4a2dSH. Peter Anvin  *
451ae4a2dSH. Peter Anvin  * Copyright (C) 2012 Intel Corporation
551ae4a2dSH. Peter Anvin  * Author: H. Peter Anvin <hpa@linux.intel.com>
651ae4a2dSH. Peter Anvin  *
751ae4a2dSH. Peter Anvin  * This program is free software; you can redistribute it and/or
851ae4a2dSH. Peter Anvin  * modify it under the terms of the GNU General Public License
951ae4a2dSH. Peter Anvin  * as published by the Free Software Foundation; version 2
1051ae4a2dSH. Peter Anvin  * of the License.
1151ae4a2dSH. Peter Anvin  */
1251ae4a2dSH. Peter Anvin 
1351ae4a2dSH. Peter Anvin #ifndef _ASM_X86_SMAP_H
1451ae4a2dSH. Peter Anvin #define _ASM_X86_SMAP_H
1551ae4a2dSH. Peter Anvin 
1651ae4a2dSH. Peter Anvin #include <linux/stringify.h>
1751ae4a2dSH. Peter Anvin #include <asm/nops.h>
1851ae4a2dSH. Peter Anvin #include <asm/cpufeature.h>
1951ae4a2dSH. Peter Anvin 
2051ae4a2dSH. Peter Anvin /* "Raw" instruction opcodes */
2151ae4a2dSH. Peter Anvin #define __ASM_CLAC	.byte 0x0f,0x01,0xca
2251ae4a2dSH. Peter Anvin #define __ASM_STAC	.byte 0x0f,0x01,0xcb
2351ae4a2dSH. Peter Anvin 
2451ae4a2dSH. Peter Anvin #ifdef __ASSEMBLY__
2551ae4a2dSH. Peter Anvin 
2651ae4a2dSH. Peter Anvin #include <asm/alternative-asm.h>
2751ae4a2dSH. Peter Anvin 
2851ae4a2dSH. Peter Anvin #ifdef CONFIG_X86_SMAP
2951ae4a2dSH. Peter Anvin 
3051ae4a2dSH. Peter Anvin #define ASM_CLAC							\
3151ae4a2dSH. Peter Anvin 	661: ASM_NOP3 ;							\
3251ae4a2dSH. Peter Anvin 	.pushsection .altinstr_replacement, "ax" ;			\
3351ae4a2dSH. Peter Anvin 	662: __ASM_CLAC ;						\
3451ae4a2dSH. Peter Anvin 	.popsection ;							\
3551ae4a2dSH. Peter Anvin 	.pushsection .altinstructions, "a" ;				\
3651ae4a2dSH. Peter Anvin 	altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;	\
3751ae4a2dSH. Peter Anvin 	.popsection
3851ae4a2dSH. Peter Anvin 
3951ae4a2dSH. Peter Anvin #define ASM_STAC							\
4051ae4a2dSH. Peter Anvin 	661: ASM_NOP3 ;							\
4151ae4a2dSH. Peter Anvin 	.pushsection .altinstr_replacement, "ax" ;			\
4251ae4a2dSH. Peter Anvin 	662: __ASM_STAC ;						\
4351ae4a2dSH. Peter Anvin 	.popsection ;							\
4451ae4a2dSH. Peter Anvin 	.pushsection .altinstructions, "a" ;				\
4551ae4a2dSH. Peter Anvin 	altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;	\
4651ae4a2dSH. Peter Anvin 	.popsection
4751ae4a2dSH. Peter Anvin 
4851ae4a2dSH. Peter Anvin #else /* CONFIG_X86_SMAP */
4951ae4a2dSH. Peter Anvin 
5051ae4a2dSH. Peter Anvin #define ASM_CLAC
5151ae4a2dSH. Peter Anvin #define ASM_STAC
5251ae4a2dSH. Peter Anvin 
5351ae4a2dSH. Peter Anvin #endif /* CONFIG_X86_SMAP */
5451ae4a2dSH. Peter Anvin 
5551ae4a2dSH. Peter Anvin #else /* __ASSEMBLY__ */
5651ae4a2dSH. Peter Anvin 
5751ae4a2dSH. Peter Anvin #include <asm/alternative.h>
5851ae4a2dSH. Peter Anvin 
5951ae4a2dSH. Peter Anvin #ifdef CONFIG_X86_SMAP
6051ae4a2dSH. Peter Anvin 
6151ae4a2dSH. Peter Anvin static inline void clac(void)
6251ae4a2dSH. Peter Anvin {
6351ae4a2dSH. Peter Anvin 	/* Note: a barrier is implicit in alternative() */
6451ae4a2dSH. Peter Anvin 	alternative(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP);
6551ae4a2dSH. Peter Anvin }
6651ae4a2dSH. Peter Anvin 
6751ae4a2dSH. Peter Anvin static inline void stac(void)
6851ae4a2dSH. Peter Anvin {
6951ae4a2dSH. Peter Anvin 	/* Note: a barrier is implicit in alternative() */
7051ae4a2dSH. Peter Anvin 	alternative(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP);
7151ae4a2dSH. Peter Anvin }
7251ae4a2dSH. Peter Anvin 
7351ae4a2dSH. Peter Anvin /* These macros can be used in asm() statements */
7451ae4a2dSH. Peter Anvin #define ASM_CLAC \
7551ae4a2dSH. Peter Anvin 	ALTERNATIVE(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP)
7651ae4a2dSH. Peter Anvin #define ASM_STAC \
7751ae4a2dSH. Peter Anvin 	ALTERNATIVE(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP)
7851ae4a2dSH. Peter Anvin 
7951ae4a2dSH. Peter Anvin #else /* CONFIG_X86_SMAP */
8051ae4a2dSH. Peter Anvin 
8151ae4a2dSH. Peter Anvin static inline void clac(void) { }
8251ae4a2dSH. Peter Anvin static inline void stac(void) { }
8351ae4a2dSH. Peter Anvin 
8451ae4a2dSH. Peter Anvin #define ASM_CLAC
8551ae4a2dSH. Peter Anvin #define ASM_STAC
8651ae4a2dSH. Peter Anvin 
8751ae4a2dSH. Peter Anvin #endif /* CONFIG_X86_SMAP */
8851ae4a2dSH. Peter Anvin 
8951ae4a2dSH. Peter Anvin #endif /* __ASSEMBLY__ */
9051ae4a2dSH. Peter Anvin 
9151ae4a2dSH. Peter Anvin #endif /* _ASM_X86_SMAP_H */
92