summaryrefslogtreecommitdiff
path: root/kexec/arch
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/arch')
-rw-r--r--kexec/arch/i386/crashdump-x86.c86
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);