head-64.h 12.7 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 41 42 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
/*
 * 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

 * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address)
 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, end_address)
 * 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 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

#define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start)		\
	USE_FIXED_SECTION(sname);				\
	name##_start = (start);					\
	.if (start) < sname##_start;				\
	.error "Fixed section underflow";			\
	.abort;							\
	.endif;							\
	. = (start) - sname##_start;				\
	.global name;						\
name:

#define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, end)		\
	.if (end) > sname##_end;				\
	.error "Fixed section overflow";			\
	.abort;							\
	.endif;							\
	.if (. - name > end - name##_start);			\
	.error "Fixed entry overflow";				\
	.abort;							\
	.endif;							\
	. = ((end) - sname##_start);				\


/*
 * 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.
 *
 * EXC_REAL_*        - real, unrelocated exception vectors
 * EXC_VIRT_*        - virt (AIL), unrelocated exception vectors
 * TRAMP_REAL_*   - real, unrelocated helpers (virt can call these)
 * 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
 *
 * 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.
 */

194
#define EXC_REAL_BEGIN(name, start, end)			\
195
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start)
196

197 198
#define EXC_REAL_END(name, start, end)			\
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, end)
199 200

#define EXC_VIRT_BEGIN(name, start, end)			\
201
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start)
202

203 204
#define EXC_VIRT_END(name, start, end)			\
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, end)
205

206
#define EXC_COMMON_BEGIN(name)						\
207
	USE_TEXT_SECTION();						\
208
	.balign IFETCH_ALIGN_BYTES;					\
209
	.global name;							\
210
	DEFINE_FIXED_SYMBOL(name);					\
211 212 213
name:

#define TRAMP_REAL_BEGIN(name)					\
214 215 216 217
	FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)

#define TRAMP_VIRT_BEGIN(name)					\
	FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
218 219 220 221 222 223 224 225

#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
#define TRAMP_KVM_BEGIN(name)						\
	TRAMP_REAL_BEGIN(name)
#else
#define TRAMP_KVM_BEGIN(name)
#endif

226 227 228
#define EXC_REAL_NONE(start, end)				\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start); \
	FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, end)
229

230 231 232
#define EXC_VIRT_NONE(start, end)				\
	FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start); \
	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, end);
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273


#define EXC_REAL(name, start, end)				\
	EXC_REAL_BEGIN(name, start, end);			\
	STD_EXCEPTION_PSERIES(start, name##_common);			\
	EXC_REAL_END(name, start, end);

#define EXC_VIRT(name, start, end, realvec)			\
	EXC_VIRT_BEGIN(name, start, end);			\
	STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common);	\
	EXC_VIRT_END(name, start, end);

