aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kexec_file.c
diff options
context:
space:
mode:
authorPhilipp Rudo <prudo@linux.vnet.ibm.com>2018-04-13 18:36:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-13 20:10:28 -0400
commit3be3f61d25e04ecf90d65d52fad632af5ba8805b (patch)
treee74b43ccd63d1d063f01281903b7639d226f3bf1 /kernel/kexec_file.c
parent8da0b724959ccd3f8435214ebdaf1aef548967bb (diff)
kernel/kexec_file.c: allow archs to set purgatory load address
For s390 new kernels are loaded to fixed addresses in memory before they are booted. With the current code this is a problem as it assumes the kernel will be loaded to an 'arbitrary' address. In particular, kexec_locate_mem_hole searches for a large enough memory region and sets the load address (kexec_bufer->mem) to it. Luckily there is a simple workaround for this problem. By returning 1 in arch_kexec_walk_mem, kexec_locate_mem_hole is turned off. This allows the architecture to set kbuf->mem by hand. While the trick works fine for the kernel it does not for the purgatory as here the architectures don't have access to its kexec_buffer. Give architectures access to the purgatories kexec_buffer by changing kexec_load_purgatory to take a pointer to it. With this change architectures have access to the buffer and can edit it as they need. A nice side effect of this change is that we can get rid of the purgatory_info->purgatory_load_address field. As now the information stored there can directly be accessed from kbuf->mem. Link: http://lkml.kernel.org/r/20180321112751.22196-11-prudo@linux.vnet.ibm.com Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com> Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Acked-by: Dave Young <dyoung@redhat.com> Cc: AKASHI Takahiro <takahiro.akashi@linaro.org> Cc: Eric Biederman <ebiederm@xmission.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kexec_file.c')
-rw-r--r--kernel/kexec_file.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 269116fd932c..75d8e7cf040e 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -730,8 +730,8 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
730 int i, ret; 730 int i, ret;
731 731
732 sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff; 732 sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
733 bss_align = 1; 733 kbuf->buf_align = bss_align = 1;
734 bss_sz = 0; 734 kbuf->bufsz = bss_sz = 0;
735 735
736 for (i = 0; i < pi->ehdr->e_shnum; i++) { 736 for (i = 0; i < pi->ehdr->e_shnum; i++) {
737 if (!(sechdrs[i].sh_flags & SHF_ALLOC)) 737 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -763,7 +763,6 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
763 ret = kexec_add_buffer(kbuf); 763 ret = kexec_add_buffer(kbuf);
764 if (ret) 764 if (ret)
765 goto out; 765 goto out;
766 pi->purgatory_load_addr = kbuf->mem;
767 766
768 return 0; 767 return 0;
769out: 768out:
@@ -901,27 +900,32 @@ static int kexec_apply_relocations(struct kimage *image)
901 return 0; 900 return 0;
902} 901}
903 902
904/* Load relocatable purgatory object and relocate it appropriately */ 903/*
905int kexec_load_purgatory(struct kimage *image, unsigned long min, 904 * kexec_load_purgatory - Load and relocate the purgatory object.
906 unsigned long max, int top_down, 905 * @image: Image to add the purgatory to.
907 unsigned long *load_addr) 906 * @kbuf: Memory parameters to use.
907 *
908 * Allocates the memory needed for image->purgatory_info.sechdrs and
909 * image->purgatory_info.purgatory_buf/kbuf->buffer. Caller is responsible
910 * to free the memory after use.
911 *
912 * Return: 0 on success, negative errno on error.
913 */
914int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
908{ 915{
909 struct purgatory_info *pi = &image->purgatory_info; 916 struct purgatory_info *pi = &image->purgatory_info;
910 int ret; 917 int ret;
911 struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
912 .buf_min = min, .buf_max = max,
913 .top_down = top_down };
914 918
915 if (kexec_purgatory_size <= 0) 919 if (kexec_purgatory_size <= 0)
916 return -EINVAL; 920 return -EINVAL;
917 921
918 pi->ehdr = (const Elf_Ehdr *)kexec_purgatory; 922 pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
919 923
920 ret = kexec_purgatory_setup_kbuf(pi, &kbuf); 924 ret = kexec_purgatory_setup_kbuf(pi, kbuf);
921 if (ret) 925 if (ret)
922 return ret; 926 return ret;
923 927
924 ret = kexec_purgatory_setup_sechdrs(pi, &kbuf); 928 ret = kexec_purgatory_setup_sechdrs(pi, kbuf);
925 if (ret) 929 if (ret)
926 goto out_free_kbuf; 930 goto out_free_kbuf;
927 931
@@ -929,7 +933,6 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
929 if (ret) 933 if (ret)
930 goto out; 934 goto out;
931 935
932 *load_addr = pi->purgatory_load_addr;
933 return 0; 936 return 0;
934out: 937out:
935 vfree(pi->sechdrs); 938 vfree(pi->sechdrs);