diff options
-rw-r--r-- | arch/x86/include/asm/realmode.h | 32 | ||||
-rw-r--r-- | arch/x86/kernel/realmode.c | 27 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 2 | ||||
-rw-r--r-- | arch/x86/realmode/rm/header.S | 35 | ||||
-rw-r--r-- | arch/x86/realmode/rm/trampoline_32.S | 36 | ||||
-rw-r--r-- | arch/x86/realmode/rm/trampoline_64.S | 18 | ||||
-rw-r--r-- | arch/x86/realmode/rm/trampoline_common.S | 23 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup_asm.S | 2 |
8 files changed, 87 insertions, 88 deletions
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index d3ae49f4c3ef..1421eed1c8e8 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h | |||
@@ -8,25 +8,33 @@ | |||
8 | struct real_mode_header { | 8 | struct real_mode_header { |
9 | u32 text_start; | 9 | u32 text_start; |
10 | u32 ro_end; | 10 | u32 ro_end; |
11 | /* reboot */ | ||
12 | #ifdef CONFIG_X86_32 | ||
13 | u32 machine_real_restart_asm; | ||
14 | #endif | ||
15 | /* SMP trampoline */ | 11 | /* SMP trampoline */ |
16 | u32 trampoline_data; | 12 | u32 trampoline_start; |
17 | u32 trampoline_status; | 13 | u32 trampoline_status; |
18 | #ifdef CONFIG_X86_32 | 14 | u32 trampoline_header; |
19 | u32 startup_32_smp; | 15 | #ifdef CONFIG_X86_64 |
20 | u32 boot_gdt; | 16 | u32 trampoline_pgd; |
21 | #else | ||
22 | u32 startup_64_smp; | ||
23 | u32 level3_ident_pgt; | ||
24 | u32 level3_kernel_pgt; | ||
25 | #endif | 17 | #endif |
18 | /* ACPI S3 wakeup */ | ||
26 | #ifdef CONFIG_ACPI_SLEEP | 19 | #ifdef CONFIG_ACPI_SLEEP |
27 | u32 wakeup_start; | 20 | u32 wakeup_start; |
28 | u32 wakeup_header; | 21 | u32 wakeup_header; |
29 | #endif | 22 | #endif |
23 | /* APM/BIOS reboot */ | ||
24 | #ifdef CONFIG_X86_32 | ||
25 | u32 machine_real_restart_asm; | ||
26 | #endif | ||
27 | } __attribute__((__packed__)); | ||
28 | |||
29 | /* This must match data at trampoline_32/64.S */ | ||
30 | struct trampoline_header { | ||
31 | #ifdef CONFIG_X86_32 | ||
32 | u32 start; | ||
33 | u16 gdt_limit; | ||
34 | u32 gdt_base; | ||
35 | #else | ||
36 | u64 start; | ||
37 | #endif | ||
30 | } __attribute__((__packed__)); | 38 | } __attribute__((__packed__)); |
31 | 39 | ||
32 | extern struct real_mode_header *real_mode_header; | 40 | extern struct real_mode_header *real_mode_header; |
diff --git a/arch/x86/kernel/realmode.c b/arch/x86/kernel/realmode.c index 632c810ec8ea..712fba8fd774 100644 --- a/arch/x86/kernel/realmode.c +++ b/arch/x86/kernel/realmode.c | |||
@@ -17,8 +17,11 @@ void __init setup_real_mode(void) | |||
17 | u16 *seg; | 17 | u16 *seg; |
18 | int i; | 18 | int i; |
19 | unsigned char *base; | 19 | unsigned char *base; |
20 | 20 | struct trampoline_header *trampoline_header; | |
21 | size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); | 21 | size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); |
22 | #ifdef CONFIG_X86_64 | ||
23 | u64 *trampoline_pgd; | ||
24 | #endif | ||
22 | 25 | ||
23 | /* Has to be in very low memory so we can execute real-mode AP code. */ | 26 | /* Has to be in very low memory so we can execute real-mode AP code. */ |
24 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); | 27 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); |
@@ -28,7 +31,6 @@ void __init setup_real_mode(void) | |||
28 | base = __va(mem); | 31 | base = __va(mem); |
29 | memblock_reserve(mem, size); | 32 | memblock_reserve(mem, size); |
30 | real_mode_header = (struct real_mode_header *) base; | 33 | real_mode_header = (struct real_mode_header *) base; |
31 | |||
32 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", | 34 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", |
33 | base, (unsigned long long)mem, size); | 35 | base, (unsigned long long)mem, size); |
34 | 36 | ||
@@ -53,18 +55,19 @@ void __init setup_real_mode(void) | |||
53 | *ptr += __pa(base); | 55 | *ptr += __pa(base); |
54 | } | 56 | } |
55 | 57 | ||
58 | /* Must be perfomed *after* relocation. */ | ||
59 | trampoline_header = (struct trampoline_header *) | ||
60 | __va(real_mode_header->trampoline_header); | ||
61 | |||
56 | #ifdef CONFIG_X86_32 | 62 | #ifdef CONFIG_X86_32 |
57 | *((u32 *)__va(real_mode_header->startup_32_smp)) = __pa(startup_32_smp); | 63 | trampoline_header->start = __pa(startup_32_smp); |
58 | *((u32 *)__va(real_mode_header->boot_gdt)) = __pa(boot_gdt); | 64 | trampoline_header->gdt_limit = __BOOT_DS + 7; |
65 | trampoline_header->gdt_base = __pa(boot_gdt); | ||
59 | #else | 66 | #else |
60 | *((u64 *) __va(real_mode_header->startup_64_smp)) = | 67 | trampoline_header->start = (u64) secondary_startup_64; |
61 | (u64)secondary_startup_64; | 68 | trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); |
62 | 69 | trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE; | |
63 | *((u64 *) __va(real_mode_header->level3_ident_pgt)) = | 70 | trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE; |
64 | __pa(level3_ident_pgt) + _KERNPG_TABLE; | ||
65 | |||
66 | *((u64 *) __va(real_mode_header->level3_kernel_pgt)) = | ||
67 | __pa(level3_kernel_pgt) + _KERNPG_TABLE; | ||
68 | #endif | 71 | #endif |
69 | } | 72 | } |
70 | 73 | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index b8c0661e2341..757c4b1d0a02 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -667,7 +667,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) | |||
667 | volatile u32 *trampoline_status = | 667 | volatile u32 *trampoline_status = |
668 | (volatile u32 *) __va(real_mode_header->trampoline_status); | 668 | (volatile u32 *) __va(real_mode_header->trampoline_status); |
669 | /* start_ip had better be page-aligned! */ | 669 | /* start_ip had better be page-aligned! */ |
670 | unsigned long start_ip = real_mode_header->trampoline_data; | 670 | unsigned long start_ip = real_mode_header->trampoline_start; |
671 | 671 | ||
672 | unsigned long boot_error = 0; | 672 | unsigned long boot_error = 0; |
673 | int timeout; | 673 | int timeout; |
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index c83005c4d455..b4c32632bf16 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S | |||
@@ -7,28 +7,25 @@ | |||
7 | #include <linux/linkage.h> | 7 | #include <linux/linkage.h> |
8 | #include <asm/page_types.h> | 8 | #include <asm/page_types.h> |
9 | 9 | ||
10 | .section ".header", "a" | 10 | .section ".header", "a" |
11 | 11 | ||
12 | GLOBAL(real_mode_header) | 12 | GLOBAL(real_mode_header) |
13 | .long pa_text_start | 13 | .long pa_text_start |
14 | .long pa_ro_end | 14 | .long pa_ro_end |
15 | #ifdef CONFIG_X86_32 | 15 | /* SMP trampoline */ |
16 | .long pa_machine_real_restart_asm | 16 | .long pa_trampoline_start |
17 | #endif | 17 | .long pa_trampoline_status |
18 | /* SMP trampoline */ | 18 | .long pa_trampoline_header |
19 | .long pa_trampoline_data | 19 | #ifdef CONFIG_X86_64 |
20 | .long pa_trampoline_status | 20 | .long pa_trampoline_pgd; |
21 | #ifdef CONFIG_X86_32 | ||
22 | .long pa_startup_32_smp | ||
23 | .long pa_boot_gdt | ||
24 | #else | ||
25 | .long pa_startup_64_smp | ||
26 | .long pa_level3_ident_pgt | ||
27 | .long pa_level3_kernel_pgt | ||
28 | #endif | 21 | #endif |
29 | /* ACPI sleep */ | 22 | /* ACPI S3 wakeup */ |
30 | #ifdef CONFIG_ACPI_SLEEP | 23 | #ifdef CONFIG_ACPI_SLEEP |
31 | .long pa_wakeup_start | 24 | .long pa_wakeup_start |
32 | .long pa_wakeup_header | 25 | .long pa_wakeup_header |
26 | #endif | ||
27 | /* APM/BIOS reboot */ | ||
28 | #ifdef CONFIG_X86_32 | ||
29 | .long pa_machine_real_restart_asm | ||
33 | #endif | 30 | #endif |
34 | END(real_mode_header) | 31 | END(real_mode_header) |
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S index 1ecdbb59191b..6fc064b4d2b9 100644 --- a/arch/x86/realmode/rm/trampoline_32.S +++ b/arch/x86/realmode/rm/trampoline_32.S | |||
@@ -13,16 +13,10 @@ | |||
13 | * | 13 | * |
14 | * We jump into arch/x86/kernel/head_32.S. | 14 | * We jump into arch/x86/kernel/head_32.S. |
15 | * | 15 | * |
16 | * On entry to trampoline_data, the processor is in real mode | 16 | * On entry to trampoline_start, the processor is in real mode |
17 | * with 16-bit addressing and 16-bit data. CS has some value | 17 | * with 16-bit addressing and 16-bit data. CS has some value |
18 | * and IP is zero. Thus, we load CS to the physical segment | 18 | * and IP is zero. Thus, we load CS to the physical segment |
19 | * of the real mode code before doing anything further. | 19 | * of the real mode code before doing anything further. |
20 | * | ||
21 | * The structure real_mode_header includes entries that need | ||
22 | * to be set up before executing this code: | ||
23 | * | ||
24 | * startup_32_smp | ||
25 | * boot_gdt | ||
26 | */ | 20 | */ |
27 | 21 | ||
28 | #include <linux/linkage.h> | 22 | #include <linux/linkage.h> |
@@ -35,7 +29,7 @@ | |||
35 | .code16 | 29 | .code16 |
36 | 30 | ||
37 | .balign PAGE_SIZE | 31 | .balign PAGE_SIZE |
38 | ENTRY(trampoline_data) | 32 | ENTRY(trampoline_start) |
39 | wbinvd # Needed for NUMA-Q should be harmless for others | 33 | wbinvd # Needed for NUMA-Q should be harmless for others |
40 | 34 | ||
41 | LJMPW_RM(1f) | 35 | LJMPW_RM(1f) |
@@ -45,7 +39,7 @@ ENTRY(trampoline_data) | |||
45 | 39 | ||
46 | cli # We should be safe anyway | 40 | cli # We should be safe anyway |
47 | 41 | ||
48 | movl startup_32_smp, %eax # where we need to go | 42 | movl tr_start, %eax # where we need to go |
49 | 43 | ||
50 | movl $0xA5A5A5A5, trampoline_status | 44 | movl $0xA5A5A5A5, trampoline_status |
51 | # write marker for master knows we're running | 45 | # write marker for master knows we're running |
@@ -56,8 +50,8 @@ ENTRY(trampoline_data) | |||
56 | * operand size is 16bit. Use lgdtl instead to force operand size | 50 | * operand size is 16bit. Use lgdtl instead to force operand size |
57 | * to 32 bit. | 51 | * to 32 bit. |
58 | */ | 52 | */ |
59 | lidtl boot_idt_descr # load idt with 0, 0 | 53 | lidtl tr_idt # load idt with 0, 0 |
60 | lgdtl boot_gdt_descr # load gdt with whatever is appropriate | 54 | lgdtl tr_gdt # load gdt with whatever is appropriate |
61 | 55 | ||
62 | movw $1, %dx # protected mode (PE) bit | 56 | movw $1, %dx # protected mode (PE) bit |
63 | lmsw %dx # into protected mode | 57 | lmsw %dx # into protected mode |
@@ -69,22 +63,4 @@ ENTRY(trampoline_data) | |||
69 | ENTRY(startup_32) # note: also used from wakeup_asm.S | 63 | ENTRY(startup_32) # note: also used from wakeup_asm.S |
70 | jmp *%eax | 64 | jmp *%eax |
71 | 65 | ||
72 | .section ".rodata","a" | 66 | #include "trampoline_common.S" |
73 | |||
74 | .balign 4 | ||
75 | boot_idt_descr: | ||
76 | .word 0 # idt limit = 0 | ||
77 | .long 0 # idt base = 0L | ||
78 | |||
79 | .data | ||
80 | |||
81 | boot_gdt_descr: | ||
82 | .word __BOOT_DS + 7 # gdt limit | ||
83 | GLOBAL(boot_gdt) | ||
84 | .long 0 # gdt base | ||
85 | |||
86 | .bss | ||
87 | |||
88 | .balign 4 | ||
89 | GLOBAL(trampoline_status) .space 4 | ||
90 | GLOBAL(startup_32_smp) .space 4 | ||
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index f71ea0800d3d..3f7293239365 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S | |||
@@ -10,7 +10,7 @@ | |||
10 | * trampoline page to make our stack and everything else | 10 | * trampoline page to make our stack and everything else |
11 | * is a mystery. | 11 | * is a mystery. |
12 | * | 12 | * |
13 | * On entry to trampoline_data, the processor is in real mode | 13 | * On entry to trampoline_start, the processor is in real mode |
14 | * with 16-bit addressing and 16-bit data. CS has some value | 14 | * with 16-bit addressing and 16-bit data. CS has some value |
15 | * and IP is zero. Thus, data addresses need to be absolute | 15 | * and IP is zero. Thus, data addresses need to be absolute |
16 | * (no relocation) and are taken with regard to r_base. | 16 | * (no relocation) and are taken with regard to r_base. |
@@ -37,7 +37,7 @@ | |||
37 | .balign PAGE_SIZE | 37 | .balign PAGE_SIZE |
38 | .code16 | 38 | .code16 |
39 | 39 | ||
40 | ENTRY(trampoline_data) | 40 | ENTRY(trampoline_start) |
41 | cli # We should be safe anyway | 41 | cli # We should be safe anyway |
42 | wbinvd | 42 | wbinvd |
43 | 43 | ||
@@ -97,7 +97,7 @@ ENTRY(startup_32) | |||
97 | movl %eax, %cr4 # Enable PAE mode | 97 | movl %eax, %cr4 # Enable PAE mode |
98 | 98 | ||
99 | # Setup trampoline 4 level pagetables | 99 | # Setup trampoline 4 level pagetables |
100 | movl $pa_level3_ident_pgt, %eax | 100 | movl $pa_trampoline_pgd, %eax |
101 | movl %eax, %cr3 | 101 | movl %eax, %cr3 |
102 | 102 | ||
103 | movl $MSR_EFER, %ecx | 103 | movl $MSR_EFER, %ecx |
@@ -122,7 +122,7 @@ ENTRY(startup_32) | |||
122 | .balign 4 | 122 | .balign 4 |
123 | ENTRY(startup_64) | 123 | ENTRY(startup_64) |
124 | # Now jump into the kernel using virtual addresses | 124 | # Now jump into the kernel using virtual addresses |
125 | jmpq *startup_64_smp(%rip) | 125 | jmpq *tr_start(%rip) |
126 | 126 | ||
127 | .section ".rodata","a" | 127 | .section ".rodata","a" |
128 | .balign 16 | 128 | .balign 16 |
@@ -143,12 +143,4 @@ tgdt: | |||
143 | .quad 0x00cf93000000ffff # __KERNEL_DS | 143 | .quad 0x00cf93000000ffff # __KERNEL_DS |
144 | tgdt_end: | 144 | tgdt_end: |
145 | 145 | ||
146 | .bss | 146 | #include "trampoline_common.S" |
147 | |||
148 | .balign PAGE_SIZE | ||
149 | GLOBAL(level3_ident_pgt) .space 511*8 | ||
150 | GLOBAL(level3_kernel_pgt) .space 8 | ||
151 | |||
152 | .balign 8 | ||
153 | GLOBAL(startup_64_smp) .space 8 | ||
154 | GLOBAL(trampoline_status) .space 4 | ||
diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S new file mode 100644 index 000000000000..c3f951c468c5 --- /dev/null +++ b/arch/x86/realmode/rm/trampoline_common.S | |||
@@ -0,0 +1,23 @@ | |||
1 | .section ".rodata","a" | ||
2 | |||
3 | .balign 4 | ||
4 | tr_idt: .fill 1, 6, 0 | ||
5 | |||
6 | .bss | ||
7 | |||
8 | .balign 4 | ||
9 | GLOBAL(trampoline_status) .space 4 | ||
10 | |||
11 | GLOBAL(trampoline_header) | ||
12 | #ifdef CONFIG_X86_32 | ||
13 | tr_start: .space 4 | ||
14 | tr_gdt: .space 6 | ||
15 | #else | ||
16 | tr_start: .space 8 | ||
17 | #endif | ||
18 | END(trampoline_header) | ||
19 | |||
20 | #ifdef CONFIG_X86_64 | ||
21 | .balign PAGE_SIZE | ||
22 | GLOBAL(trampoline_pgd) .space PAGE_SIZE | ||
23 | #endif | ||
diff --git a/arch/x86/realmode/rm/wakeup_asm.S b/arch/x86/realmode/rm/wakeup_asm.S index 8a57c5a05fbc..46108f05e04e 100644 --- a/arch/x86/realmode/rm/wakeup_asm.S +++ b/arch/x86/realmode/rm/wakeup_asm.S | |||
@@ -132,7 +132,7 @@ ENTRY(wakeup_start) | |||
132 | ljmpl $__KERNEL_CS, $pa_startup_32 | 132 | ljmpl $__KERNEL_CS, $pa_startup_32 |
133 | /* -> jmp *%eax in trampoline_32.S */ | 133 | /* -> jmp *%eax in trampoline_32.S */ |
134 | #else | 134 | #else |
135 | jmp trampoline_data | 135 | jmp trampoline_start |
136 | #endif | 136 | #endif |
137 | 137 | ||
138 | bogus_real_magic: | 138 | bogus_real_magic: |