Commit de55bbbff21ce8e11271c3032086b082af815864
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "Microcode fixes, a Xen fix and a KASLR boot loading fix with certain memory layouts" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, microcode, AMD: Fix ucode patch stashing on 32-bit x86/core, x86/xen/smp: Use 'die_complete' completion when taking CPU down x86, microcode: Fix accessing dis_ucode_ldr on 32-bit x86, kaslr: Prevent .bss from overlaping initrd x86, microcode, AMD: Fix early ucode loading on 32-bit
Showing 11 changed files Side-by-side Diff
- arch/x86/boot/compressed/Makefile
- arch/x86/boot/compressed/head_32.S
- arch/x86/boot/compressed/head_64.S
- arch/x86/boot/compressed/misc.c
- arch/x86/boot/compressed/mkpiggy.c
- arch/x86/include/asm/smp.h
- arch/x86/kernel/cpu/microcode/amd_early.c
- arch/x86/kernel/cpu/microcode/core_early.c
- arch/x86/kernel/smpboot.c
- arch/x86/tools/calc_run_size.pl
- arch/x86/xen/smp.c
arch/x86/boot/compressed/Makefile
... | ... | @@ -76,8 +76,10 @@ |
76 | 76 | suffix-$(CONFIG_KERNEL_LZO) := lzo |
77 | 77 | suffix-$(CONFIG_KERNEL_LZ4) := lz4 |
78 | 78 | |
79 | +RUN_SIZE = $(shell objdump -h vmlinux | \ | |
80 | + perl $(srctree)/arch/x86/tools/calc_run_size.pl) | |
79 | 81 | quiet_cmd_mkpiggy = MKPIGGY $@ |
80 | - cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) | |
82 | + cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) | |
81 | 83 | |
82 | 84 | targets += piggy.S |
83 | 85 | $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE |
arch/x86/boot/compressed/head_32.S
... | ... | @@ -207,7 +207,8 @@ |
207 | 207 | * Do the decompression, and jump to the new kernel.. |
208 | 208 | */ |
209 | 209 | /* push arguments for decompress_kernel: */ |
210 | - pushl $z_output_len /* decompressed length */ | |
210 | + pushl $z_run_size /* size of kernel with .bss and .brk */ | |
211 | + pushl $z_output_len /* decompressed length, end of relocs */ | |
211 | 212 | leal z_extract_offset_negative(%ebx), %ebp |
212 | 213 | pushl %ebp /* output address */ |
213 | 214 | pushl $z_input_len /* input_len */ |
... | ... | @@ -217,7 +218,7 @@ |
217 | 218 | pushl %eax /* heap area */ |
218 | 219 | pushl %esi /* real mode pointer */ |
219 | 220 | call decompress_kernel /* returns kernel location in %eax */ |
220 | - addl $24, %esp | |
221 | + addl $28, %esp | |
221 | 222 | |
222 | 223 | /* |
223 | 224 | * Jump to the decompressed kernel. |
arch/x86/boot/compressed/head_64.S
... | ... | @@ -402,13 +402,16 @@ |
402 | 402 | * Do the decompression, and jump to the new kernel.. |
403 | 403 | */ |
404 | 404 | pushq %rsi /* Save the real mode argument */ |
405 | + movq $z_run_size, %r9 /* size of kernel with .bss and .brk */ | |
406 | + pushq %r9 | |
405 | 407 | movq %rsi, %rdi /* real mode address */ |
406 | 408 | leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ |
407 | 409 | leaq input_data(%rip), %rdx /* input_data */ |
408 | 410 | movl $z_input_len, %ecx /* input_len */ |
409 | 411 | movq %rbp, %r8 /* output target address */ |
410 | - movq $z_output_len, %r9 /* decompressed length */ | |
412 | + movq $z_output_len, %r9 /* decompressed length, end of relocs */ | |
411 | 413 | call decompress_kernel /* returns kernel location in %rax */ |
414 | + popq %r9 | |
412 | 415 | popq %rsi |
413 | 416 | |
414 | 417 | /* |
arch/x86/boot/compressed/misc.c
... | ... | @@ -358,7 +358,8 @@ |
358 | 358 | unsigned char *input_data, |
359 | 359 | unsigned long input_len, |
360 | 360 | unsigned char *output, |
361 | - unsigned long output_len) | |
361 | + unsigned long output_len, | |
362 | + unsigned long run_size) | |
362 | 363 | { |
363 | 364 | real_mode = rmode; |
364 | 365 | |
... | ... | @@ -381,8 +382,14 @@ |
381 | 382 | free_mem_ptr = heap; /* Heap */ |
382 | 383 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; |
383 | 384 | |
384 | - output = choose_kernel_location(input_data, input_len, | |
385 | - output, output_len); | |
385 | + /* | |
386 | + * The memory hole needed for the kernel is the larger of either | |
387 | + * the entire decompressed kernel plus relocation table, or the | |
388 | + * entire decompressed kernel plus .bss and .brk sections. | |
389 | + */ | |
390 | + output = choose_kernel_location(input_data, input_len, output, | |
391 | + output_len > run_size ? output_len | |
392 | + : run_size); | |
386 | 393 | |
387 | 394 | /* Validate memory location choices. */ |
388 | 395 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) |
arch/x86/boot/compressed/mkpiggy.c
... | ... | @@ -36,11 +36,13 @@ |
36 | 36 | uint32_t olen; |
37 | 37 | long ilen; |
38 | 38 | unsigned long offs; |
39 | + unsigned long run_size; | |
39 | 40 | FILE *f = NULL; |
40 | 41 | int retval = 1; |
41 | 42 | |
42 | - if (argc < 2) { | |
43 | - fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); | |
43 | + if (argc < 3) { | |
44 | + fprintf(stderr, "Usage: %s compressed_file run_size\n", | |
45 | + argv[0]); | |
44 | 46 | goto bail; |
45 | 47 | } |
46 | 48 | |
... | ... | @@ -74,6 +76,7 @@ |
74 | 76 | offs += olen >> 12; /* Add 8 bytes for each 32K block */ |
75 | 77 | offs += 64*1024 + 128; /* Add 64K + 128 bytes slack */ |
76 | 78 | offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ |
79 | + run_size = atoi(argv[2]); | |
77 | 80 | |
78 | 81 | printf(".section \".rodata..compressed\",\"a\",@progbits\n"); |
79 | 82 | printf(".globl z_input_len\n"); |
... | ... | @@ -85,6 +88,8 @@ |
85 | 88 | /* z_extract_offset_negative allows simplification of head_32.S */ |
86 | 89 | printf(".globl z_extract_offset_negative\n"); |
87 | 90 | printf("z_extract_offset_negative = -0x%lx\n", offs); |
91 | + printf(".globl z_run_size\n"); | |
92 | + printf("z_run_size = %lu\n", run_size); | |
88 | 93 | |
89 | 94 | printf(".globl input_data, input_data_end\n"); |
90 | 95 | printf("input_data:\n"); |
arch/x86/include/asm/smp.h
arch/x86/kernel/cpu/microcode/amd_early.c
... | ... | @@ -108,12 +108,13 @@ |
108 | 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in |
109 | 109 | * kernel heap memory. |
110 | 110 | */ |
111 | -static void apply_ucode_in_initrd(void *ucode, size_t size) | |
111 | +static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) | |
112 | 112 | { |
113 | 113 | struct equiv_cpu_entry *eq; |
114 | 114 | size_t *cont_sz; |
115 | 115 | u32 *header; |
116 | 116 | u8 *data, **cont; |
117 | + u8 (*patch)[PATCH_MAX_SIZE]; | |
117 | 118 | u16 eq_id = 0; |
118 | 119 | int offset, left; |
119 | 120 | u32 rev, eax, ebx, ecx, edx; |
120 | 121 | |
... | ... | @@ -123,10 +124,12 @@ |
123 | 124 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); |
124 | 125 | cont_sz = (size_t *)__pa_nodebug(&container_size); |
125 | 126 | cont = (u8 **)__pa_nodebug(&container); |
127 | + patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); | |
126 | 128 | #else |
127 | 129 | new_rev = &ucode_new_rev; |
128 | 130 | cont_sz = &container_size; |
129 | 131 | cont = &container; |
132 | + patch = &amd_ucode_patch; | |
130 | 133 | #endif |
131 | 134 | |
132 | 135 | data = ucode; |
... | ... | @@ -213,9 +216,9 @@ |
213 | 216 | rev = mc->hdr.patch_id; |
214 | 217 | *new_rev = rev; |
215 | 218 | |
216 | - /* save ucode patch */ | |
217 | - memcpy(amd_ucode_patch, mc, | |
218 | - min_t(u32, header[1], PATCH_MAX_SIZE)); | |
219 | + if (save_patch) | |
220 | + memcpy(patch, mc, | |
221 | + min_t(u32, header[1], PATCH_MAX_SIZE)); | |
219 | 222 | } |
220 | 223 | } |
221 | 224 | |
... | ... | @@ -246,7 +249,7 @@ |
246 | 249 | *data = cp.data; |
247 | 250 | *size = cp.size; |
248 | 251 | |
249 | - apply_ucode_in_initrd(cp.data, cp.size); | |
252 | + apply_ucode_in_initrd(cp.data, cp.size, true); | |
250 | 253 | } |
251 | 254 | |
252 | 255 | #ifdef CONFIG_X86_32 |
... | ... | @@ -263,7 +266,7 @@ |
263 | 266 | size_t *usize; |
264 | 267 | void **ucode; |
265 | 268 | |
266 | - mc = (struct microcode_amd *)__pa(amd_ucode_patch); | |
269 | + mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch); | |
267 | 270 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { |
268 | 271 | __apply_microcode_amd(mc); |
269 | 272 | return; |
... | ... | @@ -275,7 +278,7 @@ |
275 | 278 | if (!*ucode || !*usize) |
276 | 279 | return; |
277 | 280 | |
278 | - apply_ucode_in_initrd(*ucode, *usize); | |
281 | + apply_ucode_in_initrd(*ucode, *usize, false); | |
279 | 282 | } |
280 | 283 | |
281 | 284 | static void __init collect_cpu_sig_on_bsp(void *arg) |
... | ... | @@ -339,7 +342,7 @@ |
339 | 342 | * AP has a different equivalence ID than BSP, looks like |
340 | 343 | * mixed-steppings silicon so go through the ucode blob anew. |
341 | 344 | */ |
342 | - apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); | |
345 | + apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false); | |
343 | 346 | } |
344 | 347 | } |
345 | 348 | #endif |
346 | 349 | |
... | ... | @@ -347,7 +350,9 @@ |
347 | 350 | int __init save_microcode_in_initrd_amd(void) |
348 | 351 | { |
349 | 352 | unsigned long cont; |
353 | + int retval = 0; | |
350 | 354 | enum ucode_state ret; |
355 | + u8 *cont_va; | |
351 | 356 | u32 eax; |
352 | 357 | |
353 | 358 | if (!container) |
354 | 359 | |
... | ... | @@ -355,13 +360,15 @@ |
355 | 360 | |
356 | 361 | #ifdef CONFIG_X86_32 |
357 | 362 | get_bsp_sig(); |
358 | - cont = (unsigned long)container; | |
363 | + cont = (unsigned long)container; | |
364 | + cont_va = __va(container); | |
359 | 365 | #else |
360 | 366 | /* |
361 | 367 | * We need the physical address of the container for both bitness since |
362 | 368 | * boot_params.hdr.ramdisk_image is a physical address. |
363 | 369 | */ |
364 | - cont = __pa(container); | |
370 | + cont = __pa(container); | |
371 | + cont_va = container; | |
365 | 372 | #endif |
366 | 373 | |
367 | 374 | /* |
... | ... | @@ -372,6 +379,8 @@ |
372 | 379 | if (relocated_ramdisk) |
373 | 380 | container = (u8 *)(__va(relocated_ramdisk) + |
374 | 381 | (cont - boot_params.hdr.ramdisk_image)); |
382 | + else | |
383 | + container = cont_va; | |
375 | 384 | |
376 | 385 | if (ucode_new_rev) |
377 | 386 | pr_info("microcode: updated early to new patch_level=0x%08x\n", |
... | ... | @@ -382,7 +391,7 @@ |
382 | 391 | |
383 | 392 | ret = load_microcode_amd(eax, container, container_size); |
384 | 393 | if (ret != UCODE_OK) |
385 | - return -EINVAL; | |
394 | + retval = -EINVAL; | |
386 | 395 | |
387 | 396 | /* |
388 | 397 | * This will be freed any msec now, stash patches for the current |
... | ... | @@ -391,6 +400,6 @@ |
391 | 400 | container = NULL; |
392 | 401 | container_size = 0; |
393 | 402 | |
394 | - return 0; | |
403 | + return retval; | |
395 | 404 | } |
arch/x86/kernel/cpu/microcode/core_early.c
arch/x86/kernel/smpboot.c
... | ... | @@ -1303,10 +1303,14 @@ |
1303 | 1303 | numa_remove_cpu(cpu); |
1304 | 1304 | } |
1305 | 1305 | |
1306 | +static DEFINE_PER_CPU(struct completion, die_complete); | |
1307 | + | |
1306 | 1308 | void cpu_disable_common(void) |
1307 | 1309 | { |
1308 | 1310 | int cpu = smp_processor_id(); |
1309 | 1311 | |
1312 | + init_completion(&per_cpu(die_complete, smp_processor_id())); | |
1313 | + | |
1310 | 1314 | remove_siblinginfo(cpu); |
1311 | 1315 | |
1312 | 1316 | /* It's now safe to remove this processor from the online map */ |
... | ... | @@ -1316,8 +1320,6 @@ |
1316 | 1320 | fixup_irqs(); |
1317 | 1321 | } |
1318 | 1322 | |
1319 | -static DEFINE_PER_CPU(struct completion, die_complete); | |
1320 | - | |
1321 | 1323 | int native_cpu_disable(void) |
1322 | 1324 | { |
1323 | 1325 | int ret; |
1324 | 1326 | |
1325 | 1327 | |
... | ... | @@ -1327,16 +1329,21 @@ |
1327 | 1329 | return ret; |
1328 | 1330 | |
1329 | 1331 | clear_local_APIC(); |
1330 | - init_completion(&per_cpu(die_complete, smp_processor_id())); | |
1331 | 1332 | cpu_disable_common(); |
1332 | 1333 | |
1333 | 1334 | return 0; |
1334 | 1335 | } |
1335 | 1336 | |
1337 | +void cpu_die_common(unsigned int cpu) | |
1338 | +{ | |
1339 | + wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ); | |
1340 | +} | |
1341 | + | |
1336 | 1342 | void native_cpu_die(unsigned int cpu) |
1337 | 1343 | { |
1338 | 1344 | /* We don't do anything here: idle task is faking death itself. */ |
1339 | - wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ); | |
1345 | + | |
1346 | + cpu_die_common(cpu); | |
1340 | 1347 | |
1341 | 1348 | /* They ack this in play_dead() by setting CPU_DEAD */ |
1342 | 1349 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { |
arch/x86/tools/calc_run_size.pl
1 | +#!/usr/bin/perl | |
2 | +# | |
3 | +# Calculate the amount of space needed to run the kernel, including room for | |
4 | +# the .bss and .brk sections. | |
5 | +# | |
6 | +# Usage: | |
7 | +# objdump -h a.out | perl calc_run_size.pl | |
8 | +use strict; | |
9 | + | |
10 | +my $mem_size = 0; | |
11 | +my $file_offset = 0; | |
12 | + | |
13 | +my $sections=" *[0-9]+ \.(?:bss|brk) +"; | |
14 | +while (<>) { | |
15 | + if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) { | |
16 | + my $size = hex($1); | |
17 | + my $offset = hex($2); | |
18 | + $mem_size += $size; | |
19 | + if ($file_offset == 0) { | |
20 | + $file_offset = $offset; | |
21 | + } elsif ($file_offset != $offset) { | |
22 | + die ".bss and .brk lack common file offset\n"; | |
23 | + } | |
24 | + } | |
25 | +} | |
26 | + | |
27 | +if ($file_offset == 0) { | |
28 | + die "Never found .bss or .brk file offset\n"; | |
29 | +} | |
30 | +printf("%d\n", $mem_size + $file_offset); |
arch/x86/xen/smp.c