Commit 78de91b4 authored by Youling Tang's avatar Youling Tang Committed by Huacai Chen

LoongArch: Use generic interface to support crashkernel=X,[high,low]

LoongArch already supports two crashkernel regions in kexec-tools, so we
can directly use the common interface to support crashkernel=X,[high,low]
after commit 0ab97169 ("crash_core: add generic function to do
reservation").

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>, then define CRASH_ALIGN,
   CRASH_ADDR_LOW_MAX and CRASH_ADDR_HIGH_MAX and in <asm/crash_core.h>;

2) Add arch_reserve_crashkernel() to call parse_crashkernel() and
   reserve_crashkernel_generic();

3) Add ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION Kconfig in
   arch/loongarch/Kconfig.

One can reserve the crash kernel from high memory above DMA zone range
by explicitly passing "crashkernel=X,high"; or reserve a memory range
below 4G with "crashkernel=X,low". Besides, there are few rules need to
take notice:

1) "crashkernel=X,[high,low]" will be ignored if "crashkernel=size" is
   specified.
2) "crashkernel=X,low" is valid only when "crashkernel=X,high" is passed
   and there is enough memory to be allocated under 4G.
3) When allocating crashkernel above 4G and no "crashkernel=X,low" is
   specified, a 128M low memory will be allocated automatically for
   swiotlb bounce buffer.
See Documentation/admin-guide/kernel-parameters.txt for more information.

Following test cases have been performed as expected:
1) crashkernel=256M                          //low=256M
2) crashkernel=1G                            //low=1G
3) crashkernel=4G                            //high=4G, low=128M(default)
4) crashkernel=4G crashkernel=256M,high      //high=4G, low=128M(default), high is ignored
5) crashkernel=4G crashkernel=256M,low       //high=4G, low=128M(default), low is ignored
6) crashkernel=4G,high                       //high=4G, low=128M(default)
7) crashkernel=256M,low                      //low=0M, invalid
8) crashkernel=4G,high crashkernel=256M,low  //high=4G, low=256M
9) crashkernel=4G,high crashkernel=4G,low    //high=0M, low=0M, invalid
10) crashkernel=512M@2560M                   //low=512M
11) crashkernel=1G,high crashkernel=0M,low   //high=1G, low=0M

