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