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/core.h> 22#include <asm/vectors.h> 23 24OUTPUT_ARCH(xtensa) 25ENTRY(_start) 26 27#ifdef __XTENSA_EB__ 28jiffies = jiffies_64 + 4; 29#else 30jiffies = jiffies_64; 31#endif 32 33/* Note: In the following macros, it would be nice to specify only the 34 vector name and section kind and construct "sym" and "section" using 35 CPP concatenation, but that does not work reliably. Concatenating a 36 string with "." produces an invalid token. CPP will not print a 37 warning because it thinks this is an assembly file, but it leaves 38 them as multiple tokens and there may or may not be whitespace 39 between them. */ 40 41/* Macro for a relocation entry */ 42 43#define RELOCATE_ENTRY(sym, section) \ 44 LONG(sym ## _start); \ 45 LONG(sym ## _end); \ 46 LONG(LOADADDR(section)) 47 48/* 49 * Macro to define a section for a vector. When CONFIG_VECTORS_OFFSET is 50 * defined code for every vector is located with other init data. At startup 51 * time head.S copies code for every vector to its final position according 52 * to description recorded in the corresponding RELOCATE_ENTRY. 53 */ 54 55#ifdef CONFIG_VECTORS_OFFSET 56#define SECTION_VECTOR(sym, section, addr, prevsec) \ 57 section addr : AT(((LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \ 58 { \ 59 . = ALIGN(4); \ 60 sym ## _start = ABSOLUTE(.); \ 61 *(section) \ 62 sym ## _end = ABSOLUTE(.); \ 63 } 64#else 65#define SECTION_VECTOR(section, addr) \ 66 . = addr; \ 67 *(section) 68#endif 69 70/* 71 * Mapping of input sections to output sections when linking. 72 */ 73 74SECTIONS 75{ 76 . = KERNELOFFSET; 77 /* .text section */ 78 79 _text = .; 80 _stext = .; 81 82 .text : 83 { 84 /* The HEAD_TEXT section must be the first section! */ 85 HEAD_TEXT 86 87#ifndef CONFIG_VECTORS_OFFSET 88 . = ALIGN(PAGE_SIZE); 89 _vecbase = .; 90 91 SECTION_VECTOR (.WindowVectors.text, WINDOW_VECTORS_VADDR) 92#if XCHAL_EXCM_LEVEL >= 2 93 SECTION_VECTOR (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR) 94#endif 95#if XCHAL_EXCM_LEVEL >= 3 96 SECTION_VECTOR (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR) 97#endif 98#if XCHAL_EXCM_LEVEL >= 4 99 SECTION_VECTOR (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR) 100#endif 101#if XCHAL_EXCM_LEVEL >= 5 102 SECTION_VECTOR (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR) 103#endif 104#if XCHAL_EXCM_LEVEL >= 6 105 SECTION_VECTOR (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR) 106#endif 107 SECTION_VECTOR (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR) 108 SECTION_VECTOR (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR) 109 SECTION_VECTOR (.UserExceptionVector.text, USER_VECTOR_VADDR) 110 SECTION_VECTOR (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR) 111#endif 112 113 IRQENTRY_TEXT 114 SOFTIRQENTRY_TEXT 115 ENTRY_TEXT 116 TEXT_TEXT 117 SCHED_TEXT 118 CPUIDLE_TEXT 119 LOCK_TEXT 120 121 } 122 _etext = .; 123 PROVIDE (etext = .); 124 125 . = ALIGN(16); 126 127 RODATA 128 129 /* Relocation table */ 130 131 .fixup : { *(.fixup) } 132 133 EXCEPTION_TABLE(16) 134 NOTES 135 /* Data section */ 136 137 _sdata = .; 138 RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) 139 _edata = .; 140 141 /* Initialization code and data: */ 142 143 . = ALIGN(PAGE_SIZE); 144 __init_begin = .; 145 INIT_TEXT_SECTION(PAGE_SIZE) 146 147 .init.data : 148 { 149 INIT_DATA 150 . = ALIGN(0x4); 151 __tagtable_begin = .; 152 *(.taglist) 153 __tagtable_end = .; 154 155 . = ALIGN(16); 156 __boot_reloc_table_start = ABSOLUTE(.); 157 158#ifdef CONFIG_VECTORS_OFFSET 159 RELOCATE_ENTRY(_WindowVectors_text, 160 .WindowVectors.text); 161#if XCHAL_EXCM_LEVEL >= 2 162 RELOCATE_ENTRY(_Level2InterruptVector_text, 163 .Level2InterruptVector.text); 164#endif 165#if XCHAL_EXCM_LEVEL >= 3 166 RELOCATE_ENTRY(_Level3InterruptVector_text, 167 .Level3InterruptVector.text); 168#endif 169#if XCHAL_EXCM_LEVEL >= 4 170 RELOCATE_ENTRY(_Level4InterruptVector_text, 171 .Level4InterruptVector.text); 172#endif 173#if XCHAL_EXCM_LEVEL >= 5 174 RELOCATE_ENTRY(_Level5InterruptVector_text, 175 .Level5InterruptVector.text); 176#endif 177#if XCHAL_EXCM_LEVEL >= 6 178 RELOCATE_ENTRY(_Level6InterruptVector_text, 179 .Level6InterruptVector.text); 180#endif 181 RELOCATE_ENTRY(_KernelExceptionVector_text, 182 .KernelExceptionVector.text); 183 RELOCATE_ENTRY(_UserExceptionVector_text, 184 .UserExceptionVector.text); 185 RELOCATE_ENTRY(_DoubleExceptionVector_text, 186 .DoubleExceptionVector.text); 187 RELOCATE_ENTRY(_DebugInterruptVector_text, 188 .DebugInterruptVector.text); 189#endif 190#if defined(CONFIG_SMP) 191 RELOCATE_ENTRY(_SecondaryResetVector_text, 192 .SecondaryResetVector.text); 193#endif 194 195 196 __boot_reloc_table_end = ABSOLUTE(.) ; 197 198 INIT_SETUP(XCHAL_ICACHE_LINESIZE) 199 INIT_CALLS 200 CON_INITCALL 201 INIT_RAM_FS 202 } 203 204 PERCPU_SECTION(XCHAL_ICACHE_LINESIZE) 205 206 /* We need this dummy segment here */ 207 208 . = ALIGN(4); 209 .dummy : { LONG(0) } 210 211#ifdef CONFIG_VECTORS_OFFSET 212 /* The vectors are relocated to the real position at startup time */ 213 214 SECTION_VECTOR (_WindowVectors_text, 215 .WindowVectors.text, 216 WINDOW_VECTORS_VADDR, 217 .dummy) 218 SECTION_VECTOR (_DebugInterruptVector_text, 219 .DebugInterruptVector.text, 220 DEBUG_VECTOR_VADDR, 221 .WindowVectors.text) 222#undef LAST 223#define LAST .DebugInterruptVector.text 224#if XCHAL_EXCM_LEVEL >= 2 225 SECTION_VECTOR (_Level2InterruptVector_text, 226 .Level2InterruptVector.text, 227 INTLEVEL2_VECTOR_VADDR, 228 LAST) 229# undef LAST 230# define LAST .Level2InterruptVector.text 231#endif 232#if XCHAL_EXCM_LEVEL >= 3 233 SECTION_VECTOR (_Level3InterruptVector_text, 234 .Level3InterruptVector.text, 235 INTLEVEL3_VECTOR_VADDR, 236 LAST) 237# undef LAST 238# define LAST .Level3InterruptVector.text 239#endif 240#if XCHAL_EXCM_LEVEL >= 4 241 SECTION_VECTOR (_Level4InterruptVector_text, 242 .Level4InterruptVector.text, 243 INTLEVEL4_VECTOR_VADDR, 244 LAST) 245# undef LAST 246# define LAST .Level4InterruptVector.text 247#endif 248#if XCHAL_EXCM_LEVEL >= 5 249 SECTION_VECTOR (_Level5InterruptVector_text, 250 .Level5InterruptVector.text, 251 INTLEVEL5_VECTOR_VADDR, 252 LAST) 253# undef LAST 254# define LAST .Level5InterruptVector.text 255#endif 256#if XCHAL_EXCM_LEVEL >= 6 257 SECTION_VECTOR (_Level6InterruptVector_text, 258 .Level6InterruptVector.text, 259 INTLEVEL6_VECTOR_VADDR, 260 LAST) 261# undef LAST 262# define LAST .Level6InterruptVector.text 263#endif 264 SECTION_VECTOR (_KernelExceptionVector_text, 265 .KernelExceptionVector.text, 266 KERNEL_VECTOR_VADDR, 267 LAST) 268#undef LAST 269 SECTION_VECTOR (_UserExceptionVector_text, 270 .UserExceptionVector.text, 271 USER_VECTOR_VADDR, 272 .KernelExceptionVector.text) 273 SECTION_VECTOR (_DoubleExceptionVector_text, 274 .DoubleExceptionVector.text, 275 DOUBLEEXC_VECTOR_VADDR, 276 .UserExceptionVector.text) 277 278 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; 279 280#endif 281#if defined(CONFIG_SMP) 282 283 SECTION_VECTOR (_SecondaryResetVector_text, 284 .SecondaryResetVector.text, 285 RESET_VECTOR1_VADDR, 286 .DoubleExceptionVector.text) 287 288 . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text); 289 290#endif 291 292 . = ALIGN(PAGE_SIZE); 293 294 __init_end = .; 295 296 BSS_SECTION(0, 8192, 0) 297 298 _end = .; 299 300 DWARF_DEBUG 301 302 .xt.prop 0 : { KEEP(*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) } 303 .xt.insn 0 : { KEEP(*(.xt.insn .xt.insn.* .gnu.linkonce.x*)) } 304 .xt.lit 0 : { KEEP(*(.xt.lit .xt.lit.* .gnu.linkonce.p*)) } 305 306 /* Sections to be discarded */ 307 DISCARDS 308} 309