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) 42 * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, end_address) 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 .align __align; \ 99 .global name; \ 100 name: 101 102 #define FIXED_SECTION_ENTRY_BEGIN(sname, name) \ 103 __FIXED_SECTION_ENTRY_BEGIN(sname, name, 0) 104 105 #define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start) \ 106 USE_FIXED_SECTION(sname); \ 107 name##_start = (start); \ 108 .if (start) < sname##_start; \ 109 .error "Fixed section underflow"; \ 110 .abort; \ 111 .endif; \ 112 . = (start) - sname##_start; \ 113 .global name; \ 114 name: 115 116 #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, end) \ 117 .if (end) > sname##_end; \ 118 .error "Fixed section overflow"; \ 119 .abort; \ 120 .endif; \ 121 .if (. - name > end - name##_start); \ 122 .error "Fixed entry overflow"; \ 123 .abort; \ 124 .endif; \ 125 . = ((end) - sname##_start); \ 126 127 128 /* 129 * These macros are used to change symbols in other fixed sections to be 130 * absolute or related to our current fixed section. 131 * 132 * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the 133 * absolute address of a symbol within a fixed section, from any section. 134 * 135 * - ABS_ADDR is used to find the absolute address of any symbol, from within 136 * a fixed section. 137 */ 138 #define DEFINE_FIXED_SYMBOL(label) \ 139 label##_absolute = (label - fs_label + fs_start) 140 141 #define FIXED_SYMBOL_ABS_ADDR(label) \ 142 (label##_absolute) 143 144 #define ABS_ADDR(label) (label - fs_label + fs_start) 145 146 /* 147 * Following are the BOOK3S exception handler helper macros. 148 * Handlers come in a number of types, and each type has a number of varieties. 149 * 150 * EXC_REAL_* - real, unrelocated exception vectors 151 * EXC_VIRT_* - virt (AIL), unrelocated exception vectors 152 * TRAMP_REAL_* - real, unrelocated helpers (virt can call these) 153 * TRAMP_VIRT_* - virt, unreloc helpers (in practice, real can use) 154 * TRAMP_KVM - KVM handlers that get put into real, unrelocated 155 * EXC_COMMON_* - virt, relocated common handlers 156 * 157 * The EXC handlers are given a name, and branch to name_common, or the 158 * appropriate KVM or masking function. Vector handler verieties are as 159 * follows: 160 * 161 * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception 162 * 163 * EXC_{REAL|VIRT} - standard exception 164 * 165 * EXC_{REAL|VIRT}_suffix 166 * where _suffix is: 167 * - _MASKABLE - maskable exception 168 * - _OOL - out of line with trampoline to common handler 169 * - _HV - HV exception 170 * 171 * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV 172 * 173 * The one unusual case is __EXC_REAL_OOL_HV_DIRECT, which is 174 * an OOL vector that branches to a specified handler rather than the usual 175 * trampoline that goes to common. It, and other underscore macros, should 176 * be used with care. 177 * 178 * KVM handlers come in the following verieties: 179 * TRAMP_KVM 180 * TRAMP_KVM_SKIP 181 * TRAMP_KVM_HV 182 * TRAMP_KVM_HV_SKIP 183 * 184 * COMMON handlers come in the following verieties: 185 * EXC_COMMON_BEGIN/END - used to open-code the handler 186 * EXC_COMMON 187 * EXC_COMMON_ASYNC 188 * EXC_COMMON_HV 189 * 190 * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM 191 * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers. 192 */ 193 194 #define EXC_REAL_BEGIN(name, start, end) \ 195 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start) 196 197 #define EXC_REAL_END(name, start, end) \ 198 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 #define EXC_VIRT_END(name, start, end) \ 204 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, end) 205 206 #define EXC_COMMON_BEGIN(name) \ 207 USE_TEXT_SECTION(); \ 208 .align 7; \ 209 .global name; \ 210 DEFINE_FIXED_SYMBOL(name); \ 211 name: 212 213 #define TRAMP_REAL_BEGIN(name) \ 214 FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name) 215 216 #define TRAMP_VIRT_BEGIN(name) \ 217 FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name) 218 219 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER 220 #define TRAMP_KVM_BEGIN(name) \ 221 TRAMP_REAL_BEGIN(name) 222 #else 223 #define TRAMP_KVM_BEGIN(name) 224 #endif 225 226 #define EXC_REAL_NONE(start, end) \ 227 FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start); \ 228 FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, end) 229 230 #define EXC_VIRT_NONE(start, end) \ 231 FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start); \ 232 FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, end); 233 234 235 #define EXC_REAL(name, start, end) \ 236 EXC_REAL_BEGIN(name, start, end); \ 237 STD_EXCEPTION_PSERIES(start, name##_common); \ 238 EXC_REAL_END(name, start, end); 239 240 #define EXC_VIRT(name, start, end, realvec) \ 241 EXC_VIRT_BEGIN(name, start, end); \ 242 STD_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \ 243 EXC_VIRT_END(name, start, end); 244 245 #define EXC_REAL_MASKABLE(name, start, end) \ 246 EXC_REAL_BEGIN(name, start, end); \ 247 MASKABLE_EXCEPTION_PSERIES(start, start, name##_common); \ 248 EXC_REAL_END(name, start, end); 249 250 #define EXC_VIRT_MASKABLE(name, start, end, realvec) \ 251 EXC_VIRT_BEGIN(name, start, end); \ 252 MASKABLE_RELON_EXCEPTION_PSERIES(start, realvec, name##_common); \ 253 EXC_VIRT_END(name, start, end); 254 255 #define EXC_REAL_HV(name, start, end) \ 256 EXC_REAL_BEGIN(name, start, end); \ 257 STD_EXCEPTION_HV(start, start, name##_common); \ 258 EXC_REAL_END(name, start, end); 259 260 #define EXC_VIRT_HV(name, start, end, realvec) \ 261 EXC_VIRT_BEGIN(name, start, end); \ 262 STD_RELON_EXCEPTION_HV(start, realvec, name##_common); \ 263 EXC_VIRT_END(name, start, end); 264 265 #define __EXC_REAL_OOL(name, start, end) \ 266 EXC_REAL_BEGIN(name, start, end); \ 267 __OOL_EXCEPTION(start, label, tramp_real_##name); \ 268 EXC_REAL_END(name, start, end); 269 270 #define __TRAMP_REAL_REAL_OOL(name, vec) \ 271 TRAMP_REAL_BEGIN(tramp_real_##name); \ 272 STD_EXCEPTION_PSERIES_OOL(vec, name##_common); \ 273 274 #define EXC_REAL_OOL(name, start, end) \ 275 __EXC_REAL_OOL(name, start, end); \ 276 __TRAMP_REAL_REAL_OOL(name, start); 277 278 #define __EXC_REAL_OOL_MASKABLE(name, start, end) \ 279 __EXC_REAL_OOL(name, start, end); 280 281 #define __TRAMP_REAL_REAL_OOL_MASKABLE(name, vec) \ 282 TRAMP_REAL_BEGIN(tramp_real_##name); \ 283 MASKABLE_EXCEPTION_PSERIES_OOL(vec, name##_common); \ 284 285 #define EXC_REAL_OOL_MASKABLE(name, start, end) \ 286 __EXC_REAL_OOL_MASKABLE(name, start, end); \ 287 __TRAMP_REAL_REAL_OOL_MASKABLE(name, start); 288 289 #define __EXC_REAL_OOL_HV_DIRECT(name, start, end, handler) \ 290 EXC_REAL_BEGIN(name, start, end); \ 291 __OOL_EXCEPTION(start, label, handler); \ 292 EXC_REAL_END(name, start, end); 293 294 #define __EXC_REAL_OOL_HV(name, start, end) \ 295 __EXC_REAL_OOL(name, start, end); 296 297 #define __TRAMP_REAL_REAL_OOL_HV(name, vec) \ 298 TRAMP_REAL_BEGIN(tramp_real_##name); \ 299 STD_EXCEPTION_HV_OOL(vec, name##_common); \ 300 301 #define EXC_REAL_OOL_HV(name, start, end) \ 302 __EXC_REAL_OOL_HV(name, start, end); \ 303 __TRAMP_REAL_REAL_OOL_HV(name, start); 304 305 #define __EXC_REAL_OOL_MASKABLE_HV(name, start, end) \ 306 __EXC_REAL_OOL(name, start, end); 307 308 #define __TRAMP_REAL_REAL_OOL_MASKABLE_HV(name, vec) \ 309 TRAMP_REAL_BEGIN(tramp_real_##name); \ 310 MASKABLE_EXCEPTION_HV_OOL(vec, name##_common); \ 311 312 #define EXC_REAL_OOL_MASKABLE_HV(name, start, end) \ 313 __EXC_REAL_OOL_MASKABLE_HV(name, start, end); \ 314 __TRAMP_REAL_REAL_OOL_MASKABLE_HV(name, start); 315 316 #define __EXC_VIRT_OOL(name, start, end) \ 317 EXC_VIRT_BEGIN(name, start, end); \ 318 __OOL_EXCEPTION(start, label, tramp_virt_##name); \ 319 EXC_VIRT_END(name, start, end); 320 321 #define __TRAMP_REAL_VIRT_OOL(name, realvec) \ 322 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 323 STD_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \ 324 325 #define EXC_VIRT_OOL(name, start, end, realvec) \ 326 __EXC_VIRT_OOL(name, start, end); \ 327 __TRAMP_REAL_VIRT_OOL(name, realvec); 328 329 #define __EXC_VIRT_OOL_MASKABLE(name, start, end) \ 330 __EXC_VIRT_OOL(name, start, end); 331 332 #define __TRAMP_REAL_VIRT_OOL_MASKABLE(name, realvec) \ 333 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 334 MASKABLE_RELON_EXCEPTION_PSERIES_OOL(realvec, name##_common); \ 335 336 #define EXC_VIRT_OOL_MASKABLE(name, start, end, realvec) \ 337 __EXC_VIRT_OOL_MASKABLE(name, start, end); \ 338 __TRAMP_REAL_VIRT_OOL_MASKABLE(name, realvec); 339 340 #define __EXC_VIRT_OOL_HV(name, start, end) \ 341 __EXC_VIRT_OOL(name, start, end); 342 343 #define __TRAMP_REAL_VIRT_OOL_HV(name, realvec) \ 344 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 345 STD_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \ 346 347 #define EXC_VIRT_OOL_HV(name, start, end, realvec) \ 348 __EXC_VIRT_OOL_HV(name, start, end); \ 349 __TRAMP_REAL_VIRT_OOL_HV(name, realvec); 350 351 #define __EXC_VIRT_OOL_MASKABLE_HV(name, start, end) \ 352 __EXC_VIRT_OOL(name, start, end); 353 354 #define __TRAMP_REAL_VIRT_OOL_MASKABLE_HV(name, realvec) \ 355 TRAMP_VIRT_BEGIN(tramp_virt_##name); \ 356 MASKABLE_RELON_EXCEPTION_HV_OOL(realvec, name##_common); \ 357 358 #define EXC_VIRT_OOL_MASKABLE_HV(name, start, end, realvec) \ 359 __EXC_VIRT_OOL_MASKABLE_HV(name, start, end); \ 360 __TRAMP_REAL_VIRT_OOL_MASKABLE_HV(name, realvec); 361 362 #define TRAMP_KVM(area, n) \ 363 TRAMP_KVM_BEGIN(do_kvm_##n); \ 364 KVM_HANDLER(area, EXC_STD, n); \ 365 366 #define TRAMP_KVM_SKIP(area, n) \ 367 TRAMP_KVM_BEGIN(do_kvm_##n); \ 368 KVM_HANDLER_SKIP(area, EXC_STD, n); \ 369 370 /* 371 * HV variant exceptions get the 0x2 bit added to their trap number. 372 */ 373 #define TRAMP_KVM_HV(area, n) \ 374 TRAMP_KVM_BEGIN(do_kvm_H##n); \ 375 KVM_HANDLER(area, EXC_HV, n + 0x2); \ 376 377 #define TRAMP_KVM_HV_SKIP(area, n) \ 378 TRAMP_KVM_BEGIN(do_kvm_H##n); \ 379 KVM_HANDLER_SKIP(area, EXC_HV, n + 0x2); \ 380 381 #define EXC_COMMON(name, realvec, hdlr) \ 382 EXC_COMMON_BEGIN(name); \ 383 STD_EXCEPTION_COMMON(realvec, name, hdlr); \ 384 385 #define EXC_COMMON_ASYNC(name, realvec, hdlr) \ 386 EXC_COMMON_BEGIN(name); \ 387 STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr); \ 388 389 #define EXC_COMMON_HV(name, realvec, hdlr) \ 390 EXC_COMMON_BEGIN(name); \ 391 STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr); \ 392 393 #endif /* _ASM_POWERPC_HEAD_64_H */ 394