[PATCH] Reserve crashkernel memory region

Mohan Kumar M mohan at in.ibm.com
Mon Apr 24 16:10:15 EST 2006


Hi,

Now kexec'ed kernel in a PPC64 machine does not reserve memory for crashkernel region. So kexec'ed kernel can not load kdump kernel reliably.

Attached kexec-tools patch reserves memory for kdump kernel by adding an entry in the reserve memory table. So while kexec'ed kernel is booting, it reserves memory for crashkernel region.

Regards,
Mohan.
-------------- next part --------------

In PPC64, kexec'ed kernel does not reserve memory for crashkernel. So 
kexec'ed kernel can not load kdump kernel reliably.

reserve-crashkernel-mem patch adds a reserve entry for crashkernel to the
reserve memory list, so that kexec'ed kernel reserves memory for kdump kernel.
This is done when user passes --append="crashkernel=X at Y" parameter to
kexec command. If user does not pass crashkernel option, memory is not
reserved for kdump kernel.

Signed-off-by: Mohan <mohan at in.ibm.com>
---

 kexec-tools-1.101-kdump9/kexec/arch/ppc64/fs2dt.c       |  135 ++++++++++++----
 kexec-tools-1.101-kdump9/kexec/arch/ppc64/kexec-ppc64.h |    2 
 2 files changed, 107 insertions(+), 30 deletions(-)

diff -puN kexec-tools-1.101-kdump9/kexec/arch/ppc64/fs2dt.c~reserve-crashkernel kexec-tools-1.101-kdump9/kexec/arch/ppc64/fs2dt.c
--- patch/kexec-tools-1.101-kdump9/kexec/arch/ppc64/fs2dt.c~reserve-crashkernel	2006-04-19 18:49:06.000000000 +0530
+++ patch-mohan/kexec-tools-1.101-kdump9/kexec/arch/ppc64/fs2dt.c	2006-04-19 18:55:48.000000000 +0530
@@ -64,8 +64,7 @@ char propnames[NAMESPACE];
 dvt dtstruct[TREEWORDS], *dt;
 unsigned long long mem_rsrv[2*MEMRESERVE];
 
-static int initrd_found = 0;
-static int crash_param = 0;
+static unsigned long crashk_base = 0, crashk_size = 0;
 char local_cmdline[COMMAND_LINE_SIZE] = { "" };
 dvt *dt_len; /* changed len of modified cmdline in flat device-tree */
 extern mem_rgns_t usablemem_rgns;
@@ -191,6 +190,50 @@ void add_usable_mem_property(int fd, int
 	dt += (rlen + 3)/4;
 }
 
