diff options
Diffstat (limited to 'arch/x86/kernel/vmlinux_64.lds.S')
-rw-r--r-- | arch/x86/kernel/vmlinux_64.lds.S | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 1a614c0e6bef..fbfced6f6800 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
@@ -5,7 +5,8 @@ | |||
5 | #define LOAD_OFFSET __START_KERNEL_map | 5 | #define LOAD_OFFSET __START_KERNEL_map |
6 | 6 | ||
7 | #include <asm-generic/vmlinux.lds.h> | 7 | #include <asm-generic/vmlinux.lds.h> |
8 | #include <asm/page.h> | 8 | #include <asm/asm-offsets.h> |
9 | #include <asm/page_types.h> | ||
9 | 10 | ||
10 | #undef i386 /* in case the preprocessor is a 32bit one */ | 11 | #undef i386 /* in case the preprocessor is a 32bit one */ |
11 | 12 | ||
@@ -13,12 +14,15 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") | |||
13 | OUTPUT_ARCH(i386:x86-64) | 14 | OUTPUT_ARCH(i386:x86-64) |
14 | ENTRY(phys_startup_64) | 15 | ENTRY(phys_startup_64) |
15 | jiffies_64 = jiffies; | 16 | jiffies_64 = jiffies; |
16 | _proxy_pda = 1; | ||
17 | PHDRS { | 17 | PHDRS { |
18 | text PT_LOAD FLAGS(5); /* R_E */ | 18 | text PT_LOAD FLAGS(5); /* R_E */ |
19 | data PT_LOAD FLAGS(7); /* RWE */ | 19 | data PT_LOAD FLAGS(7); /* RWE */ |
20 | user PT_LOAD FLAGS(7); /* RWE */ | 20 | user PT_LOAD FLAGS(7); /* RWE */ |
21 | data.init PT_LOAD FLAGS(7); /* RWE */ | 21 | data.init PT_LOAD FLAGS(7); /* RWE */ |
22 | #ifdef CONFIG_SMP | ||
23 | percpu PT_LOAD FLAGS(7); /* RWE */ | ||
24 | #endif | ||
25 | data.init2 PT_LOAD FLAGS(7); /* RWE */ | ||
22 | note PT_NOTE FLAGS(0); /* ___ */ | 26 | note PT_NOTE FLAGS(0); /* ___ */ |
23 | } | 27 | } |
24 | SECTIONS | 28 | SECTIONS |
@@ -208,14 +212,28 @@ SECTIONS | |||
208 | __initramfs_end = .; | 212 | __initramfs_end = .; |
209 | #endif | 213 | #endif |
210 | 214 | ||
215 | #ifdef CONFIG_SMP | ||
216 | /* | ||
217 | * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the | ||
218 | * output PHDR, so the next output section - __data_nosave - should | ||
219 | * start another section data.init2. Also, pda should be at the head of | ||
220 | * percpu area. Preallocate it and define the percpu offset symbol | ||
221 | * so that it can be accessed as a percpu variable. | ||
222 | */ | ||
223 | . = ALIGN(PAGE_SIZE); | ||
224 | PERCPU_VADDR(0, :percpu) | ||
225 | #else | ||
211 | PERCPU(PAGE_SIZE) | 226 | PERCPU(PAGE_SIZE) |
227 | #endif | ||
212 | 228 | ||
213 | . = ALIGN(PAGE_SIZE); | 229 | . = ALIGN(PAGE_SIZE); |
214 | __init_end = .; | 230 | __init_end = .; |
215 | 231 | ||
216 | . = ALIGN(PAGE_SIZE); | 232 | . = ALIGN(PAGE_SIZE); |
217 | __nosave_begin = .; | 233 | __nosave_begin = .; |
218 | .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } | 234 | .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { |
235 | *(.data.nosave) | ||
236 | } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */ | ||
219 | . = ALIGN(PAGE_SIZE); | 237 | . = ALIGN(PAGE_SIZE); |
220 | __nosave_end = .; | 238 | __nosave_end = .; |
221 | 239 | ||
@@ -239,8 +257,21 @@ SECTIONS | |||
239 | DWARF_DEBUG | 257 | DWARF_DEBUG |
240 | } | 258 | } |
241 | 259 | ||
260 | /* | ||
261 | * Per-cpu symbols which need to be offset from __per_cpu_load | ||
262 | * for the boot processor. | ||
263 | */ | ||
264 | #define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load | ||
265 | INIT_PER_CPU(gdt_page); | ||
266 | INIT_PER_CPU(irq_stack_union); | ||
267 | |||
242 | /* | 268 | /* |
243 | * Build-time check on the image size: | 269 | * Build-time check on the image size: |
244 | */ | 270 | */ |
245 | ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), | 271 | ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), |
246 | "kernel image bigger than KERNEL_IMAGE_SIZE") | 272 | "kernel image bigger than KERNEL_IMAGE_SIZE") |
273 | |||
274 | #ifdef CONFIG_SMP | ||
275 | ASSERT((per_cpu__irq_stack_union == 0), | ||
276 | "irq_stack_union is not at start of per-cpu area"); | ||
277 | #endif | ||