| 1 | /* |
| 2 | * arch/ubicom32/kernel/vmlinux.lds.S |
| 3 | * vmlinux primary linker script |
| 4 | * |
| 5 | * (C) Copyright 2009, Ubicom, Inc. |
| 6 | * |
| 7 | * This file is part of the Ubicom32 Linux Kernel Port. |
| 8 | * |
| 9 | * The Ubicom32 Linux Kernel Port is free software: you can redistribute |
| 10 | * it and/or modify it under the terms of the GNU General Public License |
| 11 | * as published by the Free Software Foundation, either version 2 of the |
| 12 | * License, or (at your option) any later version. |
| 13 | * |
| 14 | * The Ubicom32 Linux Kernel Port is distributed in the hope that it |
| 15 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 16 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 17 | * the GNU General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with the Ubicom32 Linux Kernel Port. If not, |
| 21 | * see <http://www.gnu.org/licenses/>. |
| 22 | * |
| 23 | * Ubicom32 implementation derived from (with many thanks): |
| 24 | * arch/m68knommu |
| 25 | * arch/blackfin |
| 26 | * arch/parisc |
| 27 | */ |
| 28 | #include <asm-generic/vmlinux.lds.h> |
| 29 | #include <asm/ocm_size.h> |
| 30 | #include <asm/memory_map.h> |
| 31 | #include <asm/thread_info.h> |
| 32 | #include <linux/threads.h> |
| 33 | |
| 34 | /* |
| 35 | * Sanity checks to prevent errors later on that are much harder to understand |
| 36 | */ |
| 37 | #if !defined APP_OCM_CODE_SIZE |
| 38 | #error APP_OCM_CODE_SIZE has not been defined in ocm_size.h |
| 39 | #endif |
| 40 | |
| 41 | #if !defined APP_OCM_DATA_SIZE |
| 42 | #error APP_OCM_DATA_SIZE has not been defined in ocm_size.h |
| 43 | #endif |
| 44 | |
| 45 | /* |
| 46 | * The `free' ocm area that ultra does not use. |
| 47 | */ |
| 48 | #if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE |
| 49 | #define OCM_FREE_START (OCMSTART + APP_OCM_CODE_SIZE) |
| 50 | #define OCM_FREE_LENGTH (OCMSIZE - APP_OCM_CODE_SIZE - APP_OCM_DATA_SIZE) |
| 51 | #else |
| 52 | #define OCM_FREE_START OCMEND |
| 53 | #define OCM_FREE_LENGTH 0 |
| 54 | #endif |
| 55 | |
| 56 | /* |
| 57 | * If you want to limit OCM use for text/data or completely disable it |
| 58 | * you can change these values. |
| 59 | */ |
| 60 | #define OCM_TEXT_LENGTH OCM_FREE_LENGTH |
| 61 | #define OCM_DATA_LENGTH OCM_FREE_LENGTH |
| 62 | |
| 63 | #define RAM_START KERNELSTART |
| 64 | #define RAM_LENGTH ((SDRAMSTART + CONFIG_MIN_RAMSIZE) - RAM_START) |
| 65 | #define TEXT ram |
| 66 | #define DATA ram |
| 67 | #define INIT ram |
| 68 | #define BSS ram |
| 69 | |
| 70 | #ifndef DATA_ADDR |
| 71 | #define DATA_ADDR |
| 72 | #endif |
| 73 | |
| 74 | #include <asm-generic/vmlinux.lds.h> |
| 75 | |
| 76 | OUTPUT_ARCH(ubicom32) |
| 77 | ENTRY(_start) |
| 78 | |
| 79 | MEMORY { |
| 80 | ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH |
| 81 | syscall : ORIGIN = OS_SYSCALL_BEGIN, LENGTH = (OS_SYSCALL_END - OS_SYSCALL_BEGIN) |
| 82 | ocm : ORIGIN = OCM_FREE_START, LENGTH = OCM_FREE_LENGTH |
| 83 | } |
| 84 | |
| 85 | jiffies = jiffies_64 + 4; |
| 86 | |
| 87 | /* |
| 88 | * Fixed locations required by gdb coredumps. |
| 89 | * |
| 90 | * Note that the names are what gdb is expecting so renaming will break |
| 91 | * the toolchain. |
| 92 | */ |
| 93 | __ocm_begin = OCMSTART; |
| 94 | __ocm_limit = __ocm_begin + OCMSIZE; |
| 95 | __sdram_begin = SDRAMSTART; |
| 96 | __sdram_limit = __sdram_begin + CONFIG_MIN_RAMSIZE; |
| 97 | __filemedia_begin_addr = FLASHSTART; |
| 98 | __filemedia_end_addr = __filemedia_begin_addr + 0x00800000; |
| 99 | |
| 100 | /* |
| 101 | * For internal diagnostics |
| 102 | */ |
| 103 | __os_syscall_begin = OS_SYSCALL_BEGIN; |
| 104 | __os_syscall_end = OS_SYSCALL_END; |
| 105 | |
| 106 | SECTIONS { |
| 107 | |
| 108 | .fixed_text : { |
| 109 | _begin = .; |
| 110 | *(.skip_syscall) |
| 111 | *(.old_syscall_entry.text) |
| 112 | __fixed_text_end = .; |
| 113 | } > TEXT |
| 114 | . = _begin + SIZEOF(.fixed_text) ; |
| 115 | |
| 116 | /* |
| 117 | * System call text in lower ocm (fixed location, can never change) |
| 118 | */ |
| 119 | __syscall_text_load_begin = .; |
| 120 | __syscall_text_run_begin = OS_SYSCALL_BEGIN; |
| 121 | |
| 122 | .syscall_text __syscall_text_run_begin : AT(__syscall_text_load_begin) { |
| 123 | *(.syscall_entry.text) /* Must be at OS_SYSCALL_BEGIN 0x3ffc0040 */ |
| 124 | *(.kernel_unprotected) |
| 125 | . = ALIGN(4); |
| 126 | __syscall_text_run_end = .; |
| 127 | } > syscall /* .syscall_text */ |
| 128 | . = __syscall_text_load_begin + __syscall_text_run_end - __syscall_text_run_begin ; |
| 129 | __ocm_text_load_begin = .; |
| 130 | __ocm_text_run_begin = OCM_FREE_START ; |
| 131 | .ocm_text __ocm_text_run_begin : AT(__ocm_text_load_begin) { |
| 132 | #if OCM_TEXT_LENGTH |
| 133 | *(.ocm_text) |
| 134 | *(.sched.text) |
| 135 | *(.spinlock.text) |
| 136 | #include <asm/ocm_text.lds.inc> |
| 137 | . = ALIGN(4); |
| 138 | #endif |
| 139 | __ocm_text_run_end = .; |
| 140 | __data_begin = ALIGN(OCM_SECTOR_SIZE); |
| 141 | } > ocm /* .ocm_text */ |
| 142 | |
| 143 | .ocm_module_text __ocm_text_run_end (NOLOAD) : AT(__ocm_text_run_end) { |
| 144 | __ocm_inst_heap_begin = .; |
| 145 | /* Reserve the min requested */ |
| 146 | . += (CONFIG_OCM_MODULES_RESERVATION) * 1024; |
| 147 | #ifdef CONFIG_OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE |
| 148 | /* Round up to OCM sector size (we cannot use it for data) */ |
| 149 | . = ALIGN(OCM_SECTOR_SIZE); |
| 150 | #endif |
| 151 | __ocm_inst_heap_end = .; |
| 152 | /* update __data_begin */ |
| 153 | __data_begin = ALIGN(OCM_SECTOR_SIZE); |
| 154 | } > ocm /* .ocm_module_text */ |
| 155 | |
| 156 | . = __ocm_text_load_begin + __ocm_text_run_end - __ocm_text_run_begin ; |
| 157 | __ocm_text_load_end = .; |
| 158 | |
| 159 | __ocm_data_load_begin = .; |
| 160 | __ocm_data_run_begin = __data_begin ; |
| 161 | #if OCM_DATA_LENGTH |
| 162 | .ocm_data __ocm_data_run_begin : AT(__ocm_data_load_begin) { |
| 163 | #if defined(CONFIG_IRQSTACKS_USEOCM) |
| 164 | percpu_irq_stacks = .; |
| 165 | . += NR_CPUS * THREAD_SIZE; |
| 166 | #endif |
| 167 | *(.ocm_data) |
| 168 | . = ALIGN(4) ; |
| 169 | __ocm_data_run_end = .; |
| 170 | } > ocm |
| 171 | . = __ocm_data_load_begin + __ocm_data_run_end - __ocm_data_run_begin ; |
| 172 | #else |
| 173 | __ocm_data_run_end = __ocm_data_run_begin; |
| 174 | #endif |
| 175 | __ocm_data_load_end = .; |
| 176 | |
| 177 | __ocm_free_begin = __ocm_data_run_end; |
| 178 | __ocm_free_end = OCM_FREE_START + OCM_FREE_LENGTH; |
| 179 | |
| 180 | .text __ocm_data_load_end : AT(__ocm_data_load_end) { |
| 181 | . = ALIGN(4); |
| 182 | _stext = .; |
| 183 | _text = .; |
| 184 | TEXT_TEXT |
| 185 | SCHED_TEXT |
| 186 | LOCK_TEXT |
| 187 | *(.text.lock) |
| 188 | *(.text.__libgcc_udivmodsi) |
| 189 | *(.text.__libgcc_divmodsi) |
| 190 | *(.text.__libgcc_muldi3) |
| 191 | *(.text.__libgcc_udivmoddi) |
| 192 | *(.text.__libgcc_divmoddi) |
| 193 | *(.text.*) |
| 194 | #if OCM_TEXT_LENGTH == 0 |
| 195 | *(.ocm_text) |
| 196 | *(.sched.text) |
| 197 | *(.spinlock.text) |
| 198 | #endif |
| 199 | . = ALIGN(16); /* Exception table */ |
| 200 | __start___ex_table = .; |
| 201 | *(__ex_table) |
| 202 | __stop___ex_table = .; |
| 203 | |
| 204 | *(.rodata) *(.rodata.*) |
| 205 | *(__vermagic) /* Kernel version magic */ |
| 206 | *(__markers_strings) |
| 207 | *(.rodata1) |
| 208 | *(.rodata.str1.1) |
| 209 | *(__tracepoints_strings) |
| 210 | |
| 211 | /* PCI quirks */ |
| 212 | __start_pci_fixups_early = . ; |
| 213 | *(.pci_fixup_early) |
| 214 | __end_pci_fixups_early = . ; |
| 215 | __start_pci_fixups_header = . ; |
| 216 | *(.pci_fixup_header) |
| 217 | __end_pci_fixups_header = . ; |
| 218 | __start_pci_fixups_final = . ; |
| 219 | *(.pci_fixup_final) |
| 220 | __end_pci_fixups_final = . ; |
| 221 | __start_pci_fixups_enable = . ; |
| 222 | *(.pci_fixup_enable) |
| 223 | __end_pci_fixups_enable = . ; |
| 224 | __start_pci_fixups_resume = . ; |
| 225 | *(.pci_fixup_resume) |
| 226 | __end_pci_fixups_resume = . ; |
| 227 | __start_pci_fixups_resume_early = . ; |
| 228 | *(.pci_fixup_resume_early) |
| 229 | __end_pci_fixups_resume_early = . ; |
| 230 | __start_pci_fixups_suspend = . ; |
| 231 | *(.pci_fixup_suspend) |
| 232 | __end_pci_fixups_suspend = . ; |
| 233 | |
| 234 | __start_builtin_fw = . ; |
| 235 | *(.builtin_fw) |
| 236 | __end_builtin_fw = . ; |
| 237 | |
| 238 | |
| 239 | /* Kernel symbol table: Normal symbols */ |
| 240 | . = ALIGN(4); |
| 241 | __start___ksymtab = .; |
| 242 | *(__ksymtab) |
| 243 | __stop___ksymtab = .; |
| 244 | |
| 245 | /* Kernel symbol table: GPL-only symbols */ |
| 246 | __start___ksymtab_gpl = .; |
| 247 | *(__ksymtab_gpl) |
| 248 | __stop___ksymtab_gpl = .; |
| 249 | |
| 250 | /* Kernel symbol table: Normal unused symbols */ |
| 251 | __start___ksymtab_unused = .; |
| 252 | *(__ksymtab_unused) |
| 253 | __stop___ksymtab_unused = .; |
| 254 | |
| 255 | /* Kernel symbol table: GPL-only unused symbols */ |
| 256 | __start___ksymtab_unused_gpl = .; |
| 257 | *(__ksymtab_unused_gpl) |
| 258 | __stop___ksymtab_unused_gpl = .; |
| 259 | |
| 260 | /* Kernel symbol table: GPL-future symbols */ |
| 261 | __start___ksymtab_gpl_future = .; |
| 262 | *(__ksymtab_gpl_future) |
| 263 | __stop___ksymtab_gpl_future = .; |
| 264 | |
| 265 | /* Kernel symbol table: Normal symbols */ |
| 266 | __start___kcrctab = .; |
| 267 | *(__kcrctab) |
| 268 | __stop___kcrctab = .; |
| 269 | |
| 270 | /* Kernel symbol table: GPL-only symbols */ |
| 271 | __start___kcrctab_gpl = .; |
| 272 | *(__kcrctab_gpl) |
| 273 | __stop___kcrctab_gpl = .; |
| 274 | |
| 275 | /* Kernel symbol table: GPL-future symbols */ |
| 276 | __start___kcrctab_gpl_future = .; |
| 277 | *(__kcrctab_gpl_future) |
| 278 | __stop___kcrctab_gpl_future = .; |
| 279 | |
| 280 | /* Kernel symbol table: strings */ |
| 281 | *(__ksymtab_strings) |
| 282 | |
| 283 | /* Built-in module parameters */ |
| 284 | . = ALIGN(4) ; |
| 285 | __start___param = .; |
| 286 | *(__param) |
| 287 | __stop___param = .; |
| 288 | |
| 289 | . = ALIGN(4) ; |
| 290 | _etext = . ; |
| 291 | } > TEXT |
| 292 | |
| 293 | .data DATA_ADDR : { |
| 294 | . = ALIGN(4); |
| 295 | _sdata = . ; |
| 296 | DATA_DATA |
| 297 | #if OCM_DATA_LENGTH == 0 |
| 298 | *(.ocm_data) |
| 299 | #endif |
| 300 | . = ALIGN(8192) ; |
| 301 | _data_protection_end = .; |
| 302 | *(.data.init_task) |
| 303 | . = ALIGN(4); |
| 304 | _edata = . ; |
| 305 | } > DATA |
| 306 | |
| 307 | .init : { |
| 308 | . = ALIGN(4096); |
| 309 | __init_begin = .; |
| 310 | _sinittext = .; |
| 311 | INIT_TEXT |
| 312 | _einittext = .; |
| 313 | *(.init.rodata) |
| 314 | INIT_DATA |
| 315 | . = ALIGN(16); |
| 316 | __setup_start = .; |
| 317 | *(.init.setup) |
| 318 | __setup_end = .; |
| 319 | __initcall_start = .; |
| 320 | INITCALLS |
| 321 | __initcall_end = .; |
| 322 | __con_initcall_start = .; |
| 323 | *(.con_initcall.init) |
| 324 | __con_initcall_end = .; |
| 325 | ___security_initcall_start = .; |
| 326 | *(.security_initcall.init) |
| 327 | ___security_initcall_end = .; |
| 328 | #ifdef CONFIG_BLK_DEV_INITRD |
| 329 | . = ALIGN(4); |
| 330 | __initramfs_start = .; |
| 331 | *(.init.ramfs) |
| 332 | __initramfs_end = .; |
| 333 | #endif |
| 334 | . = ALIGN(4096); |
| 335 | __per_cpu_start = .; |
| 336 | *(.data.percpu) |
| 337 | *(.data.percpu.shared_aligned) |
| 338 | __per_cpu_end = .; |
| 339 | |
| 340 | . = ALIGN(4096); |
| 341 | __init_end = .; |
| 342 | } > INIT |
| 343 | |
| 344 | .eh_frame : |
| 345 | { |
| 346 | PROVIDE (___eh_frame_begin = .); |
| 347 | *(.eh_frame) |
| 348 | LONG (0); |
| 349 | PROVIDE (___eh_frame_end = .); |
| 350 | } > INIT |
| 351 | |
| 352 | /DISCARD/ : { |
| 353 | EXIT_TEXT |
| 354 | EXIT_DATA |
| 355 | *(.exitcall.exit) |
| 356 | } |
| 357 | |
| 358 | .bss : { |
| 359 | . = ALIGN(4); |
| 360 | _sbss = . ; |
| 361 | *(.bss) |
| 362 | *(COMMON) |
| 363 | . = ALIGN(4) ; |
| 364 | _ebss = . ; |
| 365 | _end = . ; |
| 366 | } > BSS |
| 367 | |
| 368 | NOTES > BSS |
| 369 | |
| 370 | } |
| 371 | |