summaryrefslogtreecommitdiffstats
path: root/kernel/kexec_file.c
diff options
context:
space:
mode:
authorThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>2016-11-29 07:45:48 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-11-30 07:14:59 -0500
commitec2b9bfaac44ea889625a6b9473d33898b10d35f (patch)
treeabb247ab853ca78135948da2e30da525b4a5839f /kernel/kexec_file.c
parent60fe3910bb029e3671ce7ac080a7acb7e032b9e0 (diff)
kexec_file: Change kexec_add_buffer to take kexec_buf as argument.
This is done to simplify the kexec_add_buffer argument list. Adapt all callers to set up a kexec_buf to pass to kexec_add_buffer. In addition, change the type of kexec_buf.buffer from char * to void *. There is no particular reason for it to be a char *, and the change allows us to get rid of 3 existing casts to char * in the code. Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Acked-by: Dave Young <dyoung@redhat.com> Acked-by: Balbir Singh <bsingharora@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'kernel/kexec_file.c')
-rw-r--r--kernel/kexec_file.c88
1 files changed, 40 insertions, 48 deletions
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