aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/crash.c37
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c48
-rw-r--r--include/linux/kexec.h8
-rw-r--r--kernel/kexec_file.c88
4 files changed, 87 insertions, 94 deletions
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 650830e39e3a..3741461c63a0 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -631,9 +631,9 @@ static int determine_backup_region(u64 start, u64 end, void *arg)
631 631
632int crash_load_segments(struct kimage *image) 632int crash_load_segments(struct kimage *image)
633{ 633{
634 unsigned long src_start, src_sz, elf_sz;
635 void *elf_addr;
636 int ret; 634 int ret;
635 struct kexec_buf kbuf = { .image = image, .buf_min = 0,
636 .buf_max = ULONG_MAX, .top_down = false };
637 637
638 /* 638 /*
639 * Determine and load a segment for backup area. First 640K RAM 639 * Determine and load a segment for backup area. First 640K RAM
@@ -647,43 +647,44 @@ int crash_load_segments(struct kimage *image)
647 if (ret < 0) 647 if (ret < 0)
648 return ret; 648 return ret;
649 649
650 src_start = image->arch.backup_src_start;
651 src_sz = image->arch.backup_src_sz;
652
653 /* Add backup segment. */ 650 /* Add backup segment. */
654 if (src_sz) { 651 if (image->arch.backup_src_sz) {
652 kbuf.buffer = &crash_zero_bytes;
653 kbuf.bufsz = sizeof(crash_zero_bytes);
654 kbuf.memsz = image->arch.backup_src_sz;
655 kbuf.buf_align = PAGE_SIZE;
655 /* 656 /*
656 * Ideally there is no source for backup segment. This is 657 * Ideally there is no source for backup segment. This is
657 * copied in purgatory after crash. Just add a zero filled 658 * copied in purgatory after crash. Just add a zero filled
658 * segment for now to make sure checksum logic works fine. 659 * segment for now to make sure checksum logic works fine.
659 */ 660 */
660 ret = kexec_add_buffer(image, (char *)&crash_zero_bytes, 661 ret = kexec_add_buffer(&kbuf);
661 sizeof(crash_zero_bytes), src_sz,
662 PAGE_SIZE, 0, -1, 0,
663 &image->arch.backup_load_addr);
664 if (ret) 662 if (ret)
665 return ret; 663 return ret;
664 image->arch.backup_load_addr = kbuf.mem;
666 pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n", 665 pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n",
667 image->arch.backup_load_addr, src_start, src_sz); 666 image->arch.backup_load_addr,
667 image->arch.backup_src_start, kbuf.memsz);
668 } 668 }
669 669
670 /* Prepare elf headers and add a segment */ 670 /* Prepare elf headers and add a segment */
671 ret = prepare_elf_headers(image, &elf_addr, &elf_sz); 671 ret = prepare_elf_headers(image, &kbuf.buffer, &kbuf.bufsz);
672 if (ret) 672 if (ret)
673 return ret; 673 return ret;
674 674
675 image->arch.elf_headers = elf_addr; 675 image->arch.elf_headers = kbuf.buffer;
676 image->arch.elf_headers_sz = elf_sz; 676 image->arch.elf_headers_sz = kbuf.bufsz;
677 677
678 ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz, 678 kbuf.memsz = kbuf.bufsz;
679 ELF_CORE_HEADER_ALIGN, 0, -1, 0, 679 kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
680 &image->arch.elf_load_addr); 680 ret = kexec_add_buffer(&kbuf);
681 if (ret) { 681 if (ret) {
682 vfree((void *)image->arch.elf_headers); 682 vfree((void *)image->arch.elf_headers);
683 return ret; 683 return ret;
684 } 684 }
685 image->arch.elf_load_addr = kbuf.mem;
685 pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 686 pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
686 image->arch.elf_load_addr, elf_sz, elf_sz); 687 image->arch.elf_load_addr, kbuf.bufsz, kbuf.bufsz);
687 688
688 return ret; 689 return ret;
689} 690}
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 3407b148c240..d0a814a9d96a 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -331,17 +331,17 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
331 331
332 struct setup_header *header; 332 struct setup_header *header;
333 int setup_sects, kern16_size, ret = 0; 333 int setup_sects, kern16_size, ret = 0;
334 unsigned long setup_header_size, params_cmdline_sz, params_misc_sz; 334 unsigned long setup_header_size, params_cmdline_sz;
335 struct boot_params *params; 335 struct boot_params *params;
336 unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr; 336 unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
337 unsigned long purgatory_load_addr; 337 unsigned long purgatory_load_addr;
338 unsigned long kernel_bufsz, kernel_memsz, kernel_align;
339 char *kernel_buf;
340 struct bzimage64_data *ldata; 338 struct bzimage64_data *ldata;
341 struct kexec_entry64_regs regs64; 339 struct kexec_entry64_regs regs64;
342 void *stack; 340 void *stack;
343 unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr); 341 unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr);
344 unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset; 342 unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
343 struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
344 .top_down = true };
345 345
346 header = (struct setup_header *)(kernel + setup_hdr_offset); 346 header = (struct setup_header *)(kernel + setup_hdr_offset);
347 setup_sects = header->setup_sects; 347 setup_sects = header->setup_sects;
@@ -402,11 +402,11 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
402 params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + 402 params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
403 MAX_ELFCOREHDR_STR_LEN; 403 MAX_ELFCOREHDR_STR_LEN;
404 params_cmdline_sz = ALIGN(params_cmdline_sz, 16); 404 params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
405 params_misc_sz = params_cmdline_sz + efi_map_sz + 405 kbuf.bufsz = params_cmdline_sz + efi_map_sz +
406 sizeof(struct setup_data) + 406 sizeof(struct setup_data) +
407 sizeof(struct efi_setup_data); 407 sizeof(struct efi_setup_data);
408 408
409 params = kzalloc(params_misc_sz, GFP_KERNEL); 409 params = kzalloc(kbuf.bufsz, GFP_KERNEL);
410 if (!params) 410 if (!params)
411 return ERR_PTR(-ENOMEM); 411 return ERR_PTR(-ENOMEM);
412 efi_map_offset = params_cmdline_sz; 412 efi_map_offset = params_cmdline_sz;
@@ -418,37 +418,41 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
418 /* Is there a limit on setup header size? */ 418 /* Is there a limit on setup header size? */
419 memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size); 419 memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size);
420 420
421 ret = kexec_add_buffer(image, (char *)params, params_misc_sz, 421 kbuf.buffer = params;
422 params_misc_sz, 16, MIN_BOOTPARAM_ADDR, 422 kbuf.memsz = kbuf.bufsz;
423 ULONG_MAX, 1, &bootparam_load_addr); 423 kbuf.buf_align = 16;
424 kbuf.buf_min = MIN_BOOTPARAM_ADDR;
425 ret = kexec_add_buffer(&kbuf);
424 if (ret) 426 if (ret)
425 goto out_free_params; 427 goto out_free_params;
428 bootparam_load_addr = kbuf.mem;
426 pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 429 pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
427 bootparam_load_addr, params_misc_sz, params_misc_sz); 430 bootparam_load_addr, kbuf.bufsz, kbuf.bufsz);
428 431
429 /* Load kernel */ 432 /* Load kernel */
430 kernel_buf = kernel + kern16_size; 433 kbuf.buffer = kernel + kern16_size;
431 kernel_bufsz = kernel_len - kern16_size; 434 kbuf.bufsz = kernel_len - kern16_size;
432 kernel_memsz = PAGE_ALIGN(header->init_size); 435 kbuf.memsz = PAGE_ALIGN(header->init_size);
433 kernel_align = header->kernel_alignment; 436 kbuf.buf_align = header->kernel_alignment;
434 437 kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
435 ret = kexec_add_buffer(image, kernel_buf, 438 ret = kexec_add_buffer(&kbuf);
436 kernel_bufsz, kernel_memsz, kernel_align,
437 MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
438 &kernel_load_addr);
439 if (ret) 439 if (ret)
440 goto out_free_params; 440 goto out_free_params;
441 kernel_load_addr = kbuf.mem;
441 442
442 pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 443 pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
443 kernel_load_addr, kernel_memsz, kernel_memsz); 444 kernel_load_addr, kbuf.bufsz, kbuf.memsz);
444 445
445 /* Load initrd high */ 446 /* Load initrd high */
446 if (initrd) { 447 if (initrd) {
447 ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len, 448 kbuf.buffer = initrd;
448 PAGE_SIZE, MIN_INITRD_LOAD_ADDR, 449 kbuf.bufsz = kbuf.memsz = initrd_len;
449 ULONG_MAX, 1, &initrd_load_addr); 450 kbuf.buf_align = PAGE_SIZE;
451 kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
452 ret = kexec_add_buffer(&kbuf);
450 if (ret) 453 if (ret)
451 goto out_free_params; 454 goto out_free_params;
455 initrd_load_addr = kbuf.mem;
452 456
453 pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 457 pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
454 initrd_load_addr, initrd_len, initrd_len); 458 initrd_load_addr, initrd_len, initrd_len);
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 5e320ddaaa82..437ef1b47428 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -163,7 +163,7 @@ struct kexec_file_ops {
163 */ 163 */
164struct kexec_buf { 164struct kexec_buf {
165 struct kimage *image; 165 struct kimage *image;
166 char *buffer; 166 void *buffer;
167 unsigned long bufsz; 167 unsigned long bufsz;
168 unsigned long mem; 168 unsigned long mem;
169 unsigned long memsz; 169 unsigned long memsz;
@@ -175,6 +175,7 @@ struct kexec_buf {
175 175
176int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, 176int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
177 int (*func)(u64, u64, void *)); 177 int (*func)(u64, u64, void *));
178extern int kexec_add_buffer(struct kexec_buf *kbuf);
178#endif /* CONFIG_KEXEC_FILE */ 179#endif /* CONFIG_KEXEC_FILE */
179 180
180struct kimage { 181struct kimage {
@@ -239,11 +240,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
239 struct kexec_segment __user *segments, 240 struct kexec_segment __user *segments,
240 unsigned long flags); 241 unsigned long flags);
241extern int kernel_kexec(void); 242extern int kernel_kexec(void);
242extern int kexec_add_buffer(struct kimage *image, char *buffer,
243 unsigned long bufsz, unsigned long memsz,
244 unsigned long buf_align, unsigned long buf_min,
245 unsigned long buf_max, bool top_down,
246 unsigned long *load_addr);
247extern struct page *kimage_alloc_control_pages(struct kimage *image, 243extern struct page *kimage_alloc_control_pages(struct kimage *image,
248 unsigned int order); 244 unsigned int order);
249extern int kexec_load_purgatory(struct kimage *image, unsigned long min, 245extern int kexec_load_purgatory(struct kimage *image, unsigned long min,
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index f865674bff51..efd2c094af7e 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -449,25 +449,27 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
449 return walk_system_ram_res(0, ULONG_MAX, kbuf, func); 449 return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
450} 450}
451 451
452/* 452/**
453 * Helper function for placing a buffer in a kexec segment. This assumes 453 * kexec_add_buffer - place a buffer in a kexec segment
454 * that kexec_mutex is held. 454 * @kbuf: Buffer contents and memory parameters.
455 *
456 * This function assumes that kexec_mutex is held.
457 * On successful return, @kbuf->mem will have the physical address of
458 * the buffer in memory.
459 *
460 * Return: 0 on success, negative errno on error.
455 */ 461 */
456int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, 462int kexec_add_buffer(struct kexec_buf *kbuf)
457 unsigned long memsz, unsigned long buf_align,
458 unsigned long buf_min, unsigned long buf_max,
459 bool top_down, unsigned long *load_addr)
460{ 463{
461 464
462 struct kexec_segment *ksegment; 465 struct kexec_segment *ksegment;
463 struct kexec_buf buf, *kbuf;
464 int ret; 466 int ret;
465 467
466 /* Currently adding segment this way is allowed only in file mode */ 468 /* Currently adding segment this way is allowed only in file mode */
467 if (!image->file_mode) 469 if (!kbuf->image->file_mode)
468 return -EINVAL; 470 return -EINVAL;
469 471
470 if (image->nr_segments >= KEXEC_SEGMENT_MAX) 472 if (kbuf->image->nr_segments >= KEXEC_SEGMENT_MAX)
471 return -EINVAL; 473 return -EINVAL;
472 474
473 /* 475 /*
@@ -477,22 +479,14 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
477 * logic goes through list of segments to make sure there are 479 * logic goes through list of segments to make sure there are
478 * no destination overlaps. 480 * no destination overlaps.
479 */ 481 */
480 if (!list_empty(&image->control_pages)) { 482 if (!list_empty(&kbuf->image->control_pages)) {
481 WARN_ON(1); 483 WARN_ON(1);
482 return -EINVAL; 484 return -EINVAL;
483 } 485 }
484 486
485 memset(&buf, 0, sizeof(struct kexec_buf)); 487 /* Ensure minimum alignment needed for segments. */
486 kbuf = &buf; 488 kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
487 kbuf->image = image; 489 kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
488 kbuf->buffer = buffer;
489 kbuf->bufsz = bufsz;
490
491 kbuf->memsz = ALIGN(memsz, PAGE_SIZE);
492 kbuf->buf_align = max(buf_align, PAGE_SIZE);
493 kbuf->buf_min = buf_min;
494 kbuf->buf_max = buf_max;
495 kbuf->top_down = top_down;
496 490
497 /* Walk the RAM ranges and allocate a suitable range for the buffer */ 491 /* Walk the RAM ranges and allocate a suitable range for the buffer */
498 ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback); 492 ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
@@ -502,13 +496,12 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
502 } 496 }
503 497
504 /* Found a suitable memory range */ 498 /* Found a suitable memory range */
505 ksegment = &image->segment[image->nr_segments]; 499 ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
506 ksegment->kbuf = kbuf->buffer; 500 ksegment->kbuf = kbuf->buffer;
507 ksegment->bufsz = kbuf->bufsz; 501 ksegment->bufsz = kbuf->bufsz;
508 ksegment->mem = kbuf->mem; 502 ksegment->mem = kbuf->mem;
509 ksegment->memsz = kbuf->memsz; 503 ksegment->memsz = kbuf->memsz;
510 image->nr_segments++; 504 kbuf->image->nr_segments++;
511 *load_addr = ksegment->mem;
512 return 0; 505 return 0;
513} 506}
514 507
@@ -630,13 +623,15 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
630 unsigned long max, int top_down) 623 unsigned long max, int top_down)
631{ 624{
632 struct purgatory_info *pi = &image->purgatory_info; 625 struct purgatory_info *pi = &image->purgatory_info;
633 unsigned long align, buf_align, bss_align, buf_sz, bss_sz, bss_pad; 626 unsigned long align, bss_align, bss_sz, bss_pad;
634 unsigned long memsz, entry, load_addr, curr_load_addr, bss_addr, offset; 627 unsigned long entry, load_addr, curr_load_addr, bss_addr, offset;
635 unsigned char *buf_addr, *src; 628 unsigned char *buf_addr, *src;
636 int i, ret = 0, entry_sidx = -1; 629 int i, ret = 0, entry_sidx = -1;
637 const Elf_Shdr *sechdrs_c; 630 const Elf_Shdr *sechdrs_c;
638 Elf_Shdr *sechdrs = NULL; 631 Elf_Shdr *sechdrs = NULL;
639 void *purgatory_buf = NULL; 632 struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
633 .buf_min = min, .buf_max = max,
634 .top_down = top_down };
640 635
641 /* 636 /*
642 * sechdrs_c points to section headers in purgatory and are read 637 * sechdrs_c points to section headers in purgatory and are read
@@ -702,9 +697,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
702 } 697 }
703 698
704 /* Determine how much memory is needed to load relocatable object. */ 699 /* Determine how much memory is needed to load relocatable object. */
705 buf_align = 1;
706 bss_align = 1; 700 bss_align = 1;
707 buf_sz = 0;
708 bss_sz = 0; 701 bss_sz = 0;
709 702
710 for (i = 0; i < pi->ehdr->e_shnum; i++) { 703 for (i = 0; i < pi->ehdr->e_shnum; i++) {
@@ -713,10 +706,10 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
713 706
714 align = sechdrs[i].sh_addralign; 707 align = sechdrs[i].sh_addralign;
715 if (sechdrs[i].sh_type != SHT_NOBITS) { 708 if (sechdrs[i].sh_type != SHT_NOBITS) {
716 if (buf_align < align) 709 if (kbuf.buf_align < align)
717 buf_align = align; 710 kbuf.buf_align = align;
718 buf_sz = ALIGN(buf_sz, align); 711 kbuf.bufsz = ALIGN(kbuf.bufsz, align);
719 buf_sz += sechdrs[i].sh_size; 712 kbuf.bufsz += sechdrs[i].sh_size;
720 } else { 713 } else {
721 /* bss section */ 714 /* bss section */
722 if (bss_align < align) 715 if (bss_align < align)
@@ -728,32 +721,31 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
728 721
729 /* Determine the bss padding required to align bss properly */ 722 /* Determine the bss padding required to align bss properly */
730 bss_pad = 0; 723 bss_pad = 0;
731 if (buf_sz & (bss_align - 1)) 724 if (kbuf.bufsz & (bss_align - 1))
732 bss_pad = bss_align - (buf_sz & (bss_align - 1)); 725 bss_pad = bss_align - (kbuf.bufsz & (bss_align - 1));
733 726
734 memsz = buf_sz + bss_pad + bss_sz; 727 kbuf.memsz = kbuf.bufsz + bss_pad + bss_sz;
735 728
736 /* Allocate buffer for purgatory */ 729 /* Allocate buffer for purgatory */
737 purgatory_buf = vzalloc(buf_sz); 730 kbuf.buffer = vzalloc(kbuf.bufsz);
738 if (!purgatory_buf) { 731 if (!kbuf.buffer) {
739 ret = -ENOMEM; 732 ret = -ENOMEM;
740 goto out; 733 goto out;
741 } 734 }
742 735
743 if (buf_align < bss_align) 736 if (kbuf.buf_align < bss_align)
744 buf_align = bss_align; 737 kbuf.buf_align = bss_align;
745 738
746 /* Add buffer to segment list */ 739 /* Add buffer to segment list */
747 ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz, 740 ret = kexec_add_buffer(&kbuf);
748 buf_align, min, max, top_down,
749 &pi->purgatory_load_addr);
750 if (ret) 741 if (ret)
751 goto out; 742 goto out;
743 pi->purgatory_load_addr = kbuf.mem;
752 744
753 /* Load SHF_ALLOC sections */ 745 /* Load SHF_ALLOC sections */
754 buf_addr = purgatory_buf; 746 buf_addr = kbuf.buffer;
755 load_addr = curr_load_addr = pi->purgatory_load_addr; 747 load_addr = curr_load_addr = pi->purgatory_load_addr;
756 bss_addr = load_addr + buf_sz + bss_pad; 748 bss_addr = load_addr + kbuf.bufsz + bss_pad;
757 749
758 for (i = 0; i < pi->ehdr->e_shnum; i++) { 750 for (i = 0; i < pi->ehdr->e_shnum; i++) {
759 if (!(sechdrs[i].sh_flags & SHF_ALLOC)) 751 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -799,11 +791,11 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
799 * Used later to identify which section is purgatory and skip it 791 * Used later to identify which section is purgatory and skip it
800 * from checksumming. 792 * from checksumming.
801 */ 793 */
802 pi->purgatory_buf = purgatory_buf; 794 pi->purgatory_buf = kbuf.buffer;
803 return ret; 795 return ret;
804out: 796out:
805 vfree(sechdrs); 797 vfree(sechdrs);
806 vfree(purgatory_buf); 798 vfree(kbuf.buffer);
807 return ret; 799 return ret;
808} 800}
809 801