xref: /openbmc/linux/arch/arm/kernel/vmlinux.lds.S (revision 39b6f3aa)
1/* ld script to make ARM Linux kernel
2 * taken from the i386 version by Russell King
3 * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
4 */
5
6#include <asm-generic/vmlinux.lds.h>
7#include <asm/cache.h>
8#include <asm/thread_info.h>
9#include <asm/memory.h>
10#include <asm/page.h>
11
12#define PROC_INFO							\
13	. = ALIGN(4);							\
14	VMLINUX_SYMBOL(__proc_info_begin) = .;				\
15	*(.proc.info.init)						\
16	VMLINUX_SYMBOL(__proc_info_end) = .;
17
18#define IDMAP_TEXT							\
19	ALIGN_FUNCTION();						\
20	VMLINUX_SYMBOL(__idmap_text_start) = .;				\
21	*(.idmap.text)							\
22	VMLINUX_SYMBOL(__idmap_text_end) = .;				\
23	. = ALIGN(32);							\
24	VMLINUX_SYMBOL(__hyp_idmap_text_start) = .;			\
25	*(.hyp.idmap.text)						\
26	VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
27
28#ifdef CONFIG_HOTPLUG_CPU
29#define ARM_CPU_DISCARD(x)
30#define ARM_CPU_KEEP(x)		x
31#else
32#define ARM_CPU_DISCARD(x)	x
33#define ARM_CPU_KEEP(x)
34#endif
35
36#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
37	defined(CONFIG_GENERIC_BUG)
38#define ARM_EXIT_KEEP(x)	x
39#define ARM_EXIT_DISCARD(x)
40#else
41#define ARM_EXIT_KEEP(x)
42#define ARM_EXIT_DISCARD(x)	x
43#endif
44
45OUTPUT_ARCH(arm)
46ENTRY(stext)
47
48#ifndef __ARMEB__
49jiffies = jiffies_64;
50#else
51jiffies = jiffies_64 + 4;
52#endif
53
54SECTIONS
55{
56	/*
57	 * XXX: The linker does not define how output sections are
58	 * assigned to input sections when there are multiple statements
59	 * matching the same input section name.  There is no documented
60	 * order of matching.
61	 *
62	 * unwind exit sections must be discarded before the rest of the
63	 * unwind sections get included.
64	 */
65	/DISCARD/ : {
66		*(.ARM.exidx.exit.text)
67		*(.ARM.extab.exit.text)
68		ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
69		ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
70		ARM_EXIT_DISCARD(EXIT_TEXT)
71		ARM_EXIT_DISCARD(EXIT_DATA)
72		EXIT_CALL
73#ifndef CONFIG_HOTPLUG
74		*(.ARM.exidx.devexit.text)
75		*(.ARM.extab.devexit.text)
76#endif
77#ifndef CONFIG_MMU
78		*(.fixup)
79		*(__ex_table)
80#endif
81#ifndef CONFIG_SMP_ON_UP
82		*(.alt.smp.init)
83#endif
84		*(.discard)
85		*(.discard.*)
86	}
87
88#ifdef CONFIG_XIP_KERNEL
89	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
90#else
91	. = PAGE_OFFSET + TEXT_OFFSET;
92#endif
93	.head.text : {
94		_text = .;
95		HEAD_TEXT
96	}
97	.text : {			/* Real text segment		*/
98		_stext = .;		/* Text and read-only data	*/
99			__exception_text_start = .;
100			*(.exception.text)
101			__exception_text_end = .;
102			IRQENTRY_TEXT
103			TEXT_TEXT
104			SCHED_TEXT
105			LOCK_TEXT
106			KPROBES_TEXT
107			IDMAP_TEXT
108#ifdef CONFIG_MMU
109			*(.fixup)
110#endif
111			*(.gnu.warning)
112			*(.glue_7)
113			*(.glue_7t)
114		. = ALIGN(4);
115		*(.got)			/* Global offset table		*/
116			ARM_CPU_KEEP(PROC_INFO)
117	}
118
119	RO_DATA(PAGE_SIZE)
120
121	. = ALIGN(4);
122	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
123		__start___ex_table = .;
124#ifdef CONFIG_MMU
125		*(__ex_table)
126#endif
127		__stop___ex_table = .;
128	}
129
130#ifdef CONFIG_ARM_UNWIND
131	/*
132	 * Stack unwinding tables
133	 */
134	. = ALIGN(8);
135	.ARM.unwind_idx : {
136		__start_unwind_idx = .;
137		*(.ARM.exidx*)
138		__stop_unwind_idx = .;
139	}
140	.ARM.unwind_tab : {
141		__start_unwind_tab = .;
142		*(.ARM.extab*)
143		__stop_unwind_tab = .;
144	}
145#endif
146
147	NOTES
148
149	_etext = .;			/* End of text and rodata section */
150
151#ifndef CONFIG_XIP_KERNEL
152	. = ALIGN(PAGE_SIZE);
153	__init_begin = .;
154#endif
155
156	INIT_TEXT_SECTION(8)
157	.exit.text : {
158		ARM_EXIT_KEEP(EXIT_TEXT)
159	}
160	.init.proc.info : {
161		ARM_CPU_DISCARD(PROC_INFO)
162	}
163	.init.arch.info : {
164		__arch_info_begin = .;
165		*(.arch.info.init)
166		__arch_info_end = .;
167	}
168	.init.tagtable : {
169		__tagtable_begin = .;
170		*(.taglist.init)
171		__tagtable_end = .;
172	}
173#ifdef CONFIG_SMP_ON_UP
174	.init.smpalt : {
175		__smpalt_begin = .;
176		*(.alt.smp.init)
177		__smpalt_end = .;
178	}
179#endif
180	.init.pv_table : {
181		__pv_table_begin = .;
182		*(.pv_table)
183		__pv_table_end = .;
184	}
185	.init.data : {
186#ifndef CONFIG_XIP_KERNEL
187		INIT_DATA
188#endif
189		INIT_SETUP(16)
190		INIT_CALLS
191		CON_INITCALL
192		SECURITY_INITCALL
193		INIT_RAM_FS
194	}
195#ifndef CONFIG_XIP_KERNEL
196	.exit.data : {
197		ARM_EXIT_KEEP(EXIT_DATA)
198	}
199#endif
200
201#ifdef CONFIG_SMP
202	PERCPU_SECTION(L1_CACHE_BYTES)
203#endif
204
205#ifdef CONFIG_XIP_KERNEL
206	__data_loc = ALIGN(4);		/* location in binary */
207	. = PAGE_OFFSET + TEXT_OFFSET;
208#else
209	__init_end = .;
210	. = ALIGN(THREAD_SIZE);
211	__data_loc = .;
212#endif
213
214	.data : AT(__data_loc) {
215		_data = .;		/* address in memory */
216		_sdata = .;
217
218		/*
219		 * first, the init task union, aligned
220		 * to an 8192 byte boundary.
221		 */
222		INIT_TASK_DATA(THREAD_SIZE)
223
224#ifdef CONFIG_XIP_KERNEL
225		. = ALIGN(PAGE_SIZE);
226		__init_begin = .;
227		INIT_DATA
228		ARM_EXIT_KEEP(EXIT_DATA)
229		. = ALIGN(PAGE_SIZE);
230		__init_end = .;
231#endif
232
233		NOSAVE_DATA
234		CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
235		READ_MOSTLY_DATA(L1_CACHE_BYTES)
236
237		/*
238		 * and the usual data section
239		 */
240		DATA_DATA
241		CONSTRUCTORS
242
243		_edata = .;
244	}
245	_edata_loc = __data_loc + SIZEOF(.data);
246
247#ifdef CONFIG_HAVE_TCM
248        /*
249	 * We align everything to a page boundary so we can
250	 * free it after init has commenced and TCM contents have
251	 * been copied to its destination.
252	 */
253	.tcm_start : {
254		. = ALIGN(PAGE_SIZE);
255		__tcm_start = .;
256		__itcm_start = .;
257	}
258
259	/*
260	 * Link these to the ITCM RAM
261	 * Put VMA to the TCM address and LMA to the common RAM
262	 * and we'll upload the contents from RAM to TCM and free
263	 * the used RAM after that.
264	 */
265	.text_itcm ITCM_OFFSET : AT(__itcm_start)
266	{
267		__sitcm_text = .;
268		*(.tcm.text)
269		*(.tcm.rodata)
270		. = ALIGN(4);
271		__eitcm_text = .;
272	}
273
274	/*
275	 * Reset the dot pointer, this is needed to create the
276	 * relative __dtcm_start below (to be used as extern in code).
277	 */
278	. = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm);
279
280	.dtcm_start : {
281		__dtcm_start = .;
282	}
283
284	/* TODO: add remainder of ITCM as well, that can be used for data! */
285	.data_dtcm DTCM_OFFSET : AT(__dtcm_start)
286	{
287		. = ALIGN(4);
288		__sdtcm_data = .;
289		*(.tcm.data)
290		. = ALIGN(4);
291		__edtcm_data = .;
292	}
293
294	/* Reset the dot pointer or the linker gets confused */
295	. = ADDR(.dtcm_start) + SIZEOF(.data_dtcm);
296
297	/* End marker for freeing TCM copy in linked object */
298	.tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){
299		. = ALIGN(PAGE_SIZE);
300		__tcm_end = .;
301	}
302#endif
303
304	BSS_SECTION(0, 0, 0)
305	_end = .;
306
307	STABS_DEBUG
308	.comment 0 : { *(.comment) }
309}
310
311/*
312 * These must never be empty
313 * If you have to comment these two assert statements out, your
314 * binutils is too old (for other reasons as well)
315 */
316ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
317ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
318/*
319 * The HYP init code can't be more than a page long.
320 * The above comment applies as well.
321 */
322ASSERT(((__hyp_idmap_text_end - __hyp_idmap_text_start) <= PAGE_SIZE), "HYP init code too big")
323