diff options
author | Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> | 2016-11-29 07:45:48 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-11-30 07:14:59 -0500 |
commit | ec2b9bfaac44ea889625a6b9473d33898b10d35f (patch) | |
tree | abb247ab853ca78135948da2e30da525b4a5839f /kernel/kexec_file.c | |
parent | 60fe3910bb029e3671ce7ac080a7acb7e032b9e0 (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.c | 88 |
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 | */ |
456 | int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, | 462 | int 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; |
804 | out: | 796 | out: |
805 | vfree(sechdrs); | 797 | vfree(sechdrs); |
806 | vfree(purgatory_buf); | 798 | vfree(kbuf.buffer); |
807 | return ret; | 799 | return ret; |
808 | } | 800 | } |
809 | 801 | ||