mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 13:22:57 +00:00
x86: kdump: use generic interface to simplify crashkernel reservation code
With the help of newly changed function parse_crashkernel() and generic reserve_crashkernel_generic(), crashkernel reservation can be simplified by steps: 1) Add a new header file <asm/crash_core.h>, and define CRASH_ALIGN, CRASH_ADDR_LOW_MAX, CRASH_ADDR_HIGH_MAX and DEFAULT_CRASH_KERNEL_LOW_SIZE in <asm/crash_core.h>; 2) Add arch_reserve_crashkernel() to call parse_crashkernel() and reserve_crashkernel_generic(), and do the ARCH specific work if needed. 3) Add ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION Kconfig in arch/x86/Kconfig. When adding DEFAULT_CRASH_KERNEL_LOW_SIZE, add crash_low_size_default() to calculate crashkernel low memory because x86_64 has special requirement. The old reserve_crashkernel_low() and reserve_crashkernel() can be removed. [bhe@redhat.com: move crash_low_size_default() code into <asm/crash_core.h>] Link: https://lkml.kernel.org/r/ZQpeAjOmuMJBFw1/@MiWiFi-R3L-srv Link: https://lkml.kernel.org/r/20230914033142.676708-7-bhe@redhat.com Signed-off-by: Baoquan He <bhe@redhat.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Chen Jiahao <chenjiahao16@huawei.com> Cc: Zhen Lei <thunder.leizhen@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
b631b95dde
commit
9c08a2a139
3 changed files with 56 additions and 137 deletions
|
@ -2062,6 +2062,9 @@ config ARCH_SUPPORTS_CRASH_DUMP
|
||||||
config ARCH_SUPPORTS_CRASH_HOTPLUG
|
config ARCH_SUPPORTS_CRASH_HOTPLUG
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
|
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
|
||||||
|
def_bool CRASH_CORE
|
||||||
|
|
||||||
config PHYSICAL_START
|
config PHYSICAL_START
|
||||||
hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
|
hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
|
||||||
default "0x1000000"
|
default "0x1000000"
|
||||||
|
|
42
arch/x86/include/asm/crash_core.h
Normal file
42
arch/x86/include/asm/crash_core.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _X86_CRASH_CORE_H
|
||||||
|
#define _X86_CRASH_CORE_H
|
||||||
|
|
||||||
|
/* 16M alignment for crash kernel regions */
|
||||||
|
#define CRASH_ALIGN SZ_16M
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep the crash kernel below this limit.
|
||||||
|
*
|
||||||
|
* Earlier 32-bits kernels would limit the kernel to the low 512 MB range
|
||||||
|
* due to mapping restrictions.
|
||||||
|
*
|
||||||
|
* 64-bit kdump kernels need to be restricted to be under 64 TB, which is
|
||||||
|
* the upper limit of system RAM in 4-level paging mode. Since the kdump
|
||||||
|
* jump could be from 5-level paging to 4-level paging, the jump will fail if
|
||||||
|
* the kernel is put above 64 TB, and during the 1st kernel bootup there's
|
||||||
|
* no good way to detect the paging mode of the target kernel which will be
|
||||||
|
* loaded for dumping.
|
||||||
|
*/
|
||||||
|
extern unsigned long swiotlb_size_or_default(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
# define CRASH_ADDR_LOW_MAX SZ_512M
|
||||||
|
# define CRASH_ADDR_HIGH_MAX SZ_512M
|
||||||
|
#else
|
||||||
|
# define CRASH_ADDR_LOW_MAX SZ_4G
|
||||||
|
# define CRASH_ADDR_HIGH_MAX SZ_64T
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define DEFAULT_CRASH_KERNEL_LOW_SIZE crash_low_size_default()
|
||||||
|
|
||||||
|
static inline unsigned long crash_low_size_default(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
return max(swiotlb_size_or_default() + (8UL << 20), 256UL << 20);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _X86_CRASH_CORE_H */
|
|
@ -466,155 +466,29 @@ static void __init memblock_x86_reserve_range_setup_data(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void __init arch_reserve_crashkernel(void)
|
||||||
* --------- Crashkernel reservation ------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 16M alignment for crash kernel regions */
|
|
||||||
#define CRASH_ALIGN SZ_16M
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keep the crash kernel below this limit.
|
|
||||||
*
|
|
||||||
* Earlier 32-bits kernels would limit the kernel to the low 512 MB range
|
|
||||||
* due to mapping restrictions.
|
|
||||||
*
|
|
||||||
* 64-bit kdump kernels need to be restricted to be under 64 TB, which is
|
|
||||||
* the upper limit of system RAM in 4-level paging mode. Since the kdump
|
|
||||||
* jump could be from 5-level paging to 4-level paging, the jump will fail if
|
|
||||||
* the kernel is put above 64 TB, and during the 1st kernel bootup there's
|
|
||||||
* no good way to detect the paging mode of the target kernel which will be
|
|
||||||
* loaded for dumping.
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
# define CRASH_ADDR_LOW_MAX SZ_512M
|
|
||||||
# define CRASH_ADDR_HIGH_MAX SZ_512M
|
|
||||||
#else
|
|
||||||
# define CRASH_ADDR_LOW_MAX SZ_4G
|
|
||||||
# define CRASH_ADDR_HIGH_MAX SZ_64T
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int __init reserve_crashkernel_low(void)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_64
|
unsigned long long crash_base, crash_size, low_size = 0;
|
||||||
unsigned long long base, low_base = 0, low_size = 0;
|
char *cmdline = boot_command_line;
|
||||||
unsigned long low_mem_limit;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
low_mem_limit = min(memblock_phys_mem_size(), CRASH_ADDR_LOW_MAX);
|
|
||||||
|
|
||||||
/* crashkernel=Y,low */
|
|
||||||
ret = parse_crashkernel_low(boot_command_line, low_mem_limit, &low_size, &base);
|
|
||||||
if (ret) {
|
|
||||||
/*
|
|
||||||
* two parts from kernel/dma/swiotlb.c:
|
|
||||||
* -swiotlb size: user-specified with swiotlb= or default.
|
|
||||||
*
|
|
||||||
* -swiotlb overflow buffer: now hardcoded to 32k. We round it
|
|
||||||
* to 8M for other buffers that may need to stay low too. Also
|
|
||||||
* make sure we allocate enough extra low memory so that we
|
|
||||||
* don't run out of DMA buffers for 32-bit devices.
|
|
||||||
*/
|
|
||||||
low_size = max(swiotlb_size_or_default() + (8UL << 20), 256UL << 20);
|
|
||||||
} else {
|
|
||||||
/* passed with crashkernel=0,low ? */
|
|
||||||
if (!low_size)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX);
|
|
||||||
if (!low_base) {
|
|
||||||
pr_err("Cannot reserve %ldMB crashkernel low memory, please try smaller size.\n",
|
|
||||||
(unsigned long)(low_size >> 20));
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("Reserving %ldMB of low memory at %ldMB for crashkernel (low RAM limit: %ldMB)\n",
|
|
||||||
(unsigned long)(low_size >> 20),
|
|
||||||
(unsigned long)(low_base >> 20),
|
|
||||||
(unsigned long)(low_mem_limit >> 20));
|
|
||||||
|
|
||||||
crashk_low_res.start = low_base;
|
|
||||||
crashk_low_res.end = low_base + low_size - 1;
|
|
||||||
insert_resource(&iomem_resource, &crashk_low_res);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init reserve_crashkernel(void)
|
|
||||||
{
|
|
||||||
unsigned long long crash_size, crash_base, total_mem;
|
|
||||||
bool high = false;
|
bool high = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
total_mem = memblock_phys_mem_size();
|
ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
|
||||||
|
&crash_size, &crash_base,
|
||||||
/* crashkernel=XM */
|
&low_size, &high);
|
||||||
ret = parse_crashkernel(boot_command_line, total_mem,
|
if (ret)
|
||||||
&crash_size, &crash_base, NULL, NULL);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xen_pv_domain()) {
|
if (xen_pv_domain()) {
|
||||||
pr_info("Ignoring crashkernel for a Xen PV domain\n");
|
pr_info("Ignoring crashkernel for a Xen PV domain\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0 means: find the address automatically */
|
reserve_crashkernel_generic(cmdline, crash_size, crash_base,
|
||||||
if (!crash_base) {
|
low_size, high);
|
||||||
/*
|
|
||||||
* Set CRASH_ADDR_LOW_MAX upper bound for crash memory,
|
|
||||||
* crashkernel=x,high reserves memory over 4G, also allocates
|
|
||||||
* 256M extra low memory for DMA buffers and swiotlb.
|
|
||||||
* But the extra memory is not required for all machines.
|
|
||||||
* So try low memory first and fall back to high memory
|
|
||||||
* unless "crashkernel=size[KMG],high" is specified.
|
|
||||||
*/
|
|
||||||
if (!high)
|
|
||||||
crash_base = memblock_phys_alloc_range(crash_size,
|
|
||||||
CRASH_ALIGN, CRASH_ALIGN,
|
|
||||||
CRASH_ADDR_LOW_MAX);
|
|
||||||
if (!crash_base)
|
|
||||||
crash_base = memblock_phys_alloc_range(crash_size,
|
|
||||||
CRASH_ALIGN, CRASH_ALIGN,
|
|
||||||
CRASH_ADDR_HIGH_MAX);
|
|
||||||
if (!crash_base) {
|
|
||||||
pr_info("crashkernel reservation failed - No suitable area found.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsigned long long start;
|
|
||||||
|
|
||||||
start = memblock_phys_alloc_range(crash_size, SZ_1M, crash_base,
|
|
||||||
crash_base + crash_size);
|
|
||||||
if (start != crash_base) {
|
|
||||||
pr_info("crashkernel reservation failed - memory is in use.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crash_base >= (1ULL << 32) && reserve_crashkernel_low()) {
|
|
||||||
memblock_phys_free(crash_base, crash_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n",
|
|
||||||
(unsigned long)(crash_size >> 20),
|
|
||||||
(unsigned long)(crash_base >> 20),
|
|
||||||
(unsigned long)(total_mem >> 20));
|
|
||||||
|
|
||||||
crashk_res.start = crash_base;
|
|
||||||
crashk_res.end = crash_base + crash_size - 1;
|
|
||||||
insert_resource(&iomem_resource, &crashk_res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct resource standard_io_resources[] = {
|
static struct resource standard_io_resources[] = {
|
||||||
|
@ -1228,7 +1102,7 @@ void __init setup_arch(char **cmdline_p)
|
||||||
* Reserve memory for crash kernel after SRAT is parsed so that it
|
* Reserve memory for crash kernel after SRAT is parsed so that it
|
||||||
* won't consume hotpluggable memory.
|
* won't consume hotpluggable memory.
|
||||||
*/
|
*/
|
||||||
reserve_crashkernel();
|
arch_reserve_crashkernel();
|
||||||
|
|
||||||
memblock_find_dma_reserve();
|
memblock_find_dma_reserve();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue