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