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#include <asm-generic/vmlinux.lds.h> 18#include <asm/page.h> 19#include <asm/thread_info.h> 20 21#include <asm/vectors.h> 22#include <variant/core.h> 23#include <platform/hardware.h> 24OUTPUT_ARCH(xtensa) 25ENTRY(_start) 26 27#ifdef __XTENSA_EB__ 28jiffies = jiffies_64 + 4; 29#else 30jiffies = jiffies_64; 31#endif 32 33#ifndef KERNELOFFSET 34#define KERNELOFFSET 0xd0003000 35#endif 36 37/* Note: In the following macros, it would be nice to specify only the 38 vector name and section kind and construct "sym" and "section" using 39 CPP concatenation, but that does not work reliably. Concatenating a 40 string with "." produces an invalid token. CPP will not print a 41 warning because it thinks this is an assembly file, but it leaves 42 them as multiple tokens and there may or may not be whitespace 43 between them. */ 44 45/* Macro for a relocation entry */ 46 47#define RELOCATE_ENTRY(sym, section) \ 48 LONG(sym ## _start); \ 49 LONG(sym ## _end); \ 50 LONG(LOADADDR(section)) 51 52/* Macro to define a section for a vector. 53 * 54 * Use of the MIN function catches the types of errors illustrated in 55 * the following example: 56 * 57 * Assume the section .DoubleExceptionVector.literal is completely 58 * full. Then a programmer adds code to .DoubleExceptionVector.text 59 * that produces another literal. The final literal position will 60 * overlay onto the first word of the adjacent code section 61 * .DoubleExceptionVector.text. (In practice, the literals will 62 * overwrite the code, and the first few instructions will be 63 * garbage.) 64 */ 65 66#define SECTION_VECTOR(sym, section, addr, max_prevsec_size, prevsec) \ 67 section addr : AT((MIN(LOADADDR(prevsec) + max_prevsec_size, \ 68 LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \ 69 { \ 70 . = ALIGN(4); \ 71 sym ## _start = ABSOLUTE(.); \ 72 *(section) \ 73 sym ## _end = ABSOLUTE(.); \ 74 } 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 TEXT_TEXT 93 VMLINUX_SYMBOL(__sched_text_start) = .; 94 *(.sched.literal .sched.text) 95 VMLINUX_SYMBOL(__sched_text_end) = .; 96 VMLINUX_SYMBOL(__lock_text_start) = .; 97 *(.spinlock.literal .spinlock.text) 98 VMLINUX_SYMBOL(__lock_text_end) = .; 99 100 } 101 _etext = .; 102 PROVIDE (etext = .); 103 104 . = ALIGN(16); 105 106 RODATA 107 108 /* Relocation table */ 109 110 .fixup : { *(.fixup) } 111 112 EXCEPTION_TABLE(16) 113 /* Data section */ 114 115 _sdata = .; 116 RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) 117 _edata = .; 118 119 /* Initialization code and data: */ 120 121 . = ALIGN(PAGE_SIZE); 122 __init_begin = .; 123 INIT_TEXT_SECTION(PAGE_SIZE) 124 125 .init.data : 126 { 127 INIT_DATA 128 . = ALIGN(0x4); 129 __tagtable_begin = .; 130 *(.taglist) 131 __tagtable_end = .; 132 133 . = ALIGN(16); 134 __boot_reloc_table_start = ABSOLUTE(.); 135 136 RELOCATE_ENTRY(_WindowVectors_text, 137 .WindowVectors.text); 138#if XCHAL_EXCM_LEVEL >= 2 139 RELOCATE_ENTRY(_Level2InterruptVector_text, 140 .Level2InterruptVector.text); 141#endif 142#if XCHAL_EXCM_LEVEL >= 3 143 RELOCATE_ENTRY(_Level3InterruptVector_text, 144 .Level3InterruptVector.text); 145#endif 146#if XCHAL_EXCM_LEVEL >= 4 147 RELOCATE_ENTRY(_Level4InterruptVector_text, 148 .Level4InterruptVector.text); 149#endif 150#if XCHAL_EXCM_LEVEL >= 5 151 RELOCATE_ENTRY(_Level5InterruptVector_text, 152 .Level5InterruptVector.text); 153#endif 154#if XCHAL_EXCM_LEVEL >= 6 155 RELOCATE_ENTRY(_Level6InterruptVector_text, 156 .Level6InterruptVector.text); 157#endif 158 RELOCATE_ENTRY(_KernelExceptionVector_text, 159 .KernelExceptionVector.text); 160 RELOCATE_ENTRY(_UserExceptionVector_text, 161 .UserExceptionVector.text); 162 RELOCATE_ENTRY(_DoubleExceptionVector_literal, 163 .DoubleExceptionVector.literal); 164 RELOCATE_ENTRY(_DoubleExceptionVector_text, 165 .DoubleExceptionVector.text); 166 RELOCATE_ENTRY(_DebugInterruptVector_text, 167 .DebugInterruptVector.text); 168#if defined(CONFIG_SMP) 169 RELOCATE_ENTRY(_SecondaryResetVector_literal, 170 .SecondaryResetVector.literal); 171 RELOCATE_ENTRY(_SecondaryResetVector_text, 172 .SecondaryResetVector.text); 173#endif 174 175 176 __boot_reloc_table_end = ABSOLUTE(.) ; 177 178 INIT_SETUP(XCHAL_ICACHE_LINESIZE) 179 INIT_CALLS 180 CON_INITCALL 181 SECURITY_INITCALL 182 INIT_RAM_FS 183 } 184 185 PERCPU_SECTION(XCHAL_ICACHE_LINESIZE) 186 187 /* We need this dummy segment here */ 188 189 . = ALIGN(4); 190 .dummy : { LONG(0) } 191 192 /* The vectors are relocated to the real position at startup time */ 193 194 SECTION_VECTOR (_WindowVectors_text, 195 .WindowVectors.text, 196 WINDOW_VECTORS_VADDR, 4, 197 .dummy) 198 SECTION_VECTOR (_DebugInterruptVector_literal, 199 .DebugInterruptVector.literal, 200 DEBUG_VECTOR_VADDR - 4, 201 SIZEOF(.WindowVectors.text), 202 .WindowVectors.text) 203 SECTION_VECTOR (_DebugInterruptVector_text, 204 .DebugInterruptVector.text, 205 DEBUG_VECTOR_VADDR, 206 4, 207 .DebugInterruptVector.literal) 208#undef LAST 209#define LAST .DebugInterruptVector.text 210#if XCHAL_EXCM_LEVEL >= 2 211 SECTION_VECTOR (_Level2InterruptVector_text, 212 .Level2InterruptVector.text, 213 INTLEVEL2_VECTOR_VADDR, 214 SIZEOF(LAST), LAST) 215# undef LAST 216# define LAST .Level2InterruptVector.text 217#endif 218#if XCHAL_EXCM_LEVEL >= 3 219 SECTION_VECTOR (_Level3InterruptVector_text, 220 .Level3InterruptVector.text, 221 INTLEVEL3_VECTOR_VADDR, 222 SIZEOF(LAST), LAST) 223# undef LAST 224# define LAST .Level3InterruptVector.text 225#endif 226#if XCHAL_EXCM_LEVEL >= 4 227 SECTION_VECTOR (_Level4InterruptVector_text, 228 .Level4InterruptVector.text, 229 INTLEVEL4_VECTOR_VADDR, 230 SIZEOF(LAST), LAST) 231# undef LAST 232# define LAST .Level4InterruptVector.text 233#endif 234#if XCHAL_EXCM_LEVEL >= 5 235 SECTION_VECTOR (_Level5InterruptVector_text, 236 .Level5InterruptVector.text, 237 INTLEVEL5_VECTOR_VADDR, 238 SIZEOF(LAST), LAST) 239# undef LAST 240# define LAST .Level5InterruptVector.text 241#endif 242#if XCHAL_EXCM_LEVEL >= 6 243 SECTION_VECTOR (_Level6InterruptVector_text, 244 .Level6InterruptVector.text, 245 INTLEVEL6_VECTOR_VADDR, 246 SIZEOF(LAST), LAST) 247# undef LAST 248# define LAST .Level6InterruptVector.text 249#endif 250 SECTION_VECTOR (_KernelExceptionVector_literal, 251 .KernelExceptionVector.literal, 252 KERNEL_VECTOR_VADDR - 4, 253 SIZEOF(LAST), LAST) 254#undef LAST 255 SECTION_VECTOR (_KernelExceptionVector_text, 256 .KernelExceptionVector.text, 257 KERNEL_VECTOR_VADDR, 258 4, 259 .KernelExceptionVector.literal) 260 SECTION_VECTOR (_UserExceptionVector_literal, 261 .UserExceptionVector.literal, 262 USER_VECTOR_VADDR - 4, 263 SIZEOF(.KernelExceptionVector.text), 264 .KernelExceptionVector.text) 265 SECTION_VECTOR (_UserExceptionVector_text, 266 .UserExceptionVector.text, 267 USER_VECTOR_VADDR, 268 4, 269 .UserExceptionVector.literal) 270 SECTION_VECTOR (_DoubleExceptionVector_literal, 271 .DoubleExceptionVector.literal, 272 DOUBLEEXC_VECTOR_VADDR - 48, 273 SIZEOF(.UserExceptionVector.text), 274 .UserExceptionVector.text) 275 SECTION_VECTOR (_DoubleExceptionVector_text, 276 .DoubleExceptionVector.text, 277 DOUBLEEXC_VECTOR_VADDR, 278 48, 279 .DoubleExceptionVector.literal) 280 281 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; 282 283#if defined(CONFIG_SMP) 284 285 SECTION_VECTOR (_SecondaryResetVector_literal, 286 .SecondaryResetVector.literal, 287 RESET_VECTOR1_VADDR - 4, 288 SIZEOF(.DoubleExceptionVector.text), 289 .DoubleExceptionVector.text) 290 291 SECTION_VECTOR (_SecondaryResetVector_text, 292 .SecondaryResetVector.text, 293 RESET_VECTOR1_VADDR, 294 4, 295 .SecondaryResetVector.literal) 296 297 . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text); 298 299#endif 300 301 . = ALIGN(PAGE_SIZE); 302 303 __init_end = .; 304 305 BSS_SECTION(0, 8192, 0) 306 307 _end = .; 308 309 /* only used by the boot loader */ 310 311 . = ALIGN(0x10); 312 .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) } 313 314 .ResetVector.text RESET_VECTOR_VADDR : 315 { 316 *(.ResetVector.text) 317 } 318 319 320 /* 321 * This is a remapped copy of the Secondary Reset Vector Code. 322 * It keeps gdb in sync with the PC after switching 323 * to the temporary mapping used while setting up 324 * the V2 MMU mappings for Linux. 325 * 326 * Only debug information about this section is put in the kernel image. 327 */ 328 .SecondaryResetVector.remapped_text 0x46000000 (INFO): 329 { 330 *(.SecondaryResetVector.remapped_text) 331 } 332 333 334 .xt.lit : { *(.xt.lit) } 335 .xt.prop : { *(.xt.prop) } 336 337 .debug 0 : { *(.debug) } 338 .line 0 : { *(.line) } 339 .debug_srcinfo 0 : { *(.debug_srcinfo) } 340 .debug_sfnames 0 : { *(.debug_sfnames) } 341 .debug_aranges 0 : { *(.debug_aranges) } 342 .debug_pubnames 0 : { *(.debug_pubnames) } 343 .debug_info 0 : { *(.debug_info) } 344 .debug_abbrev 0 : { *(.debug_abbrev) } 345 .debug_line 0 : { *(.debug_line) } 346 .debug_frame 0 : { *(.debug_frame) } 347 .debug_str 0 : { *(.debug_str) } 348 .debug_loc 0 : { *(.debug_loc) } 349 .debug_macinfo 0 : { *(.debug_macinfo) } 350 .debug_weaknames 0 : { *(.debug_weaknames) } 351 .debug_funcnames 0 : { *(.debug_funcnames) } 352 .debug_typenames 0 : { *(.debug_typenames) } 353 .debug_varnames 0 : { *(.debug_varnames) } 354 355 .xt.insn 0 : 356 { 357 *(.xt.insn) 358 *(.gnu.linkonce.x*) 359 } 360 361 .xt.lit 0 : 362 { 363 *(.xt.lit) 364 *(.gnu.linkonce.p*) 365 } 366 367 /* Sections to be discarded */ 368 DISCARDS 369 /DISCARD/ : { *(.exit.literal) } 370} 371