| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef _ASM_POWERPC_HEAD_64_H | |
| #define _ASM_POWERPC_HEAD_64_H | |
| #include <asm/cache.h> | |
| #ifdef __ASSEMBLER__ | |
| /* | |
| * 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\()","ax",@progbits | |
| .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, size) | |
| * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size) | |
| * 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/tools/head_check.sh | |
| * comments. | |
| * - 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: | |
| /* | |
| * .linker_stub_catch section is used to catch linker stubs from being | |
| * inserted in our .text section, above the start_text label (which breaks | |
| * the ABS_ADDR calculation). See kernel/vmlinux.lds.S and tools/head_check.sh | |
| * for more details. We would prefer to just keep a cacheline (0x80), but | |
| * 0x100 seems to be how the linker aligns branch stub groups. | |
| */ | |
| #ifdef CONFIG_LD_HEAD_STUB_CATCH | |
| #define OPEN_TEXT_SECTION(start) \ | |
| .section ".linker_stub_catch","ax",@progbits; \ | |
| linker_stub_catch: \ | |
| . = 0x4; \ | |
| text_start = (start) + 0x100; \ | |
| .section ".text","ax",@progbits; \ | |
| .balign 0x100; \ | |
| start_text: | |
| #else | |
| #define OPEN_TEXT_SECTION(start) \ | |
| text_start = (start); \ | |
| .section ".text","ax",@progbits; \ | |
| . = 0x0; \ | |
| start_text: | |
| #endif | |
| #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) \ | |
| use_ftsec sname; | |
| #define USE_TEXT_SECTION() \ | |
| .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); \ | |
| .balign __align; \ | |
| .global name; \ | |
| name: | |
| #define FIXED_SECTION_ENTRY_BEGIN(sname, name) \ | |
| __FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES) | |
| #define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \ | |
| USE_FIXED_SECTION(sname); \ | |
| name##_start = (start); \ | |
| .if ((start) % (size) != 0); \ | |
| .error "Fixed section exception vector misalignment"; \ | |
| .endif; \ | |
| .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100) && ((size) != 0x1000); \ | |
| .error "Fixed section exception vector bad size"; \ | |
| .endif; \ | |
| .if (start) < sname##_start; \ | |
| .error "Fixed section underflow"; \ | |
| .abort; \ | |
| .endif; \ | |
| . = (start) - sname##_start; \ | |
| .global name; \ | |
| name: | |
| #define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \ | |
| .if (start) + (size) > sname##_end; \ | |
| .error "Fixed section overflow"; \ | |
| .abort; \ | |
| .endif; \ | |
| .if (. - name > (start) + (size) - name##_start); \ | |
| .error "Fixed entry overflow"; \ | |
| .abort; \ | |
| .endif; \ | |
| . = ((start) + (size) - 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 label as being _in_ sname | |
| #define DEFINE_FIXED_SYMBOL(label, sname) \ | |
| label##_absolute = (label - start_ ## sname + sname ## _start) | |
| #define FIXED_SYMBOL_ABS_ADDR(label) \ | |
| (label##_absolute) | |
| // find label from _within_ sname | |
| #define ABS_ADDR(label, sname) (label - start_ ## sname + sname ## _start) | |
| #endif /* __ASSEMBLER__ */ | |
| #endif /* _ASM_POWERPC_HEAD_64_H */ |