[PATCH] kexec: include reserved e820 sections in crash kernel

Cliff Wickman cpw at sgi.com
Mon Feb 4 14:54:00 EST 2013


From: Cliff Wickman <cpw at sgi.com>

The crash kernel is not able to find its root device if that device is not
on PCI 0.

This is because it is booted with the command line option memmap=exactmap
which currently clears the e820 table and does not restore reserved spaces.

This works for a device on PCI 0 because ACPI falls back to a legacy mode.
But the error message " [Firmware Bug]: PCI: MMCONFIG at
 [mem 0x80000000-0x80cfffff] not reserved in ACPI motherboard resources"
is written to the log even in this functioning case.

It fails for some devices on UV2, and only for UV2, because SGI seems to
be the only manufacturer currently using the extended PCI(>0).

The fix is simple, as long as the command line is long enough to include
all the reserved spaces.
The command line may have to be lengthened. See
  [PATCH] kexec: lengthen the kernel command line image

Signed-off-by: Cliff Wickman <cpw at sgi.com>
---
 kexec/arch/i386/crashdump-x86.c |   43 ++++++++++++++++++++++++++++++++++++++--
 kexec/kexec-syscall.h           |    2 -
 2 files changed, 42 insertions(+), 3 deletions(-)

Index: kexec-tools-2.0.3/kexec/arch/i386/crashdump-x86.c
===================================================================
--- kexec-tools-2.0.3.orig/kexec/arch/i386/crashdump-x86.c
+++ kexec-tools-2.0.3/kexec/arch/i386/crashdump-x86.c
@@ -236,6 +236,8 @@ static int get_crash_memory_ranges(struc
 			type = RANGE_ACPI;
 		} else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) {
 			type = RANGE_ACPI_NVS;
+		} else if(memcmp(str,"reserved\n", 9) == 0 ) {
+			type = RANGE_RESERVED;
 		} else if (memcmp(str, "GART\n", 5) == 0) {
 			gart_start = start;
 			gart_end = end;
@@ -708,6 +710,39 @@ static void get_backup_area(unsigned lon
 	fclose(fp);
 }
 
+/* Appends memmap=X$Y commandline for reserved memory to command line*/
+static int cmdline_add_memmap_reserved(char *cmdline, unsigned long start,
+					unsigned long end)
+{
+	int cmdlen, len, align = 1024;
+	unsigned long startk, endk;
+	char str_mmap[256], str_tmp[20];
+
+	if (!(end - start))
+		return 0;
+
+	startk = start/1024;
+	endk = (end + align - 1)/1024;
+	strcpy (str_mmap, " memmap=");
+	ultoa((endk - startk), str_tmp);
+	strcat (str_mmap, str_tmp);
+	strcat (str_mmap, "K$");
+	ultoa(startk, str_tmp);
+	strcat (str_mmap, str_tmp);
+	strcat (str_mmap, "K");
+	len = strlen(str_mmap);
+	cmdlen = strlen(cmdline) + len;
+	if (cmdlen > (COMMAND_LINE_SIZE - 1))
+		die("Command line overflow\n");
+	strcat(cmdline, str_mmap);
+
+#ifdef DEBUG
+		printf("Command line after adding reserved memmap\n");
+		printf("%s\n", cmdline);
+#endif
+	return 0;
+}
+
 /* Loads additional segments in case of a panic kernel is being loaded.
  * One segment for backup region, another segment for storing elf headers
  * for crash memory image.
@@ -844,11 +879,15 @@ int load_crashdump_segments(struct kexec
 	for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
 		unsigned long start, end;
 		if ( !( mem_range[i].type == RANGE_ACPI
-			|| mem_range[i].type == RANGE_ACPI_NVS) )
+			|| mem_range[i].type == RANGE_ACPI_NVS
+			|| mem_range[i].type == RANGE_RESERVED) )
 			continue;
 		start = mem_range[i].start;
 		end = mem_range[i].end;
-		cmdline_add_memmap_acpi(mod_cmdline, start, end);
+		if (mem_range[i].type == RANGE_RESERVED)
+			cmdline_add_memmap_reserved(mod_cmdline, start, end);
+		else
+			cmdline_add_memmap_acpi(mod_cmdline, start, end);
 	}
 	return 0;
 }
Index: kexec-tools-2.0.3/kexec/kexec-syscall.h
===================================================================
--- kexec-tools-2.0.3.orig/kexec/kexec-syscall.h
+++ kexec-tools-2.0.3/kexec/kexec-syscall.h
@@ -96,7 +96,7 @@ static inline long kexec_reboot(void)
 #define KEXEC_ARCH_MIPS    ( 8 << 16)
 #define KEXEC_ARCH_CRIS    (76 << 16)
 
-#define KEXEC_MAX_SEGMENTS 16
+#define KEXEC_MAX_SEGMENTS 70
 
 #ifdef __i386__
 #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_386



More information about the kexec mailing list