aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 23:37:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 23:37:50 -0400
commit10f2a2b0f68abf39c06cf519cbc1740fa50f900b (patch)
tree70b33e4437ae0d5ac92f56c60b048756bde7f3e4 /arch/x86/kernel
parent8814011679d1a47d8b0158fc991727a5859471a0 (diff)
parentb40827fa7268fda8a62490728a61c2856f33830b (diff)
Merge branch 'x86-trampoline-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-trampoline-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86-32, mm: Add an initial page table for core bootstrapping
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/acpi/sleep.c7
-rw-r--r--arch/x86/kernel/head32.c1
-rw-r--r--arch/x86/kernel/head_32.S55
-rw-r--r--arch/x86/kernel/reboot.c10
-rw-r--r--arch/x86/kernel/setup.c18
-rw-r--r--arch/x86/kernel/smpboot.c16
-rw-r--r--arch/x86/kernel/trampoline.c16
7 files changed, 55 insertions, 68 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index e1252074ea40..74a847835bab 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -13,6 +13,11 @@
13#include <asm/segment.h> 13#include <asm/segment.h>
14#include <asm/desc.h> 14#include <asm/desc.h>
15 15
16#ifdef CONFIG_X86_32
17#include <asm/pgtable.h>
18#include <asm/pgtable_32.h>
19#endif
20
16#include "realmode/wakeup.h" 21#include "realmode/wakeup.h"
17#include "sleep.h" 22#include "sleep.h"
18 23
@@ -91,7 +96,7 @@ int acpi_save_state_mem(void)
91 96
92#ifndef CONFIG_64BIT 97#ifndef CONFIG_64BIT
93 header->pmode_entry = (u32)&wakeup_pmode_return; 98 header->pmode_entry = (u32)&wakeup_pmode_return;
94 header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET); 99 header->pmode_cr3 = (u32)__pa(&initial_page_table);
95 saved_magic = 0x12345678; 100 saved_magic = 0x12345678;
96#else /* CONFIG_64BIT */ 101#else /* CONFIG_64BIT */
97 header->trampoline_segment = setup_trampoline() >> 4; 102 header->trampoline_segment = setup_trampoline() >> 4;
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 9a6ca2392170..763310165fa0 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -18,6 +18,7 @@
18#include <asm/apic.h> 18#include <asm/apic.h>
19#include <asm/io_apic.h> 19#include <asm/io_apic.h>
20#include <asm/bios_ebda.h> 20#include <asm/bios_ebda.h>
21#include <asm/tlbflush.h>
21 22
22static void __init i386_default_early_setup(void) 23static void __init i386_default_early_setup(void)
23{ 24{
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index fa8c1b8e09fb..bcece91dd311 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -183,13 +183,12 @@ default_entry:
183#ifdef CONFIG_X86_PAE 183#ifdef CONFIG_X86_PAE
184 184
185 /* 185 /*
186 * In PAE mode swapper_pg_dir is statically defined to contain enough 186 * In PAE mode initial_page_table is statically defined to contain
187 * entries to cover the VMSPLIT option (that is the top 1, 2 or 3 187 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
188 * entries). The identity mapping is handled by pointing two PGD 188 * entries). The identity mapping is handled by pointing two PGD entries
189 * entries to the first kernel PMD. 189 * to the first kernel PMD.
190 * 190 *
191 * Note the upper half of each PMD or PTE are always zero at 191 * Note the upper half of each PMD or PTE are always zero at this stage.
192 * this stage.
193 */ 192 */
194 193
195#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ 194#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
@@ -197,7 +196,7 @@ default_entry:
197 xorl %ebx,%ebx /* %ebx is kept at zero */ 196 xorl %ebx,%ebx /* %ebx is kept at zero */
198 197
199 movl $pa(__brk_base), %edi 198 movl $pa(__brk_base), %edi
200 movl $pa(swapper_pg_pmd), %edx 199 movl $pa(initial_pg_pmd), %edx
201 movl $PTE_IDENT_ATTR, %eax 200 movl $PTE_IDENT_ATTR, %eax
20210: 20110:
203 leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ 202 leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */
@@ -226,14 +225,14 @@ default_entry:
226 movl %eax, pa(max_pfn_mapped) 225 movl %eax, pa(max_pfn_mapped)
227 226
228 /* Do early initialization of the fixmap area */ 227 /* Do early initialization of the fixmap area */
229 movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax 228 movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
230 movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8) 229 movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
231#else /* Not PAE */ 230#else /* Not PAE */
232 231
233page_pde_offset = (__PAGE_OFFSET >> 20); 232page_pde_offset = (__PAGE_OFFSET >> 20);
234 233
235 movl $pa(__brk_base), %edi 234 movl $pa(__brk_base), %edi
236 movl $pa(swapper_pg_dir), %edx 235 movl $pa(initial_page_table), %edx
237 movl $PTE_IDENT_ATTR, %eax 236 movl $PTE_IDENT_ATTR, %eax
23810: 23710:
239 leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ 238 leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */
@@ -257,8 +256,8 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
257 movl %eax, pa(max_pfn_mapped) 256 movl %eax, pa(max_pfn_mapped)
258 257
259 /* Do early initialization of the fixmap area */ 258 /* Do early initialization of the fixmap area */
260 movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax 259 movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
261 movl %eax,pa(swapper_pg_dir+0xffc) 260 movl %eax,pa(initial_page_table+0xffc)
262#endif 261#endif
263 jmp 3f 262 jmp 3f
264/* 263/*
@@ -334,7 +333,7 @@ ENTRY(startup_32_smp)
334/* 333/*
335 * Enable paging 334 * Enable paging
336 */ 335 */
337 movl pa(initial_page_table), %eax 336 movl $pa(initial_page_table), %eax
338 movl %eax,%cr3 /* set the page table pointer.. */ 337 movl %eax,%cr3 /* set the page table pointer.. */
339 movl %cr0,%eax 338 movl %cr0,%eax
340 orl $X86_CR0_PG,%eax 339 orl $X86_CR0_PG,%eax
@@ -614,8 +613,6 @@ ignore_int:
614.align 4 613.align 4
615ENTRY(initial_code) 614ENTRY(initial_code)
616 .long i386_start_kernel 615 .long i386_start_kernel
617ENTRY(initial_page_table)
618 .long pa(swapper_pg_dir)
619 616
620/* 617/*
621 * BSS section 618 * BSS section
@@ -623,20 +620,18 @@ ENTRY(initial_page_table)
623__PAGE_ALIGNED_BSS 620__PAGE_ALIGNED_BSS
624 .align PAGE_SIZE_asm 621 .align PAGE_SIZE_asm
625#ifdef CONFIG_X86_PAE 622#ifdef CONFIG_X86_PAE
626swapper_pg_pmd: 623initial_pg_pmd:
627 .fill 1024*KPMDS,4,0 624 .fill 1024*KPMDS,4,0
628#else 625#else
629ENTRY(swapper_pg_dir) 626ENTRY(initial_page_table)
630 .fill 1024,4,0 627 .fill 1024,4,0
631#endif 628#endif
632swapper_pg_fixmap: 629initial_pg_fixmap:
633 .fill 1024,4,0 630 .fill 1024,4,0
634#ifdef CONFIG_X86_TRAMPOLINE
635ENTRY(trampoline_pg_dir)
636 .fill 1024,4,0
637#endif
638ENTRY(empty_zero_page) 631ENTRY(empty_zero_page)
639 .fill 4096,1,0 632 .fill 4096,1,0
633ENTRY(swapper_pg_dir)
634 .fill 1024,4,0
640 635
641/* 636/*
642 * This starts the data section. 637 * This starts the data section.
@@ -645,20 +640,20 @@ ENTRY(empty_zero_page)
645__PAGE_ALIGNED_DATA 640__PAGE_ALIGNED_DATA
646 /* Page-aligned for the benefit of paravirt? */ 641 /* Page-aligned for the benefit of paravirt? */
647 .align PAGE_SIZE_asm 642 .align PAGE_SIZE_asm
648ENTRY(swapper_pg_dir) 643ENTRY(initial_page_table)
649 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ 644 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */
650# if KPMDS == 3 645# if KPMDS == 3
651 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 646 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
652 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 647 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
653 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0 648 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
654# elif KPMDS == 2 649# elif KPMDS == 2
655 .long 0,0 650 .long 0,0
656 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 651 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
657 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 652 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
658# elif KPMDS == 1 653# elif KPMDS == 1
659 .long 0,0 654 .long 0,0
660 .long 0,0 655 .long 0,0
661 .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 656 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
662# else 657# else
663# error "Kernel PMDs should be 1, 2 or 3" 658# error "Kernel PMDs should be 1, 2 or 3"
664# endif 659# endif
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 7a4cf14223ba..f7f53dcd3e0a 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -371,16 +371,10 @@ void machine_real_restart(const unsigned char *code, int length)
371 CMOS_WRITE(0x00, 0x8f); 371 CMOS_WRITE(0x00, 0x8f);
372 spin_unlock(&rtc_lock); 372 spin_unlock(&rtc_lock);
373 373
374 /* Remap the kernel at virtual address zero, as well as offset zero
375 from the kernel segment. This assumes the kernel segment starts at
376 virtual address PAGE_OFFSET. */
377 memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
378 sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
379
380 /* 374 /*
381 * Use `swapper_pg_dir' as our page directory. 375 * Switch back to the initial page table.
382 */ 376 */
383 load_cr3(swapper_pg_dir); 377 load_cr3(initial_page_table);
384 378
385 /* Write 0x1234 to absolute memory location 0x472. The BIOS reads 379 /* Write 0x1234 to absolute memory location 0x472. The BIOS reads
386 this on booting to tell it to "Bypass memory test (also warm 380 this on booting to tell it to "Bypass memory test (also warm
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 420e64197850..95a32746fbf9 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -700,6 +700,17 @@ void __init setup_arch(char **cmdline_p)
700#ifdef CONFIG_X86_32 700#ifdef CONFIG_X86_32
701 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); 701 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
702 visws_early_detect(); 702 visws_early_detect();
703
704 /*
705 * copy kernel address range established so far and switch
706 * to the proper swapper page table
707 */
708 clone_pgd_range(swapper_pg_dir + KERNEL_PGD_BOUNDARY,
709 initial_page_table + KERNEL_PGD_BOUNDARY,
710 KERNEL_PGD_PTRS);
711
712 load_cr3(swapper_pg_dir);
713 __flush_tlb_all();
703#else 714#else
704 printk(KERN_INFO "Command line: %s\n", boot_command_line); 715 printk(KERN_INFO "Command line: %s\n", boot_command_line);
705#endif 716#endif
@@ -985,7 +996,12 @@ void __init setup_arch(char **cmdline_p)
985 paging_init(); 996 paging_init();
986 x86_init.paging.pagetable_setup_done(swapper_pg_dir); 997 x86_init.paging.pagetable_setup_done(swapper_pg_dir);
987 998
988 setup_trampoline_page_table(); 999#ifdef CONFIG_X86_32
1000 /* sync back kernel address range */
1001 clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
1002 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
1003 KERNEL_PGD_PTRS);
1004#endif
989 1005
990 tboot_probe(); 1006 tboot_probe();
991 1007
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index dfb50890b5b7..6af118511b4a 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -299,22 +299,16 @@ notrace static void __cpuinit start_secondary(void *unused)
299 * fragile that we want to limit the things done here to the 299 * fragile that we want to limit the things done here to the
300 * most necessary things. 300 * most necessary things.
301 */ 301 */
302 cpu_init();
303 preempt_disable();
304 smp_callin();
302 305
303#ifdef CONFIG_X86_32 306#ifdef CONFIG_X86_32
304 /* 307 /* switch away from the initial page table */
305 * Switch away from the trampoline page-table
306 *
307 * Do this before cpu_init() because it needs to access per-cpu
308 * data which may not be mapped in the trampoline page-table.
309 */
310 load_cr3(swapper_pg_dir); 308 load_cr3(swapper_pg_dir);
311 __flush_tlb_all(); 309 __flush_tlb_all();
312#endif 310#endif
313 311
314 cpu_init();
315 preempt_disable();
316 smp_callin();
317
318 /* otherwise gcc will move up smp_processor_id before the cpu_init */ 312 /* otherwise gcc will move up smp_processor_id before the cpu_init */
319 barrier(); 313 barrier();
320 /* 314 /*
@@ -785,7 +779,6 @@ do_rest:
785#ifdef CONFIG_X86_32 779#ifdef CONFIG_X86_32
786 /* Stack for startup_32 can be just as for start_secondary onwards */ 780 /* Stack for startup_32 can be just as for start_secondary onwards */
787 irq_ctx_init(cpu); 781 irq_ctx_init(cpu);
788 initial_page_table = __pa(&trampoline_pg_dir);
789#else 782#else
790 clear_tsk_thread_flag(c_idle.idle, TIF_FORK); 783 clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
791 initial_gs = per_cpu_offset(cpu); 784 initial_gs = per_cpu_offset(cpu);
@@ -934,7 +927,6 @@ int __cpuinit native_cpu_up(unsigned int cpu)
934 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; 927 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
935 928
936 err = do_boot_cpu(apicid, cpu); 929 err = do_boot_cpu(apicid, cpu);
937
938 if (err) { 930 if (err) {
939 pr_debug("do_boot_cpu failed %d\n", err); 931 pr_debug("do_boot_cpu failed %d\n", err);
940 return -EIO; 932 return -EIO;
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
index 4c3da5674e67..a375616d77f7 100644
--- a/arch/x86/kernel/trampoline.c
+++ b/arch/x86/kernel/trampoline.c
@@ -38,19 +38,3 @@ unsigned long __trampinit setup_trampoline(void)
38 memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE); 38 memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
39 return virt_to_phys(trampoline_base); 39 return virt_to_phys(trampoline_base);
40} 40}
41
42void __init setup_trampoline_page_table(void)
43{
44#ifdef CONFIG_X86_32
45 /* Copy kernel address range */
46 clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
47 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
48 KERNEL_PGD_PTRS);
49
50 /* Initialize low mappings */
51 clone_pgd_range(trampoline_pg_dir,
52 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
53 min_t(unsigned long, KERNEL_PGD_PTRS,
54 KERNEL_PGD_BOUNDARY));
55#endif
56}