1
2#ifndef __ASM_ALTERNATIVE_MACROS_H
3#define __ASM_ALTERNATIVE_MACROS_H
4
5#include <asm/cpucaps.h>
6#include <asm/insn-def.h>
7
8#define ARM64_CB_PATCH ARM64_NCAPS
9
10#ifndef __ASSEMBLY__
11
12#include <linux/stringify.h>
13
14#define ALTINSTR_ENTRY(feature) \
15 " .word 661b - .\n" \
16 " .word 663f - .\n" \
17 " .hword " __stringify(feature) "\n" \
18 " .byte 662b-661b\n" \
19 " .byte 664f-663f\n"
20
21#define ALTINSTR_ENTRY_CB(feature, cb) \
22 " .word 661b - .\n" \
23 " .word " __stringify(cb) "- .\n" \
24 " .hword " __stringify(feature) "\n" \
25 " .byte 662b-661b\n" \
26 " .byte 664f-663f\n"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \
45 ".if "__stringify(cfg_enabled)" == 1\n" \
46 "661:\n\t" \
47 oldinstr "\n" \
48 "662:\n" \
49 ".pushsection .altinstructions,\"a\"\n" \
50 ALTINSTR_ENTRY(feature) \
51 ".popsection\n" \
52 ".subsection 1\n" \
53 "663:\n\t" \
54 newinstr "\n" \
55 "664:\n\t" \
56 ".org . - (664b-663b) + (662b-661b)\n\t" \
57 ".org . - (662b-661b) + (664b-663b)\n\t" \
58 ".previous\n" \
59 ".endif\n"
60
61#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \
62 ".if "__stringify(cfg_enabled)" == 1\n" \
63 "661:\n\t" \
64 oldinstr "\n" \
65 "662:\n" \
66 ".pushsection .altinstructions,\"a\"\n" \
67 ALTINSTR_ENTRY_CB(feature, cb) \
68 ".popsection\n" \
69 "663:\n\t" \
70 "664:\n\t" \
71 ".endif\n"
72
73#define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \
74 __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
75
76#define ALTERNATIVE_CB(oldinstr, cb) \
77 __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
78#else
79
80#include <asm/assembler.h>
81
82.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
83 .word \orig_offset - .
84 .word \alt_offset - .
85 .hword \feature
86 .byte \orig_len
87 .byte \alt_len
88.endm
89
90.macro alternative_insn insn1, insn2, cap, enable = 1
91 .if \enable
92661: \insn1
93662: .pushsection .altinstructions, "a"
94 altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
95 .popsection
96 .subsection 1
97663: \insn2
98664: .org . - (664b-663b) + (662b-661b)
99 .org . - (662b-661b) + (664b-663b)
100 .previous
101 .endif
102.endm
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126.macro alternative_if_not cap
127 .set .Lasm_alt_mode, 0
128 .pushsection .altinstructions, "a"
129 altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
130 .popsection
131661:
132.endm
133
134.macro alternative_if cap
135 .set .Lasm_alt_mode, 1
136 .pushsection .altinstructions, "a"
137 altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
138 .popsection
139 .subsection 1
140 .align 2
141661:
142.endm
143
144.macro alternative_cb cb
145 .set .Lasm_alt_mode, 0
146 .pushsection .altinstructions, "a"
147 altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0
148 .popsection
149661:
150.endm
151
152
153
154
155.macro alternative_else
156662:
157 .if .Lasm_alt_mode==0
158 .subsection 1
159 .else
160 .previous
161 .endif
162663:
163.endm
164
165
166
167
168.macro alternative_endif
169664:
170 .org . - (664b-663b) + (662b-661b)
171 .org . - (662b-661b) + (664b-663b)
172 .if .Lasm_alt_mode==0
173 .previous
174 .endif
175.endm
176
177
178
179
180.macro alternative_cb_end
181662:
182.endm
183
184
185
186
187
188
189.macro alternative_else_nop_endif
190alternative_else
191 nops (662b-661b) / AARCH64_INSN_SIZE
192alternative_endif
193.endm
194
195#define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \
196 alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
197
198#endif
199
200
201
202
203
204
205
206
207#define ALTERNATIVE(oldinstr, newinstr, ...) \
208 _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
209
210#endif
211