1/*
2 * arch/xtensa/kernel/vmlinux.lds.S
3 *
4 * Xtensa linker script
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License.  See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2008 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
15 */
16
17#define RO_EXCEPTION_TABLE_ALIGN	16
18
19#include <asm-generic/vmlinux.lds.h>
20#include <asm/page.h>
21#include <asm/thread_info.h>
22
23#include <asm/core.h>
24#include <asm/vectors.h>
25
26OUTPUT_ARCH(xtensa)
27ENTRY(_start)
28
29#ifdef __XTENSA_EB__
30jiffies = jiffies_64 + 4;
31#else
32jiffies = jiffies_64;
33#endif
34
35/* Note: In the following macros, it would be nice to specify only the
36   vector name and section kind and construct "sym" and "section" using
37   CPP concatenation, but that does not work reliably.  Concatenating a
38   string with "." produces an invalid token.  CPP will not print a
39   warning because it thinks this is an assembly file, but it leaves
40   them as multiple tokens and there may or may not be whitespace
41   between them.  */
42
43/* Macro for a relocation entry */
44
45#define RELOCATE_ENTRY(sym, section)		\
46	LONG(sym ## _start);			\
47	LONG(sym ## _end);			\
48	LONG(LOADADDR(section))
49
50#if !defined(CONFIG_VECTORS_ADDR) && XCHAL_HAVE_VECBASE
51#define MERGED_VECTORS 1
52#else
53#define MERGED_VECTORS 0
54#endif
55
56/*
57 * Macro to define a section for a vector. When MERGED_VECTORS is 0
58 * code for every vector is located with other init data. At startup
59 * time head.S copies code for every vector to its final position according
60 * to description recorded in the corresponding RELOCATE_ENTRY.
61 */
62
63#define SECTION_VECTOR4(sym, section, addr, prevsec)			    \
64  section addr : AT(((LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3)      \
65  {									    \
66    . = ALIGN(4);							    \
67    sym ## _start = ABSOLUTE(.);		 			    \
68    *(section)								    \
69    sym ## _end = ABSOLUTE(.);						    \
70  }
71
72#define SECTION_VECTOR2(section, addr)					    \
73  . = addr;								    \
74  *(section)
75
76/*
77 *  Mapping of input sections to output sections when linking.
78 */
79
80SECTIONS
81{
82  . = KERNELOFFSET;
83  /* .text section */
84
85  _text = .;
86  _stext = .;
87
88  .text :
89  {
90    /* The HEAD_TEXT section must be the first section! */
91    HEAD_TEXT
92
93#if MERGED_VECTORS
94    . = ALIGN(PAGE_SIZE);
95    _vecbase = .;
96
97#ifdef SUPPORT_WINDOWED
98    SECTION_VECTOR2 (.WindowVectors.text, WINDOW_VECTORS_VADDR)
99#endif
100#if XCHAL_EXCM_LEVEL >= 2
101    SECTION_VECTOR2 (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR)
102#endif
103#if XCHAL_EXCM_LEVEL >= 3
104    SECTION_VECTOR2 (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR)
105#endif
106#if XCHAL_EXCM_LEVEL >= 4
107    SECTION_VECTOR2 (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR)
108#endif
109#if XCHAL_EXCM_LEVEL >= 5
110    SECTION_VECTOR2 (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR)
111#endif
112#if XCHAL_EXCM_LEVEL >= 6
113    SECTION_VECTOR2 (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR)
114#endif
115    SECTION_VECTOR2 (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR)
116    SECTION_VECTOR2 (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR)
117    SECTION_VECTOR2 (.UserExceptionVector.text, USER_VECTOR_VADDR)
118    SECTION_VECTOR2 (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR)
119
120    *(.exception.text)
121#endif
122
123    IRQENTRY_TEXT
124    SOFTIRQENTRY_TEXT
125    ENTRY_TEXT
126    TEXT_TEXT
127    SCHED_TEXT
128    LOCK_TEXT
129    *(.fixup)
130  }
131  _etext = .;
132  PROVIDE (etext = .);
133
134  . = ALIGN(16);
135
136  RO_DATA(4096)
137
138  /* Data section */
139
140#ifdef CONFIG_XIP_KERNEL
141  INIT_TEXT_SECTION(PAGE_SIZE)
142#else
143  _sdata = .;
144  RW_DATA(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
145  _edata = .;
146
147  /* Initialization code and data: */
148
149  . = ALIGN(PAGE_SIZE);
150  __init_begin = .;
151  INIT_TEXT_SECTION(PAGE_SIZE)
152
153  .init.data :
154  {
155    INIT_DATA
156  }
157#endif
158
159  .init.rodata :
160  {
161    . = ALIGN(0x4);
162    __tagtable_begin = .;
163    *(.taglist)
164    __tagtable_end = .;
165
166    . = ALIGN(16);
167    __boot_reloc_table_start = ABSOLUTE(.);
168
169#if !MERGED_VECTORS
170#ifdef SUPPORT_WINDOWED
171    RELOCATE_ENTRY(_WindowVectors_text,
172		   .WindowVectors.text);
173#endif
174#if XCHAL_EXCM_LEVEL >= 2
175    RELOCATE_ENTRY(_Level2InterruptVector_text,
176		   .Level2InterruptVector.text);
177#endif
178#if XCHAL_EXCM_LEVEL >= 3
179    RELOCATE_ENTRY(_Level3InterruptVector_text,
180		   .Level3InterruptVector.text);
181#endif
182#if XCHAL_EXCM_LEVEL >= 4
183    RELOCATE_ENTRY(_Level4InterruptVector_text,
184		   .Level4InterruptVector.text);
185#endif
186#if XCHAL_EXCM_LEVEL >= 5
187    RELOCATE_ENTRY(_Level5InterruptVector_text,
188		   .Level5InterruptVector.text);
189#endif
190#if XCHAL_EXCM_LEVEL >= 6
191    RELOCATE_ENTRY(_Level6InterruptVector_text,
192		   .Level6InterruptVector.text);
193#endif
194    RELOCATE_ENTRY(_KernelExceptionVector_text,
195		   .KernelExceptionVector.text);
196    RELOCATE_ENTRY(_UserExceptionVector_text,
197		   .UserExceptionVector.text);
198    RELOCATE_ENTRY(_DoubleExceptionVector_text,
199		   .DoubleExceptionVector.text);
200    RELOCATE_ENTRY(_DebugInterruptVector_text,
201		   .DebugInterruptVector.text);
202    RELOCATE_ENTRY(_exception_text,
203		   .exception.text);
204#endif
205#ifdef CONFIG_XIP_KERNEL
206    RELOCATE_ENTRY(_xip_data, .data);
207    RELOCATE_ENTRY(_xip_init_data, .init.data);
208#endif
209#if defined(CONFIG_SECONDARY_RESET_VECTOR)
210    RELOCATE_ENTRY(_SecondaryResetVector_text,
211		   .SecondaryResetVector.text);
212#endif
213
214    __boot_reloc_table_end = ABSOLUTE(.) ;
215
216    INIT_SETUP(XCHAL_ICACHE_LINESIZE)
217    INIT_CALLS
218    CON_INITCALL
219    INIT_RAM_FS
220  }
221
222  PERCPU_SECTION(XCHAL_ICACHE_LINESIZE)
223
224  /* We need this dummy segment here */
225
226  . = ALIGN(4);
227  .dummy : { LONG(0) }
228
229#undef LAST
230#define LAST	.dummy
231
232#if !MERGED_VECTORS
233  /* The vectors are relocated to the real position at startup time */
234
235#ifdef SUPPORT_WINDOWED
236  SECTION_VECTOR4 (_WindowVectors_text,
237		  .WindowVectors.text,
238		  WINDOW_VECTORS_VADDR,
239		  LAST)
240#undef LAST
241#define LAST	.WindowVectors.text
242#endif
243  SECTION_VECTOR4 (_DebugInterruptVector_text,
244		  .DebugInterruptVector.text,
245		  DEBUG_VECTOR_VADDR,
246		  LAST)
247#undef LAST
248#define LAST	.DebugInterruptVector.text
249#if XCHAL_EXCM_LEVEL >= 2
250  SECTION_VECTOR4 (_Level2InterruptVector_text,
251		  .Level2InterruptVector.text,
252		  INTLEVEL2_VECTOR_VADDR,
253		  LAST)
254# undef LAST
255# define LAST	.Level2InterruptVector.text
256#endif
257#if XCHAL_EXCM_LEVEL >= 3
258  SECTION_VECTOR4 (_Level3InterruptVector_text,
259		  .Level3InterruptVector.text,
260		  INTLEVEL3_VECTOR_VADDR,
261		  LAST)
262# undef LAST
263# define LAST	.Level3InterruptVector.text
264#endif
265#if XCHAL_EXCM_LEVEL >= 4
266  SECTION_VECTOR4 (_Level4InterruptVector_text,
267		  .Level4InterruptVector.text,
268		  INTLEVEL4_VECTOR_VADDR,
269		  LAST)
270# undef LAST
271# define LAST	.Level4InterruptVector.text
272#endif
273#if XCHAL_EXCM_LEVEL >= 5
274  SECTION_VECTOR4 (_Level5InterruptVector_text,
275		  .Level5InterruptVector.text,
276		  INTLEVEL5_VECTOR_VADDR,
277		  LAST)
278# undef LAST
279# define LAST	.Level5InterruptVector.text
280#endif
281#if XCHAL_EXCM_LEVEL >= 6
282  SECTION_VECTOR4 (_Level6InterruptVector_text,
283		  .Level6InterruptVector.text,
284		  INTLEVEL6_VECTOR_VADDR,
285		  LAST)
286# undef LAST
287# define LAST	.Level6InterruptVector.text
288#endif
289  SECTION_VECTOR4 (_KernelExceptionVector_text,
290		  .KernelExceptionVector.text,
291		  KERNEL_VECTOR_VADDR,
292		  LAST)
293#undef LAST
294  SECTION_VECTOR4 (_UserExceptionVector_text,
295		  .UserExceptionVector.text,
296		  USER_VECTOR_VADDR,
297		  .KernelExceptionVector.text)
298  SECTION_VECTOR4 (_DoubleExceptionVector_text,
299		  .DoubleExceptionVector.text,
300		  DOUBLEEXC_VECTOR_VADDR,
301		  .UserExceptionVector.text)
302#define LAST .DoubleExceptionVector.text
303
304#endif
305#if defined(CONFIG_SECONDARY_RESET_VECTOR)
306
307  SECTION_VECTOR4 (_SecondaryResetVector_text,
308		  .SecondaryResetVector.text,
309		  RESET_VECTOR1_VADDR,
310		  LAST)
311#undef LAST
312#define LAST .SecondaryResetVector.text
313
314#endif
315#if !MERGED_VECTORS
316  SECTION_VECTOR4 (_exception_text,
317		  .exception.text,
318		  ,
319		  LAST)
320#undef LAST
321#define LAST .exception.text
322
323#endif
324  . = (LOADADDR(LAST) + SIZEOF(LAST) + 3) & ~ 3;
325
326  .dummy1 : AT(ADDR(.dummy1)) { LONG(0) }
327  . = ALIGN(PAGE_SIZE);
328
329#ifndef CONFIG_XIP_KERNEL
330  __init_end = .;
331
332  BSS_SECTION(0, 8192, 0)
333#endif
334
335  _end = .;
336
337#ifdef CONFIG_XIP_KERNEL
338  . = CONFIG_XIP_DATA_ADDR;
339
340  _xip_start = .;
341
342#undef LOAD_OFFSET
343#define LOAD_OFFSET \
344  (CONFIG_XIP_DATA_ADDR - (LOADADDR(.dummy1) + SIZEOF(.dummy1) + 3) & ~ 3)
345
346  _xip_data_start = .;
347  _sdata = .;
348  RW_DATA(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
349  _edata = .;
350  _xip_data_end = .;
351
352  /* Initialization data: */
353
354  STRUCT_ALIGN();
355
356  _xip_init_data_start = .;
357  __init_begin = .;
358  .init.data :
359  {
360    INIT_DATA
361  }
362  _xip_init_data_end = .;
363  __init_end = .;
364  BSS_SECTION(0, 8192, 0)
365
366  _xip_end = .;
367
368#undef LOAD_OFFSET
369#endif
370
371  DWARF_DEBUG
372
373  .xt.prop 0 : { KEEP(*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }
374  .xt.insn 0 : { KEEP(*(.xt.insn .xt.insn.* .gnu.linkonce.x*)) }
375  .xt.lit  0 : { KEEP(*(.xt.lit  .xt.lit.*  .gnu.linkonce.p*)) }
376
377  /* Sections to be discarded */
378  DISCARDS
379}
380