]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/powerpc/include/asm/head-64.h
Merge remote-tracking branches 'spi/fix/dw', 'spi/fix/lantiq' and 'spi/fix/pl022...
[mirror_ubuntu-artful-kernel.git] / arch / powerpc / include / asm / head-64.h
1 #ifndef _ASM_POWERPC_HEAD_64_H
2 #define _ASM_POWERPC_HEAD_64_H
3
4 #include <asm/cache.h>
5
6 /*
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.
9 */
10 .macro define_ftsec name
11 .section ".head.text.\name\()","ax",@progbits
12 .endm
13 .macro define_data_ftsec name
14 .section ".head.data.\name\()","a",@progbits
15 .endm
16 .macro use_ftsec name
17 .section ".head.text.\name\()"
18 .endm
19
20 /*
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.
24 *
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
27 *
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.
32 *
33 * OPEN_FIXED_SECTION(section_name, start_address, end_address)
34 * FIXED_SECTION_ENTRY_BEGIN(section_name, label1)
35 *
36 * USE_FIXED_SECTION(section_name)
37 * label3:
38 * li r10,128
39 * mv r11,r10
40
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)
44 *
45 * ZERO_FIXED_SECTION can be used to emit zeroed data.
46 *
47 * Troubleshooting:
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
53 * for instructions.
54 * - If the kernel crashes or hangs in very early boot, it could be linker
55 * stubs at the start of the main text.
56 */
57
58 #define OPEN_FIXED_SECTION(sname, start, end) \
59 sname##_start = (start); \
60 sname##_end = (end); \
61 sname##_len = (end) - (start); \
62 define_ftsec sname; \
63 . = 0x0; \
64 start_##sname:
65
66 #define OPEN_TEXT_SECTION(start) \
67 text_start = (start); \
68 .section ".text","ax",@progbits; \
69 . = 0x0; \
70 start_text:
71
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; \
77 . = 0x0; \
78 . = sname##_len;
79
80 #define USE_FIXED_SECTION(sname) \
81 fs_label = start_##sname; \
82 fs_start = sname##_start; \
83 use_ftsec sname;
84
85 #define USE_TEXT_SECTION() \
86 fs_label = start_text; \
87 fs_start = text_start; \
88 .text
89
90 #define CLOSE_FIXED_SECTION(sname) \
91 USE_FIXED_SECTION(sname); \
92 . = sname##_len; \
93 end_##sname:
94
95
96 #define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \
97 USE_FIXED_SECTION(sname); \
98 .balign __align; \
99 .global name; \
100 name:
101
102 #define FIXED_SECTION_ENTRY_BEGIN(sname, name) \
103 __FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
104
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"; \
110 .endif; \
111 .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100); \
112 .error "Fixed section exception vector bad size"; \
113 .endif; \
114 .if (start) < sname##_start; \
115 .error "Fixed section underflow"; \
116 .abort; \
117 .endif; \
118 . = (start) - sname##_start; \
119 .global name; \
120 name:
121
122 #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \
123 .if (start) + (size) > sname##_end; \
124 .error "Fixed section overflow"; \
125 .abort; \
126 .endif; \
127 .if (. - name > (start) + (size) - name##_start); \
128 .error "Fixed entry overflow"; \
129 .abort; \
130 .endif; \
131 . = ((start) + (size) - sname##_start); \
132
133
134 /*
135 * These macros are used to change symbols in other fixed sections to be
136 * absolute or related to our current fixed section.
137 *
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.
140 *
141 * - ABS_ADDR is used to find the absolute address of any symbol, from within
142 * a fixed section.
143 */
144 #define DEFINE_FIXED_SYMBOL(label) \
145 label##_absolute = (label - fs_label + fs_start)
146
147 #define FIXED_SYMBOL_ABS_ADDR(label) \
148 (label##_absolute)
149
150 #define ABS_ADDR(label) (label - fs_label + fs_start)
151
152 /*
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.
155 *
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
162 *
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
165 * follows:
166 *
167 * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception
168 *
169 * EXC_{REAL|VIRT} - standard exception
170 *
171 * EXC_{REAL|VIRT}_suffix
172 * where _suffix is:
173 * - _MASKABLE - maskable exception
174 * - _OOL - out of line with trampoline to common handler
175 * - _HV - HV exception
176 *
177 * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV
178 *
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
182 * be used with care.
183 *
184 * KVM handlers come in the following verieties:
185 * TRAMP_KVM
186 * TRAMP_KVM_SKIP
187 * TRAMP_KVM_HV
188 * TRAMP_KVM_HV_SKIP
189 *
190 * COMMON handlers come in the following verieties:
191 * EXC_COMMON_BEGIN/END - used to open-code the handler
192 * EXC_COMMON
193 * EXC_COMMON_ASYNC
194 * EXC_COMMON_HV
195 *
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.
198 */
199
200 #define EXC_REAL_BEGIN(name, start, size) \
201 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
202
203 #define EXC_REAL_END(name, start, size) \
204 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
205
206 #define EXC_VIRT_BEGIN(name, start, size) \
207 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
208
209 #define EXC_VIRT_END(name, start, size) \
210 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
211
212 #define EXC_COMMON_BEGIN(name) \
213 USE_TEXT_SECTION(); \
214 .balign IFETCH_ALIGN_BYTES; \
215 .global name; \
216 DEFINE_FIXED_SYMBOL(name); \
217 name:
218
219 #define TRAMP_REAL_BEGIN(name) \
220 FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)
221
222 #define TRAMP_VIRT_BEGIN(name) \
223 FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
224
225 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
226 #define TRAMP_KVM_BEGIN(name) \
227 TRAMP_VIRT_BEGIN(name)
228 #else
229 #define TRAMP_KVM_BEGIN(name)
230 #endif
231
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)
235
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);
239
240
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);
245
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);
250
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);
255
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);
260
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);
265
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);
270
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);
275
276 #define __TRAMP_REAL_OOL(name, vec) \
277 TRAMP_REAL_BEGIN(tramp_real_##name); \
278 STD_EXCEPTION_PSERIES_OOL(vec, name##_common); \
279
280 #define EXC_REAL_OOL(name, start, size) \
281 __EXC_REAL_OOL(name, start, size); \
282 __TRAMP_REAL_OOL(name, start);
283
284 #define __EXC_REAL_OOL_MASKABLE(name, start, size) \
285 __EXC_REAL_OOL(name, start, size);
286
287 #define __TRAMP_REAL_OOL_MASKABLE(name, vec) \
288 TRAMP_REAL_BEGIN(tramp_real_##name); \
289 MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common); \
290
291 #define EXC_REAL_OOL_MASKABLE(name, start, size) \
292 __EXC_REAL_OOL_MASKABLE(name, start, size); \
293 __TRAMP_REAL_OOL_MASKABLE(name, start);
294
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);
299
300 #define __EXC_REAL_OOL_HV(name, start, size) \
301 __EXC_REAL_OOL(name, start, size);
302
303 #define __TRAMP_REAL_OOL_HV(name, vec) \
304 TRAMP_REAL_BEGIN(tramp_real_##name); \
305 STD_EXCEPTION_HV_OOL(vec, name##_common); \
306
307 #define EXC_REAL_OOL_HV(name, start, size) \
308 __EXC_REAL_OOL_HV(name, start, size); \
309 __TRAMP_REAL_OOL_HV(name, start);
310
311 #define __EXC_REAL_OOL_MASKABLE_HV(name, start, size) \
312 __EXC_REAL_OOL(name, start, size);
313
314 #define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec) \
315 TRAMP_REAL_BEGIN(tramp_real_##name); \
316 MASKABLE_EXCEPTION_HV_OOL(vec, name##_common); \
317
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);
321
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);
326
327 #define __TRAMP_VIRT_OOL(name, realvec) \
328 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
329 STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \
330
331 #define EXC_VIRT_OOL(name, start, size, realvec) \
332 __EXC_VIRT_OOL(name, start, size); \
333 __TRAMP_VIRT_OOL(name, realvec);
334
335 #define __EXC_VIRT_OOL_MASKABLE(name, start, size) \
336 __EXC_VIRT_OOL(name, start, size);
337
338 #define __TRAMP_VIRT_OOL_MASKABLE(name, realvec) \
339 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
340 MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \
341
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);
345
346 #define __EXC_VIRT_OOL_HV(name, start, size) \
347 __EXC_VIRT_OOL(name, start, size);
348
349 #define __TRAMP_VIRT_OOL_HV(name, realvec) \
350 TRAMP_VIRT_BEGIN(tramp_virt_##name); \
351 STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \
352
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);
356
357 #define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size) \
358 __EXC_VIRT_OOL(name, start, size);
359
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); \
363
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);
367
368 #define TRAMP_KVM(area, n) \
369 TRAMP_KVM_BEGIN(do_kvm_##n); \
370 KVM_HANDLER(area, EXC_STD, n); \
371
372 #define TRAMP_KVM_SKIP(area, n) \
373 TRAMP_KVM_BEGIN(do_kvm_##n); \
374 KVM_HANDLER_SKIP(area, EXC_STD, n); \
375
376 /*
377 * HV variant exceptions get the 0x2 bit added to their trap number.
378 */
379 #define TRAMP_KVM_HV(area, n) \
380 TRAMP_KVM_BEGIN(do_kvm_H##n); \
381 KVM_HANDLER(area, EXC_HV, n + 0x2); \
382
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); \
386
387 #define EXC_COMMON(name, realvec, hdlr) \
388 EXC_COMMON_BEGIN(name); \
389 STD_EXCEPTION_COMMON(realvec, name, hdlr); \
390
391 #define EXC_COMMON_ASYNC(name, realvec, hdlr) \
392 EXC_COMMON_BEGIN(name); \
393 STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr); \
394
395 #define EXC_COMMON_HV(name, realvec, hdlr) \
396 EXC_COMMON_BEGIN(name); \
397 STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr); \
398
399 #endif /* _ASM_POWERPC_HEAD_64_H */