aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@intel.com>2012-05-08 14:22:43 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-08 14:48:45 -0400
commitf37240f16bec91f15ce564515f70a6ca9715ce96 (patch)
treed1e98241650bfed0d87f60e3e71a8ad716782f6d
parentc4845474a01f699966272536e8416222e3f2d2cb (diff)
x86, realmode: header for trampoline code
Added header for trampoline code that can be used to supply input data to it. This makes interface between real mode code and kernel cleaner and simpler. Replaced two confusing pointers to level4 pgt in trampoline_64.S with a single pointer to the beginning of the page table. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Link: http://lkml.kernel.org/r/1336501366-28617-21-git-send-email-jarkko.sakkinen@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-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: