Use these two variables to store the memory ranges and the number of memory ranges for crash kernel to boot into: struct memory_range crash_memory_range; int crash_memory_range; These two variables are not static now, so can be used in other file later. Signed-off-by: WANG Chao <chaowang at redhat.com> Tested-by: Linn Crosetto <linn at hp.com> --- kexec/arch/i386/crashdump-x86.c | 134 ++++++++++++++++++++++------------------ kexec/arch/i386/crashdump-x86.h | 5 +- 2 files changed, 77 insertions(+), 62 deletions(-) diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c index 979c2bd..c55a6b1 100644 --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -179,7 +179,8 @@ 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 */ -static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; +struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; +int crash_memory_ranges; /* Memory region reserved for storing panic kernel and other data. */ #define CRASH_RESERVED_MEM_NR 8 @@ -201,7 +202,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, int kexec_flags, unsigned long lowmem_limit) { const char *iomem = proc_iomem(); - int memory_ranges = 0, gart = 0, i; + int gart = 0, i; char line[MAX_LINE]; FILE *fp; unsigned long long start, end; @@ -218,7 +219,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, char *str; int type, consumed, count; - if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) + if (crash_memory_ranges >= CRASH_MAX_MEMORY_RANGES) break; count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed); @@ -250,17 +251,17 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, continue; } - crash_memory_range[memory_ranges].start = start; - crash_memory_range[memory_ranges].end = end; - crash_memory_range[memory_ranges].type = type; + crash_memory_range[crash_memory_ranges].start = start; + crash_memory_range[crash_memory_ranges].end = end; + crash_memory_range[crash_memory_ranges].type = type; - segregate_lowmem_region(&memory_ranges, lowmem_limit); + segregate_lowmem_region(&crash_memory_ranges, lowmem_limit); - memory_ranges++; + crash_memory_ranges++; } fclose(fp); if (kexec_flags & KEXEC_PRESERVE_CONTEXT) { - for (i = 0; i < memory_ranges; i++) { + for (i = 0; i < crash_memory_ranges; i++) { if (crash_memory_range[i].end > 0x0009ffff) { crash_reserved_mem[0].start = \ crash_memory_range[i].start; @@ -278,17 +279,17 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges, } for (i = 0; i < crash_reserved_mem_nr; i++) - if (exclude_region(&memory_ranges, crash_reserved_mem[i].start, + if (exclude_region(&crash_memory_ranges, crash_reserved_mem[i].start, crash_reserved_mem[i].end) < 0) return -1; if (gart) { /* exclude GART region if the system has one */ - if (exclude_region(&memory_ranges, gart_start, gart_end) < 0) + if (exclude_region(&crash_memory_ranges, gart_start, gart_end) < 0) return -1; } *range = crash_memory_range; - *ranges = memory_ranges; + *ranges = crash_memory_ranges; return 0; } @@ -324,7 +325,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range, } *range = crash_memory_range; - *ranges = j; + *ranges = crash_memory_ranges = j; qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges); @@ -417,8 +418,8 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end) /* Adds a segment from list of memory regions which new kernel can use to * boot. Segment start and end should be aligned to 1K boundary. */ -static int add_memmap(struct memory_range *memmap_p, unsigned long long addr, - size_t size) +static int add_memmap(struct memory_range *memmap_p, int *nr_range, + unsigned long long addr, size_t size) { int i, j, nr_entries = 0, tidx = 0, align = 1024; unsigned long long mstart, mend; @@ -450,29 +451,23 @@ static int add_memmap(struct memory_range *memmap_p, unsigned long long addr, else if (addr > mend) tidx = i+1; } - /* Insert the memory region. */ - for (j = nr_entries-1; j >= tidx; j--) - memmap_p[j+1] = memmap_p[j]; - memmap_p[tidx].start = addr; - memmap_p[tidx].end = addr + size - 1; + /* Insert the memory region. */ + for (j = nr_entries-1; j >= tidx; j--) + memmap_p[j+1] = memmap_p[j]; + memmap_p[tidx].start = addr; + memmap_p[tidx].end = addr + size - 1; + memmap_p[tidx].type = RANGE_RAM; + *nr_range = nr_entries + 1; - dbgprintf("Memmap after adding segment\n"); - for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) { - mstart = memmap_p[i].start; - mend = memmap_p[i].end; - if (mstart == 0 && mend == 0) - break; - dbgprintf("%016llx - %016llx\n", - mstart, mend); - } + dbgprint_mem_range("Memmap after adding segment", memmap_p, *nr_range); return 0; } /* Removes a segment from list of memory regions which new kernel can use to * boot. Segment start and end should be aligned to 1K boundary. */ -static int delete_memmap(struct memory_range *memmap_p, unsigned long long addr, - size_t size) +static int delete_memmap(struct memory_range *memmap_p, int *nr_range, + unsigned long long addr, size_t size) { int i, j, nr_entries = 0, tidx = -1, operation = 0, align = 1024; unsigned long long mstart, mend; @@ -534,24 +529,17 @@ static int delete_memmap(struct memory_range *memmap_p, unsigned long long addr, for (j = nr_entries-1; j > tidx; j--) memmap_p[j+1] = memmap_p[j]; memmap_p[tidx+1] = temp_region; + *nr_range = nr_entries + 1; } if ((operation == -1) && tidx >=0) { /* Delete the exact match memory region. */ for (j = i+1; j < CRASH_MAX_MEMMAP_NR; j++) memmap_p[j-1] = memmap_p[j]; memmap_p[j-1].start = memmap_p[j-1].end = 0; + *nr_range = nr_entries - 1; } - dbgprintf("Memmap after deleting segment\n"); - for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) { - mstart = memmap_p[i].start; - mend = memmap_p[i].end; - if (mstart == 0 && mend == 0) { - break; - } - dbgprintf("%016llx - %016llx\n", - mstart, mend); - } + dbgprint_mem_range("Memmap after deleting segment", memmap_p, *nr_range); return 0; } @@ -626,6 +614,9 @@ static int cmdline_add_memmap(char *cmdline, struct memory_range *memmap_p) /* All regions traversed. */ break; + if (memmap_p[i].type != RANGE_RAM) + continue; + /* A region is not worth adding if region size < 100K. It eats * up precious command line length. */ if ((endk - startk) < min_sizek) @@ -797,6 +788,25 @@ static void get_backup_area(struct kexec_info *info, info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1; } +static void exclude_ram(struct memory_range *mr, int *nr_mr) +{ + int ranges, i, j, m; + + ranges = *nr_mr; + for (i = 0, j = 0; i < ranges; i++) { + if (mr[j].type == RANGE_RAM) { + dbgprintf("Remove RAM %016llx-%016llxx: (%d)\n", mr[j].start, mr[j].end, mr[j].type); + for (m = j; m < *nr_mr; m++) + mr[m] = mr[m+1]; + (*nr_mr)--; + } else { + j++; + } + } + + dbgprint_mem_range("After remove RAM", mr, *nr_mr); +} + /* 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. @@ -807,7 +817,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, void *tmp; unsigned long sz, bufsz, memsz, elfcorehdr; int nr_ranges = 0, align = 1024, i; - struct memory_range *mem_range, *memmap_p; + struct memory_range *mem_range; struct crash_elf_info elf_info; unsigned kexec_arch; @@ -850,10 +860,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, get_backup_area(info, mem_range, nr_ranges); - dbgprintf("CRASH MEMORY RANGES\n"); - - for(i = 0; i < nr_ranges; ++i) - dbgprintf("%016Lx-%016Lx\n", mem_range[i].start, mem_range[i].end); + dbgprint_mem_range("CRASH MEMORY RANGES", mem_range, nr_ranges); /* * if the core type has not been set on command line, set it here @@ -878,17 +885,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, if (get_kernel_vaddr_and_size(info, &elf_info)) return -1; - /* Memory regions which panic kernel can safely use to boot into */ - sz = (sizeof(struct memory_range) * CRASH_MAX_MEMMAP_NR); - memmap_p = xmalloc(sz); - memset(memmap_p, 0, sz); - add_memmap(memmap_p, info->backup_src_start, info->backup_src_size); - for (i = 0; i < crash_reserved_mem_nr; i++) { - sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1; - if (add_memmap(memmap_p, crash_reserved_mem[i].start, sz) < 0) - return ENOCRASHKERNEL; - } - /* Create a backup region segment to store backup data*/ if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) { sz = _ALIGN(info->backup_src_size, align); @@ -898,8 +894,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, 0, max_addr, -1); dbgprintf("Created backup segment at 0x%lx\n", info->backup_start); - if (delete_memmap(memmap_p, info->backup_start, sz) < 0) - return EFAILED; } /* Create elf header segment and store crash image data. */ @@ -915,6 +909,23 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, ELF_CORE_HEADER_ALIGN) < 0) return EFAILED; } + + /* Memory regions which panic kernel can safely use to boot into */ + exclude_ram(crash_memory_range, &crash_memory_ranges); + + add_memmap(crash_memory_range, &crash_memory_ranges, info->backup_src_start, info->backup_src_size); + for (i = 0; i < crash_reserved_mem_nr; i++) { + sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1; + if (add_memmap(crash_memory_range, &crash_memory_ranges, crash_reserved_mem[i].start, sz) < 0) + return ENOCRASHKERNEL; + } + + /* exclude backup region from crash dump memory range */ + sz = _ALIGN(info->backup_src_size, align); + if (delete_memmap(crash_memory_range, &crash_memory_ranges, info->backup_start, sz) < 0) { + return EFAILED; + } + /* 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), @@ -934,9 +945,9 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, 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, memsz) < 0) + if (delete_memmap(crash_memory_range, &crash_memory_ranges, elfcorehdr, memsz) < 0) return -1; - cmdline_add_memmap(mod_cmdline, memmap_p); + cmdline_add_memmap(mod_cmdline, crash_memory_range); if (!bzImage_support_efi_boot) cmdline_add_efi(mod_cmdline); cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); @@ -951,6 +962,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, end = mem_range[i].end; cmdline_add_memmap_acpi(mod_cmdline, start, end); } + return 0; } diff --git a/kexec/arch/i386/crashdump-x86.h b/kexec/arch/i386/crashdump-x86.h index b61cf0a..633ee0e 100644 --- a/kexec/arch/i386/crashdump-x86.h +++ b/kexec/arch/i386/crashdump-x86.h @@ -20,7 +20,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, /* Kernel text size */ #define X86_64_KERNEL_TEXT_SIZE (512UL*1024*1024) -#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) +#define CRASH_MAX_MEMMAP_NR CRASH_MAX_MEMORY_RANGES #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) /* Backup Region, First 640K of System RAM. */ @@ -28,4 +28,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, #define BACKUP_SRC_END 0x0009ffff #define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) +extern struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; +extern int crash_memory_ranges; + #endif /* CRASHDUMP_X86_H */ -- 1.8.5.3