diff options
author | Jarkko Sakkinen <jarkko.sakkinen@intel.com> | 2012-05-08 14:22:43 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-08 14:48:45 -0400 |
commit | f37240f16bec91f15ce564515f70a6ca9715ce96 (patch) | |
tree | d1e98241650bfed0d87f60e3e71a8ad716782f6d | |
parent | c4845474a01f699966272536e8416222e3f2d2cb (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.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: |