head-64.h 13.8 KB
Newer Older
1 2 3 4 5
#ifndef _ASM_POWERPC_HEAD_64_H
#define _ASM_POWERPC_HEAD_64_H

#include <asm/cache.h>

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
/*
 * We can't do CPP stringification and concatination directly into the section
 * name for some reason, so these macros can do it for us.
 */
.macro define_ftsec name
	.section ".head.text.\name\()","ax",@progbits
.endm
.macro define_data_ftsec name
	.section ".head.data.\name\()","a",@progbits
.endm
.macro use_ftsec name
	.section ".head.text.\name\()"
.endm

/*
 * Fixed (location) sections are used by opening fixed sections and emitting
 * fixed section entries into them before closing them. Multiple fixed sections
 * can be open at any time.
 *
 * Each fixed section created in a .S file must have corresponding linkage
 * directives including location, added to  arch/powerpc/kernel/vmlinux.lds.S
 *
 * For each fixed section, code is generated into it in the order which it
 * appears in the source.  Fixed section entries can be placed at a fixed
 * location within the section using _LOCATION postifx variants. These must
 * be ordered according to their relative placements within the section.
 *
 * OPEN_FIXED_SECTION(section_name, start_address, end_address)
 * FIXED_SECTION_ENTRY_BEGIN(section_name, label1)
 *
 * USE_FIXED_SECTION(section_name)
 * label3:
 *     li  r10,128
 *     mv  r11,r10

41 42
 * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size)
 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
 * CLOSE_FIXED_SECTION(section_name)
 *
 * ZERO_FIXED_SECTION can be used to emit zeroed data.
 *
 * Troubleshooting:
 * - If the build dies with "Error: attempt to move .org backwards" at
 *   CLOSE_FIXED_SECTION() or elsewhere, there may be something
 *   unexpected being added there. Remove the '. = x_len' line, rebuild, and
 *   check what is pushing the section down.
 * - If the build dies in linking, check arch/powerpc/kernel/vmlinux.lds.S
 *   for instructions.
 * - If the kernel crashes or hangs in very early boot, it could be linker
 *   stubs at the start of the main text.
 */

#define OPEN_FIXED_SECTION(sname, start, end)			\
	sname##_start = (start);				\
	sname##_end = (end);					\
	sname##_len = (end) - (start);				\
	define_ftsec sname;					\
	. = 0x0;						\
start_##sname:

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/*
 * .linker_stub_catch section is used to catch linker stubs from being
 * inserted in our .text section, above the start_text label (which breaks
 * the ABS_ADDR calculation). See kernel/vmlinux.lds.S and tools/head_check.sh
 * for more details. We would prefer to just keep a cacheline (0x80), but
 * 0x100 seems to be how the linker aligns branch stub groups.
 */
#ifdef CONFIG_LD_HEAD_STUB_CATCH
#define OPEN_TEXT_SECTION(start)				\
	.section ".linker_stub_catch","ax",@progbits;		\
linker_stub_catch:						\
	. = 0x4;						\
	text_start = (start) + 0x100;				\
	.section ".text","ax",@progbits;			\
	.balign 0x100;						\
start_text:
#else
83 84 85 86 87
#define OPEN_TEXT_SECTION(start)				\
	text_start = (start);					\
	.section ".text","ax",@progbits;			\
	. = 0x0;						\
start_text:
88
#endif
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

#define ZERO_FIXED_SECTION(sname, start, end)			\
	sname##_start = (start);				\
	sname##_end = (end);					\
	sname##_len = (end) - (start);				\
	define_data_ftsec sname;				\
	. = 0x0;						\
	. = sname##_len;

#define USE_FIXED_SECTION(sname)				\
	fs_label = start_##sname;				\
	fs_start = sname##_start;				\
	use_ftsec sname;

#define USE_TEXT_SECTION()					\
	fs_label = start_text;					\
	fs_start = text_start;					\
	.text

