diff options
-rw-r--r-- | arch/powerpc/kernel/kexec_elf_64.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/kexec-bzimage64.c | 8 | ||||
-rw-r--r-- | include/linux/kexec.h | 17 | ||||
-rw-r--r-- | kernel/kexec_file.c | 29 |
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 | ||
122 | struct kimage; | 119 | struct kimage; |
@@ -171,6 +168,12 @@ struct kexec_buf { | |||
171 | bool top_down; | 168 | bool top_down; |
172 | }; | 169 | }; |
173 | 170 | ||
171 | int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf); | ||
172 | int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name, | ||
173 | void *buf, unsigned int size, | ||
174 | bool get_value); | ||
175 | void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name); | ||
176 | |||
174 | int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi, | 177 | int __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); | |||
266 | extern int kernel_kexec(void); | 269 | extern int kernel_kexec(void); |
267 | extern struct page *kimage_alloc_control_pages(struct kimage *image, | 270 | extern struct page *kimage_alloc_control_pages(struct kimage *image, |
268 | unsigned int order); | 271 | unsigned int order); |
269 | extern int kexec_load_purgatory(struct kimage *image, unsigned long min, | ||
270 | unsigned long max, int top_down, | ||
271 | unsigned long *load_addr); | ||
272 | extern int kexec_purgatory_get_set_symbol(struct kimage *image, | ||
273 | const char *name, void *buf, | ||
274 | unsigned int size, bool get_value); | ||
275 | extern void *kexec_purgatory_get_symbol_addr(struct kimage *image, | ||
276 | const char *name); | ||
277 | extern void __crash_kexec(struct pt_regs *); | 272 | extern void __crash_kexec(struct pt_regs *); |
278 | extern void crash_kexec(struct pt_regs *); | 273 | extern void crash_kexec(struct pt_regs *); |
279 | int kexec_should_crash(struct task_struct *); | 274 | int 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; |
769 | out: | 768 | out: |
@@ -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 | /* |
905 | int 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 | */ | ||
914 | int 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; |
934 | out: | 937 | out: |
935 | vfree(pi->sechdrs); | 938 | vfree(pi->sechdrs); |