summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCliff Wickman <cpw@sgi.com>2013-02-04 13:54:00 -0600
committerSimon Horman <horms@verge.net.au>2013-03-05 10:52:03 +0900
commite35aa29fb40b37bf86d980b2e19af5e01c2d2549 (patch)
tree5e5c99d7529f478bc7f9f0bdc53a95a9358ef790
parent49320340f705694e387d794f7f19d407ad9baefa (diff)
downloadkexec-tools-e35aa29fb40b37bf86d980b2e19af5e01c2d2549.tar.gz
kexec: include reserved e820 sections in crash kernel
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@sgi.com> [ horms@verge.net.au: Manually applied due to conflicts ] Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/i386/crashdump-x86.c43
-rw-r--r--kexec/kexec-syscall.h2
2 files changed, 42 insertions, 3 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 6e447413..b7fbac2a 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -246,6 +246,8 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
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;
@@ -899,6 +901,39 @@ static void get_backup_area(struct kexec_info *info,
info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
}
+/* 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.
@@ -1051,11 +1086,15 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
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;
}
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index b56cb00f..f5ee9926 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -78,7 +78,7 @@ static inline long kexec_load(void *entry, unsigned long nr_segments,
#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