aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/alternative.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/include/asm/alternative.h')
-rw-r--r--arch/x86/include/asm/alternative.h43
1 files changed, 31 insertions, 12 deletions
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 69b74a7b877f..bc6abb7bc7ee 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -28,27 +28,26 @@
28 */ 28 */
29 29
30#ifdef CONFIG_SMP 30#ifdef CONFIG_SMP
31#define LOCK_PREFIX \ 31#define LOCK_PREFIX_HERE \
32 ".section .smp_locks,\"a\"\n" \ 32 ".section .smp_locks,\"a\"\n" \
33 _ASM_ALIGN "\n" \ 33 ".balign 4\n" \
34 _ASM_PTR "661f\n" /* address */ \ 34 ".long 671f - .\n" /* offset */ \
35 ".previous\n" \ 35 ".previous\n" \
36 "661:\n\tlock; " 36 "671:"
37
38#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; "
37 39
38#else /* ! CONFIG_SMP */ 40#else /* ! CONFIG_SMP */
41#define LOCK_PREFIX_HERE ""
39#define LOCK_PREFIX "" 42#define LOCK_PREFIX ""
40#endif 43#endif
41 44
42/* This must be included *after* the definition of LOCK_PREFIX */
43#include <asm/cpufeature.h>
44
45struct alt_instr { 45struct alt_instr {
46 u8 *instr; /* original instruction */ 46 u8 *instr; /* original instruction */
47 u8 *replacement; 47 u8 *replacement;
48 u8 cpuid; /* cpuid bit set for replacement */ 48 u16 cpuid; /* cpuid bit set for replacement */
49 u8 instrlen; /* length of original instruction */ 49 u8 instrlen; /* length of original instruction */
50 u8 replacementlen; /* length of new instruction, <= instrlen */ 50 u8 replacementlen; /* length of new instruction, <= instrlen */
51 u8 pad1;
52#ifdef CONFIG_X86_64 51#ifdef CONFIG_X86_64
53 u32 pad2; 52 u32 pad2;
54#endif 53#endif
@@ -65,12 +64,17 @@ extern void alternatives_smp_module_add(struct module *mod, char *name,
65 void *text, void *text_end); 64 void *text, void *text_end);
66extern void alternatives_smp_module_del(struct module *mod); 65extern void alternatives_smp_module_del(struct module *mod);
67extern void alternatives_smp_switch(int smp); 66extern void alternatives_smp_switch(int smp);
67extern int alternatives_text_reserved(void *start, void *end);
68#else 68#else
69static inline void alternatives_smp_module_add(struct module *mod, char *name, 69static inline void alternatives_smp_module_add(struct module *mod, char *name,
70 void *locks, void *locks_end, 70 void *locks, void *locks_end,
71 void *text, void *text_end) {} 71 void *text, void *text_end) {}
72static inline void alternatives_smp_module_del(struct module *mod) {} 72static inline void alternatives_smp_module_del(struct module *mod) {}
73static inline void alternatives_smp_switch(int smp) {} 73static inline void alternatives_smp_switch(int smp) {}
74static inline int alternatives_text_reserved(void *start, void *end)
75{
76 return 0;
77}
74#endif /* CONFIG_SMP */ 78#endif /* CONFIG_SMP */
75 79
76/* alternative assembly primitive: */ 80/* alternative assembly primitive: */
@@ -81,9 +85,11 @@ static inline void alternatives_smp_switch(int smp) {}
81 _ASM_ALIGN "\n" \ 85 _ASM_ALIGN "\n" \
82 _ASM_PTR "661b\n" /* label */ \ 86 _ASM_PTR "661b\n" /* label */ \
83 _ASM_PTR "663f\n" /* new instruction */ \ 87 _ASM_PTR "663f\n" /* new instruction */ \
84 " .byte " __stringify(feature) "\n" /* feature bit */ \ 88 " .word " __stringify(feature) "\n" /* feature bit */ \
85 " .byte 662b-661b\n" /* sourcelen */ \ 89 " .byte 662b-661b\n" /* sourcelen */ \
86 " .byte 664f-663f\n" /* replacementlen */ \ 90 " .byte 664f-663f\n" /* replacementlen */ \
91 ".previous\n" \
92 ".section .discard,\"aw\",@progbits\n" \
87 " .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */ \ 93 " .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */ \
88 ".previous\n" \ 94 ".previous\n" \
89 ".section .altinstr_replacement, \"ax\"\n" \ 95 ".section .altinstr_replacement, \"ax\"\n" \
@@ -91,6 +97,12 @@ static inline void alternatives_smp_switch(int smp) {}
91 ".previous" 97 ".previous"
92 98
93/* 99/*
100 * This must be included *after* the definition of ALTERNATIVE due to
101 * <asm/arch_hweight.h>
102 */
103#include <asm/cpufeature.h>
104
105/*
94 * Alternative instructions for different CPU types or capabilities. 106 * Alternative instructions for different CPU types or capabilities.
95 * 107 *
96 * This allows to use optimized instructions even on generic binary 108 * This allows to use optimized instructions even on generic binary
@@ -125,11 +137,16 @@ static inline void alternatives_smp_switch(int smp) {}
125 asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \ 137 asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
126 : output : "i" (0), ## input) 138 : output : "i" (0), ## input)
127 139
140/* Like alternative_io, but for replacing a direct call with another one. */
141#define alternative_call(oldfunc, newfunc, feature, output, input...) \
142 asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \
143 : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
144
128/* 145/*
129 * use this macro(s) if you need more than one output parameter 146 * use this macro(s) if you need more than one output parameter
130 * in alternative_io 147 * in alternative_io
131 */ 148 */
132#define ASM_OUTPUT2(a, b) a, b 149#define ASM_OUTPUT2(a...) a
133 150
134struct paravirt_patch_site; 151struct paravirt_patch_site;
135#ifdef CONFIG_PARAVIRT 152#ifdef CONFIG_PARAVIRT
@@ -155,10 +172,12 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
155 * invalid instruction possible) or if the instructions are changed from a 172 * invalid instruction possible) or if the instructions are changed from a
156 * consistent state to another consistent state atomically. 173 * consistent state to another consistent state atomically.
157 * More care must be taken when modifying code in the SMP case because of 174 * More care must be taken when modifying code in the SMP case because of
158 * Intel's errata. 175 * Intel's errata. text_poke_smp() takes care that errata, but still
176 * doesn't support NMI/MCE handler code modifying.
159 * On the local CPU you need to be protected again NMI or MCE handlers seeing an 177 * On the local CPU you need to be protected again NMI or MCE handlers seeing an
160 * inconsistent instruction while you patch. 178 * inconsistent instruction while you patch.
161 */ 179 */
162extern void *text_poke(void *addr, const void *opcode, size_t len); 180extern void *text_poke(void *addr, const void *opcode, size_t len);
181extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
163 182
164#endif /* _ASM_X86_ALTERNATIVE_H */ 183#endif /* _ASM_X86_ALTERNATIVE_H */