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); |
