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 169 __boot_reloc_table_end = ABSOLUTE(.) ; 170 171 INIT_SETUP(XCHAL_ICACHE_LINESIZE) 172 INIT_CALLS 173 CON_INITCALL 174 SECURITY_INITCALL 175 INIT_RAM_FS 176 } 177 178 PERCPU_SECTION(XCHAL_ICACHE_LINESIZE) 179 180 /* We need this dummy segment here */ 181 182 . = ALIGN(4); 183 .dummy : { LONG(0) } 184 185 /* The vectors are relocated to the real position at startup time */ 186 187 SECTION_VECTOR (_WindowVectors_text, 188 .WindowVectors.text, 189 WINDOW_VECTORS_VADDR, 4, 190 .dummy) 191 SECTION_VECTOR (_DebugInterruptVector_literal, 192 .DebugInterruptVector.literal, 193 DEBUG_VECTOR_VADDR - 4, 194 SIZEOF(.WindowVectors.text), 195 .WindowVectors.text) 196 SECTION_VECTOR (_DebugInterruptVector_text, 197 .DebugInterruptVector.text, 198 DEBUG_VECTOR_VADDR, 199 4, 200 .DebugInterruptVector.literal) 201#undef LAST 202#define LAST .DebugInterruptVector.text 203#if XCHAL_EXCM_LEVEL >= 2 204 SECTION_VECTOR (_Level2InterruptVector_text, 205 .Level2InterruptVector.text, 206 INTLEVEL2_VECTOR_VADDR, 207 SIZEOF(LAST), LAST) 208# undef LAST 209# define LAST .Level2InterruptVector.text 210#endif 211#if XCHAL_EXCM_LEVEL >= 3 212 SECTION_VECTOR (_Level3InterruptVector_text, 213 .Level3InterruptVector.text, 214 INTLEVEL3_VECTOR_VADDR, 215 SIZEOF(LAST), LAST) 216# undef LAST 217# define LAST .Level3InterruptVector.text 218#endif 219#if XCHAL_EXCM_LEVEL >= 4 220 SECTION_VECTOR (_Level4InterruptVector_text, 221 .Level4InterruptVector.text, 222 INTLEVEL4_VECTOR_VADDR, 223 SIZEOF(LAST), LAST) 224# undef LAST 225# define LAST .Level4InterruptVector.text 226#endif 227#if XCHAL_EXCM_LEVEL >= 5 228 SECTION_VECTOR (_Level5InterruptVector_text, 229 .Level5InterruptVector.text, 230 INTLEVEL5_VECTOR_VADDR, 231 SIZEOF(LAST), LAST) 232# undef LAST 233# define LAST .Level5InterruptVector.text 234#endif 235#if XCHAL_EXCM_LEVEL >= 6 236 SECTION_VECTOR (_Level6InterruptVector_text, 237 .Level6InterruptVector.text, 238 INTLEVEL6_VECTOR_VADDR, 239 SIZEOF(LAST), LAST) 240# undef LAST 241# define LAST .Level6InterruptVector.text 242#endif 243 SECTION_VECTOR (_KernelExceptionVector_literal, 244 .KernelExceptionVector.literal, 245 KERNEL_VECTOR_VADDR - 4, 246 SIZEOF(LAST), LAST) 247#undef LAST 248 SECTION_VECTOR (_KernelExceptionVector_text, 249 .KernelExceptionVector.text, 250 KERNEL_VECTOR_VADDR, 251 4, 252 .KernelExceptionVector.literal) 253 SECTION_VECTOR (_UserExceptionVector_literal, 254 .UserExceptionVector.literal, 255 USER_VECTOR_VADDR - 4, 256 SIZEOF(.KernelExceptionVector.text), 257 .KernelExceptionVector.text) 258 SECTION_VECTOR (_UserExceptionVector_text, 259 .UserExceptionVector.text, 260 USER_VECTOR_VADDR, 261 4, 262 .UserExceptionVector.literal) 263 SECTION_VECTOR (_DoubleExceptionVector_literal, 264 .DoubleExceptionVector.literal, 265 DOUBLEEXC_VECTOR_VADDR - 16, 266 SIZEOF(.UserExceptionVector.text), 267 .UserExceptionVector.text) 268 SECTION_VECTOR (_DoubleExceptionVector_text, 269 .DoubleExceptionVector.text, 270 DOUBLEEXC_VECTOR_VADDR, 271 32, 272 .DoubleExceptionVector.literal) 273 274 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; 275 . = ALIGN(PAGE_SIZE); 276 277 __init_end = .; 278 279 BSS_SECTION(0, 8192, 0) 280 281 _end = .; 282 283 /* only used by the boot loader */ 284 285 . = ALIGN(0x10); 286 .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) } 287 288 .ResetVector.text RESET_VECTOR_VADDR : 289 { 290 *(.ResetVector.text) 291 } 292 293 294 /* 295 * This is a remapped copy of the Secondary Reset Vector Code. 296 * It keeps gdb in sync with the PC after switching 297 * to the temporary mapping used while setting up 298 * the V2 MMU mappings for Linux. 299 * 300 * Only debug information about this section is put in the kernel image. 301 */ 302 .SecondaryResetVector.remapped_text 0x46000000 (INFO): 303 { 304 *(.SecondaryResetVector.remapped_text) 305 } 306 307 308 .xt.lit : { *(.xt.lit) } 309 .xt.prop : { *(.xt.prop) } 310 311 .debug 0 : { *(.debug) } 312 .line 0 : { *(.line) } 313 .debug_srcinfo 0 : { *(.debug_srcinfo) } 314 .debug_sfnames 0 : { *(.debug_sfnames) } 315 .debug_aranges 0 : { *(.debug_aranges) } 316 .debug_pubnames 0 : { *(.debug_pubnames) } 317 .debug_info 0 : { *(.debug_info) } 318 .debug_abbrev 0 : { *(.debug_abbrev) } 319 .debug_line 0 : { *(.debug_line) } 320 .debug_frame 0 : { *(.debug_frame) } 321 .debug_str 0 : { *(.debug_str) } 322 .debug_loc 0 : { *(.debug_loc) } 323 .debug_macinfo 0 : { *(.debug_macinfo) } 324 .debug_weaknames 0 : { *(.debug_weaknames) } 325 .debug_funcnames 0 : { *(.debug_funcnames) } 326 .debug_typenames 0 : { *(.debug_typenames) } 327 .debug_varnames 0 : { *(.debug_varnames) } 328 329 .xt.insn 0 : 330 { 331 *(.xt.insn) 332 *(.gnu.linkonce.x*) 333 } 334 335 .xt.lit 0 : 336 { 337 *(.xt.lit) 338 *(.gnu.linkonce.p*) 339 } 340 341 /* Sections to be discarded */ 342 DISCARDS 343 /DISCARD/ : { *(.exit.literal) } 344} 345