1/* SPDX-License-Identifier: GPL-2.0-or-later */
2#ifndef __ASM_POWERPC_FEATURE_FIXUPS_H
3#define __ASM_POWERPC_FEATURE_FIXUPS_H
4
5#include <asm/asm-const.h>
6
7/*
8 */
9
10/*
11 * Feature section common macros
12 *
13 * Note that the entries now contain offsets between the table entry
14 * and the code rather than absolute code pointers in order to be
15 * useable with the vdso shared library. There is also an assumption
16 * that values will be negative, that is, the fixup table has to be
17 * located after the code it fixes up.
18 */
19#if defined(CONFIG_PPC64) && !defined(__powerpc64__)
20/* 64 bits kernel, 32 bits code (ie. vdso32) */
21#define FTR_ENTRY_LONG		.8byte
22#define FTR_ENTRY_OFFSET	.long 0xffffffff; .long
23#elif defined(CONFIG_PPC64)
24#define FTR_ENTRY_LONG		.8byte
25#define FTR_ENTRY_OFFSET	.8byte
26#else
27#define FTR_ENTRY_LONG		.long
28#define FTR_ENTRY_OFFSET	.long
29#endif
30
31#define START_FTR_SECTION(label)	label##1:
32
33#define FTR_SECTION_ELSE_NESTED(label)			\
34label##2:						\
35	.pushsection __ftr_alt_##label,"a";		\
36	.align 2;					\
37label##3:
38
39#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)		\
40label##4:							\
41	.popsection;						\
42	.pushsection sect,"a";					\
43	.align 3;						\
44label##5:							\
45	FTR_ENTRY_LONG msk;					\
46	FTR_ENTRY_LONG val;					\
47	FTR_ENTRY_OFFSET label##1b-label##5b;			\
48	FTR_ENTRY_OFFSET label##2b-label##5b;			\
49	FTR_ENTRY_OFFSET label##3b-label##5b;			\
50	FTR_ENTRY_OFFSET label##4b-label##5b;			\
51	.ifgt (label##4b- label##3b)-(label##2b- label##1b);	\
52	.error "Feature section else case larger than body";	\
53	.endif;							\
54	.popsection;
55
56
57/* CPU feature dependent sections */
58#define BEGIN_FTR_SECTION_NESTED(label)	START_FTR_SECTION(label)
59#define BEGIN_FTR_SECTION		START_FTR_SECTION(97)
60
61#define END_FTR_SECTION_NESTED(msk, val, label) 		\
62	FTR_SECTION_ELSE_NESTED(label)				\
63	MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
64
65#define END_FTR_SECTION(msk, val)		\
66	END_FTR_SECTION_NESTED(msk, val, 97)
67
68#define END_FTR_SECTION_NESTED_IFSET(msk, label)	\
69	END_FTR_SECTION_NESTED((msk), (msk), label)
70
71#define END_FTR_SECTION_IFSET(msk)	END_FTR_SECTION((msk), (msk))
72#define END_FTR_SECTION_IFCLR(msk)	END_FTR_SECTION((msk), 0)
73
74/* CPU feature sections with alternatives, use BEGIN_FTR_SECTION to start */
75#define FTR_SECTION_ELSE	FTR_SECTION_ELSE_NESTED(97)
76#define ALT_FTR_SECTION_END_NESTED(msk, val, label)	\
77	MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
78#define ALT_FTR_SECTION_END_NESTED_IFSET(msk, label)	\
79	ALT_FTR_SECTION_END_NESTED(msk, msk, label)
80#define ALT_FTR_SECTION_END_NESTED_IFCLR(msk, label)	\
81	ALT_FTR_SECTION_END_NESTED(msk, 0, label)
82#define ALT_FTR_SECTION_END(msk, val)	\
83	ALT_FTR_SECTION_END_NESTED(msk, val, 97)
84#define ALT_FTR_SECTION_END_IFSET(msk)	\
85	ALT_FTR_SECTION_END_NESTED_IFSET(msk, 97)
86#define ALT_FTR_SECTION_END_IFCLR(msk)	\
87	ALT_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
88
89/* MMU feature dependent sections */
90#define BEGIN_MMU_FTR_SECTION_NESTED(label)	START_FTR_SECTION(label)
91#define BEGIN_MMU_FTR_SECTION			START_FTR_SECTION(97)
92
93#define END_MMU_FTR_SECTION_NESTED(msk, val, label) 		\
94	FTR_SECTION_ELSE_NESTED(label)				\
95	MAKE_FTR_SECTION_ENTRY(msk, val, label, __mmu_ftr_fixup)
96
97#define END_MMU_FTR_SECTION(msk, val)		\
98	END_MMU_FTR_SECTION_NESTED(msk, val, 97)
99
100#define END_MMU_FTR_SECTION_NESTED_IFSET(msk, label)	\
101	END_MMU_FTR_SECTION_NESTED((msk), (msk), label)
102
103#define END_MMU_FTR_SECTION_IFSET(msk)	END_MMU_FTR_SECTION((msk), (msk))
104#define END_MMU_FTR_SECTION_IFCLR(msk)	END_MMU_FTR_SECTION((msk), 0)
105
106/* MMU feature sections with alternatives, use BEGIN_FTR_SECTION to start */
107#define MMU_FTR_SECTION_ELSE_NESTED(label)	FTR_SECTION_ELSE_NESTED(label)
108#define MMU_FTR_SECTION_ELSE	MMU_FTR_SECTION_ELSE_NESTED(97)
109#define ALT_MMU_FTR_SECTION_END_NESTED(msk, val, label)	\
110	MAKE_FTR_SECTION_ENTRY(msk, val, label, __mmu_ftr_fixup)
111#define ALT_MMU_FTR_SECTION_END_NESTED_IFSET(msk, label)	\
112	ALT_MMU_FTR_SECTION_END_NESTED(msk, msk, label)
113#define ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(msk, label)	\
114	ALT_MMU_FTR_SECTION_END_NESTED(msk, 0, label)
115#define ALT_MMU_FTR_SECTION_END(msk, val)	\
116	ALT_MMU_FTR_SECTION_END_NESTED(msk, val, 97)
117#define ALT_MMU_FTR_SECTION_END_IFSET(msk)	\
118	ALT_MMU_FTR_SECTION_END_NESTED_IFSET(msk, 97)
119#define ALT_MMU_FTR_SECTION_END_IFCLR(msk)	\
120	ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
121
122/* Firmware feature dependent sections */
123#define BEGIN_FW_FTR_SECTION_NESTED(label)	START_FTR_SECTION(label)
124#define BEGIN_FW_FTR_SECTION			START_FTR_SECTION(97)
125
126#define END_FW_FTR_SECTION_NESTED(msk, val, label) 		\
127	FTR_SECTION_ELSE_NESTED(label)				\
128	MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
129
130#define END_FW_FTR_SECTION(msk, val)		\
131	END_FW_FTR_SECTION_NESTED(msk, val, 97)
132
133#define END_FW_FTR_SECTION_IFSET(msk)	END_FW_FTR_SECTION((msk), (msk))
134#define END_FW_FTR_SECTION_IFCLR(msk)	END_FW_FTR_SECTION((msk), 0)
135
136/* Firmware feature sections with alternatives */
137#define FW_FTR_SECTION_ELSE_NESTED(label)	FTR_SECTION_ELSE_NESTED(label)
138#define FW_FTR_SECTION_ELSE	FTR_SECTION_ELSE_NESTED(97)
139#define ALT_FW_FTR_SECTION_END_NESTED(msk, val, label)	\
140	MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
141#define ALT_FW_FTR_SECTION_END_NESTED_IFSET(msk, label)	\
142	ALT_FW_FTR_SECTION_END_NESTED(msk, msk, label)
143#define ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, label)	\
144	ALT_FW_FTR_SECTION_END_NESTED(msk, 0, label)
145#define ALT_FW_FTR_SECTION_END(msk, val)	\
146	ALT_FW_FTR_SECTION_END_NESTED(msk, val, 97)
147#define ALT_FW_FTR_SECTION_END_IFSET(msk)	\
148	ALT_FW_FTR_SECTION_END_NESTED_IFSET(msk, 97)
149#define ALT_FW_FTR_SECTION_END_IFCLR(msk)	\
150	ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
151
152#ifndef __ASSEMBLY__
153
154#define ASM_FTR_IF(section_if, section_else, msk, val)	\
155	stringify_in_c(BEGIN_FTR_SECTION)			\
156	section_if "; "						\
157	stringify_in_c(FTR_SECTION_ELSE)			\
158	section_else "; "					\
159	stringify_in_c(ALT_FTR_SECTION_END((msk), (val)))
160
161#define ASM_FTR_IFSET(section_if, section_else, msk)	\
162	ASM_FTR_IF(section_if, section_else, (msk), (msk))
163
164#define ASM_FTR_IFCLR(section_if, section_else, msk)	\
165	ASM_FTR_IF(section_if, section_else, (msk), 0)
166
167#define ASM_MMU_FTR_IF(section_if, section_else, msk, val)	\
168	stringify_in_c(BEGIN_MMU_FTR_SECTION)			\
169	section_if "; "						\
170	stringify_in_c(MMU_FTR_SECTION_ELSE)			\
171	section_else "; "					\
172	stringify_in_c(ALT_MMU_FTR_SECTION_END((msk), (val)))
173
174#define ASM_MMU_FTR_IFSET(section_if, section_else, msk)	\
175	ASM_MMU_FTR_IF(section_if, section_else, (msk), (msk))
176
177#define ASM_MMU_FTR_IFCLR(section_if, section_else, msk)	\
178	ASM_MMU_FTR_IF(section_if, section_else, (msk), 0)
179
180#endif /* __ASSEMBLY__ */
181
182/* LWSYNC feature sections */
183#define START_LWSYNC_SECTION(label)	label##1:
184#define MAKE_LWSYNC_SECTION_ENTRY(label, sect)		\
185label##2:						\
186	.pushsection sect,"a";				\
187	.align 2;					\
188label##3:					       	\
189	FTR_ENTRY_OFFSET label##1b-label##3b;		\
190	.popsection;
191
192#define STF_ENTRY_BARRIER_FIXUP_SECTION			\
193953:							\
194	.pushsection __stf_entry_barrier_fixup,"a";	\
195	.align 2;					\
196954:							\
197	FTR_ENTRY_OFFSET 953b-954b;			\
198	.popsection;
199
200#define STF_EXIT_BARRIER_FIXUP_SECTION			\
201955:							\
202	.pushsection __stf_exit_barrier_fixup,"a";	\
203	.align 2;					\
204956:							\
205	FTR_ENTRY_OFFSET 955b-956b;			\
206	.popsection;
207
208#define UACCESS_FLUSH_FIXUP_SECTION			\
209959:							\
210	.pushsection __uaccess_flush_fixup,"a";		\
211	.align 2;					\
212960:							\
213	FTR_ENTRY_OFFSET 959b-960b;			\
214	.popsection;
215
216#define ENTRY_FLUSH_FIXUP_SECTION			\
217957:							\
218	.pushsection __entry_flush_fixup,"a";		\
219	.align 2;					\
220958:							\
221	FTR_ENTRY_OFFSET 957b-958b;			\
222	.popsection;
223
224#define SCV_ENTRY_FLUSH_FIXUP_SECTION			\
225957:							\
226	.pushsection __scv_entry_flush_fixup,"a";	\
227	.align 2;					\
228958:							\
229	FTR_ENTRY_OFFSET 957b-958b;			\
230	.popsection;
231
232#define RFI_FLUSH_FIXUP_SECTION				\
233951:							\
234	.pushsection __rfi_flush_fixup,"a";		\
235	.align 2;					\
236952:							\
237	FTR_ENTRY_OFFSET 951b-952b;			\
238	.popsection;
239
240#define NOSPEC_BARRIER_FIXUP_SECTION			\
241953:							\
242	.pushsection __barrier_nospec_fixup,"a";	\
243	.align 2;					\
244954:							\
245	FTR_ENTRY_OFFSET 953b-954b;			\
246	.popsection;
247
248#define START_BTB_FLUSH_SECTION			\
249955:							\
250
251#define END_BTB_FLUSH_SECTION			\
252956:							\
253	.pushsection __btb_flush_fixup,"a";	\
254	.align 2;							\
255957:						\
256	FTR_ENTRY_OFFSET 955b-957b;			\
257	FTR_ENTRY_OFFSET 956b-957b;			\
258	.popsection;
259
260#ifndef __ASSEMBLY__
261#include <linux/types.h>
262
263extern long stf_barrier_fallback;
264extern long entry_flush_fallback;
265extern long scv_entry_flush_fallback;
266extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
267extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
268extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
269extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
270extern long __start___scv_entry_flush_fixup, __stop___scv_entry_flush_fixup;
271extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
272extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
273extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
274
275void apply_feature_fixups(void);
276void setup_feature_keys(void);
277#endif
278
279#endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */
280