hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/arm64/include/asm/alternative.h
....@@ -2,19 +2,13 @@
22 #ifndef __ASM_ALTERNATIVE_H
33 #define __ASM_ALTERNATIVE_H
44
5
-#include <asm/cpucaps.h>
6
-#include <asm/insn.h>
7
-
8
-#define ARM64_CB_PATCH ARM64_NCAPS
5
+#include <asm/alternative-macros.h>
96
107 #ifndef __ASSEMBLY__
118
129 #include <linux/init.h>
1310 #include <linux/types.h>
1411 #include <linux/stddef.h>
15
-#include <linux/stringify.h>
16
-
17
-extern int alternatives_applied;
1812
1913 struct alt_instr {
2014 s32 orig_offset; /* offset to original instruction */
....@@ -27,7 +21,9 @@
2721 typedef void (*alternative_cb_t)(struct alt_instr *alt,
2822 __le32 *origptr, __le32 *updptr, int nr_inst);
2923
24
+void __init apply_boot_alternatives(void);
3025 void __init apply_alternatives_all(void);
26
+bool alternative_is_applied(u16 cpufeature);
3127
3228 #ifdef CONFIG_MODULES
3329 void apply_alternatives_module(void *start, size_t length);
....@@ -35,270 +31,5 @@
3531 static inline void apply_alternatives_module(void *start, size_t length) { }
3632 #endif
3733
38
-#ifdef CONFIG_KVM_ARM_HOST
39
-void kvm_compute_layout(void);
40
-#else
41
-static inline void kvm_compute_layout(void) { }
42
-#endif
43
-
44
-#define ALTINSTR_ENTRY(feature) \
45
- " .word 661b - .\n" /* label */ \
46
- " .word 663f - .\n" /* new instruction */ \
47
- " .hword " __stringify(feature) "\n" /* feature bit */ \
48
- " .byte 662b-661b\n" /* source len */ \
49
- " .byte 664f-663f\n" /* replacement len */
50
-
51
-#define ALTINSTR_ENTRY_CB(feature, cb) \
52
- " .word 661b - .\n" /* label */ \
53
- " .word " __stringify(cb) "- .\n" /* callback */ \
54
- " .hword " __stringify(feature) "\n" /* feature bit */ \
55
- " .byte 662b-661b\n" /* source len */ \
56
- " .byte 664f-663f\n" /* replacement len */
57
-
58
-/*
59
- * alternative assembly primitive:
60
- *
61
- * If any of these .org directive fail, it means that insn1 and insn2
62
- * don't have the same length. This used to be written as
63
- *
64
- * .if ((664b-663b) != (662b-661b))
65
- * .error "Alternatives instruction length mismatch"
66
- * .endif
67
- *
68
- * but most assemblers die if insn1 or insn2 have a .inst. This should
69
- * be fixed in a binutils release posterior to 2.25.51.0.2 (anything
70
- * containing commit 4e4d08cf7399b606 or c1baaddf8861).
71
- *
72
- * Alternatives with callbacks do not generate replacement instructions.
73
- */
74
-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \
75
- ".if "__stringify(cfg_enabled)" == 1\n" \
76
- "661:\n\t" \
77
- oldinstr "\n" \
78
- "662:\n" \
79
- ".pushsection .altinstructions,\"a\"\n" \
80
- ALTINSTR_ENTRY(feature) \
81
- ".popsection\n" \
82
- ".pushsection .altinstr_replacement, \"a\"\n" \
83
- "663:\n\t" \
84
- newinstr "\n" \
85
- "664:\n\t" \
86
- ".popsection\n\t" \
87
- ".org . - (664b-663b) + (662b-661b)\n\t" \
88
- ".org . - (662b-661b) + (664b-663b)\n" \
89
- ".endif\n"
90
-
91
-#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \
92
- ".if "__stringify(cfg_enabled)" == 1\n" \
93
- "661:\n\t" \
94
- oldinstr "\n" \
95
- "662:\n" \
96
- ".pushsection .altinstructions,\"a\"\n" \
97
- ALTINSTR_ENTRY_CB(feature, cb) \
98
- ".popsection\n" \
99
- "663:\n\t" \
100
- "664:\n\t" \
101
- ".endif\n"
102
-
103
-#define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \
104
- __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
105
-
106
-#define ALTERNATIVE_CB(oldinstr, cb) \
107
- __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
108
-#else
109
-
110
-#include <asm/assembler.h>
111
-
112
-.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
113
- .word \orig_offset - .
114
- .word \alt_offset - .
115
- .hword \feature
116
- .byte \orig_len
117
- .byte \alt_len
118
-.endm
119
-
120
-.macro alternative_insn insn1, insn2, cap, enable = 1
121
- .if \enable
122
-661: \insn1
123
-662: .pushsection .altinstructions, "a"
124
- altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
125
- .popsection
126
- .pushsection .altinstr_replacement, "ax"
127
-663: \insn2
128
-664: .org . - (664b-663b) + (662b-661b)
129
- .org . - (662b-661b) + (664b-663b)
130
- .popsection
131
- .endif
132
-.endm
133
-
134
-/*
135
- * Alternative sequences
136
- *
137
- * The code for the case where the capability is not present will be
138
- * assembled and linked as normal. There are no restrictions on this
139
- * code.
140
- *
141
- * The code for the case where the capability is present will be
142
- * assembled into a special section to be used for dynamic patching.
143
- * Code for that case must:
144
- *
145
- * 1. Be exactly the same length (in bytes) as the default code
146
- * sequence.
147
- *
148
- * 2. Not contain a branch target that is used outside of the
149
- * alternative sequence it is defined in (branches into an
150
- * alternative sequence are not fixed up).
151
- */
152
-
153
-/*
154
- * Begin an alternative code sequence.
155
- */
156
-.macro alternative_if_not cap
157
- .set .Lasm_alt_mode, 0
158
- .pushsection .altinstructions, "a"
159
- altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
160
- .popsection
161
-661:
162
-.endm
163
-
164
-.macro alternative_if cap
165
- .set .Lasm_alt_mode, 1
166
- .pushsection .altinstructions, "a"
167
- altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
168
- .popsection
169
- .pushsection .altinstr_replacement, "ax"
170
- .align 2 /* So GAS knows label 661 is suitably aligned */
171
-661:
172
-.endm
173
-
174
-.macro alternative_cb cb
175
- .set .Lasm_alt_mode, 0
176
- .pushsection .altinstructions, "a"
177
- altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0
178
- .popsection
179
-661:
180
-.endm
181
-
182
-/*
183
- * Provide the other half of the alternative code sequence.
184
- */
185
-.macro alternative_else
186
-662:
187
- .if .Lasm_alt_mode==0
188
- .pushsection .altinstr_replacement, "ax"
189
- .else
190
- .popsection
191
- .endif
192
-663:
193
-.endm
194
-
195
-/*
196
- * Complete an alternative code sequence.
197
- */
198
-.macro alternative_endif
199
-664:
200
- .org . - (664b-663b) + (662b-661b)
201
- .org . - (662b-661b) + (664b-663b)
202
- .if .Lasm_alt_mode==0
203
- .popsection
204
- .endif
205
-.endm
206
-
207
-/*
208
- * Callback-based alternative epilogue
209
- */
210
-.macro alternative_cb_end
211
-662:
212
-.endm
213
-
214
-/*
215
- * Provides a trivial alternative or default sequence consisting solely
216
- * of NOPs. The number of NOPs is chosen automatically to match the
217
- * previous case.
218
- */
219
-.macro alternative_else_nop_endif
220
-alternative_else
221
- nops (662b-661b) / AARCH64_INSN_SIZE
222
-alternative_endif
223
-.endm
224
-
225
-#define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \
226
- alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
227
-
228
-.macro user_alt, label, oldinstr, newinstr, cond
229
-9999: alternative_insn "\oldinstr", "\newinstr", \cond
230
- _asm_extable 9999b, \label
231
-.endm
232
-
233
-/*
234
- * Generate the assembly for UAO alternatives with exception table entries.
235
- * This is complicated as there is no post-increment or pair versions of the
236
- * unprivileged instructions, and USER() only works for single instructions.
237
- */
238
-#ifdef CONFIG_ARM64_UAO
239
- .macro uao_ldp l, reg1, reg2, addr, post_inc
240
- alternative_if_not ARM64_HAS_UAO
241
-8888: ldp \reg1, \reg2, [\addr], \post_inc;
242
-8889: nop;
243
- nop;
244
- alternative_else
245
- ldtr \reg1, [\addr];
246
- ldtr \reg2, [\addr, #8];
247
- add \addr, \addr, \post_inc;
248
- alternative_endif
249
-
250
- _asm_extable 8888b,\l;
251
- _asm_extable 8889b,\l;
252
- .endm
253
-
254
- .macro uao_stp l, reg1, reg2, addr, post_inc
255
- alternative_if_not ARM64_HAS_UAO
256
-8888: stp \reg1, \reg2, [\addr], \post_inc;
257
-8889: nop;
258
- nop;
259
- alternative_else
260
- sttr \reg1, [\addr];
261
- sttr \reg2, [\addr, #8];
262
- add \addr, \addr, \post_inc;
263
- alternative_endif
264
-
265
- _asm_extable 8888b,\l;
266
- _asm_extable 8889b,\l;
267
- .endm
268
-
269
- .macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc
270
- alternative_if_not ARM64_HAS_UAO
271
-8888: \inst \reg, [\addr], \post_inc;
272
- nop;
273
- alternative_else
274
- \alt_inst \reg, [\addr];
275
- add \addr, \addr, \post_inc;
276
- alternative_endif
277
-
278
- _asm_extable 8888b,\l;
279
- .endm
280
-#else
281
- .macro uao_ldp l, reg1, reg2, addr, post_inc
282
- USER(\l, ldp \reg1, \reg2, [\addr], \post_inc)
283
- .endm
284
- .macro uao_stp l, reg1, reg2, addr, post_inc
285
- USER(\l, stp \reg1, \reg2, [\addr], \post_inc)
286
- .endm
287
- .macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc
288
- USER(\l, \inst \reg, [\addr], \post_inc)
289
- .endm
290
-#endif
291
-
292
-#endif /* __ASSEMBLY__ */
293
-
294
-/*
295
- * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature));
296
- *
297
- * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO));
298
- * N.B. If CONFIG_FOO is specified, but not selected, the whole block
299
- * will be omitted, including oldinstr.
300
- */
301
-#define ALTERNATIVE(oldinstr, newinstr, ...) \
302
- _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
303
-
34
+#endif /* __ASSEMBLY__ */
30435 #endif /* __ASM_ALTERNATIVE_H */