1 #ifndef _ASM_POWERPC_HEAD_64_H 2 #define _ASM_POWERPC_HEAD_64_H 3 4 #include <asm/cache.h> 5 6 /* 7 * We can't do CPP stringification and concatination directly into the section 8 * name for some reason, so these macros can do it for us. 9 */ 10 .macro define_ftsec name 11 .section ".head.text.\name\()","ax",@progbits 12 .endm 13 .macro define_data_ftsec name 14 .section ".head.data.\name\()","a",@progbits 15 .endm 16 .macro use_ftsec name 17 .section ".head.text.\name\()" 18 .endm 19 20 /* 21 * Fixed (location) sections are used by opening fixed sections and emitting 22 * fixed section entries into them before closing them. Multiple fixed sections 23 * can be open at any time. 24 * 25 * Each fixed section created in a .S file must have corresponding linkage 26 * directives including location, added to arch/powerpc/kernel/vmlinux.lds.S 27 * 28 * For each fixed section, code is generated into it in the order which it 29 * appears in the source. Fixed section entries can be placed at a fixed 30 * location within the section using _LOCATION postifx variants. These must 31 * be ordered according to their relative placements within the section. 32 * 33 * OPEN_FIXED_SECTION(section_name, start_address, end_address) 34 * FIXED_SECTION_ENTRY_BEGIN(section_name, label1) 35 * 36 * USE_FIXED_SECTION(section_name) 37 * label3: 38 * li r10,128 39 * mv r11,r10 40 41 * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size) 42 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size) 43 * CLOSE_FIXED_SECTION(section_name) 44 * 45 * ZERO_FIXED_SECTION can be used to emit zeroed data. 46 * 47 * Troubleshooting: 48 * - If the build dies with "Error: attempt to move .org backwards" at 49 * CLOSE_FIXED_SECTION() or elsewhere, there may be something 50 * unexpected being added there. Remove the '. = x_len' line, rebuild, and 51 * check what is pushing the section down. 52 * - If the build dies in linking, check arch/powerpc/kernel/vmlinux.lds.S 53 * for instructions. 54 * - If the kernel crashes or hangs in very early boot, it could be linker 55 * stubs at the start of the main text. 56 */ 57 58 #define OPEN_FIXED_SECTION(sname, start, end) \ 59 sname##_start = (start); \ 60 sname##_end = (end); \ 61 sname##_len = (end) - (start); \ 62 define_ftsec sname; \ 63 . = 0x0; \ 64 start_##sname: 65 66 #define OPEN_TEXT_SECTION(start) \ 67 text_start = (start); \ 68 .section ".text","ax",@progbits; \ 69 . = 0x0; \ 70 start_text: 71 72 #define ZERO_FIXED_SECTION(sname, start, end) \ 73 sname##_start = (start); \ 74 sname##_end = (end); \ 75 sname##_len = (end) - (start); \ 76 define_data_ftsec sname; \ 77 . = 0x0; \ 78 . = sname##_len; 79 80 #define USE_FIXED_SECTION(sname) \ 81 fs_label = start_##sname; \ 82 fs_start = sname##_start; \ 83 use_ftsec sname; 84 85 #define USE_TEXT_SECTION() \ 86 fs_label = start_text; \ 87 fs_start = text_start; \ 88 .text 89 90 #define CLOSE_FIXED_SECTION(sname) \ 91 USE_FIXED_SECTION(sname); \ 92 . = sname##_len; \ 93 end_##sname: 94 95 96 #define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \ 97 USE_FIXED_SECTION(sname); \ 98 .balign __align; \ 99 .global name; \ 100 name: 101 102 #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 USE_FIXED_SECTION(sname); \ 107 name##_start = (start); \ 108 .if ((start) % (size) != 0); \ 109 .error "Fixed section exception vector misalignment"; \ 110 .endif; \ 111 .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100); \ 112 .error "Fixed section exception vector bad size"; \ 113 .endif; \ 114 .if (start) < sname##_start; \ 115 .error "Fixed section underflow"; \ 116 .abort; \ 117 .endif; \ 118 . = (start) - sname##_start; \ 119 .global name; \ 120 name: 121 122 #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \ 123 .if (start) + (size) > sname##_end; \ 124 .error "Fixed section overflow"; \ 125 .abort; \ 126 .endif; \ 127 .if (. - name > (start) + (size) - name##_start); \ 128 .error "Fixed entry overflow"; \ 129 .abort; \ 130 .endif; \ 131 . = ((start) + (size) - sname##_start); \ 132 133 134 /* 135 * These macros are used to change symbols in other fixed sections to be 136 * absolute or related to our current fixed section. 137 * 138 * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the 139 * absolute address of a symbol within a fixed section, from any section. 140 * 141 * - ABS_ADDR is used to find the absolute address of any symbol, from within 142 * a fixed section. 143 */ 144 #define DEFINE_FIXED_SYMBOL(label) \ 145 label##_absolute = (label - fs_label + fs_start) 146 147 #define FIXED_SYMBOL_ABS_ADDR(label) \ 148 (label##_absolute) 149 150 #define ABS_ADDR(label) (label - fs_label + fs_start) 151 152 /* 153 * Following are the BOOK3S exception handler helper macros. 154 * Handlers come in a number of types, and each type has a number of varieties. 155 * 156 * EXC_REAL_* - real, unrelocated exception vectors 157 * EXC_VIRT_* - virt (AIL), unrelocated exception vectors 158 * TRAMP_REAL_* - real, unrelocated helpers (virt can call these) 159 * TRAMP_VIRT_* - virt, unreloc helpers (in practice, real can use) 160 * TRAMP_KVM - KVM handlers that get put into real, unrelocated 161 * EXC_COMMON_* - virt, relocated common handlers 162 * 163 * The EXC handlers are given a name, and branch to name_common, or the 164 * appropriate KVM or masking function. Vector handler verieties are as 165 * follows: 166 * 167 * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception 168 * 169 * EXC_{REAL|VIRT} - standard exception 170 * 171 * EXC_{REAL|VIRT}_suffix 172 * where _suffix is: 173 * - _MASKABLE - maskable exception 174 * - _OOL - out of line with trampoline to common handler 175 * - _HV - HV exception 176 * 177 * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV 178 * 179 * The one unusual case is __EXC_REAL_OOL_HV_DIRECT, which is 180 * an OOL vector that branches to a specified handler rather than the usual 181 * trampoline that goes to common. It, and other underscore macros, should 182 * be used with care. 183 * 184 * KVM handlers come in the following verieties: 185 * TRAMP_KVM 186 * TRAMP_KVM_SKIP 187 * TRAMP_KVM_HV 188 * TRAMP_KVM_HV_SKIP 189 * 190 * COMMON handlers come in the following verieties: 191 * EXC_COMMON_BEGIN/END - used to open-code the handler 192 * EXC_COMMON 193 * EXC_COMMON_ASYNC 194 * EXC_COMMON_HV 195 * 196 * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM 197 * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers. 198 */ 199 200 #define EXC_REAL_BEGIN(name, start, size) \ 201 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size) 202 203 #define EXC_REAL_END(name, start, size) \ 204 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size) 205 206 #define EXC_VIRT_BEGIN(name, start, size) \ 207 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size) 208 209 #define EXC_VIRT_END(name, start, size) \ 210 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size) 211 212 #define EXC_COMMON_BEGIN(name) \ 213 USE_TEXT_SECTION(); \ 214 .balign IFETCH_ALIGN_BYTES; \ 215 .global name; \ 216 DEFINE_FIXED_SYMBOL(name); \ 217 name: 218 219 #define TRAMP_REAL_BEGIN(name) \ 220 FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name) 221 222 #define TRAMP_VIRT_BEGIN(name) \ 223 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 #else 229 #define TRAMP_KVM_BEGIN(name) 230 #endif 231 232 #define EXC_REAL_NONE(start, size) \ 233 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start, size); \ 234 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, start, size) 235 236 #define EXC_VIRT_NONE(start, size) \ 237 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); \ 238 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); 239 240 241 #define EXC_REAL(name, start, size) \ 242 EXC_REAL_BEGIN(name, start, size); \ 243 STD_EXCEPTION_PSERIES(start, name##_common); \ 244 EXC_REAL_END(name, start, size); 245 246 #define EXC_VIRT(name, start, size, realvec) \ 247 EXC_VIRT_BEGIN(name, start, size); \ 248 STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \ 249 EXC_VIRT_END(name, start, size); 250 251 #define EXC_REAL_MASKABLE(name, start, size) \ 252 EXC_REAL_BEGIN(name, start, size); \ 253 MASKABLE_EXCEPTION_PSERIES(start, start, name##_common); \ 254 EXC_REAL_END(name, start, size); 255 256 #define EXC_VIRT_MASKABLE(name, start, size, realvec) \ 257 EXC_VIRT_BEGIN(name, start, size); \ 258 MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \ 259 EXC_VIRT_END(name, start, size); 260 261 #define EXC_REAL_HV(name, start, size) \ 262 EXC_REAL_BEGIN(name, start, size); \ 263 STD_EXCEPTION_HV(start, start, name##_common); \ 264 EXC_REAL_END(name, start, size); 265 266 #define EXC_VIRT_HV(name, start, size, realvec) \ 267 EXC_VIRT_BEGIN(name, start, size); \ 268 STD_RELON_EXCEPTION_HV(start, realvec, name##_common); \ 269 EXC_VIRT_END(name, start, size); 270 271 #define __EXC_REAL_OOL(name, start, size) \ 272 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 TRAMP_REAL_BEGIN(tramp_real_##name); \ 278 STD_EXCEPTION_PSERIES_OOL(vec, name##_common); \ 279 280 #define EXC_REAL_OOL(name, start, size) \ 281 __EXC_REAL_OOL(name, start, size); \ 282 __TRAMP_REAL_OOL(name, start); 283 284 #define __EXC_REAL_OOL_MASKABLE(name, start, size) \ 285 __EXC_REAL_OOL(name, start, size); 286 287 #define __TRAMP_REAL_OOL_MASKABLE(name, vec) \ 288 TRAMP_REAL_BEGIN(tramp_real_##name); \ 289 MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common); \ 290 291 #define EXC_REAL_OOL_MASKABLE(name, start, size) \ 292 __EXC_REAL_OOL_MASKABLE(name, start, size); \ 293 __TRAMP_REAL_OOL_MASKABLE(name, start); 294 295 #define __EXC_REAL_OOL_HV_DIRECT(name, start, size, handler) \ 296 EXC_REAL_BEGIN(name, start, size); \ 297 __OOL_EXCEPTION(start, label, handler); \ 298 EXC_REAL_END(name, start, size); 299 300 #define __EXC_REAL_OOL_HV(name, start, size) \ 301 __EXC_REAL_OOL(name, start, size); 302 303 #define __TRAMP_REAL_OOL_HV(name, vec) \ 304 TRAMP_REAL_BEGIN(tramp_real_##name); \ 305 STD_EXCEPTION_HV_OOL(vec, name##_common); \ 306 307 #define EXC_REAL_OOL_HV(name, start, size) \ 308 __EXC_REAL_OOL_HV(name, start, size); \ 309 __TRAMP_REAL_OOL_HV(name, start); 310 311 #define __EXC_REAL_OOL_MASKABLE_HV(name, start, size) \ 312 __EXC_REAL_OOL(name, start, size); 313 314 #define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec) \ 315 TRAMP_REAL_BEGIN(tramp_real_##name); \ 316 MASKABLE_EXCEPTION_HV_OOL(vec, name##_common); \ 317 318 #define EXC_REAL_OOL_MASKABLE_HV(name, start, size) \ 319 __EXC_REAL_OOL_MASKABLE_HV(name, start, size); \ 320 __TRAMP_REAL_OOL_MASKABLE_HV(name, start); 321 322 #define __EXC_VIRT_OOL(name, start, size) \ 323 EXC_VIRT_BEGIN(name, start, size); \ 324 __OOL_EXCEPTION(start, label, tramp_virt_##name); \ 325 EXC_VIRT_END(name, start, size); 326 327 #define __TRAMP_VIRT_OOL(name, realvec) \ 328 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 329 STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \ 330 331 #define EXC_VIRT_OOL(name, start, size, realvec) \ 332 __EXC_VIRT_OOL(name, start, size); \ 333 __TRAMP_VIRT_OOL(name, realvec); 334 335 #define __EXC_VIRT_OOL_MASKABLE(name, start, size) \ 336 __EXC_VIRT_OOL(name, start, size); 337 338 #define __TRAMP_VIRT_OOL_MASKABLE(name, realvec) \ 339 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 340 MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \ 341 342 #define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec) \ 343 __EXC_VIRT_OOL_MASKABLE(name, start, size); \ 344 __TRAMP_VIRT_OOL_MASKABLE(name, realvec); 345 346 #define __EXC_VIRT_OOL_HV(name, start, size) \ 347 __EXC_VIRT_OOL(name, start, size); 348 349 #define __TRAMP_VIRT_OOL_HV(name, realvec) \ 350 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 351 STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \ 352 353 #define EXC_VIRT_OOL_HV(name, start, size, realvec) \ 354 __EXC_VIRT_OOL_HV(name, start, size); \ 355 __TRAMP_VIRT_OOL_HV(name, realvec); 356 357 #define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size) \ 358 __EXC_VIRT_OOL(name, start, size); 359 360 #define __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec) \ 361 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 362 MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \ 363 364 #define EXC_VIRT_OOL_MASKABLE_HV(name, start, size, realvec) \ 365 __EXC_VIRT_OOL_MASKABLE_HV(name, start, size); \ 366 __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec); 367 368 #define TRAMP_KVM(area, n) \ 369 TRAMP_KVM_BEGIN(do_kvm_##n); \ 370 KVM_HANDLER(area, EXC_STD, n); \ 371 372 #define TRAMP_KVM_SKIP(area, n) \ 373 TRAMP_KVM_BEGIN(do_kvm_##n); \ 374 KVM_HANDLER_SKIP(area, EXC_STD, n); \ 375 376 /* 377 * HV variant exceptions get the 0x2 bit added to their trap number. 378 */ 379 #define TRAMP_KVM_HV(area, n) \ 380 TRAMP_KVM_BEGIN(do_kvm_H##n); \ 381 KVM_HANDLER(area, EXC_HV, n + 0x2); \ 382 383 #define TRAMP_KVM_HV_SKIP(area, n) \ 384 TRAMP_KVM_BEGIN(do_kvm_H##n); \ 385 KVM_HANDLER_SKIP(area, EXC_HV, n + 0x2); \ 386 387 #define EXC_COMMON(name, realvec, hdlr) \ 388 EXC_COMMON_BEGIN(name); \ 389 STD_EXCEPTION_COMMON(realvec, name, hdlr); \ 390 391 #define EXC_COMMON_ASYNC(name, realvec, hdlr) \ 392 EXC_COMMON_BEGIN(name); \ 393 STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr); \ 394 395 #define EXC_COMMON_HV(name, realvec, hdlr) \ 396 EXC_COMMON_BEGIN(name); \ 397 STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr); \ 398 399 #endif /* _ASM_POWERPC_HEAD_64_H */ 400