Recommended usage in general:
1) In the case of small memory: crashkernel=512M
2) In the case of large memory: crashkernel=1024M,high crashkernel=128M,low
Signed-off-by: default avatarYouling Tang <tangyouling@kylinos.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent c2396651
...@@ -877,9 +877,9 @@ ...@@ -877,9 +877,9 @@
memory region [offset, offset + size] for that kernel memory region [offset, offset + size] for that kernel
image. If '@offset' is omitted, then a suitable offset image. If '@offset' is omitted, then a suitable offset
is selected automatically. is selected automatically.
[KNL, X86-64, ARM64, RISCV] Select a region under 4G first, and [KNL, X86-64, ARM64, RISCV, LoongArch] Select a region
fall back to reserve region above 4G when '@offset' under 4G first, and fall back to reserve region above
hasn't been specified. 4G when '@offset' hasn't been specified.
See Documentation/admin-guide/kdump/kdump.rst for further details. See Documentation/admin-guide/kdump/kdump.rst for further details.
crashkernel=range1:size1[,range2:size2,...][@offset] crashkernel=range1:size1[,range2:size2,...][@offset]
...@@ -890,25 +890,27 @@ ...@@ -890,25 +890,27 @@
Documentation/admin-guide/kdump/kdump.rst for an example. Documentation/admin-guide/kdump/kdump.rst for an example.
crashkernel=size[KMG],high crashkernel=size[KMG],high
[KNL, X86-64, ARM64, RISCV] range could be above 4G. [KNL, X86-64, ARM64, RISCV, LoongArch] range could be
above 4G.
Allow kernel to allocate physical memory region from top, Allow kernel to allocate physical memory region from top,
so could be above 4G if system have more than 4G ram so could be above 4G if system have more than 4G ram
installed. Otherwise memory region will be allocated installed. Otherwise memory region will be allocated
below 4G, if available. below 4G, if available.
It will be ignored if crashkernel=X is specified. It will be ignored if crashkernel=X is specified.
crashkernel=size[KMG],low crashkernel=size[KMG],low
[KNL, X86-64, ARM64, RISCV] range under 4G. When crashkernel=X,high [KNL, X86-64, ARM64, RISCV, LoongArch] range under 4G.
is passed, kernel could allocate physical memory region When crashkernel=X,high is passed, kernel could allocate
above 4G, that cause second kernel crash on system physical memory region above 4G, that cause second kernel
that require some amount of low memory, e.g. swiotlb crash on system that require some amount of low memory,
requires at least 64M+32K low memory, also enough extra e.g. swiotlb requires at least 64M+32K low memory, also
low memory is needed to make sure DMA buffers for 32-bit enough extra low memory is needed to make sure DMA buffers
devices won't run out. Kernel would try to allocate for 32-bit devices won't run out. Kernel would try to allocate
default size of memory below 4G automatically. The default default size of memory below 4G automatically. The default
size is platform dependent. size is platform dependent.
--> x86: max(swiotlb_size_or_default() + 8MiB, 256MiB) --> x86: max(swiotlb_size_or_default() + 8MiB, 256MiB)
--> arm64: 128MiB --> arm64: 128MiB
--> riscv: 128MiB --> riscv: 128MiB
--> loongarch: 128MiB
This one lets the user specify own low range under 4G This one lets the user specify own low range under 4G
for second kernel instead. for second kernel instead.
0: to disable low allocation. 0: to disable low allocation.
......
...@@ -594,6 +594,9 @@ config ARCH_SELECTS_CRASH_DUMP ...@@ -594,6 +594,9 @@ config ARCH_SELECTS_CRASH_DUMP
depends on CRASH_DUMP depends on CRASH_DUMP
select RELOCATABLE select RELOCATABLE
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
def_bool CRASH_CORE
config RELOCATABLE config RELOCATABLE
bool "Relocatable kernel" bool "Relocatable kernel"
help help
......
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _LOONGARCH_CRASH_CORE_H
#define _LOONGARCH_CRASH_CORE_H
#define CRASH_ALIGN SZ_2M
#define CRASH_ADDR_LOW_MAX SZ_4G
#define CRASH_ADDR_HIGH_MAX memblock_end_of_DRAM()
extern phys_addr_t memblock_end_of_DRAM(void);
#endif
...@@ -252,38 +252,23 @@ static void __init arch_reserve_vmcore(void) ...@@ -252,38 +252,23 @@ static void __init arch_reserve_vmcore(void)
#endif #endif
} }
/* 2MB alignment for crash kernel regions */ static void __init arch_reserve_crashkernel(void)
#define CRASH_ALIGN SZ_2M
#define CRASH_ADDR_MAX SZ_4G
static void __init arch_parse_crashkernel(void)
{ {
#ifdef CONFIG_KEXEC
int ret; int ret;
unsigned long long total_mem; unsigned long long low_size = 0;
unsigned long long crash_base, crash_size; unsigned long long crash_base, crash_size;
char *cmdline = boot_command_line;
bool high = false;
total_mem = memblock_phys_mem_size(); if (!IS_ENABLED(CONFIG_KEXEC_CORE))
ret = parse_crashkernel(boot_command_line, total_mem,
&crash_size, &crash_base,
NULL, NULL);
if (ret < 0 || crash_size <= 0)
return; return;
if (crash_base <= 0) { ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, CRASH_ALIGN, CRASH_ADDR_MAX); &crash_size, &crash_base, &low_size, &high);
if (!crash_base) { if (ret)
pr_warn("crashkernel reservation failed - No suitable area found.\n");
return;
}
} else if (!memblock_phys_alloc_range(crash_size, CRASH_ALIGN, crash_base, crash_base + crash_size)) {
pr_warn("Invalid memory region reserved for crash kernel\n");
return; return;
}
crashk_res.start = crash_base; reserve_crashkernel_generic(cmdline, crash_size, crash_base, low_size, high);
crashk_res.end = crash_base + crash_size - 1;
#endif
} }
static void __init fdt_setup(void) static void __init fdt_setup(void)
...@@ -363,7 +348,7 @@ static void __init bootcmdline_init(char **cmdline_p) ...@@ -363,7 +348,7 @@ static void __init bootcmdline_init(char **cmdline_p)
void __init platform_init(void) void __init platform_init(void)
{ {
arch_reserve_vmcore(); arch_reserve_vmcore();
arch_parse_crashkernel(); arch_reserve_crashkernel();
#ifdef CONFIG_ACPI_TABLE_UPGRADE #ifdef CONFIG_ACPI_TABLE_UPGRADE
acpi_table_upgrade(); acpi_table_upgrade();
...@@ -473,15 +458,6 @@ static void __init resource_init(void) ...@@ -473,15 +458,6 @@ static void __init resource_init(void)
request_resource(res, &data_resource); request_resource(res, &data_resource);
request_resource(res, &bss_resource); request_resource(res, &bss_resource);
} }
#ifdef CONFIG_KEXEC
if (crashk_res.start < crashk_res.end) {
insert_resource(&iomem_resource, &crashk_res);
pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n",
(unsigned long)((crashk_res.end - crashk_res.start + 1) >> 20),
(unsigned long)(crashk_res.start >> 20));
}
#endif
} }
static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, static int __init add_legacy_isa_io(struct fwnode_handle *fwnode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment