aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/realmode.h32
-rw-r--r--arch/x86/kernel/realmode.c27
-rw-r--r--arch/x86/kernel/smpboot.c2
-rw-r--r--arch/x86/realmode/rm/header.S35
-rw-r--r--arch/x86/realmode/rm/trampoline_32.S36
-rw-r--r--arch/x86/realmode/rm/trampoline_64.S18
-rw-r--r--arch/x86/realmode/rm/trampoline_common.S23
-rw-r--r--arch/x86/realmode/rm/wakeup_asm.S2
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 @@
8struct real_mode_header { 8struct 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 */
30struct 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
32extern struct real_mode_header *real_mode_header; 40extern 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
12GLOBAL(real_mode_header) 12GLOBAL(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
34END(real_mode_header) 31END(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
38ENTRY(trampoline_data) 32ENTRY(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)
69ENTRY(startup_32) # note: also used from wakeup_asm.S 63ENTRY(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
75boot_idt_descr:
76 .word 0 # idt limit = 0
77 .long 0 # idt base = 0L
78
79 .data
80
81boot_gdt_descr:
82 .word __BOOT_DS + 7 # gdt limit
83GLOBAL(boot_gdt)
84 .long 0 # gdt base
85
86 .bss
87
88 .balign 4
89GLOBAL(trampoline_status) .space 4
90GLOBAL(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
40ENTRY(trampoline_data) 40ENTRY(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
123ENTRY(startup_64) 123ENTRY(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
144tgdt_end: 144tgdt_end:
145 145
146 .bss 146#include "trampoline_common.S"
147
148 .balign PAGE_SIZE
149GLOBAL(level3_ident_pgt) .space 511*8
150GLOBAL(level3_kernel_pgt) .space 8
151
152 .balign 8
153GLOBAL(startup_64_smp) .space 8
154GLOBAL(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
4tr_idt: .fill 1, 6, 0
5
6 .bss
7
8 .balign 4
9GLOBAL(trampoline_status) .space 4
10
11GLOBAL(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
18END(trampoline_header)
19
20#ifdef CONFIG_X86_64
21 .balign PAGE_SIZE
22GLOBAL(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
138bogus_real_magic: 138bogus_real_magic: