diff options
| -rw-r--r-- | arch/x86/boot/compressed/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/head_32.S | 5 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/head_64.S | 5 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/misc.c | 13 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/mkpiggy.c | 9 | ||||
| -rw-r--r-- | arch/x86/include/asm/smp.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 33 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 15 | ||||
| -rw-r--r-- | arch/x86/tools/calc_run_size.pl | 30 | ||||
| -rw-r--r-- | arch/x86/xen/smp.c | 3 |
11 files changed, 94 insertions, 26 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 704f58aa79cd..be1e07d4b596 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
| @@ -76,8 +76,10 @@ suffix-$(CONFIG_KERNEL_XZ) := xz | |||
| 76 | suffix-$(CONFIG_KERNEL_LZO) := lzo | 76 | suffix-$(CONFIG_KERNEL_LZO) := lzo |
| 77 | suffix-$(CONFIG_KERNEL_LZ4) := lz4 | 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 | quiet_cmd_mkpiggy = MKPIGGY $@ | 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 | targets += piggy.S | 84 | targets += piggy.S |
| 83 | $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE | 85 | $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE |
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index cbed1407a5cd..1d7fbbcc196d 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
| @@ -207,7 +207,8 @@ relocated: | |||
| 207 | * Do the decompression, and jump to the new kernel.. | 207 | * Do the decompression, and jump to the new kernel.. |
| 208 | */ | 208 | */ |
| 209 | /* push arguments for decompress_kernel: */ | 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 | leal z_extract_offset_negative(%ebx), %ebp | 212 | leal z_extract_offset_negative(%ebx), %ebp |
| 212 | pushl %ebp /* output address */ | 213 | pushl %ebp /* output address */ |
| 213 | pushl $z_input_len /* input_len */ | 214 | pushl $z_input_len /* input_len */ |
| @@ -217,7 +218,7 @@ relocated: | |||
| 217 | pushl %eax /* heap area */ | 218 | pushl %eax /* heap area */ |
| 218 | pushl %esi /* real mode pointer */ | 219 | pushl %esi /* real mode pointer */ |
| 219 | call decompress_kernel /* returns kernel location in %eax */ | 220 | call decompress_kernel /* returns kernel location in %eax */ |
| 220 | addl $24, %esp | 221 | addl $28, %esp |
| 221 | 222 | ||
| 222 | /* | 223 | /* |
| 223 | * Jump to the decompressed kernel. | 224 | * Jump to the decompressed kernel. |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 2884e0c3e8a5..6b1766c6c082 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
| @@ -402,13 +402,16 @@ relocated: | |||
| 402 | * Do the decompression, and jump to the new kernel.. | 402 | * Do the decompression, and jump to the new kernel.. |
| 403 | */ | 403 | */ |
| 404 | pushq %rsi /* Save the real mode argument */ | 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 | movq %rsi, %rdi /* real mode address */ | 407 | movq %rsi, %rdi /* real mode address */ |
| 406 | leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ | 408 | leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ |
| 407 | leaq input_data(%rip), %rdx /* input_data */ | 409 | leaq input_data(%rip), %rdx /* input_data */ |
| 408 | movl $z_input_len, %ecx /* input_len */ | 410 | movl $z_input_len, %ecx /* input_len */ |
| 409 | movq %rbp, %r8 /* output target address */ | 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 | call decompress_kernel /* returns kernel location in %rax */ | 413 | call decompress_kernel /* returns kernel location in %rax */ |
| 414 | popq %r9 | ||
| 412 | popq %rsi | 415 | popq %rsi |
| 413 | 416 | ||
| 414 | /* | 417 | /* |
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 57ab74df7eea..30dd59a9f0b4 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
| @@ -358,7 +358,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, | |||
| 358 | unsigned char *input_data, | 358 | unsigned char *input_data, |
| 359 | unsigned long input_len, | 359 | unsigned long input_len, |
| 360 | unsigned char *output, | 360 | unsigned char *output, |
| 361 | unsigned long output_len) | 361 | unsigned long output_len, |
| 362 | unsigned long run_size) | ||
| 362 | { | 363 | { |
| 363 | real_mode = rmode; | 364 | real_mode = rmode; |
| 364 | 365 | ||
| @@ -381,8 +382,14 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, | |||
| 381 | free_mem_ptr = heap; /* Heap */ | 382 | free_mem_ptr = heap; /* Heap */ |
| 382 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; | 383 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; |
| 383 | 384 | ||
| 384 | output = choose_kernel_location(input_data, input_len, | 385 | /* |
| 385 | output, output_len); | 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 | /* Validate memory location choices. */ | 394 | /* Validate memory location choices. */ |
| 388 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) | 395 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) |
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c index b669ab65bf6c..d8222f213182 100644 --- a/arch/x86/boot/compressed/mkpiggy.c +++ b/arch/x86/boot/compressed/mkpiggy.c | |||
| @@ -36,11 +36,13 @@ int main(int argc, char *argv[]) | |||
| 36 | uint32_t olen; | 36 | uint32_t olen; |
| 37 | long ilen; | 37 | long ilen; |
| 38 | unsigned long offs; | 38 | unsigned long offs; |
| 39 | unsigned long run_size; | ||
| 39 | FILE *f = NULL; | 40 | FILE *f = NULL; |
| 40 | int retval = 1; | 41 | int retval = 1; |
| 41 | 42 | ||
| 42 | if (argc < 2) { | 43 | if (argc < 3) { |
| 43 | fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); | 44 | fprintf(stderr, "Usage: %s compressed_file run_size\n", |
| 45 | argv[0]); | ||
| 44 | goto bail; | 46 | goto bail; |
| 45 | } | 47 | } |
| 46 | 48 | ||
| @@ -74,6 +76,7 @@ int main(int argc, char *argv[]) | |||
| 74 | offs += olen >> 12; /* Add 8 bytes for each 32K block */ | 76 | offs += olen >> 12; /* Add 8 bytes for each 32K block */ |
| 75 | offs += 64*1024 + 128; /* Add 64K + 128 bytes slack */ | 77 | offs += 64*1024 + 128; /* Add 64K + 128 bytes slack */ |
| 76 | offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ | 78 | offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ |
| 79 | run_size = atoi(argv[2]); | ||
| 77 | 80 | ||
| 78 | printf(".section \".rodata..compressed\",\"a\",@progbits\n"); | 81 | printf(".section \".rodata..compressed\",\"a\",@progbits\n"); |
| 79 | printf(".globl z_input_len\n"); | 82 | printf(".globl z_input_len\n"); |
| @@ -85,6 +88,8 @@ int main(int argc, char *argv[]) | |||
| 85 | /* z_extract_offset_negative allows simplification of head_32.S */ | 88 | /* z_extract_offset_negative allows simplification of head_32.S */ |
| 86 | printf(".globl z_extract_offset_negative\n"); | 89 | printf(".globl z_extract_offset_negative\n"); |
| 87 | printf("z_extract_offset_negative = -0x%lx\n", offs); | 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 | printf(".globl input_data, input_data_end\n"); | 94 | printf(".globl input_data, input_data_end\n"); |
| 90 | printf("input_data:\n"); | 95 | printf("input_data:\n"); |
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 8cd27e08e23c..8cd1cc3bc835 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h | |||
| @@ -150,6 +150,7 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) | |||
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void cpu_disable_common(void); | 152 | void cpu_disable_common(void); |
| 153 | void cpu_die_common(unsigned int cpu); | ||
| 153 | void native_smp_prepare_boot_cpu(void); | 154 | void native_smp_prepare_boot_cpu(void); |
| 154 | void native_smp_prepare_cpus(unsigned int max_cpus); | 155 | void native_smp_prepare_cpus(unsigned int max_cpus); |
| 155 | void native_smp_cpus_done(unsigned int max_cpus); | 156 | void native_smp_cpus_done(unsigned int max_cpus); |
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index 7aa1acc79789..06674473b0e6 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
| @@ -108,12 +108,13 @@ static size_t compute_container_size(u8 *data, u32 total_size) | |||
| 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in | 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in |
| 109 | * kernel heap memory. | 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 | struct equiv_cpu_entry *eq; | 113 | struct equiv_cpu_entry *eq; |
| 114 | size_t *cont_sz; | 114 | size_t *cont_sz; |
| 115 | u32 *header; | 115 | u32 *header; |
| 116 | u8 *data, **cont; | 116 | u8 *data, **cont; |
| 117 | u8 (*patch)[PATCH_MAX_SIZE]; | ||
| 117 | u16 eq_id = 0; | 118 | u16 eq_id = 0; |
| 118 | int offset, left; | 119 | int offset, left; |
| 119 | u32 rev, eax, ebx, ecx, edx; | 120 | u32 rev, eax, ebx, ecx, edx; |
| @@ -123,10 +124,12 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
| 123 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); | 124 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); |
| 124 | cont_sz = (size_t *)__pa_nodebug(&container_size); | 125 | cont_sz = (size_t *)__pa_nodebug(&container_size); |
| 125 | cont = (u8 **)__pa_nodebug(&container); | 126 | cont = (u8 **)__pa_nodebug(&container); |
| 127 | patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); | ||
| 126 | #else | 128 | #else |
| 127 | new_rev = &ucode_new_rev; | 129 | new_rev = &ucode_new_rev; |
| 128 | cont_sz = &container_size; | 130 | cont_sz = &container_size; |
| 129 | cont = &container; | 131 | cont = &container; |
| 132 | patch = &amd_ucode_patch; | ||
| 130 | #endif | 133 | #endif |
| 131 | 134 | ||
| 132 | data = ucode; | 135 | data = ucode; |
| @@ -213,9 +216,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
| 213 | rev = mc->hdr.patch_id; | 216 | rev = mc->hdr.patch_id; |
| 214 | *new_rev = rev; | 217 | *new_rev = rev; |
| 215 | 218 | ||
| 216 | /* save ucode patch */ | 219 | if (save_patch) |
| 217 | memcpy(amd_ucode_patch, mc, | 220 | memcpy(patch, mc, |
| 218 | min_t(u32, header[1], PATCH_MAX_SIZE)); | 221 | min_t(u32, header[1], PATCH_MAX_SIZE)); |
| 219 | } | 222 | } |
| 220 | } | 223 | } |
| 221 | 224 | ||
| @@ -246,7 +249,7 @@ void __init load_ucode_amd_bsp(void) | |||
| 246 | *data = cp.data; | 249 | *data = cp.data; |
| 247 | *size = cp.size; | 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 | #ifdef CONFIG_X86_32 | 255 | #ifdef CONFIG_X86_32 |
| @@ -263,7 +266,7 @@ void load_ucode_amd_ap(void) | |||
| 263 | size_t *usize; | 266 | size_t *usize; |
| 264 | void **ucode; | 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 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { | 270 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { |
| 268 | __apply_microcode_amd(mc); | 271 | __apply_microcode_amd(mc); |
| 269 | return; | 272 | return; |
| @@ -275,7 +278,7 @@ void load_ucode_amd_ap(void) | |||
| 275 | if (!*ucode || !*usize) | 278 | if (!*ucode || !*usize) |
| 276 | return; | 279 | return; |
| 277 | 280 | ||
| 278 | apply_ucode_in_initrd(*ucode, *usize); | 281 | apply_ucode_in_initrd(*ucode, *usize, false); |
| 279 | } | 282 | } |
| 280 | 283 | ||
| 281 | static void __init collect_cpu_sig_on_bsp(void *arg) | 284 | static void __init collect_cpu_sig_on_bsp(void *arg) |
| @@ -339,7 +342,7 @@ void load_ucode_amd_ap(void) | |||
| 339 | * AP has a different equivalence ID than BSP, looks like | 342 | * AP has a different equivalence ID than BSP, looks like |
| 340 | * mixed-steppings silicon so go through the ucode blob anew. | 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 | #endif | 348 | #endif |
| @@ -347,7 +350,9 @@ void load_ucode_amd_ap(void) | |||
| 347 | int __init save_microcode_in_initrd_amd(void) | 350 | int __init save_microcode_in_initrd_amd(void) |
| 348 | { | 351 | { |
| 349 | unsigned long cont; | 352 | unsigned long cont; |
| 353 | int retval = 0; | ||
| 350 | enum ucode_state ret; | 354 | enum ucode_state ret; |
| 355 | u8 *cont_va; | ||
| 351 | u32 eax; | 356 | u32 eax; |
| 352 | 357 | ||
| 353 | if (!container) | 358 | if (!container) |
| @@ -355,13 +360,15 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 355 | 360 | ||
| 356 | #ifdef CONFIG_X86_32 | 361 | #ifdef CONFIG_X86_32 |
| 357 | get_bsp_sig(); | 362 | get_bsp_sig(); |
| 358 | cont = (unsigned long)container; | 363 | cont = (unsigned long)container; |
| 364 | cont_va = __va(container); | ||
| 359 | #else | 365 | #else |
| 360 | /* | 366 | /* |
| 361 | * We need the physical address of the container for both bitness since | 367 | * We need the physical address of the container for both bitness since |
| 362 | * boot_params.hdr.ramdisk_image is a physical address. | 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 | #endif | 372 | #endif |
| 366 | 373 | ||
| 367 | /* | 374 | /* |
| @@ -372,6 +379,8 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 372 | if (relocated_ramdisk) | 379 | if (relocated_ramdisk) |
| 373 | container = (u8 *)(__va(relocated_ramdisk) + | 380 | container = (u8 *)(__va(relocated_ramdisk) + |
| 374 | (cont - boot_params.hdr.ramdisk_image)); | 381 | (cont - boot_params.hdr.ramdisk_image)); |
| 382 | else | ||
| 383 | container = cont_va; | ||
| 375 | 384 | ||
| 376 | if (ucode_new_rev) | 385 | if (ucode_new_rev) |
| 377 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | 386 | pr_info("microcode: updated early to new patch_level=0x%08x\n", |
| @@ -382,7 +391,7 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 382 | 391 | ||
| 383 | ret = load_microcode_amd(eax, container, container_size); | 392 | ret = load_microcode_amd(eax, container, container_size); |
| 384 | if (ret != UCODE_OK) | 393 | if (ret != UCODE_OK) |
| 385 | return -EINVAL; | 394 | retval = -EINVAL; |
| 386 | 395 | ||
| 387 | /* | 396 | /* |
| 388 | * This will be freed any msec now, stash patches for the current | 397 | * This will be freed any msec now, stash patches for the current |
| @@ -391,5 +400,5 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 391 | container = NULL; | 400 | container = NULL; |
| 392 | container_size = 0; | 401 | container_size = 0; |
| 393 | 402 | ||
| 394 | return 0; | 403 | return retval; |
| 395 | } | 404 | } |
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index 5f28a64e71ea..2c017f242a78 100644 --- a/arch/x86/kernel/cpu/microcode/core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c | |||
| @@ -124,7 +124,7 @@ void __init load_ucode_bsp(void) | |||
| 124 | static bool check_loader_disabled_ap(void) | 124 | static bool check_loader_disabled_ap(void) |
| 125 | { | 125 | { |
| 126 | #ifdef CONFIG_X86_32 | 126 | #ifdef CONFIG_X86_32 |
| 127 | return __pa_nodebug(dis_ucode_ldr); | 127 | return *((bool *)__pa_nodebug(&dis_ucode_ldr)); |
| 128 | #else | 128 | #else |
| 129 | return dis_ucode_ldr; | 129 | return dis_ucode_ldr; |
| 130 | #endif | 130 | #endif |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 4d2128ac70bd..668d8f2a8781 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -1303,10 +1303,14 @@ static void __ref remove_cpu_from_maps(int cpu) | |||
| 1303 | numa_remove_cpu(cpu); | 1303 | numa_remove_cpu(cpu); |
| 1304 | } | 1304 | } |
| 1305 | 1305 | ||
| 1306 | static DEFINE_PER_CPU(struct completion, die_complete); | ||
| 1307 | |||
| 1306 | void cpu_disable_common(void) | 1308 | void cpu_disable_common(void) |
| 1307 | { | 1309 | { |
| 1308 | int cpu = smp_processor_id(); | 1310 | int cpu = smp_processor_id(); |
| 1309 | 1311 | ||
| 1312 | init_completion(&per_cpu(die_complete, smp_processor_id())); | ||
| 1313 | |||
| 1310 | remove_siblinginfo(cpu); | 1314 | remove_siblinginfo(cpu); |
| 1311 | 1315 | ||
| 1312 | /* It's now safe to remove this processor from the online map */ | 1316 | /* It's now safe to remove this processor from the online map */ |
| @@ -1316,8 +1320,6 @@ void cpu_disable_common(void) | |||
| 1316 | fixup_irqs(); | 1320 | fixup_irqs(); |
| 1317 | } | 1321 | } |
| 1318 | 1322 | ||
| 1319 | static DEFINE_PER_CPU(struct completion, die_complete); | ||
| 1320 | |||
| 1321 | int native_cpu_disable(void) | 1323 | int native_cpu_disable(void) |
| 1322 | { | 1324 | { |
| 1323 | int ret; | 1325 | int ret; |
| @@ -1327,16 +1329,21 @@ int native_cpu_disable(void) | |||
| 1327 | return ret; | 1329 | return ret; |
| 1328 | 1330 | ||
| 1329 | clear_local_APIC(); | 1331 | clear_local_APIC(); |
| 1330 | init_completion(&per_cpu(die_complete, smp_processor_id())); | ||
| 1331 | cpu_disable_common(); | 1332 | cpu_disable_common(); |
| 1332 | 1333 | ||
| 1333 | return 0; | 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 | void native_cpu_die(unsigned int cpu) | 1342 | void native_cpu_die(unsigned int cpu) |
| 1337 | { | 1343 | { |
| 1338 | /* We don't do anything here: idle task is faking death itself. */ | 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 | /* They ack this in play_dead() by setting CPU_DEAD */ | 1348 | /* They ack this in play_dead() by setting CPU_DEAD */ |
| 1342 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { | 1349 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { |
diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl new file mode 100644 index 000000000000..0b0b124d3ece --- /dev/null +++ b/arch/x86/tools/calc_run_size.pl | |||
| @@ -0,0 +1,30 @@ | |||
| 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); | ||
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 8650cdb53209..4c071aeb8417 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
| @@ -510,6 +510,9 @@ static void xen_cpu_die(unsigned int cpu) | |||
| 510 | current->state = TASK_UNINTERRUPTIBLE; | 510 | current->state = TASK_UNINTERRUPTIBLE; |
| 511 | schedule_timeout(HZ/10); | 511 | schedule_timeout(HZ/10); |
| 512 | } | 512 | } |
| 513 | |||
| 514 | cpu_die_common(cpu); | ||
| 515 | |||
| 513 | xen_smp_intr_free(cpu); | 516 | xen_smp_intr_free(cpu); |
| 514 | xen_uninit_lock_cpu(cpu); | 517 | xen_uninit_lock_cpu(cpu); |
| 515 | xen_teardown_timer(cpu); | 518 | xen_teardown_timer(cpu); |
