diff options
Diffstat (limited to 'kexec/arch')
-rw-r--r-- | kexec/arch/i386/crashdump-x86.c | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c index 3f85644..f295298 100644 --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -37,7 +37,7 @@ extern struct arch_options_t arch_options; /* Forward Declaration. */ -static int exclude_crash_reserve_region(int *nr_ranges); +static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end); /* Stores a sorted list of RAM memory ranges for which to create elf headers. * A separate program header is created for backup region */ @@ -58,13 +58,14 @@ static struct memory_range crash_reserved_mem; * be zone data structures exported from kernel. */ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, - int kexec_flags) + int kexec_flags, unsigned long lowmem_limit) { const char *iomem = proc_iomem(); - int memory_ranges = 0; + int memory_ranges = 0, gart = 0; char line[MAX_LINE]; FILE *fp; unsigned long long start, end; + uint64_t gart_start = 0, gart_end = 0; fp = fopen(iomem, "r"); if (!fp) { @@ -85,6 +86,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, while(fgets(line, sizeof(line), fp) != 0) { char *str; int type, consumed, count; + if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) break; count = sscanf(line, "%Lx-%Lx : %n", @@ -106,6 +108,22 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, crash_reserved_mem.end = end; crash_reserved_mem.type = RANGE_RAM; continue; + } else if (memcmp(str, "ACPI Tables\n", 12) == 0) { + /* + * ACPI Tables area need to be passed to new + * kernel with appropriate memmap= option. This + * is needed so that x86_64 kernel creates linear + * mapping for this region which is required for + * initializing acpi tables in second kernel. + */ + type = RANGE_ACPI; + } else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) { + type = RANGE_ACPI_NVS; + } else if (memcmp(str, "GART\n", 5) == 0) { + gart_start = start; + gart_end = end; + gart = 1; + continue; } else { continue; } @@ -120,11 +138,12 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, memory_ranges++; /* Segregate linearly mapped region. */ - if ((X86_MAXMEM - 1) >= start && (X86_MAXMEM - 1) <= end) { - crash_memory_range[memory_ranges-1].end = X86_MAXMEM -1; + if (lowmem_limit && + (lowmem_limit - 1) >= start && (lowmem_limit - 1) <= end) { + crash_memory_range[memory_ranges-1].end = lowmem_limit -1; /* Add segregated region. */ - crash_memory_range[memory_ranges].start = X86_MAXMEM; + crash_memory_range[memory_ranges].start = lowmem_limit; crash_memory_range[memory_ranges].end = end; crash_memory_range[memory_ranges].type = type; memory_ranges++; @@ -148,8 +167,14 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, crash_reserved_mem.end = mem_max; crash_reserved_mem.type = RANGE_RAM; } - if (exclude_crash_reserve_region(&memory_ranges) < 0) + if (exclude_region(&memory_ranges, crash_reserved_mem.start, + crash_reserved_mem.end) < 0) return -1; + if (gart) { + /* exclude GART region if the system has one */ + if (exclude_region(&memory_ranges, gart_start, gart_end) < 0) + return -1; + } *range = crash_memory_range; *ranges = memory_ranges; #if 0 @@ -167,32 +192,28 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, /* Removes crash reserve region from list of memory chunks for whom elf program * headers have to be created. Assuming crash reserve region to be a single * continuous area fully contained inside one of the memory chunks */ -static int exclude_crash_reserve_region(int *nr_ranges) +static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end) { int i, j, tidx = -1; - unsigned long long cstart, cend; struct memory_range temp_region = {0, 0, 0}; - /* Crash reserved region. */ - cstart = crash_reserved_mem.start; - cend = crash_reserved_mem.end; for (i = 0; i < (*nr_ranges); i++) { unsigned long long mstart, mend; mstart = crash_memory_range[i].start; mend = crash_memory_range[i].end; - if (cstart < mend && cend > mstart) { - if (cstart != mstart && cend != mend) { + if (start < mend && end > mstart) { + if (start != mstart && end != mend) { /* Split memory region */ - crash_memory_range[i].end = cstart - 1; - temp_region.start = cend + 1; + crash_memory_range[i].end = start - 1; + temp_region.start = end + 1; temp_region.end = mend; temp_region.type = RANGE_RAM; tidx = i+1; - } else if (cstart != mstart) - crash_memory_range[i].end = cstart - 1; + } else if (start != mstart) + crash_memory_range[i].end = start - 1; else - crash_memory_range[i].start = cend + 1; + crash_memory_range[i].start = end + 1; } } /* Insert split memory region, if any. */ @@ -512,16 +533,26 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, struct memory_range *mem_range, *memmap_p; struct crash_elf_info elf_info; - if (get_crash_memory_ranges(&mem_range, &nr_ranges, - info->kexec_flags) < 0) - return -1; - /* Constant parts of the elf_info */ elf_info.data = ELFDATA2LSB; elf_info.backup_src_start = BACKUP_SRC_START; elf_info.backup_src_end = BACKUP_SRC_END; elf_info.page_offset = X86_PAGE_OFFSET; + /* Get the elf architecture of the running kernel */ + if ((info->kexec_flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_X86_64) { + elf_info.machine = EM_X86_64; + } else { + elf_info.machine = EM_386; + elf_info.lowmem_limit = X86_MAXMEM; + elf_info.get_note_info = get_crash_notes; + } + + if (get_crash_memory_ranges(&mem_range, &nr_ranges, + info->kexec_flags, + elf_info.lowmem_limit) < 0) + return -1; + /* * if the core type has not been set on command line, set it here * automatically @@ -536,15 +567,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, elf_info.class = ELFCLASS64; } - /* Get the elf architecture of the running kernel */ - if ((info->kexec_flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_X86_64) { - elf_info.machine = EM_X86_64; - } else { - elf_info.machine = EM_386; - elf_info.lowmem_limit = X86_MAXMEM; - elf_info.get_note_info = get_crash_notes; - } - /* Memory regions which panic kernel can safely use to boot into */ sz = (sizeof(struct memory_range) * (KEXEC_MAX_SEGMENTS + 1)); memmap_p = xmalloc(sz); |