162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_HEAD_64_H 362306a36Sopenharmony_ci#define _ASM_POWERPC_HEAD_64_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <asm/cache.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifdef __ASSEMBLY__ 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * We can't do CPP stringification and concatination directly into the section 1062306a36Sopenharmony_ci * name for some reason, so these macros can do it for us. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci.macro define_ftsec name 1362306a36Sopenharmony_ci .section ".head.text.\name\()","ax",@progbits 1462306a36Sopenharmony_ci.endm 1562306a36Sopenharmony_ci.macro define_data_ftsec name 1662306a36Sopenharmony_ci .section ".head.data.\name\()","a",@progbits 1762306a36Sopenharmony_ci.endm 1862306a36Sopenharmony_ci.macro use_ftsec name 1962306a36Sopenharmony_ci .section ".head.text.\name\()","ax",@progbits 2062306a36Sopenharmony_ci.endm 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * Fixed (location) sections are used by opening fixed sections and emitting 2462306a36Sopenharmony_ci * fixed section entries into them before closing them. Multiple fixed sections 2562306a36Sopenharmony_ci * can be open at any time. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * Each fixed section created in a .S file must have corresponding linkage 2862306a36Sopenharmony_ci * directives including location, added to arch/powerpc/kernel/vmlinux.lds.S 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * For each fixed section, code is generated into it in the order which it 3162306a36Sopenharmony_ci * appears in the source. Fixed section entries can be placed at a fixed 3262306a36Sopenharmony_ci * location within the section using _LOCATION postifx variants. These must 3362306a36Sopenharmony_ci * be ordered according to their relative placements within the section. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * OPEN_FIXED_SECTION(section_name, start_address, end_address) 3662306a36Sopenharmony_ci * FIXED_SECTION_ENTRY_BEGIN(section_name, label1) 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * USE_FIXED_SECTION(section_name) 3962306a36Sopenharmony_ci * label3: 4062306a36Sopenharmony_ci * li r10,128 4162306a36Sopenharmony_ci * mv r11,r10 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci * FIXED_SECTION_ENTRY_BEGIN_LOCATION(section_name, label2, start_address, size) 4462306a36Sopenharmony_ci * FIXED_SECTION_ENTRY_END_LOCATION(section_name, label2, start_address, size) 4562306a36Sopenharmony_ci * CLOSE_FIXED_SECTION(section_name) 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * ZERO_FIXED_SECTION can be used to emit zeroed data. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * Troubleshooting: 5062306a36Sopenharmony_ci * - If the build dies with "Error: attempt to move .org backwards" at 5162306a36Sopenharmony_ci * CLOSE_FIXED_SECTION() or elsewhere, there may be something 5262306a36Sopenharmony_ci * unexpected being added there. Remove the '. = x_len' line, rebuild, and 5362306a36Sopenharmony_ci * check what is pushing the section down. 5462306a36Sopenharmony_ci * - If the build dies in linking, check arch/powerpc/tools/head_check.sh 5562306a36Sopenharmony_ci * comments. 5662306a36Sopenharmony_ci * - If the kernel crashes or hangs in very early boot, it could be linker 5762306a36Sopenharmony_ci * stubs at the start of the main text. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define OPEN_FIXED_SECTION(sname, start, end) \ 6162306a36Sopenharmony_ci sname##_start = (start); \ 6262306a36Sopenharmony_ci sname##_end = (end); \ 6362306a36Sopenharmony_ci sname##_len = (end) - (start); \ 6462306a36Sopenharmony_ci define_ftsec sname; \ 6562306a36Sopenharmony_ci . = 0x0; \ 6662306a36Sopenharmony_cistart_##sname: 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * .linker_stub_catch section is used to catch linker stubs from being 7062306a36Sopenharmony_ci * inserted in our .text section, above the start_text label (which breaks 7162306a36Sopenharmony_ci * the ABS_ADDR calculation). See kernel/vmlinux.lds.S and tools/head_check.sh 7262306a36Sopenharmony_ci * for more details. We would prefer to just keep a cacheline (0x80), but 7362306a36Sopenharmony_ci * 0x100 seems to be how the linker aligns branch stub groups. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#ifdef CONFIG_LD_HEAD_STUB_CATCH 7662306a36Sopenharmony_ci#define OPEN_TEXT_SECTION(start) \ 7762306a36Sopenharmony_ci .section ".linker_stub_catch","ax",@progbits; \ 7862306a36Sopenharmony_cilinker_stub_catch: \ 7962306a36Sopenharmony_ci . = 0x4; \ 8062306a36Sopenharmony_ci text_start = (start) + 0x100; \ 8162306a36Sopenharmony_ci .section ".text","ax",@progbits; \ 8262306a36Sopenharmony_ci .balign 0x100; \ 8362306a36Sopenharmony_cistart_text: 8462306a36Sopenharmony_ci#else 8562306a36Sopenharmony_ci#define OPEN_TEXT_SECTION(start) \ 8662306a36Sopenharmony_ci text_start = (start); \ 8762306a36Sopenharmony_ci .section ".text","ax",@progbits; \ 8862306a36Sopenharmony_ci . = 0x0; \ 8962306a36Sopenharmony_cistart_text: 9062306a36Sopenharmony_ci#endif 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define ZERO_FIXED_SECTION(sname, start, end) \ 9362306a36Sopenharmony_ci sname##_start = (start); \ 9462306a36Sopenharmony_ci sname##_end = (end); \ 9562306a36Sopenharmony_ci sname##_len = (end) - (start); \ 9662306a36Sopenharmony_ci define_data_ftsec sname; \ 9762306a36Sopenharmony_ci . = 0x0; \ 9862306a36Sopenharmony_ci . = sname##_len; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define USE_FIXED_SECTION(sname) \ 10162306a36Sopenharmony_ci use_ftsec sname; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define USE_TEXT_SECTION() \ 10462306a36Sopenharmony_ci .text 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define CLOSE_FIXED_SECTION(sname) \ 10762306a36Sopenharmony_ci USE_FIXED_SECTION(sname); \ 10862306a36Sopenharmony_ci . = sname##_len; \ 10962306a36Sopenharmony_ciend_##sname: 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \ 11362306a36Sopenharmony_ci USE_FIXED_SECTION(sname); \ 11462306a36Sopenharmony_ci .balign __align; \ 11562306a36Sopenharmony_ci .global name; \ 11662306a36Sopenharmony_ciname: 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define FIXED_SECTION_ENTRY_BEGIN(sname, name) \ 11962306a36Sopenharmony_ci __FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start, size) \ 12262306a36Sopenharmony_ci USE_FIXED_SECTION(sname); \ 12362306a36Sopenharmony_ci name##_start = (start); \ 12462306a36Sopenharmony_ci .if ((start) % (size) != 0); \ 12562306a36Sopenharmony_ci .error "Fixed section exception vector misalignment"; \ 12662306a36Sopenharmony_ci .endif; \ 12762306a36Sopenharmony_ci .if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100) && ((size) != 0x1000); \ 12862306a36Sopenharmony_ci .error "Fixed section exception vector bad size"; \ 12962306a36Sopenharmony_ci .endif; \ 13062306a36Sopenharmony_ci .if (start) < sname##_start; \ 13162306a36Sopenharmony_ci .error "Fixed section underflow"; \ 13262306a36Sopenharmony_ci .abort; \ 13362306a36Sopenharmony_ci .endif; \ 13462306a36Sopenharmony_ci . = (start) - sname##_start; \ 13562306a36Sopenharmony_ci .global name; \ 13662306a36Sopenharmony_ciname: 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#define FIXED_SECTION_ENTRY_END_LOCATION(sname, name, start, size) \ 13962306a36Sopenharmony_ci .if (start) + (size) > sname##_end; \ 14062306a36Sopenharmony_ci .error "Fixed section overflow"; \ 14162306a36Sopenharmony_ci .abort; \ 14262306a36Sopenharmony_ci .endif; \ 14362306a36Sopenharmony_ci .if (. - name > (start) + (size) - name##_start); \ 14462306a36Sopenharmony_ci .error "Fixed entry overflow"; \ 14562306a36Sopenharmony_ci .abort; \ 14662306a36Sopenharmony_ci .endif; \ 14762306a36Sopenharmony_ci . = ((start) + (size) - sname##_start); \ 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* 15162306a36Sopenharmony_ci * These macros are used to change symbols in other fixed sections to be 15262306a36Sopenharmony_ci * absolute or related to our current fixed section. 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci * - DEFINE_FIXED_SYMBOL / FIXED_SYMBOL_ABS_ADDR is used to find the 15562306a36Sopenharmony_ci * absolute address of a symbol within a fixed section, from any section. 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * - ABS_ADDR is used to find the absolute address of any symbol, from within 15862306a36Sopenharmony_ci * a fixed section. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci// define label as being _in_ sname 16162306a36Sopenharmony_ci#define DEFINE_FIXED_SYMBOL(label, sname) \ 16262306a36Sopenharmony_ci label##_absolute = (label - start_ ## sname + sname ## _start) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define FIXED_SYMBOL_ABS_ADDR(label) \ 16562306a36Sopenharmony_ci (label##_absolute) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci// find label from _within_ sname 16862306a36Sopenharmony_ci#define ABS_ADDR(label, sname) (label - start_ ## sname + sname ## _start) 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#endif /* _ASM_POWERPC_HEAD_64_H */ 173