Blob Blame History Raw
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