[PATCH v4 2/4] x86: Store memory ranges globally used for crash kernel to boot into
Dave Young
dyoung at redhat.com
Thu Mar 27 22:19:13 EDT 2014
On 03/19/14 at 04:03pm, WANG Chao wrote:
> 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)
It's not necessary to replace every static vars in the function, since there's param
*ranges and **range, so how about just replace them in caller function.
> {
> 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,
Ditto for get_crash_memory_ranges_xen, just fix the caller function instead of use
global variable in this function.
> }
>
> *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
>
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
More information about the kexec
mailing list