aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@intel.com>2012-05-08 14:22:46 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-08 18:04:27 -0400
commitcda846f101fb1396b6924f1d9b68ac3d42de5403 (patch)
tree1fa8716c308b8e10156a1caf51d8ff6c98eceea9 /arch
parentbf8b88e97716feb750c3d34492f00d9c085e1183 (diff)
x86, realmode: read cr4 and EFER from kernel for 64-bit trampoline
This patch changes 64-bit trampoline so that CR4 and EFER are provided by the kernel instead of using fixed values. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Link: http://lkml.kernel.org/r/1336501366-28617-24-git-send-email-jarkko.sakkinen@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/processor.h7
-rw-r--r--arch/x86/include/asm/realmode.h8
-rw-r--r--arch/x86/kernel/realmode.c8
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/realmode/rm/header.S1
-rw-r--r--arch/x86/realmode/rm/trampoline_64.S32
-rw-r--r--arch/x86/realmode/rm/trampoline_common.S19
7 files changed, 49 insertions, 28 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 4fa7dcceb6c0..404583ccf0cf 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -544,13 +544,16 @@ static inline void load_sp0(struct tss_struct *tss,
544 * enable), so that any CPU's that boot up 544 * enable), so that any CPU's that boot up
545 * after us can get the correct flags. 545 * after us can get the correct flags.
546 */ 546 */
547extern unsigned long mmu_cr4_features; 547extern unsigned long mmu_cr4_features;
548extern u32 *trampoline_cr4_features;
548 549
549static inline void set_in_cr4(unsigned long mask) 550static inline void set_in_cr4(unsigned long mask)
550{ 551{
551 unsigned long cr4; 552 unsigned long cr4;
552 553
553 mmu_cr4_features |= mask; 554 mmu_cr4_features |= mask;
555 if (trampoline_cr4_features)
556 *trampoline_cr4_features = mmu_cr4_features;
554 cr4 = read_cr4(); 557 cr4 = read_cr4();
555 cr4 |= mask; 558 cr4 |= mask;
556 write_cr4(cr4); 559 write_cr4(cr4);
@@ -561,6 +564,8 @@ static inline void clear_in_cr4(unsigned long mask)
561 unsigned long cr4; 564 unsigned long cr4;
562 565
563 mmu_cr4_features &= ~mask; 566 mmu_cr4_features &= ~mask;
567 if (trampoline_cr4_features)
568 *trampoline_cr4_features = mmu_cr4_features;
564 cr4 = read_cr4(); 569 cr4 = read_cr4();
565 cr4 &= ~mask; 570 cr4 &= ~mask;
566 write_cr4(cr4); 571 write_cr4(cr4);
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 1421eed1c8e8..937dc6071d76 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -24,18 +24,22 @@ struct real_mode_header {
24#ifdef CONFIG_X86_32 24#ifdef CONFIG_X86_32
25 u32 machine_real_restart_asm; 25 u32 machine_real_restart_asm;
26#endif 26#endif
27} __attribute__((__packed__)); 27};
28 28
29/* This must match data at trampoline_32/64.S */ 29/* This must match data at trampoline_32/64.S */
30struct trampoline_header { 30struct trampoline_header {
31#ifdef CONFIG_X86_32 31#ifdef CONFIG_X86_32
32 u32 start; 32 u32 start;
33 u16 gdt_pad;
33 u16 gdt_limit; 34 u16 gdt_limit;
34 u32 gdt_base; 35 u32 gdt_base;
35#else 36#else
36 u64 start; 37 u64 start;
38 u32 cr4;
39 u32 efer_low;
40 u32 efer_high;
37#endif 41#endif
38} __attribute__((__packed__)); 42};
39 43
40extern struct real_mode_header *real_mode_header; 44extern struct real_mode_header *real_mode_header;
41extern unsigned char real_mode_blob_end[]; 45extern unsigned char real_mode_blob_end[];
diff --git a/arch/x86/kernel/realmode.c b/arch/x86/kernel/realmode.c
index 712fba8fd774..66ac276cf361 100644
--- a/arch/x86/kernel/realmode.c
+++ b/arch/x86/kernel/realmode.c
@@ -6,6 +6,7 @@
6#include <asm/realmode.h> 6#include <asm/realmode.h>
7 7
8struct real_mode_header *real_mode_header; 8struct real_mode_header *real_mode_header;
9u32 *trampoline_cr4_features;
9 10
10void __init setup_real_mode(void) 11void __init setup_real_mode(void)
11{ 12{
@@ -64,7 +65,14 @@ void __init setup_real_mode(void)
64 trampoline_header->gdt_limit = __BOOT_DS + 7; 65 trampoline_header->gdt_limit = __BOOT_DS + 7;
65 trampoline_header->gdt_base = __pa(boot_gdt); 66 trampoline_header->gdt_base = __pa(boot_gdt);
66#else 67#else
68 if (rdmsr_safe(MSR_EFER, &trampoline_header->efer_low,
69 &trampoline_header->efer_high))
70 BUG();
71
67 trampoline_header->start = (u64) secondary_startup_64; 72 trampoline_header->start = (u64) secondary_startup_64;
73 trampoline_cr4_features = &trampoline_header->cr4;
74 *trampoline_cr4_features = read_cr4();
75
68 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); 76 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
69 trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE; 77 trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
70 trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE; 78 trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 7a14fece9cfc..efcf305210a4 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -975,6 +975,8 @@ void __init setup_arch(char **cmdline_p)
975 if (boot_cpu_data.cpuid_level >= 0) { 975 if (boot_cpu_data.cpuid_level >= 0) {
976 /* A CPU has %cr4 if and only if it has CPUID */ 976 /* A CPU has %cr4 if and only if it has CPUID */
977 mmu_cr4_features = read_cr4(); 977 mmu_cr4_features = read_cr4();
978 if (trampoline_cr4_features)
979 *trampoline_cr4_features = mmu_cr4_features;
978 } 980 }
979 981
980#ifdef CONFIG_X86_32 982#ifdef CONFIG_X86_32
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index b4c32632bf16..4612d5382791 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -9,6 +9,7 @@
9 9
10 .section ".header", "a" 10 .section ".header", "a"
11 11
12 .balign 16
12GLOBAL(real_mode_header) 13GLOBAL(real_mode_header)
13 .long pa_text_start 14 .long pa_text_start
14 .long pa_ro_end 15 .long pa_ro_end
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index 3f7293239365..66e26f088288 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -34,9 +34,9 @@
34#include "realmode.h" 34#include "realmode.h"
35 35
36 .text 36 .text
37 .balign PAGE_SIZE
38 .code16 37 .code16
39 38
39 .balign PAGE_SIZE
40ENTRY(trampoline_start) 40ENTRY(trampoline_start)
41 cli # We should be safe anyway 41 cli # We should be safe anyway
42 wbinvd 42 wbinvd
@@ -65,8 +65,8 @@ ENTRY(trampoline_start)
65 * to 32 bit. 65 * to 32 bit.
66 */ 66 */
67 67
68 lidtl tidt # load idt with 0, 0 68 lidtl tr_idt # load idt with 0, 0
69 lgdtl tgdt # load gdt with whatever is appropriate 69 lgdtl tr_gdt # load gdt with whatever is appropriate
70 70
71 movw $__KERNEL_DS, %dx # Data segment descriptor 71 movw $__KERNEL_DS, %dx # Data segment descriptor
72 72
@@ -93,16 +93,17 @@ ENTRY(startup_32)
93 movl %edx, %fs 93 movl %edx, %fs
94 movl %edx, %gs 94 movl %edx, %gs
95 95
96 movl $X86_CR4_PAE, %eax 96 movl pa_tr_cr4, %eax
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_trampoline_pgd, %eax 100 movl $pa_trampoline_pgd, %eax
101 movl %eax, %cr3 101 movl %eax, %cr3
102 102
103 # Set up EFER
104 movl pa_tr_efer, %eax
105 movl pa_tr_efer + 4, %edx
103 movl $MSR_EFER, %ecx 106 movl $MSR_EFER, %ecx
104 movl $((1 << _EFER_LME) | (1 << _EFER_NX)), %eax # Enable Long Mode
105 xorl %edx, %edx
106 wrmsr 107 wrmsr
107 108
108 # Enable paging and in turn activate Long Mode 109 # Enable paging and in turn activate Long Mode
@@ -124,23 +125,4 @@ ENTRY(startup_64)
124 # Now jump into the kernel using virtual addresses 125 # Now jump into the kernel using virtual addresses
125 jmpq *tr_start(%rip) 126 jmpq *tr_start(%rip)
126 127
127 .section ".rodata","a"
128 .balign 16
129tidt:
130 .word 0 # idt limit = 0
131 .word 0, 0 # idt base = 0L
132
133 # Duplicate the global descriptor table
134 # so the kernel can live anywhere
135 .balign 16
136 .globl tgdt
137tgdt:
138 .short tgdt_end - tgdt - 1 # gdt limit
139 .long pa_tgdt
140 .short 0
141 .quad 0x00cf9b000000ffff # __KERNEL32_CS
142 .quad 0x00af9b000000ffff # __KERNEL_CS
143 .quad 0x00cf93000000ffff # __KERNEL_DS
144tgdt_end:
145
146#include "trampoline_common.S" 128#include "trampoline_common.S"
diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S
index c3f951c468c5..cac444b942f8 100644
--- a/arch/x86/realmode/rm/trampoline_common.S
+++ b/arch/x86/realmode/rm/trampoline_common.S
@@ -1,5 +1,20 @@
1 .section ".rodata","a" 1 .section ".rodata","a"
2 2
3#ifdef CONFIG_X86_64
4 # Duplicate the global descriptor table
5 # so the kernel can live anywhere
6 .balign 16
7 .globl tr_gdt
8tr_gdt:
9 .short tr_gdt_end - tr_gdt - 1 # gdt limit
10 .long pa_tr_gdt
11 .short 0
12 .quad 0x00cf9b000000ffff # __KERNEL32_CS
13 .quad 0x00af9b000000ffff # __KERNEL_CS
14 .quad 0x00cf93000000ffff # __KERNEL_DS
15tr_gdt_end:
16#endif
17
3 .balign 4 18 .balign 4
4tr_idt: .fill 1, 6, 0 19tr_idt: .fill 1, 6, 0
5 20
@@ -8,12 +23,16 @@ tr_idt: .fill 1, 6, 0
8 .balign 4 23 .balign 4
9GLOBAL(trampoline_status) .space 4 24GLOBAL(trampoline_status) .space 4
10 25
26 .balign 8
11GLOBAL(trampoline_header) 27GLOBAL(trampoline_header)
12#ifdef CONFIG_X86_32 28#ifdef CONFIG_X86_32
13 tr_start: .space 4 29 tr_start: .space 4
30 tr_gdt_pad: .space 2
14 tr_gdt: .space 6 31 tr_gdt: .space 6
15#else 32#else
16 tr_start: .space 8 33 tr_start: .space 8
34 GLOBAL(tr_cr4) .space 4
35 GLOBAL(tr_efer) .space 8
17#endif 36#endif
18END(trampoline_header) 37END(trampoline_header)
19 38