diff options
Diffstat (limited to 'arch/x86/kernel/setup.c')
| -rw-r--r-- | arch/x86/kernel/setup.c | 45 | 
1 files changed, 37 insertions, 8 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 90d8cc930f5..fae9134a2de 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -507,11 +507,14 @@ static void __init memblock_x86_reserve_range_setup_data(void)  /*   * Keep the crash kernel below this limit.  On 32 bits earlier kernels   * would limit the kernel to the low 512 MiB due to mapping restrictions. + * On 64bit, old kexec-tools need to under 896MiB.   */  #ifdef CONFIG_X86_32 -# define CRASH_KERNEL_ADDR_MAX	(512 << 20) +# define CRASH_KERNEL_ADDR_LOW_MAX	(512 << 20) +# define CRASH_KERNEL_ADDR_HIGH_MAX	(512 << 20)  #else -# define CRASH_KERNEL_ADDR_MAX	MAXMEM +# define CRASH_KERNEL_ADDR_LOW_MAX	(896UL<<20) +# define CRASH_KERNEL_ADDR_HIGH_MAX	MAXMEM  #endif  static void __init reserve_crashkernel_low(void) @@ -521,19 +524,35 @@ static void __init reserve_crashkernel_low(void)  	unsigned long long low_base = 0, low_size = 0;  	unsigned long total_low_mem;  	unsigned long long base; +	bool auto_set = false;  	int ret;  	total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); +	/* crashkernel=Y,low */  	ret = parse_crashkernel_low(boot_command_line, total_low_mem,  						&low_size, &base); -	if (ret != 0 || low_size <= 0) -		return; +	if (ret != 0) { +		/* +		 * two parts from lib/swiotlb.c: +		 *	swiotlb size: user specified with swiotlb= or default. +		 *	swiotlb overflow buffer: now is hardcoded to 32k. +		 *		We round it to 8M for other buffers that +		 *		may need to stay low too. +		 */ +		low_size = swiotlb_size_or_default() + (8UL<<20); +		auto_set = true; +	} else { +		/* passed with crashkernel=0,low ? */ +		if (!low_size) +			return; +	}  	low_base = memblock_find_in_range(low_size, (1ULL<<32),  					low_size, alignment);  	if (!low_base) { -		pr_info("crashkernel low reservation failed - No suitable area found.\n"); +		if (!auto_set) +			pr_info("crashkernel low reservation failed - No suitable area found.\n");  		return;  	} @@ -554,14 +573,22 @@ static void __init reserve_crashkernel(void)  	const unsigned long long alignment = 16<<20;	/* 16M */  	unsigned long long total_mem;  	unsigned long long crash_size, crash_base; +	bool high = false;  	int ret;  	total_mem = memblock_phys_mem_size(); +	/* crashkernel=XM */  	ret = parse_crashkernel(boot_command_line, total_mem,  			&crash_size, &crash_base); -	if (ret != 0 || crash_size <= 0) -		return; +	if (ret != 0 || crash_size <= 0) { +		/* crashkernel=X,high */ +		ret = parse_crashkernel_high(boot_command_line, total_mem, +				&crash_size, &crash_base); +		if (ret != 0 || crash_size <= 0) +			return; +		high = true; +	}  	/* 0 means: find the address automatically */  	if (crash_base <= 0) { @@ -569,7 +596,9 @@ static void __init reserve_crashkernel(void)  		 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX  		 */  		crash_base = memblock_find_in_range(alignment, -			       CRASH_KERNEL_ADDR_MAX, crash_size, alignment); +					high ? CRASH_KERNEL_ADDR_HIGH_MAX : +					       CRASH_KERNEL_ADDR_LOW_MAX, +					crash_size, alignment);  		if (!crash_base) {  			pr_info("crashkernel reservation failed - No suitable area found.\n");  |