[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