1#ifndef _ASM_X86_ALTERNATIVE_H
2#define _ASM_X86_ALTERNATIVE_H
3
4#include <linux/types.h>
5#include <linux/stddef.h>
6#include <asm/asm.h>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#ifdef CONFIG_SMP
30#define LOCK_PREFIX \
31 ".section .smp_locks,\"a\"\n" \
32 _ASM_ALIGN "\n" \
33 _ASM_PTR "661f\n" \
34 ".previous\n" \
35 "661:\n\tlock; "
36
37#else
38#define LOCK_PREFIX ""
39#endif
40
41
42#include <asm/cpufeature.h>
43
44struct alt_instr {
45 u8 *instr;
46 u8 *replacement;
47 u8 cpuid;
48 u8 instrlen;
49 u8 replacementlen;
50 u8 pad1;
51#ifdef CONFIG_X86_64
52 u32 pad2;
53#endif
54};
55
56extern void alternative_instructions(void);
57extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
58
59struct module;
60
61#ifdef CONFIG_SMP
62extern void alternatives_smp_module_add(struct module *mod, char *name,
63 void *locks, void *locks_end,
64 void *text, void *text_end);
65extern void alternatives_smp_module_del(struct module *mod);
66extern void alternatives_smp_switch(int smp);
67#else
68static inline void alternatives_smp_module_add(struct module *mod, char *name,
69 void *locks, void *locks_end,
70 void *text, void *text_end) {}
71static inline void alternatives_smp_module_del(struct module *mod) {}
72static inline void alternatives_smp_switch(int smp) {}
73#endif
74
75const unsigned char *const *find_nop_table(void);
76
77
78
79
80
81
82
83
84
85
86
87
88
89#define alternative(oldinstr, newinstr, feature) \
90 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
91 ".section .altinstructions,\"a\"\n" \
92 _ASM_ALIGN "\n" \
93 _ASM_PTR "661b\n" \
94 _ASM_PTR "663f\n" \
95 " .byte %c0\n" \
96 " .byte 662b-661b\n" \
97 " .byte 664f-663f\n" \
98 ".previous\n" \
99 ".section .altinstr_replacement,\"ax\"\n" \
100 "663:\n\t" newinstr "\n664:\n" \
101 ".previous" :: "i" (feature) : "memory")
102
103
104
105
106
107
108
109
110
111
112
113#define alternative_input(oldinstr, newinstr, feature, input...) \
114 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
115 ".section .altinstructions,\"a\"\n" \
116 _ASM_ALIGN "\n" \
117 _ASM_PTR "661b\n" \
118 _ASM_PTR "663f\n" \
119 " .byte %c0\n" \
120 " .byte 662b-661b\n" \
121 " .byte 664f-663f\n" \
122 ".previous\n" \
123 ".section .altinstr_replacement,\"ax\"\n" \
124 "663:\n\t" newinstr "\n664:\n" \
125 ".previous" :: "i" (feature), ##input)
126
127
128#define alternative_io(oldinstr, newinstr, feature, output, input...) \
129 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
130 ".section .altinstructions,\"a\"\n" \
131 _ASM_ALIGN "\n" \
132 _ASM_PTR "661b\n" \
133 _ASM_PTR "663f\n" \
134 " .byte %c[feat]\n" \
135 " .byte 662b-661b\n" \
136 " .byte 664f-663f\n" \
137 ".previous\n" \
138 ".section .altinstr_replacement,\"ax\"\n" \
139 "663:\n\t" newinstr "\n664:\n" \
140 ".previous" : output : [feat] "i" (feature), ##input)
141
142
143
144
145
146#define ASM_OUTPUT2(a, b) a, b
147
148struct paravirt_patch_site;
149#ifdef CONFIG_PARAVIRT
150void apply_paravirt(struct paravirt_patch_site *start,
151 struct paravirt_patch_site *end);
152#else
153static inline void apply_paravirt(struct paravirt_patch_site *start,
154 struct paravirt_patch_site *end)
155{}
156#define __parainstructions NULL
157#define __parainstructions_end NULL
158#endif
159
160extern void add_nops(void *insns, unsigned int len);
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180extern void *text_poke(void *addr, const void *opcode, size_t len);
181extern void *text_poke_early(void *addr, const void *opcode, size_t len);
182
183#endif
184