aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/kexec_elf_64.c9
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c8
-rw-r--r--include/linux/kexec.h17
-rw-r--r--kernel/kexec_file.c29
4 files changed, 31 insertions, 32 deletions
diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 6c78c11c7faf..ba4f18a43ee8 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -572,7 +572,7 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
572{ 572{
573 int ret; 573 int ret;
574 unsigned int fdt_size; 574 unsigned int fdt_size;
575 unsigned long kernel_load_addr, purgatory_load_addr; 575 unsigned long kernel_load_addr;
576 unsigned long initrd_load_addr = 0, fdt_load_addr; 576 unsigned long initrd_load_addr = 0, fdt_load_addr;
577 void *fdt; 577 void *fdt;
578 const void *slave_code; 578 const void *slave_code;
@@ -580,6 +580,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
580 struct elf_info elf_info; 580 struct elf_info elf_info;
581 struct kexec_buf kbuf = { .image = image, .buf_min = 0, 581 struct kexec_buf kbuf = { .image = image, .buf_min = 0,
582 .buf_max = ppc64_rma_size }; 582 .buf_max = ppc64_rma_size };
583 struct kexec_buf pbuf = { .image = image, .buf_min = 0,
584 .buf_max = ppc64_rma_size, .top_down = true };
583 585
584 ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info); 586 ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
585 if (ret) 587 if (ret)
@@ -591,14 +593,13 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
591 593
592 pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr); 594 pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
593 595
594 ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true, 596 ret = kexec_load_purgatory(image, &pbuf);
595 &purgatory_load_addr);
596 if (ret) { 597 if (ret) {
597 pr_err("Loading purgatory failed.\n"); 598 pr_err("Loading purgatory failed.\n");
598 goto out; 599 goto out;
599 } 600 }
600 601
601 pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr); 602 pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
602 603
603 if (initrd != NULL) { 604 if (initrd != NULL) {
604 kbuf.buffer = initrd; 605 kbuf.buffer = initrd;
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 705654776c0c..3182908b7e6c 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -334,7 +334,6 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
334 unsigned long setup_header_size, params_cmdline_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;
338 struct bzimage64_data *ldata; 337 struct bzimage64_data *ldata;
339 struct kexec_entry64_regs regs64; 338 struct kexec_entry64_regs regs64;
340 void *stack; 339 void *stack;
@@ -342,6 +341,8 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
342 unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset; 341 unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
343 struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX, 342 struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
344 .top_down = true }; 343 .top_down = true };
344 struct kexec_buf pbuf = { .image = image, .buf_min = MIN_PURGATORY_ADDR,
345 .buf_max = ULONG_MAX, .top_down = true };
345 346
346 header = (struct setup_header *)(kernel + setup_hdr_offset); 347 header = (struct setup_header *)(kernel + setup_hdr_offset);
347 setup_sects = header->setup_sects; 348 setup_sects = header->setup_sects;
@@ -379,14 +380,13 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
379 * Load purgatory. For 64bit entry point, purgatory code can be 380 * Load purgatory. For 64bit entry point, purgatory code can be
380 * anywhere. 381 * anywhere.
381 */ 382 */
382 ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1, 383 ret = kexec_load_purgatory(image, &pbuf);
383 &purgatory_load_addr);
384 if (ret) { 384 if (ret) {
385 pr_err("Loading purgatory failed\n"); 385 pr_err("Loading purgatory failed\n");
386 return ERR_PTR(ret); 386 return ERR_PTR(ret);
387 } 387 }
388 388
389 pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr); 389 pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
390 390
391 391
392 /* 392 /*
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 0e389b9b7722..9e4e638fb505 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -114,9 +114,6 @@ struct purgatory_info {
114 * relocation. This memory can be freed post image load. 114 * relocation. This memory can be freed post image load.
115 */ 115 */
116 void *purgatory_buf; 116 void *purgatory_buf;
117
118 /* Address where purgatory is finally loaded and is executed from */
119 unsigned long purgatory_load_addr;
120}; 117};
121 118
122struct kimage; 119struct kimage;
@@ -171,6 +168,12 @@ struct kexec_buf {
171 bool top_down; 168 bool top_down;
172}; 169};
173 170
171int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
172int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
173 void *buf, unsigned int size,
174 bool get_value);
175void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
176
174int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi, 177int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
175 Elf_Shdr *section, 178 Elf_Shdr *section,
176 const Elf_Shdr *relsec, 179 const Elf_Shdr *relsec,
@@ -266,14 +269,6 @@ extern void machine_kexec_cleanup(struct kimage *image);
266extern int kernel_kexec(void); 269extern int kernel_kexec(void);
267extern struct page *kimage_alloc_control_pages(struct kimage *image, 270extern struct page *kimage_alloc_control_pages(struct kimage *image,
268 unsigned int order); 271 unsigned int order);
269extern int kexec_load_purgatory(struct kimage *image, unsigned long min,
270 unsigned long max, int top_down,
271 unsigned long *load_addr);
272extern int kexec_purgatory_get_set_symbol(struct kimage *image,
273 const char *name, void *buf,
274 unsigned int size, bool get_value);
275extern void *kexec_purgatory_get_symbol_addr(struct kimage *image,
276 const char *name);
277extern void __crash_kexec(struct pt_regs *); 272extern void __crash_kexec(struct pt_regs *);
278extern void crash_kexec(struct pt_regs *); 273extern void crash_kexec(struct pt_regs *);
279int kexec_should_crash(struct task_struct *); 274int kexec_should_crash(struct task_struct *);
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);