head-64.h 13.1 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
 * 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:

#define OPEN_TEXT_SECTION(start)				\
	text_start = (start);					\
	.section ".text","ax",@progbits;			\
	. = 0x0;						\
start_text:

#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);				\
98
	.balign __align;					\
99 100 101 102
	.global name;						\
name:

#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 107
	USE_FIXED_SECTION(sname);				\
	name##_start = (start);					\
108 109 110 111 112 113
	.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;							\
114 115 116 117 118 119 120 121
	.if (start) < sname##_start;				\
	.error "Fixed section underflow";			\
	.abort;							\
	.endif;							\
	. = (start) - sname##_start;				\
	.global name;						\
name:

122 123
#define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \
	.if (start) + (size) > sname##_end;			\
124 125 126
	.error "Fixed section overflow";			\
	.abort;							\
	.endif;							\
127
	.if (. - name > (start) + (size) - name##_start);	\
128 129 130
	.error "Fixed entry overflow";				\
	.abort;							\
	.endif;							\
131
	. = ((start) + (size) - sname##_start);			\
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155


/*
 * 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.
 *
156 157
 * EXC_REAL_*     - real, unrelocated exception vectors
 * EXC_VIRT_*     - virt (AIL), unrelocated exception vectors
158
 * TRAMP_REAL_*   - real, unrelocated helpers (virt can call these)
159 160 161
 * 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
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
 *
 * 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.
 */

200 201
#define EXC_REAL_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
202

203 204
#define EXC_REAL_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
205

206 207
#define EXC_VIRT_BEGIN(name, start, size)			\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
208

209 210
#define EXC_VIRT_END(name, start, size)				\
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
211

212 213 214 215 216
#define EXC_COMMON_BEGIN(name)					\
	USE_TEXT_SECTION();					\
	.balign IFETCH_ALIGN_BYTES;				\
	.global name;						\
	DEFINE_FIXED_SYMBOL(name);				\
217 218 219
name:

#define TRAMP_REAL_BEGIN(name)					\
220 221 222 223
	FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)

#define TRAMP_VIRT_BEGIN(name)					\
	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 229 230 231
#else
#define TRAMP_KVM_BEGIN(name)
#endif

232 233 234
#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)
235

236 237 238
#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);
239 240


241 242
#define EXC_REAL(name, start, size)					\
	EXC_REAL_BEGIN(name, start, size);				\
243
	STD_EXCEPTION_PSERIES(start, name##_common);			\
244
	EXC_REAL_END(name, start, size);
245

246 247
#define EXC_VIRT(name, start, size, realvec)				\
	EXC_VIRT_BEGIN(name, start, size);				\
248
	STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common);	\
249
	EXC_VIRT_END(name, start, size);
250

251 252
#define EXC_REAL_MASKABLE(name, start, size)				\
	EXC_REAL_BEGIN(name, start, size);				\
253
	MASKABLE_EXCEPTION_PSERIES(start, start, name##_common);	\
254
	EXC_REAL_END(name, start, size);
255

256 257
#define EXC_VIRT_MASKABLE(name, start, size, realvec)			\
	EXC_VIRT_BEGIN(name, start, size);				\
258
	MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \
259
	EXC_VIRT_END(name, start, size);
260

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

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

271 272
#define __EXC_REAL_OOL(name, start, size)				\
	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 278 279
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_PSERIES_OOL(vec, name##_common);			\

280 281
#define EXC_REAL_OOL(name, start, size)					\
	__EXC_REAL_OOL(name, start, size);				\
282
	__TRAMP_REAL_OOL(name, start);
283

284 285
#define __EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
286

287
#define __TRAMP_REAL_OOL_MASKABLE(name, vec)				\
288 289 290
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common);		\

291 292
#define EXC_REAL_OOL_MASKABLE(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE(name, start, size);			\
293
	__TRAMP_REAL_OOL_MASKABLE(name, start);
294

295 296
#define __EXC_REAL_OOL_HV_DIRECT(name, start, size, handler)		\
	EXC_REAL_BEGIN(name, start, size);				\
297
	__OOL_EXCEPTION(start, label, handler);				\
298
	EXC_REAL_END(name, start, size);
299

300 301
#define __EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL(name, start, size);
302

303
#define __TRAMP_REAL_OOL_HV(name, vec)					\
304 305 306
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_HV_OOL(vec, name##_common);			\

307 308
#define EXC_REAL_OOL_HV(name, start, size)				\
	__EXC_REAL_OOL_HV(name, start, size);				\
309
	__TRAMP_REAL_OOL_HV(name, start);
310

311 312
#define __EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL(name, start, size);
313

314
#define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec)				\
315 316 317
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_HV_OOL(vec, name##_common);			\

318 319
#define EXC_REAL_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_REAL_OOL_MASKABLE_HV(name, start, size);			\
320
	__TRAMP_REAL_OOL_MASKABLE_HV(name, start);
321

322 323
#define __EXC_VIRT_OOL(name, start, size)				\
	EXC_VIRT_BEGIN(name, start, size);				\
324
	__OOL_EXCEPTION(start, label, tramp_virt_##name);		\
325
	EXC_VIRT_END(name, start, size);
326

327 328
#define __TRAMP_VIRT_OOL(name, realvec)					\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
329 330
	STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

331 332
#define EXC_VIRT_OOL(name, start, size, realvec)			\
	__EXC_VIRT_OOL(name, start, size);				\
333
	__TRAMP_VIRT_OOL(name, realvec);
334

335 336
#define __EXC_VIRT_OOL_MASKABLE(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
337

338 339
#define __TRAMP_VIRT_OOL_MASKABLE(name, realvec)			\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
340 341
	MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

342 343
#define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec)		\
	__EXC_VIRT_OOL_MASKABLE(name, start, size);			\
344
	__TRAMP_VIRT_OOL_MASKABLE(name, realvec);
345

346 347
#define __EXC_VIRT_OOL_HV(name, start, size)				\
	__EXC_VIRT_OOL(name, start, size);
348

349 350
#define __TRAMP_VIRT_OOL_HV(name, realvec)				\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
351 352
	STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common);		\

353 354
#define EXC_VIRT_OOL_HV(name, start, size, realvec)			\
	__EXC_VIRT_OOL_HV(name, start, size);				\
355
	__TRAMP_VIRT_OOL_HV(name, realvec);
356

357 358
#define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size)			\
	__EXC_VIRT_OOL(name, start, size);
359

360 361
#define __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec)			\
	TRAMP_VIRT_BEGIN(tramp_virt_##name);				\
362 363
	MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common);	\

364 365
#define EXC_VIRT_OOL_MASKABLE_HV(name, start, size, realvec)		\
	__EXC_VIRT_OOL_MASKABLE_HV(name, start, size);			\
366
	__TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec);
367

368 369 370 371 372 373 374 375
#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);				\

376 377 378
/*
 * HV variant exceptions get the 0x2 bit added to their trap number.
 */
379 380 381 382 383 384 385 386
#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);			\

387 388
#define EXC_COMMON(name, realvec, hdlr)					\
	EXC_COMMON_BEGIN(name);						\
389 390
	STD_EXCEPTION_COMMON(realvec, name, hdlr);			\

391 392
#define EXC_COMMON_ASYNC(name, realvec, hdlr)				\
	EXC_COMMON_BEGIN(name);						\
393 394 395
	STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr);		\

#define EXC_COMMON_HV(name, realvec, hdlr)				\
396
	EXC_COMMON_BEGIN(name);						\
397 398 399
	STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr);		\

#endif	/* _ASM_POWERPC_HEAD_64_H */