#define CLOSE_FIXED_SECTION(sname)				\
	USE_FIXED_SECTION(sname);				\
	. = sname##_len;					\
end_##sname:


#define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align)	\
	USE_FIXED_SECTION(sname);				\
116
	.balign __align;					\
117 118 119 120
	.global name;						\
name:

#define FIXED_SECTION_ENTRY_BEGIN(sname, name)			\
121
	__FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
122

123
#define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \
124 125
	USE_FIXED_SECTION(sname);				\
	name##_start = (start);					\
126 127 128 129 130 131
	.if ((start) % (size) != 0);				\
	.error "Fixed section exception vector misalignment";	\
	.endif;							\
	.if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100); \
	.error "Fixed section exception vector bad size";	\
	.endif;							\
132 133 134 135 136 137 138 139
	.if (start) < sname##_start;				\
	.error "Fixed section underflow";			\
	.abort;							\
	.endif;							\
	. = (start) - sname##_start;				\
	.global name;						\
name:

140 141
#define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \
	.if (start) + (size) > sname##_end;			\
142 143 144
	.error "Fixed section overflow";			\
	.abort;							\
	.endif;							\
145
	.if (. - name > (start) + (size) - name##_start);	\
146 147 148
	.error "Fixed entry overflow";				\
	.abort;							\
	.endif;							\
149
	. = ((start) + (size) - sname##_start);			\
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173


/*
 * These macros are used to change symbols in other fixed sections to be
 * absolute or related to our current fixed section.
 *
 * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the
 *   absolute address of a symbol within a fixed section, from any section.
 *
 * - ABS_ADDR is used to find the absolute address of any symbol, from within
 *   a fixed section.
 */
#define DEFINE_FIXED_SYMBOL(label)				\
	label##_absolute = (label - fs_label + fs_start)

#define FIXED_SYMBOL_ABS_ADDR(label)				\
	(label##_absolute)

#define ABS_ADDR(label) (label - fs_label + fs_start)

/*
 * Following are the BOOK3S exception handler helper macros.
 * Handlers come in a number of types, and each type has a number of varieties.
 *
174 175
 * EXC_REAL_*     - real, unrelocated exception vectors
 * EXC_VIRT_*     - virt (AIL), unrelocated exception vectors
176
 * TRAMP_REAL_*   - real, unrelocated helpers (virt can call these)
177 178 179
 * TRAMP_VIRT_*   - virt, unreloc helpers (in practice, real can use)
 * TRAMP_KVM      - KVM handlers that get put into real, unrelocated
 * EXC_COMMON_*   - virt, relocated common handlers
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
 *
 * The EXC handlers are given a name, and branch to name_common, or the
 * appropriate KVM or masking function. Vector handler verieties are as
 * follows:
 *
 * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception
 *
 * EXC_{REAL|VIRT}  - standard exception
 *
 * EXC_{REAL|VIRT}_suffix
 *     where _suffix is:
 *   - _MASKABLE               - maskable exception
 *   - _OOL                    - out of line with trampoline to common handler
 *   - _HV                     - HV exception
 *
 * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV
 *
 * The one unusual case is __EXC_REAL_OOL_HV_DIRECT, which is
 * an OOL vector that branches to a specified handler rather than the usual
 * trampoline that goes to common. It, and other underscore macros, should
 * be used with care.
 *
 * KVM handlers come in the following verieties:
 * TRAMP_KVM
 * TRAMP_KVM_SKIP
 * TRAMP_KVM_HV
 * TRAMP_KVM_HV_SKIP
 *
 * COMMON handlers come in the following verieties:
 * EXC_COMMON_BEGIN/END - used to open-code the handler
 * EXC_COMMON
 * EXC_COMMON_ASYNC
 * EXC_COMMON_HV
 *
 * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM
 * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers.
 */

218 219
#define EXC_REAL_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
220

221 222
#define EXC_REAL_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
223

224 225
#define EXC_VIRT_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
226

227 228
#define EXC_VIRT_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
229

230 231 232 233
#define EXC_COMMON_BEGIN(name)					\
	USE_TEXT_SECTION();					\
	.balign IFETCH_ALIGN_BYTES;				\
	.global name;						\
234
	_ASM_NOKPROBE_SYMBOL(name);				\
235
	DEFINE_FIXED_SYMBOL(name);				\
236 237 238
name:

#define TRAMP_REAL_BEGIN(name)					\
239 240 241 242
	FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)

#define TRAMP_VIRT_BEGIN(name)					\
	FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
243 244

#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
245
#define TRAMP_KVM_BEGIN(name)					\
246
	TRAMP_VIRT_BEGIN(name)
247 248 249 250
#else
#define TRAMP_KVM_BEGIN(name)
#endif

251 252 253
#define EXC_REAL_NONE(start, size)				\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start, size); \
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, start, size)
254

255 256 257
#define EXC_VIRT_NONE(start, size)				\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); \
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size);
258 259


