head-64.h 13.9 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4 5 6
#ifndef _ASM_POWERPC_HEAD_64_H
#define _ASM_POWERPC_HEAD_64_H

#include <asm/cache.h>

7
#ifdef __ASSEMBLY__
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 41 42
/*
 * 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

43 44
 * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size)
 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size)
45 46 47 48 49 50 51 52 53
 * 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.
54 55
 * - If the build dies in linking, check arch/powerpc/tools/head_check.sh
 *   comments.
56 57 58 59 60 61 62 63 64 65 66 67
 * - 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:

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
/*
 * .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
85 86 87 88 89
#define OPEN_TEXT_SECTION(start)				\
	text_start = (start);					\
	.section ".text","ax",@progbits;			\
	. = 0x0;						\
start_text:
90
#endif
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 116 117

#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);				\
118
	.balign __align;					\
119 120 121 122
	.global name;						\
name:

#define FIXED_SECTION_ENTRY_BEGIN(sname, name)			\
123
	__FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
124

125
#define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \
126 127
	USE_FIXED_SECTION(sname);				\
	name##_start = (start);					\
128 129 130 131 132 133
	.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;							\
134 135 136 137 138 139 140 141
	.if (start) < sname##_start;				\
	.error "Fixed section underflow";			\
	.abort;							\
	.endif;							\
	. = (start) - sname##_start;				\
	.global name;						\
name:

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


/*
 * 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.
 *
176 177
 * EXC_REAL_*     - real, unrelocated exception vectors
 * EXC_VIRT_*     - virt (AIL), unrelocated exception vectors
178
 * TRAMP_REAL_*   - real, unrelocated helpers (virt can call these)
179 180 181
 * 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
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 218 219
 *
 * 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.
 */

220 221
#define EXC_REAL_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
222

223 224
#define EXC_REAL_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
225

226 227
#define EXC_VIRT_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
228

229 230
#define EXC_VIRT_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
231

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

#define TRAMP_REAL_BEGIN(name)					\
241 242 243 244
	FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)

#define TRAMP_VIRT_BEGIN(name)					\
	FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
245 246

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

253 254 255
#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)
256

257 258 259
#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);
260 261


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

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

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

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

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

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

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

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

301 302
#define EXC_REAL_OOL(name, start, size)					\
	__EXC_REAL_OOL(name, start, size);				\
303
	__TRAMP_REAL_OOL(name, start);
304

305 306
#define __EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
307

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

312 313
#define EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE(name, start, size);			\
314
	__TRAMP_REAL_OOL_MASKABLE(name, start);
315

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

321 322
#define __EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL(name, start, size);
323

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

328 329
#define EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL_HV(name, start, size);				\
330
	__TRAMP_REAL_OOL_HV(name, start);
331

332 333
#define __EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
334

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

339 340
#define EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE_HV(name, start, size);			\
341
	__TRAMP_REAL_OOL_MASKABLE_HV(name, start);
342

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

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

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

356 357
#define __EXC_VIRT_OOL_MASKABLE(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
358

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

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

367 368
#define __EXC_VIRT_OOL_HV(name, start, size)				\
	__EXC_VIRT_OOL(name, start, size);
369

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

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

378 379
#define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
380

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

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

389 390 391 392 393 394 395 396
#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);				\

397 398 399
/*
 * HV variant exceptions get the 0x2 bit added to their trap number.
 */
400 401 402 403 404 405 406 407
#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);			\

408 409
#define EXC_COMMON(name, realvec, hdlr)					\
	EXC_COMMON_BEGIN(name);						\
410 411
	STD_EXCEPTION_COMMON(realvec, name, hdlr);			\

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

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

420 421
#endif /* __ASSEMBLY__ */

422
#endif	/* _ASM_POWERPC_HEAD_64_H */