+unsigned long mem_parse(const char *ptr, const char **retptr)
+{
+	unsigned long ret = strtoul(ptr, (char **)retptr,10);
+
+	switch (**retptr) {
+		case 'G':
+		case 'g':
+			ret <<= 30;
+			(*retptr)++;
+			break;
+		case 'M':
+		case 'm':
+			ret <<= 20;
+			(*retptr)++;
+			break;
+		case 'K':
+		case 'k':
+			ret <<= 10;
+			(*retptr)++;
+			break;
+	}
+
+	return ret;
+}
+
+void parse_crash_param(char *param)
+{
+	char *cbase, *csize;
+	param += 12;
+	crashk_size = mem_parse(param, (const char **)&csize);
+
+	if (ALIGN(crashk_size, 0x1000000) != crashk_size)
+		printf("Warning: crashkernel size is not aligned to 16MB\n");
+
+	if (*csize == '@') {
+		csize++;
+		crashk_base = mem_parse(csize, (const char **)&cbase);
+		if (crashk_base != 0x2000000)
+			printf("Warning: PPC64 kdump kernel always runs at "
+				       "32 MB\n");
+	}
+	crashk_base = 0x2000000;
+}
+
 /* put all properties (files) in the property structure */
 void putprops(char *fn, struct dirent **nlist, int numlist)
 {
@@ -207,12 +250,6 @@ void putprops(char *fn, struct dirent **
 		if (lstat(pathname, statbuf))
 			err(pathname, ERR_STAT);
 
-		if (!crash_param && !strcmp(fn,"linux,crashkernel-base"))
-			continue;
-
-		if (!crash_param && !strcmp(fn,"linux,crashkernel-size"))
-			continue;
-
 		/*
 		 * This property will be created for each node during kexec
 		 * boot. So, ignore it.
@@ -230,6 +267,13 @@ void putprops(char *fn, struct dirent **
 			!strcmp(dp->d_name, "linux,initrd-end"))
 				continue;
 
+		/* This property will be created/modified later in putnode()
+		 * So ignore it.
+		 */
+		if (!strcmp(dp->d_name, "linux,crashkernel-base") ||
+			!strcmp(dp->d_name, "linux,crashkernel-size"))
+				continue;
+
 		if (S_ISREG(statbuf[0].st_mode)) {
 			int fd, len = statbuf[0].st_size;
 
@@ -260,7 +304,7 @@ void putprops(char *fn, struct dirent **
 					param = strstr(local_cmdline,
 							"crashkernel=");
 					if (param)
-						crash_param = 1;
+						parse_crash_param(param);
 					param = strstr(local_cmdline, "root=");
 				}
 				if (!param) {
@@ -347,35 +391,66 @@ void putnode(void)
 
 	putprops(dn, namelist, numlist);
 
-	/* Add initrd entries to the second kernel if first kernel does not
-	 * have and second kernel needs.
-	 */
-	if (initrd_base && !initrd_found && !strcmp(basename,"/chosen/")) {
+	if (!strcmp(basename,"/chosen/")) {
 		int len = 8;
 		unsigned long long initrd_end;
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-start");
 
-		if ((len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
+		/* Add initrd entries to the second kernel if first
+		 *  kernel does not have and second kernel needs.
+		 */
+		if (initrd_base) {
+			*dt++ = 3;
+			*dt++ = len;
+			*dt++ = propnum("linux,initrd-start");
+
+			if ((len >= 8) && ((unsigned long)dt & 0x4))
+				dt++;
+
+			memcpy(dt,&initrd_base,len);
+			dt += (len + 3)/4;
+
+			len = 8;
+			*dt++ = 3;
+			*dt++ = len;
+			*dt++ = propnum("linux,initrd-end");
+
+			initrd_end = initrd_base + initrd_size;
+			if ((len >= 8) && ((unsigned long)dt & 0x4))
+				dt++;
+
+			memcpy(dt,&initrd_end,len);
+			dt += (len + 3)/4;
+
+			reserve(initrd_base, initrd_size);
+		}
+
+		/* Add crashkernel details to the second kernel if first
+		 * kernel does not have and reserve memory for that
+		 */
+		if (crashk_base) {
+			*dt++ = 3;
+			*dt++ = len;
+			*dt++ = propnum("linux,crashkernel-base");
 
-		memcpy(dt,&initrd_base,len);
-		dt += (len + 3)/4;
+			if ((len >= 8) && ((unsigned long)dt & 0x4))
+				dt++;
 
-		len = 8;
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-end");
+			memcpy(dt,&crashk_base,len);
+			dt += (len + 3)/4;
 
-		initrd_end = initrd_base + initrd_size;
-		if ((len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
+			len = 8;
+			*dt++ = 3;
+			*dt++ = len;
+			*dt++ = propnum("linux,crashkernel-size");
+
+			if ((len >= 8) && ((unsigned long)dt & 0x4))
+				dt++;
 
-		memcpy(dt,&initrd_end,len);
-		dt += (len + 3)/4;
+			memcpy(dt,&crashk_size,len);
+			dt += (len + 3)/4;
 
-		reserve(initrd_base, initrd_size);
+			reserve(crashk_base, crashk_size);
+		}
 	}
 
 	for (i=0; i < numlist; i++) {
diff -puN kexec-tools-1.101-kdump9/kexec/arch/ppc64/kexec-ppc64.h~reserve-crashkernel kexec-tools-1.101-kdump9/kexec/arch/ppc64/kexec-ppc64.h
--- patch/kexec-tools-1.101-kdump9/kexec/arch/ppc64/kexec-ppc64.h~reserve-crashkernel	2006-04-19 18:49:54.000000000 +0530
+++ patch-mohan/kexec-tools-1.101-kdump9/kexec/arch/ppc64/kexec-ppc64.h	2006-04-19 18:50:29.000000000 +0530
@@ -7,6 +7,8 @@
 #define CORE_TYPE_ELF32 1
 #define CORE_TYPE_ELF64 2
 
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+
 int setup_memory_ranges(unsigned long kexec_flags);
 
 int elf_ppc64_probe(const char *buf, off_t len);
_


More information about the Linuxppc-dev mailing list