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
 * TRAMP_VIRT_*   - virt, unreloc helpers (in practice, real can use)
 * TRAMP_KVM      - KVM handlers that get put into real, unrelocated
181
 * 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
 *
 * 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
 *
 * 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.
 */

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

415 416
#endif /* __ASSEMBLY__ */

417
#endif	/* _ASM_POWERPC_HEAD_64_H */