#define EXC_REAL_MASKABLE(name, start, end)			\
	EXC_REAL_BEGIN(name, start, end);			\
	MASKABLE_EXCEPTION_PSERIES(start, start, name##_common);	\
	EXC_REAL_END(name, start, end);

#define EXC_VIRT_MASKABLE(name, start, end, realvec)		\
	EXC_VIRT_BEGIN(name, start, end);			\
	MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \
	EXC_VIRT_END(name, start, end);

#define EXC_REAL_HV(name, start, end)			\
	EXC_REAL_BEGIN(name, start, end);			\
	STD_EXCEPTION_HV(start, start, name##_common);			\
	EXC_REAL_END(name, start, end);

#define EXC_VIRT_HV(name, start, end, realvec)		\
	EXC_VIRT_BEGIN(name, start, end);			\
	STD_RELON_EXCEPTION_HV(start, realvec, name##_common);		\
	EXC_VIRT_END(name, start, end);

#define __EXC_REAL_OOL(name, start, end)			\
	EXC_REAL_BEGIN(name, start, end);			\
	__OOL_EXCEPTION(start, label, tramp_real_##name);		\
	EXC_REAL_END(name, start, end);

#define __TRAMP_REAL_REAL_OOL(name, vec)				\
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_PSERIES_OOL(vec, name##_common);			\

274 275 276 277
#define EXC_REAL_OOL(name, start, end)			\
	__EXC_REAL_OOL(name, start, end);			\
	__TRAMP_REAL_REAL_OOL(name, start);

278 279 280 281 282 283 284
#define __EXC_REAL_OOL_MASKABLE(name, start, end)		\
	__EXC_REAL_OOL(name, start, end);

#define __TRAMP_REAL_REAL_OOL_MASKABLE(name, vec)			\
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common);		\

285 286 287 288
#define EXC_REAL_OOL_MASKABLE(name, start, end)		\
	__EXC_REAL_OOL_MASKABLE(name, start, end);		\
	__TRAMP_REAL_REAL_OOL_MASKABLE(name, start);

289 290 291 292 293 294 295 296 297 298 299 300
#define __EXC_REAL_OOL_HV_DIRECT(name, start, end, handler)	\
	EXC_REAL_BEGIN(name, start, end);			\
	__OOL_EXCEPTION(start, label, handler);				\
	EXC_REAL_END(name, start, end);

#define __EXC_REAL_OOL_HV(name, start, end)			\
	__EXC_REAL_OOL(name, start, end);

#define __TRAMP_REAL_REAL_OOL_HV(name, vec)				\
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	STD_EXCEPTION_HV_OOL(vec, name##_common);			\

301 302 303 304
#define EXC_REAL_OOL_HV(name, start, end)			\
	__EXC_REAL_OOL_HV(name, start, end);			\
	__TRAMP_REAL_REAL_OOL_HV(name, start);

305 306 307 308 309 310 311
#define __EXC_REAL_OOL_MASKABLE_HV(name, start, end)		\
	__EXC_REAL_OOL(name, start, end);

#define __TRAMP_REAL_REAL_OOL_MASKABLE_HV(name, vec)			\
	TRAMP_REAL_BEGIN(tramp_real_##name);				\
	MASKABLE_EXCEPTION_HV_OOL(vec, name##_common);			\

312 313 314 315
#define EXC_REAL_OOL_MASKABLE_HV(name, start, end)		\
	__EXC_REAL_OOL_MASKABLE_HV(name, start, end);	\
	__TRAMP_REAL_REAL_OOL_MASKABLE_HV(name, start);

316 317 318 319 320 321
#define __EXC_VIRT_OOL(name, start, end)			\
	EXC_VIRT_BEGIN(name, start, end);			\
	__OOL_EXCEPTION(start, label, tramp_virt_##name);		\
	EXC_VIRT_END(name, start, end);

#define __TRAMP_REAL_VIRT_OOL(name, realvec)				\
322
	TRAMP_VIRT_BEGIN(tramp_virt_##name);			\
323 324
	STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

325 326 327 328
#define EXC_VIRT_OOL(name, start, end, realvec)		\
	__EXC_VIRT_OOL(name, start, end);			\
	__TRAMP_REAL_VIRT_OOL(name, realvec);

329 330 331 332
#define __EXC_VIRT_OOL_MASKABLE(name, start, end)		\
	__EXC_VIRT_OOL(name, start, end);

#define __TRAMP_REAL_VIRT_OOL_MASKABLE(name, realvec)		\
333
	TRAMP_VIRT_BEGIN(tramp_virt_##name);			\
334 335
	MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common);	\

336 337 338 339
#define EXC_VIRT_OOL_MASKABLE(name, start, end, realvec)	\
	__EXC_VIRT_OOL_MASKABLE(name, start, end);		\
	__TRAMP_REAL_VIRT_OOL_MASKABLE(name, realvec);

340 341 342 343
#define __EXC_VIRT_OOL_HV(name, start, end)			\
	__EXC_VIRT_OOL(name, start, end);

#define __TRAMP_REAL_VIRT_OOL_HV(name, realvec)			\
344
	TRAMP_VIRT_BEGIN(tramp_virt_##name);			\
345 346
	STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common);		\

347 348 349 350
#define EXC_VIRT_OOL_HV(name, start, end, realvec)		\
	__EXC_VIRT_OOL_HV(name, start, end);			\
	__TRAMP_REAL_VIRT_OOL_HV(name, realvec);

351 352 353 354
#define __EXC_VIRT_OOL_MASKABLE_HV(name, start, end)		\
	__EXC_VIRT_OOL(name, start, end);

#define __TRAMP_REAL_VIRT_OOL_MASKABLE_HV(name, realvec)		\
355
	TRAMP_VIRT_BEGIN(tramp_virt_##name);			\
356 357
	MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common);	\

358 359 360 361
#define EXC_VIRT_OOL_MASKABLE_HV(name, start, end, realvec)	\
	__EXC_VIRT_OOL_MASKABLE_HV(name, start, end);	\
	__TRAMP_REAL_VIRT_OOL_MASKABLE_HV(name, realvec);

362 363 364 365 366 367 368 369
#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);				\

370 371 372
/*
 * HV variant exceptions get the 0x2 bit added to their trap number.
 */
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
#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);			\

#define EXC_COMMON(name, realvec, hdlr)				\
	EXC_COMMON_BEGIN(name);					\
	STD_EXCEPTION_COMMON(realvec, name, hdlr);			\

#define EXC_COMMON_ASYNC(name, realvec, hdlr)			\
	EXC_COMMON_BEGIN(name);					\
	STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr);		\

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

#endif	/* _ASM_POWERPC_HEAD_64_H */