xref: /OK3568_Linux_fs/kernel/arch/powerpc/include/asm/head-64.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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