linker script: unify usage of discard definition
[linux-2.6.git] / arch / x86 / kernel / vmlinux.lds.S
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
32 OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT)
33
34 #ifdef CONFIG_X86_32
35 OUTPUT_ARCH(i386)
36 ENTRY(phys_startup_32)
37 jiffies = jiffies_64;
38 #else
39 OUTPUT_ARCH(i386:x86-64)
40 ENTRY(phys_startup_64)
41 jiffies_64 = jiffies;
42 #endif
43
44 PHDRS {
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
58 SECTIONS
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
116 #ifdef CONFIG_X86_64
117                 /* End of data section */
118                 _edata = .;
119 #endif
120         } :data
121
122 #ifdef CONFIG_X86_32
123         /* 32 bit has nosave before _edata */
124         . = ALIGN(PAGE_SIZE);
125         .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
126                 __nosave_begin = .;
127                 *(.data.nosave)
128                 . = ALIGN(PAGE_SIZE);
129                 __nosave_end = .;
130         }
131 #endif
132
133         . = ALIGN(PAGE_SIZE);
134         .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
135                 *(.data.page_aligned)
136                 *(.data.idt)
137         }
138
139 #ifdef CONFIG_X86_32
140         . = ALIGN(32);
141 #else
142         . = ALIGN(PAGE_SIZE);
143         . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
144 #endif
145         .data.cacheline_aligned :
146                 AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
147                 *(.data.cacheline_aligned)
148         }
149
150         /* rarely changed data like cpu maps */
151 #ifdef CONFIG_X86_32
152         . = ALIGN(32);
153 #else
154         . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
155 #endif
156         .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
157                 *(.data.read_mostly)
158
159 #ifdef CONFIG_X86_32
160                 /* End of data section */
161                 _edata = .;
162 #endif
163         }
164
165 #ifdef CONFIG_X86_64
166
167 #define VSYSCALL_ADDR (-10*1024*1024)
168 #define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + \
169                             SIZEOF(.data.read_mostly) + 4095) & ~(4095))
170 #define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + \
171                             SIZEOF(.data.read_mostly) + 4095) & ~(4095))
172
173 #define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
174 #define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
175
176 #define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
177 #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
178
179         . = VSYSCALL_ADDR;
180         .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) {
181                 *(.vsyscall_0)
182         } :user
183
184         __vsyscall_0 = VSYSCALL_VIRT_ADDR;
185
186         . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
187         .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) {
188                 *(.vsyscall_fn)
189         }
190
191         . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
192         .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) {
193                 *(.vsyscall_gtod_data)
194         }
195
196         vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
197         .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) {
198                 *(.vsyscall_clock)
199         }
200         vsyscall_clock = VVIRT(.vsyscall_clock);
201
202
203         .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) {
204                 *(.vsyscall_1)
205         }
206         .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) {
207                 *(.vsyscall_2)
208         }
209
210         .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) {
211                 *(.vgetcpu_mode)
212         }
213         vgetcpu_mode = VVIRT(.vgetcpu_mode);
214
215         . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
216         .jiffies : AT(VLOAD(.jiffies)) {
217                 *(.jiffies)
218         }
219         jiffies = VVIRT(.jiffies);
220
221         .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
222                 *(.vsyscall_3)
223         }
224
225         . = VSYSCALL_VIRT_ADDR + PAGE_SIZE;
226
227 #undef VSYSCALL_ADDR
228 #undef VSYSCALL_PHYS_ADDR
229 #undef VSYSCALL_VIRT_ADDR
230 #undef VLOAD_OFFSET
231 #undef VLOAD
232 #undef VVIRT_OFFSET
233 #undef VVIRT
234
235 #endif /* CONFIG_X86_64 */
236
237         /* init_task */
238         . = ALIGN(THREAD_SIZE);
239         .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
240                 *(.data.init_task)
241         }
242 #ifdef CONFIG_X86_64
243          :data.init
244 #endif
245
246         /*
247          * smp_locks might be freed after init
248          * start/end must be page aligned
249          */
250         . = ALIGN(PAGE_SIZE);
251         .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
252                 __smp_locks = .;
253                 *(.smp_locks)
254                 __smp_locks_end = .;
255                 . = ALIGN(PAGE_SIZE);
256         }
257
258         /* Init code and data - will be freed after init */
259         . = ALIGN(PAGE_SIZE);
260         .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
261                 __init_begin = .; /* paired with __init_end */
262                 _sinittext = .;
263                 INIT_TEXT
264                 _einittext = .;
265         }
266
267         .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
268                 INIT_DATA
269         }
270
271         . = ALIGN(16);
272         .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
273                 __setup_start = .;
274                 *(.init.setup)
275                 __setup_end = .;
276         }
277         .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
278                 __initcall_start = .;
279                 INITCALLS
280                 __initcall_end = .;
281         }
282
283         .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
284                 __con_initcall_start = .;
285                 *(.con_initcall.init)
286                 __con_initcall_end = .;
287         }
288
289         .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
290                 __x86_cpu_dev_start = .;
291                 *(.x86_cpu_dev.init)
292                 __x86_cpu_dev_end = .;
293         }
294
295         SECURITY_INIT
296
297         . = ALIGN(8);
298         .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
299                 __parainstructions = .;
300                 *(.parainstructions)
301                 __parainstructions_end = .;
302         }
303
304         . = ALIGN(8);
305         .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
306                 __alt_instructions = .;
307                 *(.altinstructions)
308                 __alt_instructions_end = .;
309         }
310
311         .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
312                 *(.altinstr_replacement)
313         }
314
315         /*
316          * .exit.text is discard at runtime, not link time, to deal with
317          *  references from .altinstructions and .eh_frame
318          */
319         .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
320                 EXIT_TEXT
321         }
322
323         .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
324                 EXIT_DATA
325         }
326
327 #ifdef CONFIG_BLK_DEV_INITRD
328         . = ALIGN(PAGE_SIZE);
329         .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
330                 __initramfs_start = .;
331                 *(.init.ramfs)
332                 __initramfs_end = .;
333         }
334 #endif
335
336 #if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
337         /*
338          * percpu offsets are zero-based on SMP.  PERCPU_VADDR() changes the
339          * output PHDR, so the next output section - __data_nosave - should
340          * start another section data.init2.  Also, pda should be at the head of
341          * percpu area.  Preallocate it and define the percpu offset symbol
342          * so that it can be accessed as a percpu variable.
343          */
344         . = ALIGN(PAGE_SIZE);
345         PERCPU_VADDR(0, :percpu)
346 #else
347         PERCPU(PAGE_SIZE)
348 #endif
349
350         . = ALIGN(PAGE_SIZE);
351
352         /* freed after init ends here */
353         .init.end : AT(ADDR(.init.end) - LOAD_OFFSET) {
354                 __init_end = .;
355         }
356
357 #ifdef CONFIG_X86_64
358         .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
359                 . = ALIGN(PAGE_SIZE);
360                 __nosave_begin = .;
361                 *(.data.nosave)
362                 . = ALIGN(PAGE_SIZE);
363                 __nosave_end = .;
364         } :data.init2
365         /* use another section data.init2, see PERCPU_VADDR() above */
366 #endif
367
368         /* BSS */
369         . = ALIGN(PAGE_SIZE);
370         .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
371                 __bss_start = .;
372                 *(.bss.page_aligned)
373                 *(.bss)
374                 . = ALIGN(4);
375                 __bss_stop = .;
376         }
377
378         . = ALIGN(PAGE_SIZE);
379         .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
380                 __brk_base = .;
381                 . += 64 * 1024;         /* 64k alignment slop space */
382                 *(.brk_reservation)     /* areas brk users have reserved */
383                 __brk_limit = .;
384         }
385
386         .end : AT(ADDR(.end) - LOAD_OFFSET) {
387                 _end = .;
388         }
389
390         STABS_DEBUG
391         DWARF_DEBUG
392
393         /* Sections to be discarded */
394         DISCARDS
395         /DISCARD/ : { *(.eh_frame) }
396 }
397
398
399 #ifdef CONFIG_X86_32
400 ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
401         "kernel image bigger than KERNEL_IMAGE_SIZE")
402 #else
403 /*
404  * Per-cpu symbols which need to be offset from __per_cpu_load
405  * for the boot processor.
406  */
407 #define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
408 INIT_PER_CPU(gdt_page);
409 INIT_PER_CPU(irq_stack_union);
410
411 /*
412  * Build-time check on the image size:
413  */
414 ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
415         "kernel image bigger than KERNEL_IMAGE_SIZE")
416
417 #ifdef CONFIG_SMP
418 ASSERT((per_cpu__irq_stack_union == 0),
419         "irq_stack_union is not at start of per-cpu area");
420 #endif
421
422 #endif /* CONFIG_X86_32 */
423
424 #ifdef CONFIG_KEXEC
425 #include <asm/kexec.h>
426
427 ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
428        "kexec control code size is too big")
429 #endif
430