xref: /openbmc/linux/arch/x86/include/asm/smap.h (revision 8e8e69d6)
1 /*
2  * Supervisor Mode Access Prevention support
3  *
4  * Copyright (C) 2012 Intel Corporation
5  * Author: H. Peter Anvin <hpa@linux.intel.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; version 2
10  * of the License.
11  */
12 
13 #ifndef _ASM_X86_SMAP_H
14 #define _ASM_X86_SMAP_H
15 
16 #include <asm/nops.h>
17 #include <asm/cpufeatures.h>
18 
19 /* "Raw" instruction opcodes */
20 #define __ASM_CLAC	".byte 0x0f,0x01,0xca"
21 #define __ASM_STAC	".byte 0x0f,0x01,0xcb"
22 
23 #ifdef __ASSEMBLY__
24 
25 #include <asm/alternative-asm.h>
26 
27 #ifdef CONFIG_X86_SMAP
28 
29 #define ASM_CLAC \
30 	ALTERNATIVE "", __ASM_CLAC, X86_FEATURE_SMAP
31 
32 #define ASM_STAC \
33 	ALTERNATIVE "", __ASM_STAC, X86_FEATURE_SMAP
34 
35 #else /* CONFIG_X86_SMAP */
36 
37 #define ASM_CLAC
38 #define ASM_STAC
39 
40 #endif /* CONFIG_X86_SMAP */
41 
42 #else /* __ASSEMBLY__ */
43 
44 #include <asm/alternative.h>
45 
46 #ifdef CONFIG_X86_SMAP
47 
48 static __always_inline void clac(void)
49 {
50 	/* Note: a barrier is implicit in alternative() */
51 	alternative("", __ASM_CLAC, X86_FEATURE_SMAP);
52 }
53 
54 static __always_inline void stac(void)
55 {
56 	/* Note: a barrier is implicit in alternative() */
57 	alternative("", __ASM_STAC, X86_FEATURE_SMAP);
58 }
59 
60 static __always_inline unsigned long smap_save(void)
61 {
62 	unsigned long flags;
63 
64 	asm volatile (ALTERNATIVE("", "pushf; pop %0; " __ASM_CLAC,
65 				  X86_FEATURE_SMAP)
66 		      : "=rm" (flags) : : "memory", "cc");
67 
68 	return flags;
69 }
70 
71 static __always_inline void smap_restore(unsigned long flags)
72 {
73 	asm volatile (ALTERNATIVE("", "push %0; popf", X86_FEATURE_SMAP)
74 		      : : "g" (flags) : "memory", "cc");
75 }
76 
77 /* These macros can be used in asm() statements */
78 #define ASM_CLAC \
79 	ALTERNATIVE("", __ASM_CLAC, X86_FEATURE_SMAP)
80 #define ASM_STAC \
81 	ALTERNATIVE("", __ASM_STAC, X86_FEATURE_SMAP)
82 
83 #else /* CONFIG_X86_SMAP */
84 
85 static inline void clac(void) { }
86 static inline void stac(void) { }
87 
88 static inline unsigned long smap_save(void) { return 0; }
89 static inline void smap_restore(unsigned long flags) { }
90 
91 #define ASM_CLAC
92 #define ASM_STAC
93 
94 #endif /* CONFIG_X86_SMAP */
95 
96 #endif /* __ASSEMBLY__ */
97 
98 #endif /* _ASM_X86_SMAP_H */
99