diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2010-09-07 13:34:43 -0700 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2010-09-09 17:02:54 +0900 |
commit | 5944fe4d86abf4571dbf915c4ea31cc1a5e3351d (patch) | |
tree | ceda08cde73e6b63bf3e9c629fd1d6c2b7a87c2a | |
parent | 75d3ea06601a2712f189f03504bb77e92cce0754 (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.c | 64 |
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; } |