diff options
-rw-r--r-- | arch/x86/kernel/crash.c | 37 | ||||
-rw-r--r-- | arch/x86/kernel/kexec-bzimage64.c | 48 | ||||
-rw-r--r-- | include/linux/kexec.h | 8 | ||||
-rw-r--r-- | kernel/kexec_file.c | 88 |
4 files changed, 87 insertions, 94 deletions
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 650830e39e3a..3741461c63a0 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c | |||
@@ -631,9 +631,9 @@ static int determine_backup_region(u64 start, u64 end, void *arg) | |||
631 | 631 | ||
632 | int crash_load_segments(struct kimage *image) | 632 | int crash_load_segments(struct kimage *image) |
633 | { | 633 | { |
634 | unsigned long src_start, src_sz, elf_sz; | ||
635 | void *elf_addr; | ||
636 | int ret; | 634 | int ret; |
635 | struct kexec_buf kbuf = { .image = image, .buf_min = 0, | ||
636 | .buf_max = ULONG_MAX, .top_down = false }; | ||
637 | 637 | ||
638 | /* | 638 | /* |
639 | * Determine and load a segment for backup area. First 640K RAM | 639 | * Determine and load a segment for backup area. First 640K RAM |
@@ -647,43 +647,44 @@ int crash_load_segments(struct kimage *image) | |||
647 | if (ret < 0) | 647 | if (ret < 0) |
648 | return ret; | 648 | return ret; |
649 | 649 | ||
650 | src_start = image->arch.backup_src_start; | ||
651 | src_sz = image->arch.backup_src_sz; | ||
652 | |||
653 | /* Add backup segment. */ | 650 | /* Add backup segment. */ |
654 | if (src_sz) { | 651 | if (image->arch.backup_src_sz) { |
652 | kbuf.buffer = &crash_zero_bytes; | ||
653 | kbuf.bufsz = sizeof(crash_zero_bytes); | ||
654 | kbuf.memsz = image->arch.backup_src_sz; | ||
655 | kbuf.buf_align = PAGE_SIZE; | ||
655 | /* | 656 | /* |
656 | * Ideally there is no source for backup segment. This is | 657 | * Ideally there is no source for backup segment. This is |
657 | * copied in purgatory after crash. Just add a zero filled | 658 | * copied in purgatory after crash. Just add a zero filled |
658 | * segment for now to make sure checksum logic works fine. | 659 | * segment for now to make sure checksum logic works fine. |
659 | */ | 660 | */ |
660 | ret = kexec_add_buffer(image, (char *)&crash_zero_bytes, | 661 | ret = kexec_add_buffer(&kbuf); |
661 | sizeof(crash_zero_bytes), src_sz, | ||
662 | PAGE_SIZE, 0, -1, 0, | ||
663 | &image->arch.backup_load_addr); | ||
664 | if (ret) | 662 | if (ret) |
665 | return ret; | 663 | return ret; |
664 | image->arch.backup_load_addr = kbuf.mem; | ||
666 | pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n", | 665 | pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n", |
667 | image->arch.backup_load_addr, src_start, src_sz); | 666 | image->arch.backup_load_addr, |
667 | image->arch.backup_src_start, kbuf.memsz); | ||
668 | } | 668 | } |
669 | 669 | ||
670 | /* Prepare elf headers and add a segment */ | 670 | /* Prepare elf headers and add a segment */ |
671 | ret = prepare_elf_headers(image, &elf_addr, &elf_sz); | 671 | ret = prepare_elf_headers(image, &kbuf.buffer, &kbuf.bufsz); |
672 | if (ret) | 672 | if (ret) |
673 | return ret; | 673 | return ret; |
674 | 674 | ||
675 | image->arch.elf_headers = elf_addr; | 675 | image->arch.elf_headers = kbuf.buffer; |
676 | image->arch.elf_headers_sz = elf_sz; | 676 | image->arch.elf_headers_sz = kbuf.bufsz; |
677 | 677 | ||
678 | ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz, | 678 | kbuf.memsz = kbuf.bufsz; |
679 | ELF_CORE_HEADER_ALIGN, 0, -1, 0, | 679 | kbuf.buf_align = ELF_CORE_HEADER_ALIGN; |
680 | &image->arch.elf_load_addr); | 680 | ret = kexec_add_buffer(&kbuf); |
681 | if (ret) { | 681 | if (ret) { |
682 | vfree((void *)image->arch.elf_headers); | 682 | vfree((void *)image->arch.elf_headers); |
683 | return ret; | 683 | return ret; |
684 | } | 684 | } |
685 | image->arch.elf_load_addr = kbuf.mem; | ||
685 | pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | 686 | pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", |
686 | image->arch.elf_load_addr, elf_sz, elf_sz); | 687 | image->arch.elf_load_addr, kbuf.bufsz, kbuf.bufsz); |
687 | 688 | ||
688 | return ret; | 689 | return ret; |
689 | } | 690 | } |
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 3407b148c240..d0a814a9d96a 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c | |||
@@ -331,17 +331,17 @@ static void *bzImage64_load(struct kimage *image, char *kernel, | |||
331 | 331 | ||
332 | struct setup_header *header; | 332 | struct setup_header *header; |
333 | int setup_sects, kern16_size, ret = 0; | 333 | int setup_sects, kern16_size, ret = 0; |
334 | unsigned long setup_header_size, params_cmdline_sz, params_misc_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; | 337 | unsigned long purgatory_load_addr; |
338 | unsigned long kernel_bufsz, kernel_memsz, kernel_align; | ||
339 | char *kernel_buf; | ||
340 | struct bzimage64_data *ldata; | 338 | struct bzimage64_data *ldata; |
341 | struct kexec_entry64_regs regs64; | 339 | struct kexec_entry64_regs regs64; |
342 | void *stack; | 340 | void *stack; |
343 | unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr); | 341 | unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr); |
344 | unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset; | 342 | unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset; |
343 | struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX, | ||
344 | .top_down = true }; | ||
345 | 345 | ||
346 | header = (struct setup_header *)(kernel + setup_hdr_offset); | 346 | header = (struct setup_header *)(kernel + setup_hdr_offset); |
347 | setup_sects = header->setup_sects; | 347 | setup_sects = header->setup_sects; |
@@ -402,11 +402,11 @@ static void *bzImage64_load(struct kimage *image, char *kernel, | |||
402 | params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + | 402 | params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + |
403 | MAX_ELFCOREHDR_STR_LEN; | 403 | MAX_ELFCOREHDR_STR_LEN; |
404 | params_cmdline_sz = ALIGN(params_cmdline_sz, 16); | 404 | params_cmdline_sz = ALIGN(params_cmdline_sz, 16); |
405 | params_misc_sz = params_cmdline_sz + efi_map_sz + | 405 | kbuf.bufsz = params_cmdline_sz + efi_map_sz + |
406 | sizeof(struct setup_data) + | 406 | sizeof(struct setup_data) + |
407 | sizeof(struct efi_setup_data); | 407 | sizeof(struct efi_setup_data); |
408 | 408 | ||
409 | params = kzalloc(params_misc_sz, GFP_KERNEL); | 409 | params = kzalloc(kbuf.bufsz, GFP_KERNEL); |
410 | if (!params) | 410 | if (!params) |
411 | return ERR_PTR(-ENOMEM); | 411 | return ERR_PTR(-ENOMEM); |
412 | efi_map_offset = params_cmdline_sz; | 412 | efi_map_offset = params_cmdline_sz; |
@@ -418,37 +418,41 @@ static void *bzImage64_load(struct kimage *image, char *kernel, | |||
418 | /* Is there a limit on setup header size? */ | 418 | /* Is there a limit on setup header size? */ |
419 | memcpy(¶ms->hdr, (kernel + setup_hdr_offset), setup_header_size); | 419 | memcpy(¶ms->hdr, (kernel + setup_hdr_offset), setup_header_size); |
420 | 420 | ||
421 | ret = kexec_add_buffer(image, (char *)params, params_misc_sz, | 421 | kbuf.buffer = params; |
422 | params_misc_sz, 16, MIN_BOOTPARAM_ADDR, | 422 | kbuf.memsz = kbuf.bufsz; |
423 | ULONG_MAX, 1, &bootparam_load_addr); | 423 | kbuf.buf_align = 16; |
424 | kbuf.buf_min = MIN_BOOTPARAM_ADDR; | ||
425 | ret = kexec_add_buffer(&kbuf); | ||
424 | if (ret) | 426 | if (ret) |
425 | goto out_free_params; | 427 | goto out_free_params; |
428 | bootparam_load_addr = kbuf.mem; | ||
426 | pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | 429 | pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n", |
427 | bootparam_load_addr, params_misc_sz, params_misc_sz); | 430 | bootparam_load_addr, kbuf.bufsz, kbuf.bufsz); |
428 | 431 | ||
429 | /* Load kernel */ | 432 | /* Load kernel */ |
430 | kernel_buf = kernel + kern16_size; | 433 | kbuf.buffer = kernel + kern16_size; |
431 | kernel_bufsz = kernel_len - kern16_size; | 434 | kbuf.bufsz = kernel_len - kern16_size; |
432 | kernel_memsz = PAGE_ALIGN(header->init_size); | 435 | kbuf.memsz = PAGE_ALIGN(header->init_size); |
433 | kernel_align = header->kernel_alignment; | 436 | kbuf.buf_align = header->kernel_alignment; |
434 | 437 | kbuf.buf_min = MIN_KERNEL_LOAD_ADDR; | |
435 | ret = kexec_add_buffer(image, kernel_buf, | 438 | ret = kexec_add_buffer(&kbuf); |
436 | kernel_bufsz, kernel_memsz, kernel_align, | ||
437 | MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1, | ||
438 | &kernel_load_addr); | ||
439 | if (ret) | 439 | if (ret) |
440 | goto out_free_params; | 440 | goto out_free_params; |
441 | kernel_load_addr = kbuf.mem; | ||
441 | 442 | ||
442 | pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | 443 | pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n", |
443 | kernel_load_addr, kernel_memsz, kernel_memsz); | 444 | kernel_load_addr, kbuf.bufsz, kbuf.memsz); |
444 | 445 | ||
445 | /* Load initrd high */ | 446 | /* Load initrd high */ |
446 | if (initrd) { | 447 | if (initrd) { |
447 | ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len, | 448 | kbuf.buffer = initrd; |
448 | PAGE_SIZE, MIN_INITRD_LOAD_ADDR, | 449 | kbuf.bufsz = kbuf.memsz = initrd_len; |
449 | ULONG_MAX, 1, &initrd_load_addr); | 450 | kbuf.buf_align = PAGE_SIZE; |
451 | kbuf.buf_min = MIN_INITRD_LOAD_ADDR; | ||
452 | ret = kexec_add_buffer(&kbuf); | ||
450 | if (ret) | 453 | if (ret) |
451 | goto out_free_params; | 454 | goto out_free_params; |
455 | initrd_load_addr = kbuf.mem; | ||
452 | 456 | ||
453 | pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | 457 | pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n", |
454 | initrd_load_addr, initrd_len, initrd_len); | 458 | initrd_load_addr, initrd_len, initrd_len); |
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 5e320ddaaa82..437ef1b47428 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
@@ -163,7 +163,7 @@ struct kexec_file_ops { | |||
163 | */ | 163 | */ |
164 | struct kexec_buf { | 164 | struct kexec_buf { |
165 | struct kimage *image; | 165 | struct kimage *image; |
166 | char *buffer; | 166 | void *buffer; |
167 | unsigned long bufsz; | 167 | unsigned long bufsz; |
168 | unsigned long mem; | 168 | unsigned long mem; |
169 | unsigned long memsz; | 169 | unsigned long memsz; |
@@ -175,6 +175,7 @@ struct kexec_buf { | |||
175 | 175 | ||
176 | int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, | 176 | int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, |
177 | int (*func)(u64, u64, void *)); | 177 | int (*func)(u64, u64, void *)); |
178 | extern int kexec_add_buffer(struct kexec_buf *kbuf); | ||
178 | #endif /* CONFIG_KEXEC_FILE */ | 179 | #endif /* CONFIG_KEXEC_FILE */ |
179 | 180 | ||
180 | struct kimage { | 181 | struct kimage { |
@@ -239,11 +240,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry, | |||
239 | struct kexec_segment __user *segments, | 240 | struct kexec_segment __user *segments, |
240 | unsigned long flags); | 241 | unsigned long flags); |
241 | extern int kernel_kexec(void); | 242 | extern int kernel_kexec(void); |
242 | extern int kexec_add_buffer(struct kimage *image, char *buffer, | ||
243 | unsigned long bufsz, unsigned long memsz, | ||
244 | unsigned long buf_align, unsigned long buf_min, | ||
245 | unsigned long buf_max, bool top_down, | ||
246 | unsigned long *load_addr); | ||
247 | extern struct page *kimage_alloc_control_pages(struct kimage *image, | 243 | extern struct page *kimage_alloc_control_pages(struct kimage *image, |
248 | unsigned int order); | 244 | unsigned int order); |
249 | extern int kexec_load_purgatory(struct kimage *image, unsigned long min, | 245 | extern int kexec_load_purgatory(struct kimage *image, unsigned long min, |
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 | ||