1/* 2 * ld script for the x86 kernel 3 * 4 * Historic 32-bit version written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> 5 * 6 * Modernisation, unification and other changes and fixes: 7 * Copyright (C) 2007-2009 Sam Ravnborg <sam@ravnborg.org> 8 * 9 * 10 * Don't define absolute symbols until and unless you know that symbol 11 * value is should remain constant even if kernel image is relocated 12 * at run time. Absolute symbols are not relocated. If symbol value should 13 * change if kernel is relocated, make the symbol section relative and 14 * put it inside the section definition. 15 */ 16 17#ifdef CONFIG_X86_32 18#define LOAD_OFFSET __PAGE_OFFSET 19#else 20#define LOAD_OFFSET __START_KERNEL_map 21#endif 22 23#include <asm-generic/vmlinux.lds.h> 24#include <asm/asm-offsets.h> 25#include <asm/thread_info.h> 26#include <asm/page_types.h> 27#include <asm/cache.h> 28#include <asm/boot.h> 29 30#undef i386 /* in case the preprocessor is a 32bit one */ 31 32OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT) 33 34#ifdef CONFIG_X86_32 35OUTPUT_ARCH(i386) 36ENTRY(phys_startup_32) 37jiffies = jiffies_64; 38#else 39OUTPUT_ARCH(i386:x86-64) 40ENTRY(phys_startup_64) 41jiffies_64 = jiffies; 42#endif 43 44PHDRS { 45 text PT_LOAD FLAGS(5); /* R_E */ 46 data PT_LOAD FLAGS(7); /* RWE */ 47#ifdef CONFIG_X86_64 48 user PT_LOAD FLAGS(7); /* RWE */ 49 data.init PT_LOAD FLAGS(7); /* RWE */ 50#ifdef CONFIG_SMP 51 percpu PT_LOAD FLAGS(7); /* RWE */ 52#endif 53 data.init2 PT_LOAD FLAGS(7); /* RWE */ 54#endif 55 note PT_NOTE FLAGS(0); /* ___ */ 56} 57 58SECTIONS 59{ 60#ifdef CONFIG_X86_32 61 . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR; 62 phys_startup_32 = startup_32 - LOAD_OFFSET; 63#else 64 . = __START_KERNEL; 65 phys_startup_64 = startup_64 - LOAD_OFFSET; 66#endif 67 68 /* Text and read-only data */ 69 70 /* bootstrapping code */ 71 .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) { 72 _text = .; 73 *(.text.head) 74 } :text = 0x9090 75 76 /* The rest of the text */ 77 .text : AT(ADDR(.text) - LOAD_OFFSET) { 78#ifdef CONFIG_X86_32 79 /* not really needed, already page aligned */ 80 . = ALIGN(PAGE_SIZE); 81 *(.text.page_aligned) 82#endif 83 . = ALIGN(8); 84 _stext = .; 85 TEXT_TEXT 86 SCHED_TEXT 87 LOCK_TEXT 88 KPROBES_TEXT 89 IRQENTRY_TEXT 90 *(.fixup) 91 *(.gnu.warning) 92 /* End of text section */ 93 _etext = .; 94 } :text = 0x9090 95 96 NOTES :text :note 97 98 /* Exception table */ 99 . = ALIGN(16); 100 __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { 101 __start___ex_table = .; 102 *(__ex_table) 103 __stop___ex_table = .; 104 } :text = 0x9090 105 106 RODATA 107 108 /* Data */ 109 . = ALIGN(PAGE_SIZE); 110 .data : AT(ADDR(.data) - LOAD_OFFSET) { 111 /* Start of data section */ 112 _sdata = .; 113 DATA_DATA 114 CONSTRUCTORS 115 } :data 116 117#ifdef CONFIG_X86_32 118 /* 32 bit has nosave before _edata */ 119 . = ALIGN(PAGE_SIZE); 120 .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { 121 __nosave_begin = .; 122 *(.data.nosave) 123 . = ALIGN(PAGE_SIZE); 124 __nosave_end = .; 125 } 126#endif 127 128 . = ALIGN(PAGE_SIZE); 129 .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { 130 *(.data.page_aligned) 131 *(.data.idt) 132 } 133 134#ifdef CONFIG_X86_32 135 . = ALIGN(32); 136#else 137 . = ALIGN(PAGE_SIZE); 138 . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); 139#endif 140 .data.cacheline_aligned : 141 AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { 142 *(.data.cacheline_aligned) 143 } 144 145 /* rarely changed data like cpu maps */ 146#ifdef CONFIG_X86_32 147 . = ALIGN(32); 148#else 149 . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES); 150#endif 151 .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { 152 *(.data.read_mostly) 153 154 /* End of data section */ 155 _edata = .; 156 } 157 158#ifdef CONFIG_X86_64 159 160#define VSYSCALL_ADDR (-10*1024*1024) 161#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + \ 162 SIZEOF(.data.read_mostly) + 4095) & ~(4095)) 163#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + \ 164 SIZEOF(.data.read_mostly) + 4095) & ~(4095)) 165 166#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR) 167#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET) 168 169#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR) 170#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) 171 172 . = VSYSCALL_ADDR; 173 .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { 174 *(.vsyscall_0) 175 } :user 176 177 __vsyscall_0 = VSYSCALL_VIRT_ADDR; 178 179 . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); 180 .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { 181 *(.vsyscall_fn) 182 } 183 184 . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); 185 .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) { 186 *(.vsyscall_gtod_data) 187 } 188 189 vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data); 190 .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) { 191 *(.vsyscall_clock) 192 } 193 vsyscall_clock = VVIRT(.vsyscall_clock); 194 195 196 .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { 197 *(.vsyscall_1) 198 } 199 .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { 200 *(.vsyscall_2) 201 } 202 203 .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { 204 *(.vgetcpu_mode) 205 } 206 vgetcpu_mode = VVIRT(.vgetcpu_mode); 207 208 . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); 209 .jiffies : AT(VLOAD(.jiffies)) { 210 *(.jiffies) 211 } 212 jiffies = VVIRT(.jiffies); 213 214 .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { 215 *(.vsyscall_3) 216 } 217 218 . = VSYSCALL_VIRT_ADDR + PAGE_SIZE; 219 220#undef VSYSCALL_ADDR 221#undef VSYSCALL_PHYS_ADDR 222#undef VSYSCALL_VIRT_ADDR 223#undef VLOAD_OFFSET 224#undef VLOAD 225#undef VVIRT_OFFSET 226#undef VVIRT 227 228#endif /* CONFIG_X86_64 */ 229 230 /* init_task */ 231 . = ALIGN(THREAD_SIZE); 232 .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { 233 *(.data.init_task) 234 } 235#ifdef CONFIG_X86_64 236 :data.init 237#endif 238 239 /* 240 * smp_locks might be freed after init 241 * start/end must be page aligned 242 */ 243 . = ALIGN(PAGE_SIZE); 244 .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { 245 __smp_locks = .; 246 *(.smp_locks) 247 __smp_locks_end = .; 248 . = ALIGN(PAGE_SIZE); 249 } 250 251 /* Init code and data - will be freed after init */ 252 . = ALIGN(PAGE_SIZE); 253 .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { 254 __init_begin = .; /* paired with __init_end */ 255 _sinittext = .; 256 INIT_TEXT 257 _einittext = .; 258 } 259 260 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { 261 INIT_DATA 262 } 263 264 . = ALIGN(16); 265 .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { 266 __setup_start = .; 267 *(.init.setup) 268 __setup_end = .; 269 } 270 .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { 271 __initcall_start = .; 272 INITCALLS 273 __initcall_end = .; 274 } 275 276 .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { 277 __con_initcall_start = .; 278 *(.con_initcall.init) 279 __con_initcall_end = .; 280 } 281 282 .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { 283 __x86_cpu_dev_start = .; 284 *(.x86_cpu_dev.init) 285 __x86_cpu_dev_end = .; 286 } 287 288 SECURITY_INIT 289 290 . = ALIGN(8); 291 .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { 292 __parainstructions = .; 293 *(.parainstructions) 294 __parainstructions_end = .; 295 } 296 297 . = ALIGN(8); 298 .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { 299 __alt_instructions = .; 300 *(.altinstructions) 301 __alt_instructions_end = .; 302 } 303 304 .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { 305 *(.altinstr_replacement) 306 } 307 308 /* 309 * .exit.text is discard at runtime, not link time, to deal with 310 * references from .altinstructions and .eh_frame 311 */ 312 .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { 313 EXIT_TEXT 314 } 315 316 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { 317 EXIT_DATA 318 } 319 320#ifdef CONFIG_BLK_DEV_INITRD 321 . = ALIGN(PAGE_SIZE); 322 .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { 323 __initramfs_start = .; 324 *(.init.ramfs) 325 __initramfs_end = .; 326 } 327#endif 328 329#if defined(CONFIG_X86_64) && defined(CONFIG_SMP) 330 /* 331 * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the 332 * output PHDR, so the next output section - __data_nosave - should 333 * start another section data.init2. Also, pda should be at the head of 334 * percpu area. Preallocate it and define the percpu offset symbol 335 * so that it can be accessed as a percpu variable. 336 */ 337 . = ALIGN(PAGE_SIZE); 338 PERCPU_VADDR(0, :percpu) 339#else 340 PERCPU(PAGE_SIZE) 341#endif 342 343 . = ALIGN(PAGE_SIZE); 344 345 /* freed after init ends here */ 346 .init.end : AT(ADDR(.init.end) - LOAD_OFFSET) { 347 __init_end = .; 348 } 349 350#ifdef CONFIG_X86_64 351 .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { 352 . = ALIGN(PAGE_SIZE); 353 __nosave_begin = .; 354 *(.data.nosave) 355 . = ALIGN(PAGE_SIZE); 356 __nosave_end = .; 357 } :data.init2 358 /* use another section data.init2, see PERCPU_VADDR() above */ 359#endif 360 361 /* BSS */ 362 . = ALIGN(PAGE_SIZE); 363 .bss : AT(ADDR(.bss) - LOAD_OFFSET) { 364 __bss_start = .; 365 *(.bss.page_aligned) 366 *(.bss) 367 . = ALIGN(4); 368 __bss_stop = .; 369 } 370 371 . = ALIGN(PAGE_SIZE); 372 .brk : AT(ADDR(.brk) - LOAD_OFFSET) { 373 __brk_base = .; 374 . += 64 * 1024; /* 64k alignment slop space */ 375 *(.brk_reservation) /* areas brk users have reserved */ 376 __brk_limit = .; 377 } 378 379 .end : AT(ADDR(.end) - LOAD_OFFSET) { 380 _end = .; 381 } 382 383 /* Sections to be discarded */ 384 /DISCARD/ : { 385 *(.exitcall.exit) 386 *(.eh_frame) 387 *(.discard) 388 } 389 390 STABS_DEBUG 391 DWARF_DEBUG 392} 393 394 395#ifdef CONFIG_X86_32 396. = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE), 397 "kernel image bigger than KERNEL_IMAGE_SIZE"); 398#else 399/* 400 * Per-cpu symbols which need to be offset from __per_cpu_load 401 * for the boot processor. 402 */ 403#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load 404INIT_PER_CPU(gdt_page); 405INIT_PER_CPU(irq_stack_union); 406 407/* 408 * Build-time check on the image size: 409 */ 410. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), 411 "kernel image bigger than KERNEL_IMAGE_SIZE"); 412 413#ifdef CONFIG_SMP 414. = ASSERT((per_cpu__irq_stack_union == 0), 415 "irq_stack_union is not at start of per-cpu area"); 416#endif 417 418#endif /* CONFIG_X86_32 */ 419 420#ifdef CONFIG_KEXEC 421#include <asm/kexec.h> 422 423. = ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE, 424 "kexec control code size is too big"); 425#endif 426 427