summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2010-09-07 13:34:43 -0700
committerSimon Horman <horms@verge.net.au>2010-09-09 17:02:54 +0900
commit5944fe4d86abf4571dbf915c4ea31cc1a5e3351d (patch)
treeceda08cde73e6b63bf3e9c629fd1d6c2b7a87c2a
parent75d3ea06601a2712f189f03504bb77e92cce0754 (diff)
i386 crashdump: pass acpi info, and generalize hack
- Pass the acpi memap to the kernel. - Port the fix from x86_64 to not truncate the elf note segment to 16K, to keep large machines happy. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/i386/crashdump-x86.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 4b45067..b3adbd0 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -519,6 +519,39 @@ static enum coretype get_core_type(struct kexec_info *info,
}
}
+/* Appends memmap=X#Y commandline for ACPI to command line*/
+static int cmdline_add_memmap_acpi(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 acpi 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.
@@ -527,8 +560,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
unsigned long max_addr, unsigned long min_base)
{
void *tmp;
- unsigned long sz, elfcorehdr;
- int nr_ranges, align = 1024;
+ unsigned long sz, bufsz, memsz, elfcorehdr;
+ int nr_ranges, align = 1024, i;
struct memory_range *mem_range, *memmap_p;
struct crash_elf_info elf_info;
@@ -591,17 +624,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
if (arch_options.core_header_type == CORE_TYPE_ELF64) {
if (crash_create_elf64_headers(info, &elf_info,
crash_memory_range, nr_ranges,
- &tmp, &sz,
+ &tmp, &bufsz,
ELF_CORE_HEADER_ALIGN) < 0)
return -1;
}
else {
if (crash_create_elf32_headers(info, &elf_info,
crash_memory_range, nr_ranges,
- &tmp, &sz,
+ &tmp, &bufsz,
ELF_CORE_HEADER_ALIGN) < 0)
return -1;
}
+ /* the size of the elf headers allocated is returned in 'bufsz' */
/* Hack: With some ld versions (GNU ld version 2.14.90.0.4 20030523),
* vmlinux program headers show a gap of two pages between bss segment
@@ -610,13 +644,31 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
* elf core header segment to 16K to avoid being placed in such gaps.
* This is a makeshift solution until it is fixed in kernel.
*/
- elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
+ if (bufsz < (16*1024)) {
+ /* bufsize is big enough for all the PT_NOTE's and PT_LOAD's */
+ memsz = 16*1024;
+ /* memsz will be the size of the memory hole we look for */
+ } else {
+ memsz = bufsz;
+ }
+ elfcorehdr = add_buffer(info, tmp, bufsz, memsz, align, min_base,
max_addr, -1);
dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
- if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
+ if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
return -1;
cmdline_add_memmap(mod_cmdline, memmap_p);
cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
+
+ /* Inform second kernel about the presence of ACPI tables. */
+ 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) )
+ continue;
+ start = mem_range[i].start;
+ end = mem_range[i].end;
+ cmdline_add_memmap_acpi(mod_cmdline, start, end);
+ }
return 0;
}