All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk@armlinux.org.uk>
To: Simon Horman <horms@verge.net.au>
Cc: kexec@lists.infradead.org
Subject: [PATCH 1/2] ARM: cleanup initrd and dtb handing
Date: Mon, 23 Oct 2017 11:05:48 +0100	[thread overview]
Message-ID: <20171023100547.GA5431@n2100.armlinux.org.uk> (raw)

There is no difference in the way the initrd is handled between an
ATAG-based kernel and a DTB-based kernel.  Therefore, this should be
handled identically in both cases.

Rearrange the code to achieve this.

Signed-off-by: Russell King <rmk@armlinux.org.uk>
---
 kexec/arch/arm/kexec-zImage-arm.c | 116 +++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 59 deletions(-)

diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index 7f02b93..c6ecb04 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -24,7 +24,7 @@
 
 #define BOOT_PARAMS_SIZE 1536
 
-off_t initrd_base = 0, initrd_size = 0;
+off_t initrd_base, initrd_size;
 unsigned int kexec_arm_image_size = 0;
 unsigned long long user_page_offset = (-1ULL);
 
@@ -200,14 +200,12 @@ int create_mem32_tag(struct tag_mem32 *tag_mem32)
 
 static
 int atag_arm_load(struct kexec_info *info, unsigned long base,
-	const char *command_line, off_t command_line_len,
-	const char *initrd, off_t initrd_len, off_t initrd_off)
+	const char *command_line, off_t command_line_len, const char *initrd)
 {
 	struct tag *saved_tags = atag_read_tags();
 	char *buf;
 	off_t len;
 	struct tag *params;
-	uint32_t *initrd_start = NULL;
 	
 	buf = xmalloc(getpagesize());
 	if (!buf) {
@@ -251,8 +249,8 @@ int atag_arm_load(struct kexec_info *info, unsigned long base,
 	if (initrd) {
 		params->hdr.size = tag_size(tag_initrd);
 		params->hdr.tag = ATAG_INITRD2;
-		initrd_start = &params->u.initrd.start;
-		params->u.initrd.size = initrd_len;
+		params->u.initrd.start = initrd_base;
+		params->u.initrd.size = initrd_size;
 		params = tag_next(params);
 	}
 
@@ -272,14 +270,6 @@ int atag_arm_load(struct kexec_info *info, unsigned long base,
 
 	add_segment(info, buf, len, base, len);
 
-	if (initrd) {
-		*initrd_start = locate_hole(info, initrd_len, getpagesize(),
-				initrd_off, ULONG_MAX, INT_MAX);
-		if (*initrd_start == ULONG_MAX)
-			return -1;
-		add_segment(info, initrd, initrd_len, *initrd_start, initrd_len);
-	}
-
 	return 0;
 }
 
@@ -348,6 +338,7 @@ static int setup_dtb_prop(char **bufp, off_t *sizep, int parentoffset,
 int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
+	unsigned long page_size = getpagesize();
 	unsigned long base, kernel_base;
 	unsigned int atag_offset = 0x1000; /* 4k offset from memory start */
 	unsigned int extra_size = 0x8000; /* TEXT_OFFSET */
@@ -513,6 +504,14 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	kernel_mem_size = len + 4;
 
 	/*
+	 * If the user didn't specify the size of the image, assume the
+	 * maximum kernel compression ratio is 4.  Note that we must
+	 * include space for the compressed image here as well.
+	 */
+	if (!kexec_arm_image_size)
+		kexec_arm_image_size = len * 5;
+
+	/*
 	 * If we are loading a dump capture kernel, we need to update kernel
 	 * command line and also add some additional segments.
 	 */
@@ -562,17 +561,28 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 
 	kernel_base = base + extra_size;
 
-	if (kexec_arm_image_size) {
-		/* If the image size was passed as command line argument,
-		 * use that value for determining the address for initrd,
-		 * atags and dtb images. page-align the given length.*/
-		initrd_base = kernel_base + _ALIGN(kexec_arm_image_size, getpagesize());
-	} else {
-		/* Otherwise, assume the maximum kernel compression ratio
-		 * is 4, and just to be safe, place ramdisk after that.
-		 * Note that we must include space for the compressed
-		 * image here as well. */
-		initrd_base = kernel_base + _ALIGN(len * 5, getpagesize());
+	/*
+	 * Calculate the minimum address of the initrd, which must be
+	 * above the memory used by the zImage while it runs.  This
+	 * needs to be page-size aligned.
+	 */
+	initrd_base = kernel_base + _ALIGN(kexec_arm_image_size, page_size);
+
+	if (ramdisk_buf) {
+		/*
+		 * Find a hole to place the initrd. The crash kernel use
+		 * fixed address, so no check is ok.
+		 */
+		if (!(info->kexec_flags & KEXEC_ON_CRASH)) {
+			initrd_base = locate_hole(info, initrd_size, page_size,
+						  initrd_base,
+						  ULONG_MAX, INT_MAX);
+			if (initrd_base == ULONG_MAX)
+				return -1;
+		}
+
+		add_segment(info, ramdisk_buf, initrd_size, initrd_base,
+			    initrd_size);
 	}
 
 	if (use_atags) {
@@ -581,7 +591,7 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		 */
 		if (atag_arm_load(info, base + atag_offset,
 		                  command_line, command_line_len,
-		                  ramdisk_buf, initrd_size, initrd_base) == -1)
+		                  ramdisk_buf) == -1)
 			return -1;
 	} else {
 		/*
@@ -611,36 +621,11 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		}
 
 		/*
-		 * Search in memory to make sure there is enough memory
-		 * to hold initrd and dtb.
-		 *
-		 * Even if no initrd is used, this check is still
-		 * required for dtb.
-		 *
-		 * Crash kernel use fixed address, no check is ok.
+		 * Add the initrd parameters to the dtb
 		 */
-		if ((info->kexec_flags & KEXEC_ON_CRASH) == 0) {
-			unsigned long page_size = getpagesize();
-			/*
-			 * DTB size may be increase a little
-			 * when setup initrd size. Add a full page
-			 * for it is enough.
-			 */
-			unsigned long hole_size = _ALIGN_UP(initrd_size, page_size) +
-				_ALIGN(dtb_length + page_size, page_size);
-			unsigned long initrd_base_new = locate_hole(info,
-					hole_size, page_size,
-					initrd_base, ULONG_MAX, INT_MAX);
-			if (initrd_base_new == ULONG_MAX)
-				return -1;
-			initrd_base = initrd_base_new;
-		}
-
 		if (ramdisk_buf) {
-			add_segment(info, ramdisk_buf, initrd_size,
-			            initrd_base, initrd_size);
-
 			unsigned long start, end;
+
 			start = cpu_to_be32((unsigned long)(initrd_base));
 			end = cpu_to_be32((unsigned long)(initrd_base + initrd_size));
 
@@ -654,14 +639,27 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 				return -1;
 		}
 
-		/* Stick the dtb at the end of the initrd and page
-		 * align it.
+		/*
+		 * The dtb must also be placed above the memory used by
+		 * the zImage.  We don't care about its position wrt the
+		 * ramdisk, but we might as well place it after the initrd.
+		 * We leave a buffer page between the initrd and the dtb.
 		 */
-		dtb_offset = initrd_base + initrd_size + getpagesize();
-		dtb_offset = _ALIGN_DOWN(dtb_offset, getpagesize());
+		dtb_offset = initrd_base + initrd_size + page_size;
+		dtb_offset = _ALIGN_DOWN(dtb_offset, page_size);
+
+		/*
+		 * Find a hole to place the dtb above the initrd.
+		 * Crash kernel use fixed address, no check is ok.
+		 */
+		if (!(info->kexec_flags & KEXEC_ON_CRASH)) {
+			dtb_offset = locate_hole(info, dtb_length, page_size,
+						 dtb_offset, ULONG_MAX, INT_MAX);
+			if (dtb_offset == ULONG_MAX)
+				return -1;
+		}
 
-		add_segment(info, dtb_buf, dtb_length,
-		            dtb_offset, dtb_length);
+		add_segment(info, dtb_buf, dtb_length, dtb_offset, dtb_length);
 	}
 
 	add_segment(info, buf, len, kernel_base, kernel_mem_size);
-- 
2.7.4


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

             reply	other threads:[~2017-10-23 10:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-23 10:05 Russell King [this message]
2017-11-01  8:10 ` [PATCH 1/2] ARM: cleanup initrd and dtb handing Simon Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171023100547.GA5431@n2100.armlinux.org.uk \
    --to=rmk@armlinux.org.uk \
    --cc=horms@verge.net.au \
    --cc=kexec@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.