1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef _ASM_POWERPC_HEAD_64_H 3*4882a593Smuzhiyun #define _ASM_POWERPC_HEAD_64_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun #include <asm/cache.h> 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun #ifdef __ASSEMBLY__ 8*4882a593Smuzhiyun /* 9*4882a593Smuzhiyun * We can't do CPP stringification and concatination directly into the section 10*4882a593Smuzhiyun * name for some reason, so these macros can do it for us. 11*4882a593Smuzhiyun */ 12*4882a593Smuzhiyun .macro define_ftsec name 13*4882a593Smuzhiyun .section ".head.text.\name\()","ax",@progbits 14*4882a593Smuzhiyun .endm 15*4882a593Smuzhiyun .macro define_data_ftsec name 16*4882a593Smuzhiyun .section ".head.data.\name\()","a",@progbits 17*4882a593Smuzhiyun .endm 18*4882a593Smuzhiyun .macro use_ftsec name 19*4882a593Smuzhiyun .section ".head.text.\name\()" 20*4882a593Smuzhiyun .endm 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun /* 23*4882a593Smuzhiyun * Fixed (location) sections are used by opening fixed sections and emitting 24*4882a593Smuzhiyun * fixed section entries into them before closing them. Multiple fixed sections 25*4882a593Smuzhiyun * can be open at any time. 26*4882a593Smuzhiyun * 27*4882a593Smuzhiyun * Each fixed section created in a .S file must have corresponding linkage 28*4882a593Smuzhiyun * directives including location, added to arch/powerpc/kernel/vmlinux.lds.S 29*4882a593Smuzhiyun * 30*4882a593Smuzhiyun * For each fixed section, code is generated into it in the order which it 31*4882a593Smuzhiyun * appears in the source. Fixed section entries can be placed at a fixed 32*4882a593Smuzhiyun * location within the section using _LOCATION postifx variants. These must 33*4882a593Smuzhiyun * be ordered according to their relative placements within the section. 34*4882a593Smuzhiyun * 35*4882a593Smuzhiyun * OPEN_FIXED_SECTION(section_name, start_address, end_address) 36*4882a593Smuzhiyun * FIXED_SECTION_ENTRY_BEGIN(section_name, label1) 37*4882a593Smuzhiyun * 38*4882a593Smuzhiyun * USE_FIXED_SECTION(section_name) 39*4882a593Smuzhiyun * label3: 40*4882a593Smuzhiyun * li r10,128 41*4882a593Smuzhiyun * mv r11,r10 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size) 44*4882a593Smuzhiyun * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size) 45*4882a593Smuzhiyun * CLOSE_FIXED_SECTION(section_name) 46*4882a593Smuzhiyun * 47*4882a593Smuzhiyun * ZERO_FIXED_SECTION can be used to emit zeroed data. 48*4882a593Smuzhiyun * 49*4882a593Smuzhiyun * Troubleshooting: 50*4882a593Smuzhiyun * - If the build dies with "Error: attempt to move .org backwards" at 51*4882a593Smuzhiyun * CLOSE_FIXED_SECTION() or elsewhere, there may be something 52*4882a593Smuzhiyun * unexpected being added there. Remove the '. = x_len' line, rebuild, and 53*4882a593Smuzhiyun * check what is pushing the section down. 54*4882a593Smuzhiyun * - If the build dies in linking, check arch/powerpc/tools/head_check.sh 55*4882a593Smuzhiyun * comments. 56*4882a593Smuzhiyun * - If the kernel crashes or hangs in very early boot, it could be linker 57*4882a593Smuzhiyun * stubs at the start of the main text. 58*4882a593Smuzhiyun */ 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun #define OPEN_FIXED_SECTION(sname, start, end) \ 61*4882a593Smuzhiyun sname##_start = (start); \ 62*4882a593Smuzhiyun sname##_end = (end); \ 63*4882a593Smuzhiyun sname##_len = (end) - (start); \ 64*4882a593Smuzhiyun define_ftsec sname; \ 65*4882a593Smuzhiyun . = 0x0; \ 66*4882a593Smuzhiyun start_##sname: 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun /* 69*4882a593Smuzhiyun * .linker_stub_catch section is used to catch linker stubs from being 70*4882a593Smuzhiyun * inserted in our .text section, above the start_text label (which breaks 71*4882a593Smuzhiyun * the ABS_ADDR calculation). See kernel/vmlinux.lds.S and tools/head_check.sh 72*4882a593Smuzhiyun * for more details. We would prefer to just keep a cacheline (0x80), but 73*4882a593Smuzhiyun * 0x100 seems to be how the linker aligns branch stub groups. 74*4882a593Smuzhiyun */ 75*4882a593Smuzhiyun #ifdef CONFIG_LD_HEAD_STUB_CATCH 76*4882a593Smuzhiyun #define OPEN_TEXT_SECTION(start) \ 77*4882a593Smuzhiyun .section ".linker_stub_catch","ax",@progbits; \ 78*4882a593Smuzhiyun linker_stub_catch: \ 79*4882a593Smuzhiyun . = 0x4; \ 80*4882a593Smuzhiyun text_start = (start) + 0x100; \ 81*4882a593Smuzhiyun .section ".text","ax",@progbits; \ 82*4882a593Smuzhiyun .balign 0x100; \ 83*4882a593Smuzhiyun start_text: 84*4882a593Smuzhiyun #else 85*4882a593Smuzhiyun #define OPEN_TEXT_SECTION(start) \ 86*4882a593Smuzhiyun text_start = (start); \ 87*4882a593Smuzhiyun .section ".text","ax",@progbits; \ 88*4882a593Smuzhiyun . = 0x0; \ 89*4882a593Smuzhiyun start_text: 90*4882a593Smuzhiyun #endif 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun #define ZERO_FIXED_SECTION(sname, start, end) \ 93*4882a593Smuzhiyun sname##_start = (start); \ 94*4882a593Smuzhiyun sname##_end = (end); \ 95*4882a593Smuzhiyun sname##_len = (end) - (start); \ 96*4882a593Smuzhiyun define_data_ftsec sname; \ 97*4882a593Smuzhiyun . = 0x0; \ 98*4882a593Smuzhiyun . = sname##_len; 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun #define USE_FIXED_SECTION(sname) \ 101*4882a593Smuzhiyun fs_label = start_##sname; \ 102*4882a593Smuzhiyun fs_start = sname##_start; \ 103*4882a593Smuzhiyun use_ftsec sname; 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun #define USE_TEXT_SECTION() \ 106*4882a593Smuzhiyun fs_label = start_text; \ 107*4882a593Smuzhiyun fs_start = text_start; \ 108*4882a593Smuzhiyun .text 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun #define CLOSE_FIXED_SECTION(sname) \ 111*4882a593Smuzhiyun USE_FIXED_SECTION(sname); \ 112*4882a593Smuzhiyun . = sname##_len; \ 113*4882a593Smuzhiyun end_##sname: 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun #define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \ 117*4882a593Smuzhiyun USE_FIXED_SECTION(sname); \ 118*4882a593Smuzhiyun .balign __align; \ 119*4882a593Smuzhiyun .global name; \ 120*4882a593Smuzhiyun name: 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun #define FIXED_SECTION_ENTRY_BEGIN(sname, name) \ 123*4882a593Smuzhiyun __FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES) 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun #define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \ 126*4882a593Smuzhiyun USE_FIXED_SECTION(sname); \ 127*4882a593Smuzhiyun name##_start = (start); \ 128*4882a593Smuzhiyun .if ((start) % (size) != 0); \ 129*4882a593Smuzhiyun .error "Fixed section exception vector misalignment"; \ 130*4882a593Smuzhiyun .endif; \ 131*4882a593Smuzhiyun .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100) && ((size) != 0x1000); \ 132*4882a593Smuzhiyun .error "Fixed section exception vector bad size"; \ 133*4882a593Smuzhiyun .endif; \ 134*4882a593Smuzhiyun .if (start) < sname##_start; \ 135*4882a593Smuzhiyun .error "Fixed section underflow"; \ 136*4882a593Smuzhiyun .abort; \ 137*4882a593Smuzhiyun .endif; \ 138*4882a593Smuzhiyun . = (start) - sname##_start; \ 139*4882a593Smuzhiyun .global name; \ 140*4882a593Smuzhiyun name: 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \ 143*4882a593Smuzhiyun .if (start) + (size) > sname##_end; \ 144*4882a593Smuzhiyun .error "Fixed section overflow"; \ 145*4882a593Smuzhiyun .abort; \ 146*4882a593Smuzhiyun .endif; \ 147*4882a593Smuzhiyun .if (. - name > (start) + (size) - name##_start); \ 148*4882a593Smuzhiyun .error "Fixed entry overflow"; \ 149*4882a593Smuzhiyun .abort; \ 150*4882a593Smuzhiyun .endif; \ 151*4882a593Smuzhiyun . = ((start) + (size) - sname##_start); \ 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun /* 155*4882a593Smuzhiyun * These macros are used to change symbols in other fixed sections to be 156*4882a593Smuzhiyun * absolute or related to our current fixed section. 157*4882a593Smuzhiyun * 158*4882a593Smuzhiyun * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the 159*4882a593Smuzhiyun * absolute address of a symbol within a fixed section, from any section. 160*4882a593Smuzhiyun * 161*4882a593Smuzhiyun * - ABS_ADDR is used to find the absolute address of any symbol, from within 162*4882a593Smuzhiyun * a fixed section. 163*4882a593Smuzhiyun */ 164*4882a593Smuzhiyun #define DEFINE_FIXED_SYMBOL(label) \ 165*4882a593Smuzhiyun label##_absolute = (label - fs_label + fs_start) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun #define FIXED_SYMBOL_ABS_ADDR(label) \ 168*4882a593Smuzhiyun (label##_absolute) 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun #define ABS_ADDR(label) (label - fs_label + fs_start) 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun #endif /* __ASSEMBLY__ */ 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun #endif /* _ASM_POWERPC_HEAD_64_H */ 175