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/* 51 * Macro to define a section for a vector. When CONFIG_VECTORS_OFFSET is 52 * defined code for every vector is located with other init data. At startup 53 * time head.S copies code for every vector to its final position according 54 * to description recorded in the corresponding RELOCATE_ENTRY. 55 */ 56 57#ifdef CONFIG_VECTORS_OFFSET 58#define SECTION_VECTOR(sym, section, addr, prevsec) \ 59 section addr : AT(((LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \ 60 { \ 61 . = ALIGN(4); \ 62 sym ## _start = ABSOLUTE(.); \ 63 *(section) \ 64 sym ## _end = ABSOLUTE(.); \ 65 } 66#else 67#define SECTION_VECTOR(section, addr) \ 68 . = addr; \ 69 *(section) 70#endif 71 72/* 73 * Mapping of input sections to output sections when linking. 74 */ 75 76SECTIONS 77{ 78 . = KERNELOFFSET; 79 /* .text section */ 80 81 _text = .; 82 _stext = .; 83 84 .text : 85 { 86 /* The HEAD_TEXT section must be the first section! */ 87 HEAD_TEXT 88 89#ifndef CONFIG_VECTORS_OFFSET 90 . = ALIGN(PAGE_SIZE); 91 _vecbase = .; 92 93 SECTION_VECTOR (.WindowVectors.text, WINDOW_VECTORS_VADDR) 94#if XCHAL_EXCM_LEVEL >= 2 95 SECTION_VECTOR (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR) 96#endif 97#if XCHAL_EXCM_LEVEL >= 3 98 SECTION_VECTOR (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR) 99#endif 100#if XCHAL_EXCM_LEVEL >= 4 101 SECTION_VECTOR (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR) 102#endif 103#if XCHAL_EXCM_LEVEL >= 5 104 SECTION_VECTOR (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR) 105#endif 106#if XCHAL_EXCM_LEVEL >= 6 107 SECTION_VECTOR (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR) 108#endif 109 SECTION_VECTOR (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR) 110 SECTION_VECTOR (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR) 111 SECTION_VECTOR (.UserExceptionVector.text, USER_VECTOR_VADDR) 112 SECTION_VECTOR (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR) 113#endif 114 115 IRQENTRY_TEXT 116 SOFTIRQENTRY_TEXT 117 ENTRY_TEXT 118 TEXT_TEXT 119 SCHED_TEXT 120 CPUIDLE_TEXT 121 LOCK_TEXT 122 123 } 124 _etext = .; 125 PROVIDE (etext = .); 126 127 . = ALIGN(16); 128 129 RO_DATA(4096) 130 131 /* Relocation table */ 132 133 .fixup : { *(.fixup) } 134 135 /* Data section */ 136 137 _sdata = .; 138 RW_DATA(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