260 261
#define EXC_REAL(name, start, size)					\
	EXC_REAL_BEGIN(name, start, size);				\
262
	STD_EXCEPTION_PSERIES(start, name##_common);			\
263
	EXC_REAL_END(name, start, size);
264

265 266
#define EXC_VIRT(name, start, size, realvec)				\
	EXC_VIRT_BEGIN(name, start, size);				\
267
	STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common);	\
268
	EXC_VIRT_END(name, start, size);
269

270 271
#define EXC_REAL_MASKABLE(name, start, size)				\
	EXC_REAL_BEGIN(name, start, size);				\
272
	MASKABLE_EXCEPTION_PSERIES(start, start, name##_common);	\
273
	EXC_REAL_END(name, start, size);
274

275 276
#define EXC_VIRT_MASKABLE(name, start, size, realvec)			\
	EXC_VIRT_BEGIN(name, start, size);				\
277
	MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \
278
	EXC_VIRT_END(name, start, size);
279

280 281
#define EXC_REAL_HV(name, start, size)					\
	EXC_REAL_BEGIN(name, start, size);				\
282
	STD_EXCEPTION_HV(start, start, name##_common);			\
283
	EXC_REAL_END(name, start, size);
284

285 286
#define EXC_VIRT_HV(name, start, size, realvec)				\
	EXC_VIRT_BEGIN(name, start, size);				\
287
	STD_RELON_EXCEPTION_HV(start, realvec, name##_common);		\
288
	EXC_VIRT_END(name, start, size);
289

290 291
#define __EXC_REAL_OOL(name, start, size)				\
	EXC_REAL_BEGIN(name, start, size);				\
292
	__OOL_EXCEPTION(start, label, tramp_real_##name);		\
293
	EXC_REAL_END(name, start, size);
294

295
#define __TRAMP_REAL_OOL(name, vec)					\
296 297 298
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_PSERIES_OOL(vec, name##_common);			\

299 300
#define EXC_REAL_OOL(name, start, size)					\
	__EXC_REAL_OOL(name, start, size);				\
301
	__TRAMP_REAL_OOL(name, start);
302

303 304
#define __EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
305

306
#define __TRAMP_REAL_OOL_MASKABLE(name, vec)				\
307 308 309
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common);		\

310 311
#define EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE(name, start, size);			\
312
	__TRAMP_REAL_OOL_MASKABLE(name, start);
313

314 315
#define __EXC_REAL_OOL_HV_DIRECT(name, start, size, handler)		\
	EXC_REAL_BEGIN(name, start, size);				\
316
	__OOL_EXCEPTION(start, label, handler);				\
317
	EXC_REAL_END(name, start, size);
318

319 320
#define __EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL(name, start, size);
321

322
#define __TRAMP_REAL_OOL_HV(name, vec)					\
323 324 325
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_HV_OOL(vec, name##_common);			\

326 327
#define EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL_HV(name, start, size);				\
328
	__TRAMP_REAL_OOL_HV(name, start);
329

330 331
#define __EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
332

333
#define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec)				\
334 335 336
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_HV_OOL(vec, name##_common);			\

337 338
#define EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE_HV(name, start, size);			\
339
	__TRAMP_REAL_OOL_MASKABLE_HV(name, start);
340

341 342
#define __EXC_VIRT_OOL(name, start, size)				\
	EXC_VIRT_BEGIN(name, start, size);				\
343
	__OOL_EXCEPTION(start, label, tramp_virt_##name);		\
344
	EXC_VIRT_END(name, start, size);
345

346 347
#define __TRAMP_VIRT_OOL(name, realvec)					\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
348 349
	STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

350 351
#define EXC_VIRT_OOL(name, start, size, realvec)			\
	__EXC_VIRT_OOL(name, start, size);				\
352
	__TRAMP_VIRT_OOL(name, realvec);
353

354 355
#define __EXC_VIRT_OOL_MASKABLE(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
356

357 358
#define __TRAMP_VIRT_OOL_MASKABLE(name, realvec)			\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
359 360
	MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

361 362
#define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec)		\
	__EXC_VIRT_OOL_MASKABLE(name, start, size);			\
363
	__TRAMP_VIRT_OOL_MASKABLE(name, realvec);
364

365 366
#define __EXC_VIRT_OOL_HV(name, start, size)				\
	__EXC_VIRT_OOL(name, start, size);
367

368 369
#define __TRAMP_VIRT_OOL_HV(name, realvec)				\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
370 371
	STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common);		\

372 373
#define EXC_VIRT_OOL_HV(name, start, size, realvec)			\
	__EXC_VIRT_OOL_HV(name, start, size);				\
374
	__TRAMP_VIRT_OOL_HV(name, realvec);
375

376 377
#define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
378

379 380
#define __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec)			\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
381 382
	MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common);	\

383 384
#define EXC_VIRT_OOL_MASKABLE_HV(name, start, size, realvec)		\
	__EXC_VIRT_OOL_MASKABLE_HV(name, start, size);			\
385
	__TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec);
386

387 388 389 390 391 392 393 394
#define TRAMP_KVM(area, n)						\
	TRAMP_KVM_BEGIN(do_kvm_##n);					\
	KVM_HANDLER(area, EXC_STD, n);					\

#define TRAMP_KVM_SKIP(area, n)						\
	TRAMP_KVM_BEGIN(do_kvm_##n);					\
	KVM_HANDLER_SKIP(area, EXC_STD, n);				\

395 396 397
/*
 * HV variant exceptions get the 0x2 bit added to their trap number.
 */
398 399 400 401 402 403 404 405
#define TRAMP_KVM_HV(area, n)						\
	TRAMP_KVM_BEGIN(do_kvm_H##n);					\
	KVM_HANDLER(area, EXC_HV, n + 0x2);				\

#define TRAMP_KVM_HV_SKIP(area, n)					\
	TRAMP_KVM_BEGIN(do_kvm_H##n);					\
	KVM_HANDLER_SKIP(area, EXC_HV, n + 0x2);			\

406 407
#define EXC_COMMON(name, realvec, hdlr)					\
	EXC_COMMON_BEGIN(name);						\
408 409
	STD_EXCEPTION_COMMON(realvec, name, hdlr);			\

410 411
#define EXC_COMMON_ASYNC(name, realvec, hdlr)				\
	EXC_COMMON_BEGIN(name);						\
412 413 414
	STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr);		\

#define EXC_COMMON_HV(name, realvec, hdlr)				\
415
	EXC_COMMON_BEGIN(name);						\
416 417 418
	STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr);		\

#endif	/* _ASM_POWERPC_HEAD_64_H */