From 97905e5e71d417e8bbbfa3c42d559a464a1570da Mon Sep 17 00:00:00 2001
Message-Id: <97905e5e71d417e8bbbfa3c42d559a464a1570da.1431592766.git.panand@redhat.com>
In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 22 Apr 2015 11:21:05 +0900
Subject: [PATCH 13/17] arm64: remove restriction on the segments order
Done by changing locate_hole() to add_buffer_phys_virt() in
load_other_segments() since locate_hole() assumes that the segments in
struct info be sorted properly.
This also simplifies the difference between kexec case and kdump case.
---
kexec/arch/arm64/kexec-arm64.c | 57 +++++++++++++++---------------------------
1 file changed, 20 insertions(+), 37 deletions(-)
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 190037c75186..d884c7c1707d 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -590,11 +590,10 @@ int arm64_load_other_segments(struct kexec_info *info,
{
int result;
struct mem_ehdr ehdr;
- unsigned long dtb_max;
unsigned long dtb_base;
+ unsigned long hole_min, hole_max;
char *initrd_buf = NULL;
uint64_t purgatory_sink;
- unsigned long purgatory_base;
struct dtb dtb_1 = {.name = "dtb_1"};
struct dtb dtb_2 = {.name = "dtb_2"};
char command_line[COMMAND_LINE_SIZE] = "";
@@ -648,27 +647,15 @@ int arm64_load_other_segments(struct kexec_info *info,
* to the DTB size for any DTB growth.
*/
- dtb_max = dtb_2.size + 2 * 1024;
-
- if (info->kexec_flags & KEXEC_ON_CRASH)
- dtb_base = locate_dtb_in_crashmem(info, dtb_max);
- else
- dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
- arm64_mem.memstart + arm64_mem.text_offset
- + arm64_mem.image_size,
- _ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
- 512UL * 1024 * 1024),
- 1);
-
- dbgprintf("dtb: base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
- dtb_2.size);
-
- if (dtb_base == ULONG_MAX)
- return -ENOMEM;
-
- purgatory_base = dtb_base + dtb_2.size;
- initrd_base = 0;
- initrd_size = 0;
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ hole_min = crash_reserved_mem.start + arm64_mem.text_offset
+ + arm64_mem.image_size;
+ hole_max = crash_reserved_mem.end;
+ } else {
+ hole_min = arm64_mem.memstart + arm64_mem.text_offset
+ + arm64_mem.image_size;
+ hole_max = ULONG_MAX;
+ }
if (arm64_opts.initrd) {
initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
@@ -679,8 +666,9 @@ int arm64_load_other_segments(struct kexec_info *info,
/* Put the initrd after the DTB with an alignment of
* page size. */
- initrd_base = locate_hole(info, initrd_size, 0,
- dtb_base + dtb_max, -1, 1);
+ initrd_base = add_buffer_phys_virt(info, initrd_buf,
+ initrd_size, initrd_size, 0,
+ hole_min, hole_max, 1, 0);
dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
initrd_base, initrd_size, initrd_size);
@@ -694,22 +682,17 @@ int arm64_load_other_segments(struct kexec_info *info,
if (result)
return result;
-
- purgatory_base = initrd_base + initrd_size;
}
}
- if (dtb_2.size > dtb_max) {
- fprintf(stderr, "%s: Error: Too many DTB mods.\n", __func__);
- return -EINVAL;
- }
+ dtb_base = add_buffer_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_2.size,
+ 128UL * 1024, hole_min, hole_max, 1, 0);
- add_segment_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_base,
- dtb_2.size, 0);
+ dbgprintf("dtb: base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
+ dtb_2.size);
- if (arm64_opts.initrd)
- add_segment_phys_virt(info, initrd_buf, initrd_size,
- initrd_base, initrd_size, 0);
+ if (dtb_base == ULONG_MAX)
+ return -ENOMEM;
if (arm64_opts.lite)
info->entry = (void *)kernel_entry;
@@ -724,7 +707,7 @@ int arm64_load_other_segments(struct kexec_info *info,
}
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- purgatory_base, ULONG_MAX, 1, 0);
+ hole_min, hole_max, 1, 0);
info->entry = (void *)elf_rel_get_addr(&info->rhdr,
"purgatory_start");
--
2.1.0