diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 13:41:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 13:41:29 -0500 |
commit | 5fbe4c224ce3e2e62bd487158dfd1e89f9ae3e11 (patch) | |
tree | aee3c146fb7dd3dd10cb71f44affa9c680481f08 /arch/x86/boot | |
parent | e2defd02717ebc54ae2f4862271a3093665b426a (diff) | |
parent | 570e1aa84c376ff39809442f09c7606ddf62cfd1 (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull misc x86 fixes from Ingo Molnar:
"This contains:
- EFI fixes
- a boot printout fix
- ASLR/kASLR fixes
- intel microcode driver fixes
- other misc fixes
Most of the linecount comes from an EFI revert"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/mm/ASLR: Avoid PAGE_SIZE redefinition for UML subarch
x86/microcode/intel: Handle truncated microcode images more robustly
x86/microcode/intel: Guard against stack overflow in the loader
x86, mm/ASLR: Fix stack randomization on 64-bit systems
x86/mm/init: Fix incorrect page size in init_memory_mapping() printks
x86/mm/ASLR: Propagate base load address calculation
Documentation/x86: Fix path in zero-page.txt
x86/apic: Fix the devicetree build in certain configs
Revert "efi/libstub: Call get_memory_map() to obtain map and desc sizes"
x86/efi: Avoid triple faults during EFI mixed mode calls
Diffstat (limited to 'arch/x86/boot')
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/boot/compressed/aslr.c | 34 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_stub_64.S | 25 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_thunk_64.S | 196 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 3 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.h | 6 |
6 files changed, 236 insertions, 29 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 843feb3eb20b..0a291cdfaf77 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -51,6 +51,7 @@ $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone | |||
51 | 51 | ||
52 | vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ | 52 | vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ |
53 | $(objtree)/drivers/firmware/efi/libstub/lib.a | 53 | $(objtree)/drivers/firmware/efi/libstub/lib.a |
54 | vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o | ||
54 | 55 | ||
55 | $(obj)/vmlinux: $(vmlinux-objs-y) FORCE | 56 | $(obj)/vmlinux: $(vmlinux-objs-y) FORCE |
56 | $(call if_changed,ld) | 57 | $(call if_changed,ld) |
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c index bb1376381985..7083c16cccba 100644 --- a/arch/x86/boot/compressed/aslr.c +++ b/arch/x86/boot/compressed/aslr.c | |||
@@ -14,6 +14,13 @@ | |||
14 | static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" | 14 | static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" |
15 | LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; | 15 | LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; |
16 | 16 | ||
17 | struct kaslr_setup_data { | ||
18 | __u64 next; | ||
19 | __u32 type; | ||
20 | __u32 len; | ||
21 | __u8 data[1]; | ||
22 | } kaslr_setup_data; | ||
23 | |||
17 | #define I8254_PORT_CONTROL 0x43 | 24 | #define I8254_PORT_CONTROL 0x43 |
18 | #define I8254_PORT_COUNTER0 0x40 | 25 | #define I8254_PORT_COUNTER0 0x40 |
19 | #define I8254_CMD_READBACK 0xC0 | 26 | #define I8254_CMD_READBACK 0xC0 |
@@ -295,7 +302,29 @@ static unsigned long find_random_addr(unsigned long minimum, | |||
295 | return slots_fetch_random(); | 302 | return slots_fetch_random(); |
296 | } | 303 | } |
297 | 304 | ||
298 | unsigned char *choose_kernel_location(unsigned char *input, | 305 | static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled) |
306 | { | ||
307 | struct setup_data *data; | ||
308 | |||
309 | kaslr_setup_data.type = SETUP_KASLR; | ||
310 | kaslr_setup_data.len = 1; | ||
311 | kaslr_setup_data.next = 0; | ||
312 | kaslr_setup_data.data[0] = enabled; | ||
313 | |||
314 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; | ||
315 | |||
316 | while (data && data->next) | ||
317 | data = (struct setup_data *)(unsigned long)data->next; | ||
318 | |||
319 | if (data) | ||
320 | data->next = (unsigned long)&kaslr_setup_data; | ||
321 | else | ||
322 | params->hdr.setup_data = (unsigned long)&kaslr_setup_data; | ||
323 | |||
324 | } | ||
325 | |||
326 | unsigned char *choose_kernel_location(struct boot_params *params, | ||
327 | unsigned char *input, | ||
299 | unsigned long input_size, | 328 | unsigned long input_size, |
300 | unsigned char *output, | 329 | unsigned char *output, |
301 | unsigned long output_size) | 330 | unsigned long output_size) |
@@ -306,14 +335,17 @@ unsigned char *choose_kernel_location(unsigned char *input, | |||
306 | #ifdef CONFIG_HIBERNATION | 335 | #ifdef CONFIG_HIBERNATION |
307 | if (!cmdline_find_option_bool("kaslr")) { | 336 | if (!cmdline_find_option_bool("kaslr")) { |
308 | debug_putstr("KASLR disabled by default...\n"); | 337 | debug_putstr("KASLR disabled by default...\n"); |
338 | add_kaslr_setup_data(params, 0); | ||
309 | goto out; | 339 | goto out; |
310 | } | 340 | } |
311 | #else | 341 | #else |
312 | if (cmdline_find_option_bool("nokaslr")) { | 342 | if (cmdline_find_option_bool("nokaslr")) { |
313 | debug_putstr("KASLR disabled by cmdline...\n"); | 343 | debug_putstr("KASLR disabled by cmdline...\n"); |
344 | add_kaslr_setup_data(params, 0); | ||
314 | goto out; | 345 | goto out; |
315 | } | 346 | } |
316 | #endif | 347 | #endif |
348 | add_kaslr_setup_data(params, 1); | ||
317 | 349 | ||
318 | /* Record the various known unsafe memory ranges. */ | 350 | /* Record the various known unsafe memory ranges. */ |
319 | mem_avoid_init((unsigned long)input, input_size, | 351 | mem_avoid_init((unsigned long)input, input_size, |
diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S index 7ff3632806b1..99494dff2113 100644 --- a/arch/x86/boot/compressed/efi_stub_64.S +++ b/arch/x86/boot/compressed/efi_stub_64.S | |||
@@ -3,28 +3,3 @@ | |||
3 | #include <asm/processor-flags.h> | 3 | #include <asm/processor-flags.h> |
4 | 4 | ||
5 | #include "../../platform/efi/efi_stub_64.S" | 5 | #include "../../platform/efi/efi_stub_64.S" |
6 | |||
7 | #ifdef CONFIG_EFI_MIXED | ||
8 | .code64 | ||
9 | .text | ||
10 | ENTRY(efi64_thunk) | ||
11 | push %rbp | ||
12 | push %rbx | ||
13 | |||
14 | subq $16, %rsp | ||
15 | leaq efi_exit32(%rip), %rax | ||
16 | movl %eax, 8(%rsp) | ||
17 | leaq efi_gdt64(%rip), %rax | ||
18 | movl %eax, 4(%rsp) | ||
19 | movl %eax, 2(%rax) /* Fixup the gdt base address */ | ||
20 | leaq efi32_boot_gdt(%rip), %rax | ||
21 | movl %eax, (%rsp) | ||
22 | |||
23 | call __efi64_thunk | ||
24 | |||
25 | addq $16, %rsp | ||
26 | pop %rbx | ||
27 | pop %rbp | ||
28 | ret | ||
29 | ENDPROC(efi64_thunk) | ||
30 | #endif /* CONFIG_EFI_MIXED */ | ||
diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S new file mode 100644 index 000000000000..630384a4c14a --- /dev/null +++ b/arch/x86/boot/compressed/efi_thunk_64.S | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming | ||
3 | * | ||
4 | * Early support for invoking 32-bit EFI services from a 64-bit kernel. | ||
5 | * | ||
6 | * Because this thunking occurs before ExitBootServices() we have to | ||
7 | * restore the firmware's 32-bit GDT before we make EFI serivce calls, | ||
8 | * since the firmware's 32-bit IDT is still currently installed and it | ||
9 | * needs to be able to service interrupts. | ||
10 | * | ||
11 | * On the plus side, we don't have to worry about mangling 64-bit | ||
12 | * addresses into 32-bits because we're executing with an identify | ||
13 | * mapped pagetable and haven't transitioned to 64-bit virtual addresses | ||
14 | * yet. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <asm/msr.h> | ||
19 | #include <asm/page_types.h> | ||
20 | #include <asm/processor-flags.h> | ||
21 | #include <asm/segment.h> | ||
22 | |||
23 | .code64 | ||
24 | .text | ||
25 | ENTRY(efi64_thunk) | ||
26 | push %rbp | ||
27 | push %rbx | ||
28 | |||
29 | subq $8, %rsp | ||
30 | leaq efi_exit32(%rip), %rax | ||
31 | movl %eax, 4(%rsp) | ||
32 | leaq efi_gdt64(%rip), %rax | ||
33 | movl %eax, (%rsp) | ||
34 | movl %eax, 2(%rax) /* Fixup the gdt base address */ | ||
35 | |||
36 | movl %ds, %eax | ||
37 | push %rax | ||
38 | movl %es, %eax | ||
39 | push %rax | ||
40 | movl %ss, %eax | ||
41 | push %rax | ||
42 | |||
43 | /* | ||
44 | * Convert x86-64 ABI params to i386 ABI | ||
45 | */ | ||
46 | subq $32, %rsp | ||
47 | movl %esi, 0x0(%rsp) | ||
48 | movl %edx, 0x4(%rsp) | ||
49 | movl %ecx, 0x8(%rsp) | ||
50 | movq %r8, %rsi | ||
51 | movl %esi, 0xc(%rsp) | ||
52 | movq %r9, %rsi | ||
53 | movl %esi, 0x10(%rsp) | ||
54 | |||
55 | sgdt save_gdt(%rip) | ||
56 | |||
57 | leaq 1f(%rip), %rbx | ||
58 | movq %rbx, func_rt_ptr(%rip) | ||
59 | |||
60 | /* | ||
61 | * Switch to gdt with 32-bit segments. This is the firmware GDT | ||
62 | * that was installed when the kernel started executing. This | ||
63 | * pointer was saved at the EFI stub entry point in head_64.S. | ||
64 | */ | ||
65 | leaq efi32_boot_gdt(%rip), %rax | ||
66 | lgdt (%rax) | ||
67 | |||
68 | pushq $__KERNEL_CS | ||
69 | leaq efi_enter32(%rip), %rax | ||
70 | pushq %rax | ||
71 | lretq | ||
72 | |||
73 | 1: addq $32, %rsp | ||
74 | |||
75 | lgdt save_gdt(%rip) | ||
76 | |||
77 | pop %rbx | ||
78 | movl %ebx, %ss | ||
79 | pop %rbx | ||
80 | movl %ebx, %es | ||
81 | pop %rbx | ||
82 | movl %ebx, %ds | ||
83 | |||
84 | /* | ||
85 | * Convert 32-bit status code into 64-bit. | ||
86 | */ | ||
87 | test %rax, %rax | ||
88 | jz 1f | ||
89 | movl %eax, %ecx | ||
90 | andl $0x0fffffff, %ecx | ||
91 | andl $0xf0000000, %eax | ||
92 | shl $32, %rax | ||
93 | or %rcx, %rax | ||
94 | 1: | ||
95 | addq $8, %rsp | ||
96 | pop %rbx | ||
97 | pop %rbp | ||
98 | ret | ||
99 | ENDPROC(efi64_thunk) | ||
100 | |||
101 | ENTRY(efi_exit32) | ||
102 | movq func_rt_ptr(%rip), %rax | ||
103 | push %rax | ||
104 | mov %rdi, %rax | ||
105 | ret | ||
106 | ENDPROC(efi_exit32) | ||
107 | |||
108 | .code32 | ||
109 | /* | ||
110 | * EFI service pointer must be in %edi. | ||
111 | * | ||
112 | * The stack should represent the 32-bit calling convention. | ||
113 | */ | ||
114 | ENTRY(efi_enter32) | ||
115 | movl $__KERNEL_DS, %eax | ||
116 | movl %eax, %ds | ||
117 | movl %eax, %es | ||
118 | movl %eax, %ss | ||
119 | |||
120 | /* Reload pgtables */ | ||
121 | movl %cr3, %eax | ||
122 | movl %eax, %cr3 | ||
123 | |||
124 | /* Disable paging */ | ||
125 | movl %cr0, %eax | ||
126 | btrl $X86_CR0_PG_BIT, %eax | ||
127 | movl %eax, %cr0 | ||
128 | |||
129 | /* Disable long mode via EFER */ | ||
130 | movl $MSR_EFER, %ecx | ||
131 | rdmsr | ||
132 | btrl $_EFER_LME, %eax | ||
133 | wrmsr | ||
134 | |||
135 | call *%edi | ||
136 | |||
137 | /* We must preserve return value */ | ||
138 | movl %eax, %edi | ||
139 | |||
140 | /* | ||
141 | * Some firmware will return with interrupts enabled. Be sure to | ||
142 | * disable them before we switch GDTs. | ||
143 | */ | ||
144 | cli | ||
145 | |||
146 | movl 56(%esp), %eax | ||
147 | movl %eax, 2(%eax) | ||
148 | lgdtl (%eax) | ||
149 | |||
150 | movl %cr4, %eax | ||
151 | btsl $(X86_CR4_PAE_BIT), %eax | ||
152 | movl %eax, %cr4 | ||
153 | |||
154 | movl %cr3, %eax | ||
155 | movl %eax, %cr3 | ||
156 | |||
157 | movl $MSR_EFER, %ecx | ||
158 | rdmsr | ||
159 | btsl $_EFER_LME, %eax | ||
160 | wrmsr | ||
161 | |||
162 | xorl %eax, %eax | ||
163 | lldt %ax | ||
164 | |||
165 | movl 60(%esp), %eax | ||
166 | pushl $__KERNEL_CS | ||
167 | pushl %eax | ||
168 | |||
169 | /* Enable paging */ | ||
170 | movl %cr0, %eax | ||
171 | btsl $X86_CR0_PG_BIT, %eax | ||
172 | movl %eax, %cr0 | ||
173 | lret | ||
174 | ENDPROC(efi_enter32) | ||
175 | |||
176 | .data | ||
177 | .balign 8 | ||
178 | .global efi32_boot_gdt | ||
179 | efi32_boot_gdt: .word 0 | ||
180 | .quad 0 | ||
181 | |||
182 | save_gdt: .word 0 | ||
183 | .quad 0 | ||
184 | func_rt_ptr: .quad 0 | ||
185 | |||
186 | .global efi_gdt64 | ||
187 | efi_gdt64: | ||
188 | .word efi_gdt64_end - efi_gdt64 | ||
189 | .long 0 /* Filled out by user */ | ||
190 | .word 0 | ||
191 | .quad 0x0000000000000000 /* NULL descriptor */ | ||
192 | .quad 0x00af9a000000ffff /* __KERNEL_CS */ | ||
193 | .quad 0x00cf92000000ffff /* __KERNEL_DS */ | ||
194 | .quad 0x0080890000000000 /* TS descriptor */ | ||
195 | .quad 0x0000000000000000 /* TS continued */ | ||
196 | efi_gdt64_end: | ||
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index a950864a64da..5903089c818f 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -401,7 +401,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, | |||
401 | * the entire decompressed kernel plus relocation table, or the | 401 | * the entire decompressed kernel plus relocation table, or the |
402 | * entire decompressed kernel plus .bss and .brk sections. | 402 | * entire decompressed kernel plus .bss and .brk sections. |
403 | */ | 403 | */ |
404 | output = choose_kernel_location(input_data, input_len, output, | 404 | output = choose_kernel_location(real_mode, input_data, input_len, |
405 | output, | ||
405 | output_len > run_size ? output_len | 406 | output_len > run_size ? output_len |
406 | : run_size); | 407 | : run_size); |
407 | 408 | ||
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 04477d68403f..ee3576b2666b 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h | |||
@@ -57,7 +57,8 @@ int cmdline_find_option_bool(const char *option); | |||
57 | 57 | ||
58 | #if CONFIG_RANDOMIZE_BASE | 58 | #if CONFIG_RANDOMIZE_BASE |
59 | /* aslr.c */ | 59 | /* aslr.c */ |
60 | unsigned char *choose_kernel_location(unsigned char *input, | 60 | unsigned char *choose_kernel_location(struct boot_params *params, |
61 | unsigned char *input, | ||
61 | unsigned long input_size, | 62 | unsigned long input_size, |
62 | unsigned char *output, | 63 | unsigned char *output, |
63 | unsigned long output_size); | 64 | unsigned long output_size); |
@@ -65,7 +66,8 @@ unsigned char *choose_kernel_location(unsigned char *input, | |||
65 | bool has_cpuflag(int flag); | 66 | bool has_cpuflag(int flag); |
66 | #else | 67 | #else |
67 | static inline | 68 | static inline |
68 | unsigned char *choose_kernel_location(unsigned char *input, | 69 | unsigned char *choose_kernel_location(struct boot_params *params, |
70 | unsigned char *input, | ||
69 | unsigned long input_size, | 71 | unsigned long input_size, |
70 | unsigned char *output, | 72 | unsigned char *output, |
71 | unsigned long output_size) | 73 | unsigned long output_size) |