1 #ifndef _ASM_POWERPC_HEAD_64_H
2 #define _ASM_POWERPC_HEAD_64_H
7 * We can't do CPP stringification and concatination directly into the section
8 * name for some reason, so these macros can do it for us.
10 .macro define_ftsec name
11 .section
".head.text.\name\()","ax",@progbits
13 .macro define_data_ftsec name
14 .section
".head.data.\name\()","a",@progbits
17 .section
".head.text.\name\()"
21 * Fixed (location) sections are used by opening fixed sections and emitting
22 * fixed section entries into them before closing them. Multiple fixed sections
23 * can be open at any time.
25 * Each fixed section created in a .S file must have corresponding linkage
26 * directives including location, added to arch/powerpc/kernel/vmlinux.lds.S
28 * For each fixed section, code is generated into it in the order which it
29 * appears in the source. Fixed section entries can be placed at a fixed
30 * location within the section using _LOCATION postifx variants. These must
31 * be ordered according to their relative placements within the section.
33 * OPEN_FIXED_SECTION(section_name, start_address, end_address)
34 * FIXED_SECTION_ENTRY_BEGIN(section_name, label1)
36 * USE_FIXED_SECTION(section_name)
41 * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size)
42 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size)
43 * CLOSE_FIXED_SECTION(section_name)
45 * ZERO_FIXED_SECTION can be used to emit zeroed data.
48 * - If the build dies with "Error: attempt to move .org backwards" at
49 * CLOSE_FIXED_SECTION() or elsewhere, there may be something
50 * unexpected being added there. Remove the '. = x_len' line, rebuild, and
51 * check what is pushing the section down.
52 * - If the build dies in linking, check arch/powerpc/kernel/vmlinux.lds.S
54 * - If the kernel crashes or hangs in very early boot, it could be linker
55 * stubs at the start of the main text.
58 #define OPEN_FIXED_SECTION(sname, start, end) \
59 sname##_start = (start); \
60 sname##_end = (end); \
61 sname##_len = (end) - (start); \
66 #define OPEN_TEXT_SECTION(start) \
67 text_start = (start); \
68 .section ".text","ax",@progbits; \
72 #define ZERO_FIXED_SECTION(sname, start, end) \
73 sname##_start = (start); \
74 sname##_end = (end); \
75 sname##_len = (end) - (start); \
76 define_data_ftsec sname; \
80 #define USE_FIXED_SECTION(sname) \
81 fs_label = start_##sname; \
82 fs_start = sname##_start; \
85 #define USE_TEXT_SECTION() \
86 fs_label = start_text; \
87 fs_start = text_start; \
90 #define CLOSE_FIXED_SECTION(sname) \
91 USE_FIXED_SECTION(sname); \
96 #define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \
97 USE_FIXED_SECTION(sname); \
102 #define FIXED_SECTION_ENTRY_BEGIN(sname, name) \
103 __FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
105 #define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \
106 USE_FIXED_SECTION(sname); \
107 name##_start = (start); \
108 .if ((start) % (size) != 0); \
109 .error "Fixed section exception vector misalignment"; \
111 .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100); \
112 .error "Fixed section exception vector bad size"; \
114 .if (start) < sname##_start; \
115 .error "Fixed section underflow"; \
118 . = (start) - sname##_start; \
122 #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \
123 .if (start) + (size) > sname##_end; \
124 .error "Fixed section overflow"; \
127 .if (. - name > (start) + (size) - name##_start); \
128 .error "Fixed entry overflow"; \
131 . = ((start) + (size) - sname##_start); \
135 * These macros are used to change symbols in other fixed sections to be
136 * absolute or related to our current fixed section.
138 * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the
139 * absolute address of a symbol within a fixed section, from any section.
141 * - ABS_ADDR is used to find the absolute address of any symbol, from within
144 #define DEFINE_FIXED_SYMBOL(label) \
145 label##_absolute = (label - fs_label + fs_start)
147 #define FIXED_SYMBOL_ABS_ADDR(label) \
150 #define ABS_ADDR(label) (label - fs_label + fs_start)
153 * Following are the BOOK3S exception handler helper macros.
154 * Handlers come in a number of types, and each type has a number of varieties.
156 * EXC_REAL_* - real, unrelocated exception vectors
157 * EXC_VIRT_* - virt (AIL), unrelocated exception vectors
158 * TRAMP_REAL_* - real, unrelocated helpers (virt can call these)
159 * TRAMP_VIRT_* - virt, unreloc helpers (in practice, real can use)
160 * TRAMP_KVM - KVM handlers that get put into real, unrelocated
161 * EXC_COMMON_* - virt, relocated common handlers
163 * The EXC handlers are given a name, and branch to name_common, or the
164 * appropriate KVM or masking function. Vector handler verieties are as
167 * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception
169 * EXC_{REAL|VIRT} - standard exception
171 * EXC_{REAL|VIRT}_suffix
173 * - _MASKABLE - maskable exception
174 * - _OOL - out of line with trampoline to common handler
175 * - _HV - HV exception
177 * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV
179 * The one unusual case is __EXC_REAL_OOL_HV_DIRECT, which is
180 * an OOL vector that branches to a specified handler rather than the usual
181 * trampoline that goes to common. It, and other underscore macros, should
184 * KVM handlers come in the following verieties:
190 * COMMON handlers come in the following verieties:
191 * EXC_COMMON_BEGIN/END - used to open-code the handler
196 * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM
197 * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers.
200 #define EXC_REAL_BEGIN(name, start, size) \
201 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
203 #define EXC_REAL_END(name, start, size) \
204 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
206 #define EXC_VIRT_BEGIN(name, start, size) \
207 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
209 #define EXC_VIRT_END(name, start, size) \
210 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
212 #define EXC_COMMON_BEGIN(name) \
213 USE_TEXT_SECTION(); \
214 .balign IFETCH_ALIGN_BYTES; \
216 DEFINE_FIXED_SYMBOL(name); \
219 #define TRAMP_REAL_BEGIN(name) \
220 FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)
222 #define TRAMP_VIRT_BEGIN(name) \
223 FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
225 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
226 #define TRAMP_KVM_BEGIN(name) \
227 TRAMP_VIRT_BEGIN(name)
229 #define TRAMP_KVM_BEGIN(name)
232 #define EXC_REAL_NONE(start, size) \
233 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start, size); \
234 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, start, size)
236 #define EXC_VIRT_NONE(start, size) \
237 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); \
238 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size);
241 #define EXC_REAL(name, start, size) \
242 EXC_REAL_BEGIN(name, start, size); \
243 STD_EXCEPTION_PSERIES(start, name##_common); \
244 EXC_REAL_END(name, start, size);
246 #define EXC_VIRT(name, start, size, realvec) \
247 EXC_VIRT_BEGIN(name, start, size); \
248 STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \
249 EXC_VIRT_END(name, start, size);
251 #define EXC_REAL_MASKABLE(name, start, size) \
252 EXC_REAL_BEGIN(name, start, size); \
253 MASKABLE_EXCEPTION_PSERIES(start, start, name##_common); \
254 EXC_REAL_END(name, start, size);
256 #define EXC_VIRT_MASKABLE(name, start, size, realvec) \
257 EXC_VIRT_BEGIN(name, start, size); \
258 MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \
259 EXC_VIRT_END(name, start, size);
261 #define EXC_REAL_HV(name, start, size) \
262 EXC_REAL_BEGIN(name, start, size); \
263 STD_EXCEPTION_HV(start, start, name##_common); \
264 EXC_REAL_END(name, start, size);
266 #define EXC_VIRT_HV(name, start, size, realvec) \
267 EXC_VIRT_BEGIN(name, start, size); \
268 STD_RELON_EXCEPTION_HV(start, realvec, name##_common); \
269 EXC_VIRT_END(name, start, size);
271 #define __EXC_REAL_OOL(name, start, size) \
272 EXC_REAL_BEGIN(name, start, size); \
273 __OOL_EXCEPTION(start, label, tramp_real_##name); \
274 EXC_REAL_END(name, start, size);
276 #define __TRAMP_REAL_OOL(name, vec) \
277 TRAMP_REAL_BEGIN(tramp_real_##name); \
278 STD_EXCEPTION_PSERIES_OOL(vec, name##_common); \
280 #define EXC_REAL_OOL(name, start, size) \
281 __EXC_REAL_OOL(name, start, size); \
282 __TRAMP_REAL_OOL(name, start);
284 #define __EXC_REAL_OOL_MASKABLE(name, start, size) \
285 __EXC_REAL_OOL(name, start, size);
287 #define __TRAMP_REAL_OOL_MASKABLE(name, vec) \
288 TRAMP_REAL_BEGIN(tramp_real_##name); \
289 MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common); \
291 #define EXC_REAL_OOL_MASKABLE(name, start, size) \
292 __EXC_REAL_OOL_MASKABLE(name, start, size); \
293 __TRAMP_REAL_OOL_MASKABLE(name, start);
295 #define __EXC_REAL_OOL_HV_DIRECT(name, start, size, handler) \
296 EXC_REAL_BEGIN(name, start, size); \
297 __OOL_EXCEPTION(start, label, handler); \
298 EXC_REAL_END(name, start, size);
300 #define __EXC_REAL_OOL_HV(name, start, size) \
301 __EXC_REAL_OOL(name, start, size);
303 #define __TRAMP_REAL_OOL_HV(name, vec) \
304 TRAMP_REAL_BEGIN(tramp_real_##name); \
305 STD_EXCEPTION_HV_OOL(vec, name##_common); \
307 #define EXC_REAL_OOL_HV(name, start, size) \
308 __EXC_REAL_OOL_HV(name, start, size); \
309 __TRAMP_REAL_OOL_HV(name, start);
311 #define __EXC_REAL_OOL_MASKABLE_HV(name, start, size) \
312 __EXC_REAL_OOL(name, start, size);
314 #define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec) \
315 TRAMP_REAL_BEGIN(tramp_real_##name); \
316 MASKABLE_EXCEPTION_HV_OOL(vec, name##_common); \
318 #define EXC_REAL_OOL_MASKABLE_HV(name, start, size) \
319 __EXC_REAL_OOL_MASKABLE_HV(name, start, size); \
320 __TRAMP_REAL_OOL_MASKABLE_HV(name, start);
322 #define __EXC_VIRT_OOL(name, start, size) \
323 EXC_VIRT_BEGIN(name, start, size); \
324 __OOL_EXCEPTION(start, label, tramp_virt_##name); \
325 EXC_VIRT_END(name, start, size);
327 #define __TRAMP_VIRT_OOL(name, realvec) \
328 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
329 STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \
331 #define EXC_VIRT_OOL(name, start, size, realvec) \
332 __EXC_VIRT_OOL(name, start, size); \
333 __TRAMP_VIRT_OOL(name, realvec);
335 #define __EXC_VIRT_OOL_MASKABLE(name, start, size) \
336 __EXC_VIRT_OOL(name, start, size);
338 #define __TRAMP_VIRT_OOL_MASKABLE(name, realvec) \
339 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
340 MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \
342 #define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec) \
343 __EXC_VIRT_OOL_MASKABLE(name, start, size); \
344 __TRAMP_VIRT_OOL_MASKABLE(name, realvec);
346 #define __EXC_VIRT_OOL_HV(name, start, size) \
347 __EXC_VIRT_OOL(name, start, size);
349 #define __TRAMP_VIRT_OOL_HV(name, realvec) \
350 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
351 STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \
353 #define EXC_VIRT_OOL_HV(name, start, size, realvec) \
354 __EXC_VIRT_OOL_HV(name, start, size); \
355 __TRAMP_VIRT_OOL_HV(name, realvec);
357 #define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size) \
358 __EXC_VIRT_OOL(name, start, size);
360 #define __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec) \
361 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
362 MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \
364 #define EXC_VIRT_OOL_MASKABLE_HV(name, start, size, realvec) \
365 __EXC_VIRT_OOL_MASKABLE_HV(name, start, size); \
366 __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec);
368 #define TRAMP_KVM(area, n) \
369 TRAMP_KVM_BEGIN(do_kvm_##n); \
370 KVM_HANDLER(area, EXC_STD, n); \
372 #define TRAMP_KVM_SKIP(area, n) \
373 TRAMP_KVM_BEGIN(do_kvm_##n); \
374 KVM_HANDLER_SKIP(area, EXC_STD, n); \
377 * HV variant exceptions get the 0x2 bit added to their trap number.
379 #define TRAMP_KVM_HV(area, n) \
380 TRAMP_KVM_BEGIN(do_kvm_H##n); \
381 KVM_HANDLER(area, EXC_HV, n + 0x2); \
383 #define TRAMP_KVM_HV_SKIP(area, n) \
384 TRAMP_KVM_BEGIN(do_kvm_H##n); \
385 KVM_HANDLER_SKIP(area, EXC_HV, n + 0x2); \
387 #define EXC_COMMON(name, realvec, hdlr) \
388 EXC_COMMON_BEGIN(name); \
389 STD_EXCEPTION_COMMON(realvec, name, hdlr); \
391 #define EXC_COMMON_ASYNC(name, realvec, hdlr) \
392 EXC_COMMON_BEGIN(name); \
393 STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr); \
395 #define EXC_COMMON_HV(name, realvec, hdlr) \
396 EXC_COMMON_BEGIN(name); \
397 STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr); \
399 #endif /* _ASM_POWERPC_HEAD_64_H */