[PATCH] crash: Support high memory reservation for range syntax

Youling Tang posted 1 patch 2 months, 1 week ago
Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
.../admin-guide/kernel-parameters.txt         |  2 +-
kernel/crash_reserve.c                        | 56 ++++++++++++++++---
3 files changed, 73 insertions(+), 10 deletions(-)
[PATCH] crash: Support high memory reservation for range syntax
Posted by Youling Tang 2 months, 1 week ago
From: Youling Tang <tangyouling@kylinos.cn>

The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
automatic size selection based on system RAM, but it always reserves
from low memory. When a large crashkernel is selected, this can
consume most of the low memory, causing subsequent hardware
hotplug or drivers requiring low memory to fail due to allocation
failures.

Add a new optional conditional suffix ",>boundary" to the crashkernel
range syntax. When the selected crashkernel size exceeds the specified
boundary, the kernel will automatically apply the same reservation
policy as "crashkernel=size,high" - preferring high memory first
and reserving the default low memory area.

Syntax:
    crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary

Example:
    crashkernel=2G-16G:512M,16G-:1G,>512M

This means:
  - For 2G-16G RAM: reserve 512M normally
  - For >16G RAM: reserve 1G with high memory preference (since 1G > 512M)

For systems with >16G RAM, 1G is selected which exceeds 512M, so it
will be reserved from high memory instead of consuming 1G of
precious low memory.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
 .../admin-guide/kernel-parameters.txt         |  2 +-
 kernel/crash_reserve.c                        | 56 ++++++++++++++++---
 3 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
index 7587caadbae1..b5ae4556e9ca 100644
--- a/Documentation/admin-guide/kdump/kdump.rst
+++ b/Documentation/admin-guide/kdump/kdump.rst
@@ -293,7 +293,28 @@ crashkernel syntax
        2) if the RAM size is between 512M and 2G (exclusive), then reserve 64M
        3) if the RAM size is larger than 2G, then reserve 128M
 
-3) crashkernel=size,high and crashkernel=size,low
+3) range1:size1[,range2:size2,...][@offset],>boundary
+   Optionally, the range list can be followed by a conditional suffix
+   `,>boundary`. When the selected crashkernel size matches the
+   condition, the kernel will reserve memory using the same policy as
+   `crashkernel=size,high` (i.e. prefer high memory first and reserve the
+   default low memory area).
+
+   The syntax is::
+
+        crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
+        range=start-[end]
+
+   For example::
+
+        crashkernel=2G-16G:512M,16G-:1G,>512M
+
+   This would mean:
+       1) if the RAM size is between 2G and 16G (exclusive), then reserve 512M.
+       2) if the RAM size is larger than 16G, allocation will behave like
+          `crashkernel=1G,high`.
+
+4) crashkernel=size,high and crashkernel=size,low
 
    If memory above 4G is preferred, crashkernel=size,high can be used to
    fulfill that. With it, physical memory is allowed to be allocated from top,
@@ -311,7 +332,7 @@ crashkernel syntax
 
             crashkernel=0,low
 
-4) crashkernel=size,cma
+5) crashkernel=size,cma
 
 	Reserve additional crash kernel memory from CMA. This reservation is
 	usable by the first system's userspace memory and kernel movable
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 03a550630644..b2e1892ab4d8 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1087,7 +1087,7 @@ Kernel parameters
 			4G when '@offset' hasn't been specified.
 			See Documentation/admin-guide/kdump/kdump.rst for further details.
 
-	crashkernel=range1:size1[,range2:size2,...][@offset]
+	crashkernel=range1:size1[,range2:size2,...][@offset][,>boundary]
 			[KNL] Same as above, but depends on the memory
 			in the running system. The syntax of range is
 			start-[end] where start and end are both
diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c
index 62e60e0223cf..917738412390 100644
--- a/kernel/crash_reserve.c
+++ b/kernel/crash_reserve.c
@@ -254,15 +254,47 @@ static __init char *get_last_crashkernel(char *cmdline,
 	return ck_cmdline;
 }
 
+/*
+ * This function parses command lines in the format
+ *
+ *   crashkernel=ramsize-range:size[,...][@offset],>boundary
+ */
+static void __init parse_crashkernel_boundary(char *ck_cmdline,
+					unsigned long long *boundary)
+{
+	char *cur = ck_cmdline, *next;
+	char *first_gt = false;
+
+	first_gt = strchr(cur, '>');
+	if (!first_gt)
+		return;
+
+	cur = first_gt + 1;
+	if (*cur == '\0' || *cur == ' ' || *cur == ',') {
+		pr_warn("crashkernel: '>' specified without boundary size, ignoring\n");
+		return;
+	}
+
+	*boundary = memparse(cur, &next);
+	if (cur == next) {
+		pr_warn("crashkernel: invalid boundary size after '>'\n");
+		return;
+	}
+}
+
 static int __init __parse_crashkernel(char *cmdline,
 			     unsigned long long system_ram,
 			     unsigned long long *crash_size,
 			     unsigned long long *crash_base,
-			     const char *suffix)
+			     const char *suffix,
+			     bool *high,
+			     unsigned long long *low_size)
 {
 	char *first_colon, *first_space;
 	char *ck_cmdline;
 	char *name = "crashkernel=";
+	unsigned long long boundary = 0;
+	int ret;
 
 	BUG_ON(!crash_size || !crash_base);
 	*crash_size = 0;
@@ -283,10 +315,20 @@ static int __init __parse_crashkernel(char *cmdline,
 	 */
 	first_colon = strchr(ck_cmdline, ':');
 	first_space = strchr(ck_cmdline, ' ');
-	if (first_colon && (!first_space || first_colon < first_space))
-		return parse_crashkernel_mem(ck_cmdline, system_ram,
+	if (first_colon && (!first_space || first_colon < first_space)) {
+		ret = parse_crashkernel_mem(ck_cmdline, system_ram,
 				crash_size, crash_base);
 
+		/* Handle optional ',>boundary' condition for range ':' syntax only. */
+		parse_crashkernel_boundary(ck_cmdline, &boundary);
+		if (!ret && *crash_size > boundary) {
+			*high = true;
+			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
+		}
+
+		return ret;
+	}
+
 	return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
 }
 
@@ -310,7 +352,7 @@ int __init parse_crashkernel(char *cmdline,
 
 	/* crashkernel=X[@offset] */
 	ret = __parse_crashkernel(cmdline, system_ram, crash_size,
-				crash_base, NULL);
+				crash_base, NULL, high, low_size);
 #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
 	/*
 	 * If non-NULL 'high' passed in and no normal crashkernel
@@ -318,7 +360,7 @@ int __init parse_crashkernel(char *cmdline,
 	 */
 	if (high && ret == -ENOENT) {
 		ret = __parse_crashkernel(cmdline, 0, crash_size,
-				crash_base, suffix_tbl[SUFFIX_HIGH]);
+				crash_base, suffix_tbl[SUFFIX_HIGH], high, low_size);
 		if (ret || !*crash_size)
 			return -EINVAL;
 
@@ -327,7 +369,7 @@ int __init parse_crashkernel(char *cmdline,
 		 * is not allowed.
 		 */
 		ret = __parse_crashkernel(cmdline, 0, low_size,
-				crash_base, suffix_tbl[SUFFIX_LOW]);
+				crash_base, suffix_tbl[SUFFIX_LOW], high, low_size);
 		if (ret == -ENOENT) {
 			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
 			ret = 0;
@@ -344,7 +386,7 @@ int __init parse_crashkernel(char *cmdline,
 	 */
 	if (cma_size)
 		__parse_crashkernel(cmdline, 0, cma_size,
-			&cma_base, suffix_tbl[SUFFIX_CMA]);
+			&cma_base, suffix_tbl[SUFFIX_CMA], high, low_size);
 #endif
 	if (!*crash_size)
 		ret = -EINVAL;
-- 
2.43.0
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by kernel test robot 2 months ago
Hi Youling,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on linus/master v7.0 next-20260414]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Youling-Tang/crash-Support-high-memory-reservation-for-range-syntax/20260414-205035
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260404074103.506793-1-youling.tang%40linux.dev
patch subject: [PATCH] crash: Support high memory reservation for range syntax
config: mips-randconfig-r061-20260415 (https://download.01.org/0day-ci/archive/20260415/202604151100.7wbci6vo-lkp@intel.com/config)
compiler: mips64-linux-gcc (GCC) 12.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260415/202604151100.7wbci6vo-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604151100.7wbci6vo-lkp@intel.com/

All errors (new ones prefixed by >>):

   kernel/crash_reserve.c: In function '__parse_crashkernel':
>> kernel/crash_reserve.c:324:37: error: 'DEFAULT_CRASH_KERNEL_LOW_SIZE' undeclared (first use in this function)
     324 |                         *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
         |                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/crash_reserve.c:324:37: note: each undeclared identifier is reported only once for each function it appears in


vim +/DEFAULT_CRASH_KERNEL_LOW_SIZE +324 kernel/crash_reserve.c

   282	
   283	static int __init __parse_crashkernel(char *cmdline,
   284				     unsigned long long system_ram,
   285				     unsigned long long *crash_size,
   286				     unsigned long long *crash_base,
   287				     const char *suffix,
   288				     bool *high,
   289				     unsigned long long *low_size)
   290	{
   291		char *first_colon, *first_space;
   292		char *ck_cmdline;
   293		char *name = "crashkernel=";
   294		unsigned long long boundary = 0;
   295		int ret;
   296	
   297		BUG_ON(!crash_size || !crash_base);
   298		*crash_size = 0;
   299		*crash_base = 0;
   300	
   301		ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
   302		if (!ck_cmdline)
   303			return -ENOENT;
   304	
   305		ck_cmdline += strlen(name);
   306	
   307		if (suffix)
   308			return parse_crashkernel_suffix(ck_cmdline, crash_size,
   309					suffix);
   310		/*
   311		 * if the commandline contains a ':', then that's the extended
   312		 * syntax -- if not, it must be the classic syntax
   313		 */
   314		first_colon = strchr(ck_cmdline, ':');
   315		first_space = strchr(ck_cmdline, ' ');
   316		if (first_colon && (!first_space || first_colon < first_space)) {
   317			ret = parse_crashkernel_mem(ck_cmdline, system_ram,
   318					crash_size, crash_base);
   319	
   320			/* Handle optional ',>boundary' condition for range ':' syntax only. */
   321			parse_crashkernel_boundary(ck_cmdline, &boundary);
   322			if (!ret && *crash_size > boundary) {
   323				*high = true;
 > 324				*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
   325			}
   326	
   327			return ret;
   328		}
   329	
   330		return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
   331	}
   332	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by kernel test robot 2 months ago
Hi Youling,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on linus/master v7.0 next-20260414]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Youling-Tang/crash-Support-high-memory-reservation-for-range-syntax/20260414-205035
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260404074103.506793-1-youling.tang%40linux.dev
patch subject: [PATCH] crash: Support high memory reservation for range syntax
config: s390-defconfig (https://download.01.org/0day-ci/archive/20260415/202604150941.oDguaP7A-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 5bac06718f502014fade905512f1d26d578a18f3)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260415/202604150941.oDguaP7A-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604150941.oDguaP7A-lkp@intel.com/

All errors (new ones prefixed by >>):

   kernel/crash_reserve.c:264:19: warning: expression which evaluates to zero treated as a null pointer constant of type 'char *' [-Wnon-literal-null-conversion]
     264 |         char *first_gt = false;
         |                          ^~~~~
>> kernel/crash_reserve.c:324:16: error: use of undeclared identifier 'DEFAULT_CRASH_KERNEL_LOW_SIZE'
     324 |                         *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
         |                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning and 1 error generated.


vim +/DEFAULT_CRASH_KERNEL_LOW_SIZE +324 kernel/crash_reserve.c

   282	
   283	static int __init __parse_crashkernel(char *cmdline,
   284				     unsigned long long system_ram,
   285				     unsigned long long *crash_size,
   286				     unsigned long long *crash_base,
   287				     const char *suffix,
   288				     bool *high,
   289				     unsigned long long *low_size)
   290	{
   291		char *first_colon, *first_space;
   292		char *ck_cmdline;
   293		char *name = "crashkernel=";
   294		unsigned long long boundary = 0;
   295		int ret;
   296	
   297		BUG_ON(!crash_size || !crash_base);
   298		*crash_size = 0;
   299		*crash_base = 0;
   300	
   301		ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
   302		if (!ck_cmdline)
   303			return -ENOENT;
   304	
   305		ck_cmdline += strlen(name);
   306	
   307		if (suffix)
   308			return parse_crashkernel_suffix(ck_cmdline, crash_size,
   309					suffix);
   310		/*
   311		 * if the commandline contains a ':', then that's the extended
   312		 * syntax -- if not, it must be the classic syntax
   313		 */
   314		first_colon = strchr(ck_cmdline, ':');
   315		first_space = strchr(ck_cmdline, ' ');
   316		if (first_colon && (!first_space || first_colon < first_space)) {
   317			ret = parse_crashkernel_mem(ck_cmdline, system_ram,
   318					crash_size, crash_base);
   319	
   320			/* Handle optional ',>boundary' condition for range ':' syntax only. */
   321			parse_crashkernel_boundary(ck_cmdline, &boundary);
   322			if (!ret && *crash_size > boundary) {
   323				*high = true;
 > 324				*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
   325			}
   326	
   327			return ret;
   328		}
   329	
   330		return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
   331	}
   332	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by kernel test robot 2 months ago
Hi Youling,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v7.0 next-20260414]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Youling-Tang/crash-Support-high-memory-reservation-for-range-syntax/20260414-205035
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260404074103.506793-1-youling.tang%40linux.dev
patch subject: [PATCH] crash: Support high memory reservation for range syntax
config: loongarch-randconfig-001-20260415 (https://download.01.org/0day-ci/archive/20260415/202604150808.7HxFp5b4-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260415/202604150808.7HxFp5b4-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604150808.7HxFp5b4-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> kernel/crash_reserve.c:264:19: warning: expression which evaluates to zero treated as a null pointer constant of type 'char *' [-Wnon-literal-null-conversion]
     264 |         char *first_gt = false;
         |                          ^~~~~
   1 warning generated.


vim +264 kernel/crash_reserve.c

   254	
   255	/*
   256	 * This function parses command lines in the format
   257	 *
   258	 *   crashkernel=ramsize-range:size[,...][@offset],>boundary
   259	 */
   260	static void __init parse_crashkernel_boundary(char *ck_cmdline,
   261						unsigned long long *boundary)
   262	{
   263		char *cur = ck_cmdline, *next;
 > 264		char *first_gt = false;
   265	
   266		first_gt = strchr(cur, '>');
   267		if (!first_gt)
   268			return;
   269	
   270		cur = first_gt + 1;
   271		if (*cur == '\0' || *cur == ' ' || *cur == ',') {
   272			pr_warn("crashkernel: '>' specified without boundary size, ignoring\n");
   273			return;
   274		}
   275	
   276		*boundary = memparse(cur, &next);
   277		if (cur == next) {
   278			pr_warn("crashkernel: invalid boundary size after '>'\n");
   279			return;
   280		}
   281	}
   282	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Sourabh Jain 2 months, 1 week ago

On 04/04/26 13:11, Youling Tang wrote:
> From: Youling Tang <tangyouling@kylinos.cn>
>
> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
> automatic size selection based on system RAM, but it always reserves
> from low memory. When a large crashkernel is selected, this can
> consume most of the low memory, causing subsequent hardware
> hotplug or drivers requiring low memory to fail due to allocation
> failures.
>
> Add a new optional conditional suffix ",>boundary" to the crashkernel
> range syntax. When the selected crashkernel size exceeds the specified
> boundary, the kernel will automatically apply the same reservation
> policy as "crashkernel=size,high" - preferring high memory first
> and reserving the default low memory area.
>
> Syntax:
>      crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>
> Example:
>      crashkernel=2G-16G:512M,16G-:1G,>512M
>
> This means:
>    - For 2G-16G RAM: reserve 512M normally
>    - For >16G RAM: reserve 1G with high memory preference (since 1G > 512M)
>
> For systems with >16G RAM, 1G is selected which exceeds 512M, so it
> will be reserved from high memory instead of consuming 1G of
> precious low memory.
>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>   Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
>   .../admin-guide/kernel-parameters.txt         |  2 +-
>   kernel/crash_reserve.c                        | 56 ++++++++++++++++---
>   3 files changed, 73 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
> index 7587caadbae1..b5ae4556e9ca 100644
> --- a/Documentation/admin-guide/kdump/kdump.rst
> +++ b/Documentation/admin-guide/kdump/kdump.rst
> @@ -293,7 +293,28 @@ crashkernel syntax
>          2) if the RAM size is between 512M and 2G (exclusive), then reserve 64M
>          3) if the RAM size is larger than 2G, then reserve 128M
>   
> -3) crashkernel=size,high and crashkernel=size,low
> +3) range1:size1[,range2:size2,...][@offset],>boundary
> +   Optionally, the range list can be followed by a conditional suffix
> +   `,>boundary`. When the selected crashkernel size matches the
> +   condition, the kernel will reserve memory using the same policy as
> +   `crashkernel=size,high` (i.e. prefer high memory first and reserve the
> +   default low memory area).

Since we are mentioning that this follows same policy as 
crashkernel=size,high
in certain cases I think it is good to mention crashkernel=size,low is 
ignored here.

> +
> +   The syntax is::
> +
> +        crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
> +        range=start-[end]
> +
> +   For example::
> +
> +        crashkernel=2G-16G:512M,16G-:1G,>512M
> +
> +   This would mean:
> +       1) if the RAM size is between 2G and 16G (exclusive), then reserve 512M.
> +       2) if the RAM size is larger than 16G, allocation will behave like
> +          `crashkernel=1G,high`.
> +
> +4) crashkernel=size,high and crashkernel=size,low
>   
>      If memory above 4G is preferred, crashkernel=size,high can be used to
>      fulfill that. With it, physical memory is allowed to be allocated from top,
> @@ -311,7 +332,7 @@ crashkernel syntax
>   
>               crashkernel=0,low
>   
> -4) crashkernel=size,cma
> +5) crashkernel=size,cma
>   
>   	Reserve additional crash kernel memory from CMA. This reservation is
>   	usable by the first system's userspace memory and kernel movable
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 03a550630644..b2e1892ab4d8 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1087,7 +1087,7 @@ Kernel parameters
>   			4G when '@offset' hasn't been specified.
>   			See Documentation/admin-guide/kdump/kdump.rst for further details.
>   
> -	crashkernel=range1:size1[,range2:size2,...][@offset]
> +	crashkernel=range1:size1[,range2:size2,...][@offset][,>boundary]
>   			[KNL] Same as above, but depends on the memory
>   			in the running system. The syntax of range is
>   			start-[end] where start and end are both
> diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c
> index 62e60e0223cf..917738412390 100644
> --- a/kernel/crash_reserve.c
> +++ b/kernel/crash_reserve.c
> @@ -254,15 +254,47 @@ static __init char *get_last_crashkernel(char *cmdline,
>   	return ck_cmdline;
>   }
>   
> +/*
> + * This function parses command lines in the format
> + *
> + *   crashkernel=ramsize-range:size[,...][@offset],>boundary
> + */
> +static void __init parse_crashkernel_boundary(char *ck_cmdline,
> +					unsigned long long *boundary)
> +{
> +	char *cur = ck_cmdline, *next;
> +	char *first_gt = false;

false to char *? We don't even need to initialize.

> +
> +	first_gt = strchr(cur, '>');
> +	if (!first_gt)
> +		return;
> +
> +	cur = first_gt + 1;
> +	if (*cur == '\0' || *cur == ' ' || *cur == ',') {
> +		pr_warn("crashkernel: '>' specified without boundary size, ignoring\n");
> +		return;
> +	}
> +
> +	*boundary = memparse(cur, &next);
> +	if (cur == next) {
> +		pr_warn("crashkernel: invalid boundary size after '>'\n");
> +		return;
> +	}
> +}
> +
>   static int __init __parse_crashkernel(char *cmdline,
>   			     unsigned long long system_ram,
>   			     unsigned long long *crash_size,
>   			     unsigned long long *crash_base,
> -			     const char *suffix)
> +			     const char *suffix,
> +			     bool *high,
> +			     unsigned long long *low_size)
>   {
>   	char *first_colon, *first_space;
>   	char *ck_cmdline;
>   	char *name = "crashkernel=";
> +	unsigned long long boundary = 0;
> +	int ret;
>   
>   	BUG_ON(!crash_size || !crash_base);
>   	*crash_size = 0;
> @@ -283,10 +315,20 @@ static int __init __parse_crashkernel(char *cmdline,
>   	 */
>   	first_colon = strchr(ck_cmdline, ':');
>   	first_space = strchr(ck_cmdline, ' ');
> -	if (first_colon && (!first_space || first_colon < first_space))
> -		return parse_crashkernel_mem(ck_cmdline, system_ram,
> +	if (first_colon && (!first_space || first_colon < first_space)) {
> +		ret = parse_crashkernel_mem(ck_cmdline, system_ram,
>   				crash_size, crash_base);
>   
> +		/* Handle optional ',>boundary' condition for range ':' syntax only. */
> +		parse_crashkernel_boundary(ck_cmdline, &boundary);
> +		if (!ret && *crash_size > boundary) {
> +			*high = true;
> +			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;

Not all architectures support high crashkernel reservation. So high and 
low_size
can be NULL.

I think we should just skip parse_crashkernel_boundary() call if high is 
NULL. - Sourabh Jain
> +		}
> +
> +		return ret;
> +	}
> +
>   	return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
>   }
>   
> @@ -310,7 +352,7 @@ int __init parse_crashkernel(char *cmdline,
>   
>   	/* crashkernel=X[@offset] */
>   	ret = __parse_crashkernel(cmdline, system_ram, crash_size,
> -				crash_base, NULL);
> +				crash_base, NULL, high, low_size);
>   #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
>   	/*
>   	 * If non-NULL 'high' passed in and no normal crashkernel
> @@ -318,7 +360,7 @@ int __init parse_crashkernel(char *cmdline,
>   	 */
>   	if (high && ret == -ENOENT) {
>   		ret = __parse_crashkernel(cmdline, 0, crash_size,
> -				crash_base, suffix_tbl[SUFFIX_HIGH]);
> +				crash_base, suffix_tbl[SUFFIX_HIGH], high, low_size);
>   		if (ret || !*crash_size)
>   			return -EINVAL;
>   
> @@ -327,7 +369,7 @@ int __init parse_crashkernel(char *cmdline,
>   		 * is not allowed.
>   		 */
>   		ret = __parse_crashkernel(cmdline, 0, low_size,
> -				crash_base, suffix_tbl[SUFFIX_LOW]);
> +				crash_base, suffix_tbl[SUFFIX_LOW], high, low_size);
>   		if (ret == -ENOENT) {
>   			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>   			ret = 0;
> @@ -344,7 +386,7 @@ int __init parse_crashkernel(char *cmdline,
>   	 */
>   	if (cma_size)
>   		__parse_crashkernel(cmdline, 0, cma_size,
> -			&cma_base, suffix_tbl[SUFFIX_CMA]);
> +			&cma_base, suffix_tbl[SUFFIX_CMA], high, low_size);
>   #endif
>   	if (!*crash_size)
>   		ret = -EINVAL;
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Sourabh Jain 2 months, 1 week ago
Hello Youling,

On 04/04/26 13:11, Youling Tang wrote:
> From: Youling Tang <tangyouling@kylinos.cn>
>
> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
> automatic size selection based on system RAM, but it always reserves
> from low memory. When a large crashkernel is selected, this can
> consume most of the low memory, causing subsequent hardware
> hotplug or drivers requiring low memory to fail due to allocation
> failures.


Support for high crashkernel reservation has been added to
address the above problem.

However, high crashkernel reservation is not supported with
range-based crashkernel kernel command-line arguments.
For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M

Many users, including some distributions, use range-based
crashkernel configuration. So, adding support for high crashkernel
reservation with range-based configuration would be useful.

>
> Add a new optional conditional suffix ",>boundary" to the crashkernel
> range syntax. When the selected crashkernel size exceeds the specified
> boundary, the kernel will automatically apply the same reservation
> policy as "crashkernel=size,high" - preferring high memory first
> and reserving the default low memory area.

I think the approach to enable high crashkernel reservation
with range-based configuration makes the crashkernel kernel
argument more complex.

If the goal is to support high crashkernel reservation with
range-based kernel command-line arguments, how about:

crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],high

instead of using >boundary?

>
> Syntax:
>      crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>
> Example:
>      crashkernel=2G-16G:512M,16G-:1G,>512M
>
> This means:
>    - For 2G-16G RAM: reserve 512M normally
>    - For >16G RAM: reserve 1G with high memory preference (since 1G > 512M)
>
> For systems with >16G RAM, 1G is selected which exceeds 512M, so it
> will be reserved from high memory instead of consuming 1G of
> precious low memory.
>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>   Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
>   .../admin-guide/kernel-parameters.txt         |  2 +-
>   kernel/crash_reserve.c                        | 56 ++++++++++++++++---
>   3 files changed, 73 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
> index 7587caadbae1..b5ae4556e9ca 100644
> --- a/Documentation/admin-guide/kdump/kdump.rst
> +++ b/Documentation/admin-guide/kdump/kdump.rst
> @@ -293,7 +293,28 @@ crashkernel syntax
>          2) if the RAM size is between 512M and 2G (exclusive), then reserve 64M
>          3) if the RAM size is larger than 2G, then reserve 128M
>   
> -3) crashkernel=size,high and crashkernel=size,low
> +3) range1:size1[,range2:size2,...][@offset],>boundary
> +   Optionally, the range list can be followed by a conditional suffix
> +   `,>boundary`. When the selected crashkernel size matches the
> +   condition, the kernel will reserve memory using the same policy as
> +   `crashkernel=size,high` (i.e. prefer high memory first and reserve the
> +   default low memory area).
> +
> +   The syntax is::
> +
> +        crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
> +        range=start-[end]
> +
> +   For example::
> +
> +        crashkernel=2G-16G:512M,16G-:1G,>512M
> +
> +   This would mean:
> +       1) if the RAM size is between 2G and 16G (exclusive), then reserve 512M.
> +       2) if the RAM size is larger than 16G, allocation will behave like
> +          `crashkernel=1G,high`.
> +
> +4) crashkernel=size,high and crashkernel=size,low
>   
>      If memory above 4G is preferred, crashkernel=size,high can be used to
>      fulfill that. With it, physical memory is allowed to be allocated from top,
> @@ -311,7 +332,7 @@ crashkernel syntax
>   
>               crashkernel=0,low
>   
> -4) crashkernel=size,cma
> +5) crashkernel=size,cma
>   
>   	Reserve additional crash kernel memory from CMA. This reservation is
>   	usable by the first system's userspace memory and kernel movable
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 03a550630644..b2e1892ab4d8 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1087,7 +1087,7 @@ Kernel parameters
>   			4G when '@offset' hasn't been specified.
>   			See Documentation/admin-guide/kdump/kdump.rst for further details.
>   
> -	crashkernel=range1:size1[,range2:size2,...][@offset]
> +	crashkernel=range1:size1[,range2:size2,...][@offset][,>boundary]
>   			[KNL] Same as above, but depends on the memory
>   			in the running system. The syntax of range is
>   			start-[end] where start and end are both
> diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c
> index 62e60e0223cf..917738412390 100644
> --- a/kernel/crash_reserve.c
> +++ b/kernel/crash_reserve.c
> @@ -254,15 +254,47 @@ static __init char *get_last_crashkernel(char *cmdline,
>   	return ck_cmdline;
>   }
>   
> +/*
> + * This function parses command lines in the format
> + *
> + *   crashkernel=ramsize-range:size[,...][@offset],>boundary
> + */
> +static void __init parse_crashkernel_boundary(char *ck_cmdline,
> +					unsigned long long *boundary)
> +{
> +	char *cur = ck_cmdline, *next;
> +	char *first_gt = false;
> +
> +	first_gt = strchr(cur, '>');
> +	if (!first_gt)
> +		return;
> +
> +	cur = first_gt + 1;
> +	if (*cur == '\0' || *cur == ' ' || *cur == ',') {
> +		pr_warn("crashkernel: '>' specified without boundary size, ignoring\n");
> +		return;
> +	}
> +
> +	*boundary = memparse(cur, &next);
> +	if (cur == next) {
> +		pr_warn("crashkernel: invalid boundary size after '>'\n");
> +		return;
> +	}
> +}
> +
>   static int __init __parse_crashkernel(char *cmdline,
>   			     unsigned long long system_ram,
>   			     unsigned long long *crash_size,
>   			     unsigned long long *crash_base,
> -			     const char *suffix)
> +			     const char *suffix,
> +			     bool *high,
> +			     unsigned long long *low_size)
>   {
>   	char *first_colon, *first_space;
>   	char *ck_cmdline;
>   	char *name = "crashkernel=";
> +	unsigned long long boundary = 0;
> +	int ret;
>   
>   	BUG_ON(!crash_size || !crash_base);
>   	*crash_size = 0;
> @@ -283,10 +315,20 @@ static int __init __parse_crashkernel(char *cmdline,
>   	 */
>   	first_colon = strchr(ck_cmdline, ':');
>   	first_space = strchr(ck_cmdline, ' ');
> -	if (first_colon && (!first_space || first_colon < first_space))
> -		return parse_crashkernel_mem(ck_cmdline, system_ram,
> +	if (first_colon && (!first_space || first_colon < first_space)) {
> +		ret = parse_crashkernel_mem(ck_cmdline, system_ram,
>   				crash_size, crash_base);
>   
> +		/* Handle optional ',>boundary' condition for range ':' syntax only. */
> +		parse_crashkernel_boundary(ck_cmdline, &boundary);
> +		if (!ret && *crash_size > boundary) {
> +			*high = true;
> +			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
> +		}
> +
> +		return ret;
> +	}
> +
>   	return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
>   }
>   
> @@ -310,7 +352,7 @@ int __init parse_crashkernel(char *cmdline,
>   
>   	/* crashkernel=X[@offset] */
>   	ret = __parse_crashkernel(cmdline, system_ram, crash_size,
> -				crash_base, NULL);
> +				crash_base, NULL, high, low_size);
>   #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
>   	/*
>   	 * If non-NULL 'high' passed in and no normal crashkernel
> @@ -318,7 +360,7 @@ int __init parse_crashkernel(char *cmdline,
>   	 */
>   	if (high && ret == -ENOENT) {
>   		ret = __parse_crashkernel(cmdline, 0, crash_size,
> -				crash_base, suffix_tbl[SUFFIX_HIGH]);
> +				crash_base, suffix_tbl[SUFFIX_HIGH], high, low_size);
>   		if (ret || !*crash_size)
>   			return -EINVAL;
>   
> @@ -327,7 +369,7 @@ int __init parse_crashkernel(char *cmdline,
>   		 * is not allowed.
>   		 */
>   		ret = __parse_crashkernel(cmdline, 0, low_size,
> -				crash_base, suffix_tbl[SUFFIX_LOW]);
> +				crash_base, suffix_tbl[SUFFIX_LOW], high, low_size);
>   		if (ret == -ENOENT) {
>   			*low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>   			ret = 0;
> @@ -344,7 +386,7 @@ int __init parse_crashkernel(char *cmdline,
>   	 */
>   	if (cma_size)
>   		__parse_crashkernel(cmdline, 0, cma_size,
> -			&cma_base, suffix_tbl[SUFFIX_CMA]);
> +			&cma_base, suffix_tbl[SUFFIX_CMA], high, low_size);
>   #endif
>   	if (!*crash_size)
>   		ret = -EINVAL;
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Baoquan He 2 months, 1 week ago
On 04/08/26 at 10:01am, Sourabh Jain wrote:
> Hello Youling,
> 
> On 04/04/26 13:11, Youling Tang wrote:
> > From: Youling Tang <tangyouling@kylinos.cn>
> > 
> > The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
> > automatic size selection based on system RAM, but it always reserves
> > from low memory. When a large crashkernel is selected, this can
> > consume most of the low memory, causing subsequent hardware
> > hotplug or drivers requiring low memory to fail due to allocation
> > failures.
> 
> 
> Support for high crashkernel reservation has been added to
> address the above problem.
> 
> However, high crashkernel reservation is not supported with
> range-based crashkernel kernel command-line arguments.
> For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
> 
> Many users, including some distributions, use range-based
> crashkernel configuration. So, adding support for high crashkernel
> reservation with range-based configuration would be useful.

Sorry for late response. And I have to say sorry because I have some
negative tendency on this change. 

We use crashkernel=xM|G and crashkernel=range1:size1[,range2:size2,...]
as default setting, so that people only need to set suggested amount
of memory. While crashkernel=,high|low is for advanced user to customize 
their crashkernel value. In that case, user knows what's high memory and
low memory, and how much is needed separately to achieve their goal, e.g
saving low memory, taking away more high memory.

To be honest, above grammers sounds simple, right? I believe both of you
know very well how complicated the current crashkernel code is. I would
suggest not letting them becomre more and more complicated by extending
the grammer further and further. Unless you meet unavoidable issue with
the existing grammer.

Here comes my question, do you meet unavoidable issue with the existing
grammer when you use crashkernel=range1:size1[,range2:size2,...] and
think it's not satisfactory, and at the same time crashkernel=,high|low
can't meet your demand either?

Thanks
Baoquan
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Youling Tang 2 months ago
Hi, Baoquan

On 4/8/26 21:32, Baoquan He wrote:
> On 04/08/26 at 10:01am, Sourabh Jain wrote:
>> Hello Youling,
>>
>> On 04/04/26 13:11, Youling Tang wrote:
>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>
>>> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
>>> automatic size selection based on system RAM, but it always reserves
>>> from low memory. When a large crashkernel is selected, this can
>>> consume most of the low memory, causing subsequent hardware
>>> hotplug or drivers requiring low memory to fail due to allocation
>>> failures.
>>
>> Support for high crashkernel reservation has been added to
>> address the above problem.
>>
>> However, high crashkernel reservation is not supported with
>> range-based crashkernel kernel command-line arguments.
>> For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
>>
>> Many users, including some distributions, use range-based
>> crashkernel configuration. So, adding support for high crashkernel
>> reservation with range-based configuration would be useful.
> Sorry for late response. And I have to say sorry because I have some
> negative tendency on this change.
>
> We use crashkernel=xM|G and crashkernel=range1:size1[,range2:size2,...]
> as default setting, so that people only need to set suggested amount
> of memory. While crashkernel=,high|low is for advanced user to customize
> their crashkernel value. In that case, user knows what's high memory and
> low memory, and how much is needed separately to achieve their goal, e.g
> saving low memory, taking away more high memory.
>
> To be honest, above grammers sounds simple, right? I believe both of you
> know very well how complicated the current crashkernel code is. I would
> suggest not letting them becomre more and more complicated by extending
> the grammer further and further. Unless you meet unavoidable issue with
> the existing grammer.
>
> Here comes my question, do you meet unavoidable issue with the existing
> grammer when you use crashkernel=range1:size1[,range2:size2,...] and
> think it's not satisfactory, and at the same time crashkernel=,high|low
> can't meet your demand either?

Yes, regular users generally don't know about high memory and low memory,
and probably don't know how much crashkernel memory should be reserved
either. They mostly just use the default crashkernel parameters configured
by the distribution.

For advanced users, the current grammar is sufficient, because
'crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary'
can definitely be replaced with 'crashkernel=size,high'.

The main purpose of this patch is to provide distributions with a more
reasonable default parameter configuration (satisfying most requirements),
without having to set different distribution default parameters for 
different
scenarios (physical machines, virtual machines) and different machine 
models.

Thanks,
Youling.
>
> Thanks
> Baoquan
>
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Baoquan He 2 months ago
On 04/09/26 at 09:55am, Youling Tang wrote:
> Hi, Baoquan
> 
> On 4/8/26 21:32, Baoquan He wrote:
> > On 04/08/26 at 10:01am, Sourabh Jain wrote:
> > > Hello Youling,
> > > 
> > > On 04/04/26 13:11, Youling Tang wrote:
> > > > From: Youling Tang <tangyouling@kylinos.cn>
> > > > 
> > > > The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
> > > > automatic size selection based on system RAM, but it always reserves
> > > > from low memory. When a large crashkernel is selected, this can
> > > > consume most of the low memory, causing subsequent hardware
> > > > hotplug or drivers requiring low memory to fail due to allocation
> > > > failures.
> > > 
> > > Support for high crashkernel reservation has been added to
> > > address the above problem.
> > > 
> > > However, high crashkernel reservation is not supported with
> > > range-based crashkernel kernel command-line arguments.
> > > For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
> > > 
> > > Many users, including some distributions, use range-based
> > > crashkernel configuration. So, adding support for high crashkernel
> > > reservation with range-based configuration would be useful.
> > Sorry for late response. And I have to say sorry because I have some
> > negative tendency on this change.
> > 
> > We use crashkernel=xM|G and crashkernel=range1:size1[,range2:size2,...]
> > as default setting, so that people only need to set suggested amount
> > of memory. While crashkernel=,high|low is for advanced user to customize
> > their crashkernel value. In that case, user knows what's high memory and
> > low memory, and how much is needed separately to achieve their goal, e.g
> > saving low memory, taking away more high memory.
> > 
> > To be honest, above grammers sounds simple, right? I believe both of you
> > know very well how complicated the current crashkernel code is. I would
> > suggest not letting them becomre more and more complicated by extending
> > the grammer further and further. Unless you meet unavoidable issue with
> > the existing grammer.
> > 
> > Here comes my question, do you meet unavoidable issue with the existing
> > grammer when you use crashkernel=range1:size1[,range2:size2,...] and
> > think it's not satisfactory, and at the same time crashkernel=,high|low
> > can't meet your demand either?
> 
> Yes, regular users generally don't know about high memory and low memory,
> and probably don't know how much crashkernel memory should be reserved
> either. They mostly just use the default crashkernel parameters configured
> by the distribution.
> 
> For advanced users, the current grammar is sufficient, because
> 'crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary'
> can definitely be replaced with 'crashkernel=size,high'.
> 
> The main purpose of this patch is to provide distributions with a more
> reasonable default parameter configuration (satisfying most requirements),
> without having to set different distribution default parameters for
> different
> scenarios (physical machines, virtual machines) and different machine
> models.

OK, do you have a concrete case? e.g in your distros, what will you set
with this patchset applied? Let's see if it can cover all cases with one
simple and satisfying parameter.
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Youling Tang 1 month, 4 weeks ago
On 4/15/26 19:29, Baoquan He wrote:

> On 04/09/26 at 09:55am, Youling Tang wrote:
>> Hi, Baoquan
>>
>> On 4/8/26 21:32, Baoquan He wrote:
>>> On 04/08/26 at 10:01am, Sourabh Jain wrote:
>>>> Hello Youling,
>>>>
>>>> On 04/04/26 13:11, Youling Tang wrote:
>>>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>>>
>>>>> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
>>>>> automatic size selection based on system RAM, but it always reserves
>>>>> from low memory. When a large crashkernel is selected, this can
>>>>> consume most of the low memory, causing subsequent hardware
>>>>> hotplug or drivers requiring low memory to fail due to allocation
>>>>> failures.
>>>> Support for high crashkernel reservation has been added to
>>>> address the above problem.
>>>>
>>>> However, high crashkernel reservation is not supported with
>>>> range-based crashkernel kernel command-line arguments.
>>>> For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
>>>>
>>>> Many users, including some distributions, use range-based
>>>> crashkernel configuration. So, adding support for high crashkernel
>>>> reservation with range-based configuration would be useful.
>>> Sorry for late response. And I have to say sorry because I have some
>>> negative tendency on this change.
>>>
>>> We use crashkernel=xM|G and crashkernel=range1:size1[,range2:size2,...]
>>> as default setting, so that people only need to set suggested amount
>>> of memory. While crashkernel=,high|low is for advanced user to customize
>>> their crashkernel value. In that case, user knows what's high memory and
>>> low memory, and how much is needed separately to achieve their goal, e.g
>>> saving low memory, taking away more high memory.
>>>
>>> To be honest, above grammers sounds simple, right? I believe both of you
>>> know very well how complicated the current crashkernel code is. I would
>>> suggest not letting them becomre more and more complicated by extending
>>> the grammer further and further. Unless you meet unavoidable issue with
>>> the existing grammer.
>>>
>>> Here comes my question, do you meet unavoidable issue with the existing
>>> grammer when you use crashkernel=range1:size1[,range2:size2,...] and
>>> think it's not satisfactory, and at the same time crashkernel=,high|low
>>> can't meet your demand either?
>> Yes, regular users generally don't know about high memory and low memory,
>> and probably don't know how much crashkernel memory should be reserved
>> either. They mostly just use the default crashkernel parameters configured
>> by the distribution.
>>
>> For advanced users, the current grammar is sufficient, because
>> 'crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary'
>> can definitely be replaced with 'crashkernel=size,high'.
>>
>> The main purpose of this patch is to provide distributions with a more
>> reasonable default parameter configuration (satisfying most requirements),
>> without having to set different distribution default parameters for
>> different
>> scenarios (physical machines, virtual machines) and different machine
>> models.
> OK, do you have a concrete case? e.g in your distros, what will you set
> with this patchset applied? Let's see if it can cover all cases with one
> simple and satisfying parameter.

For our production deployment across various hardware configurations
(physical servers, VMs with different memory sizes), I'm planning to
use the following crashkernel configuration:
crashkernel=1G-4G:256M,4G-12G:384M,12G-48G:512M,48G-128G:768M,128G-:1024M,>384M

Thanks,
Youling.
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Youling Tang 2 months, 1 week ago
Hi, Sourabh

On 4/8/26 12:31, Sourabh Jain wrote:
> Hello Youling,
>
> On 04/04/26 13:11, Youling Tang wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
>> automatic size selection based on system RAM, but it always reserves
>> from low memory. When a large crashkernel is selected, this can
>> consume most of the low memory, causing subsequent hardware
>> hotplug or drivers requiring low memory to fail due to allocation
>> failures.
>
>
> Support for high crashkernel reservation has been added to
> address the above problem.
>
> However, high crashkernel reservation is not supported with
> range-based crashkernel kernel command-line arguments.
> For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
>
> Many users, including some distributions, use range-based
> crashkernel configuration. So, adding support for high crashkernel
> reservation with range-based configuration would be useful.
>
>>
>> Add a new optional conditional suffix ",>boundary" to the crashkernel
>> range syntax. When the selected crashkernel size exceeds the specified
>> boundary, the kernel will automatically apply the same reservation
>> policy as "crashkernel=size,high" - preferring high memory first
>> and reserving the default low memory area.
>
> I think the approach to enable high crashkernel reservation
> with range-based configuration makes the crashkernel kernel
> argument more complex.
>
> If the goal is to support high crashkernel reservation with
> range-based kernel command-line arguments, how about:
>
> crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],high
>
> instead of using >boundary?

This approach defaults all reservations to high memory. For example,
0M-2G:100M on a 1GB machine reserves 100M + DEFAULT_CRASH_KERNEL_LOW_SIZE,
which wastes memory on small systems.

I prefer small reservations defaulting to low memory, while large
reservations start from high memory (with a default-sized segment
reserved in low memory). This provides better flexibility for
distributions to handle diverse system configurations.

Thanks,
Youling.
>
>>
>> Syntax:
>> crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>>
>> Example:
>>      crashkernel=2G-16G:512M,16G-:1G,>512M
>>
>> This means:
>>    - For 2G-16G RAM: reserve 512M normally
>>    - For >16G RAM: reserve 1G with high memory preference (since 1G > 
>> 512M)
>>
>> For systems with >16G RAM, 1G is selected which exceeds 512M, so it
>> will be reserved from high memory instead of consuming 1G of
>> precious low memory.
>>
>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>> ---
>>   Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
>>   .../admin-guide/kernel-parameters.txt         |  2 +-
>>   kernel/crash_reserve.c                        | 56 ++++++++++++++++---
>>   3 files changed, 73 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/kdump/kdump.rst 
>> b/Documentation/admin-guide/kdump/kdump.rst
>> index 7587caadbae1..b5ae4556e9ca 100644
>> --- a/Documentation/admin-guide/kdump/kdump.rst
>> +++ b/Documentation/admin-guide/kdump/kdump.rst
>> @@ -293,7 +293,28 @@ crashkernel syntax
>>          2) if the RAM size is between 512M and 2G (exclusive), then 
>> reserve 64M
>>          3) if the RAM size is larger than 2G, then reserve 128M
>>   -3) crashkernel=size,high and crashkernel=size,low
>> +3) range1:size1[,range2:size2,...][@offset],>boundary
>> +   Optionally, the range list can be followed by a conditional suffix
>> +   `,>boundary`. When the selected crashkernel size matches the
>> +   condition, the kernel will reserve memory using the same policy as
>> +   `crashkernel=size,high` (i.e. prefer high memory first and 
>> reserve the
>> +   default low memory area).
>> +
>> +   The syntax is::
>> +
>> + crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>> +        range=start-[end]
>> +
>> +   For example::
>> +
>> +        crashkernel=2G-16G:512M,16G-:1G,>512M
>> +
>> +   This would mean:
>> +       1) if the RAM size is between 2G and 16G (exclusive), then 
>> reserve 512M.
>> +       2) if the RAM size is larger than 16G, allocation will behave 
>> like
>> +          `crashkernel=1G,high`.
>> +
>> +4) crashkernel=size,high and crashkernel=size,low
>>        If memory above 4G is preferred, crashkernel=size,high can be 
>> used to
>>      fulfill that. With it, physical memory is allowed to be 
>> allocated from top,
>> @@ -311,7 +332,7 @@ crashkernel syntax
>>                 crashkernel=0,low
>>   -4) crashkernel=size,cma
>> +5) crashkernel=size,cma
>>         Reserve additional crash kernel memory from CMA. This 
>> reservation is
>>       usable by the first system's userspace memory and kernel movable
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
>> b/Documentation/admin-guide/kernel-parameters.txt
>> index 03a550630644..b2e1892ab4d8 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -1087,7 +1087,7 @@ Kernel parameters
>>               4G when '@offset' hasn't been specified.
>>               See Documentation/admin-guide/kdump/kdump.rst for 
>> further details.
>>   -    crashkernel=range1:size1[,range2:size2,...][@offset]
>> + crashkernel=range1:size1[,range2:size2,...][@offset][,>boundary]
>>               [KNL] Same as above, but depends on the memory
>>               in the running system. The syntax of range is
>>               start-[end] where start and end are both
>> diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c
>> index 62e60e0223cf..917738412390 100644
>> --- a/kernel/crash_reserve.c
>> +++ b/kernel/crash_reserve.c
>> @@ -254,15 +254,47 @@ static __init char *get_last_crashkernel(char 
>> *cmdline,
>>       return ck_cmdline;
>>   }
>>   +/*
>> + * This function parses command lines in the format
>> + *
>> + *   crashkernel=ramsize-range:size[,...][@offset],>boundary
>> + */
>> +static void __init parse_crashkernel_boundary(char *ck_cmdline,
>> +                    unsigned long long *boundary)
>> +{
>> +    char *cur = ck_cmdline, *next;
>> +    char *first_gt = false;
>> +
>> +    first_gt = strchr(cur, '>');
>> +    if (!first_gt)
>> +        return;
>> +
>> +    cur = first_gt + 1;
>> +    if (*cur == '\0' || *cur == ' ' || *cur == ',') {
>> +        pr_warn("crashkernel: '>' specified without boundary size, 
>> ignoring\n");
>> +        return;
>> +    }
>> +
>> +    *boundary = memparse(cur, &next);
>> +    if (cur == next) {
>> +        pr_warn("crashkernel: invalid boundary size after '>'\n");
>> +        return;
>> +    }
>> +}
>> +
>>   static int __init __parse_crashkernel(char *cmdline,
>>                    unsigned long long system_ram,
>>                    unsigned long long *crash_size,
>>                    unsigned long long *crash_base,
>> -                 const char *suffix)
>> +                 const char *suffix,
>> +                 bool *high,
>> +                 unsigned long long *low_size)
>>   {
>>       char *first_colon, *first_space;
>>       char *ck_cmdline;
>>       char *name = "crashkernel=";
>> +    unsigned long long boundary = 0;
>> +    int ret;
>>         BUG_ON(!crash_size || !crash_base);
>>       *crash_size = 0;
>> @@ -283,10 +315,20 @@ static int __init __parse_crashkernel(char 
>> *cmdline,
>>        */
>>       first_colon = strchr(ck_cmdline, ':');
>>       first_space = strchr(ck_cmdline, ' ');
>> -    if (first_colon && (!first_space || first_colon < first_space))
>> -        return parse_crashkernel_mem(ck_cmdline, system_ram,
>> +    if (first_colon && (!first_space || first_colon < first_space)) {
>> +        ret = parse_crashkernel_mem(ck_cmdline, system_ram,
>>                   crash_size, crash_base);
>>   +        /* Handle optional ',>boundary' condition for range ':' 
>> syntax only. */
>> +        parse_crashkernel_boundary(ck_cmdline, &boundary);
>> +        if (!ret && *crash_size > boundary) {
>> +            *high = true;
>> +            *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>> +        }
>> +
>> +        return ret;
>> +    }
>> +
>>       return parse_crashkernel_simple(ck_cmdline, crash_size, 
>> crash_base);
>>   }
>>   @@ -310,7 +352,7 @@ int __init parse_crashkernel(char *cmdline,
>>         /* crashkernel=X[@offset] */
>>       ret = __parse_crashkernel(cmdline, system_ram, crash_size,
>> -                crash_base, NULL);
>> +                crash_base, NULL, high, low_size);
>>   #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
>>       /*
>>        * If non-NULL 'high' passed in and no normal crashkernel
>> @@ -318,7 +360,7 @@ int __init parse_crashkernel(char *cmdline,
>>        */
>>       if (high && ret == -ENOENT) {
>>           ret = __parse_crashkernel(cmdline, 0, crash_size,
>> -                crash_base, suffix_tbl[SUFFIX_HIGH]);
>> +                crash_base, suffix_tbl[SUFFIX_HIGH], high, low_size);
>>           if (ret || !*crash_size)
>>               return -EINVAL;
>>   @@ -327,7 +369,7 @@ int __init parse_crashkernel(char *cmdline,
>>            * is not allowed.
>>            */
>>           ret = __parse_crashkernel(cmdline, 0, low_size,
>> -                crash_base, suffix_tbl[SUFFIX_LOW]);
>> +                crash_base, suffix_tbl[SUFFIX_LOW], high, low_size);
>>           if (ret == -ENOENT) {
>>               *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>>               ret = 0;
>> @@ -344,7 +386,7 @@ int __init parse_crashkernel(char *cmdline,
>>        */
>>       if (cma_size)
>>           __parse_crashkernel(cmdline, 0, cma_size,
>> -            &cma_base, suffix_tbl[SUFFIX_CMA]);
>> +            &cma_base, suffix_tbl[SUFFIX_CMA], high, low_size);
>>   #endif
>>       if (!*crash_size)
>>           ret = -EINVAL;
>
Re: [PATCH] crash: Support high memory reservation for range syntax
Posted by Sourabh Jain 2 months, 1 week ago

On 08/04/26 13:11, Youling Tang wrote:
> Hi, Sourabh
>
> On 4/8/26 12:31, Sourabh Jain wrote:
>> Hello Youling,
>>
>> On 04/04/26 13:11, Youling Tang wrote:
>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>
>>> The crashkernel range syntax (range1:size1[,range2:size2,...]) allows
>>> automatic size selection based on system RAM, but it always reserves
>>> from low memory. When a large crashkernel is selected, this can
>>> consume most of the low memory, causing subsequent hardware
>>> hotplug or drivers requiring low memory to fail due to allocation
>>> failures.
>>
>>
>> Support for high crashkernel reservation has been added to
>> address the above problem.
>>
>> However, high crashkernel reservation is not supported with
>> range-based crashkernel kernel command-line arguments.
>> For example: crashkernel=0M-1G:100M,1G-4G:160M,4G-8G:192M
>>
>> Many users, including some distributions, use range-based
>> crashkernel configuration. So, adding support for high crashkernel
>> reservation with range-based configuration would be useful.
>>
>>>
>>> Add a new optional conditional suffix ",>boundary" to the crashkernel
>>> range syntax. When the selected crashkernel size exceeds the specified
>>> boundary, the kernel will automatically apply the same reservation
>>> policy as "crashkernel=size,high" - preferring high memory first
>>> and reserving the default low memory area.
>>
>> I think the approach to enable high crashkernel reservation
>> with range-based configuration makes the crashkernel kernel
>> argument more complex.
>>
>> If the goal is to support high crashkernel reservation with
>> range-based kernel command-line arguments, how about:
>>
>> crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],high
>>
>> instead of using >boundary?
>
> This approach defaults all reservations to high memory. For example,
> 0M-2G:100M on a 1GB machine reserves 100M + 
> DEFAULT_CRASH_KERNEL_LOW_SIZE,
> which wastes memory on small systems.

OK, in that case, we need an option like >boundary because
DEFAULT_CRASH_KERNEL_LOW_SIZE itself is 128 MB by default
(unless the architecture overrides it).

- Sourabh Jain

>
> I prefer small reservations defaulting to low memory, while large
> reservations start from high memory (with a default-sized segment
> reserved in low memory). This provides better flexibility for
> distributions to handle diverse system configurations.
>
> Thanks,
> Youling.
>>
>>>
>>> Syntax:
>>> crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>>>
>>> Example:
>>>      crashkernel=2G-16G:512M,16G-:1G,>512M
>>>
>>> This means:
>>>    - For 2G-16G RAM: reserve 512M normally
>>>    - For >16G RAM: reserve 1G with high memory preference (since 1G 
>>> > 512M)
>>>
>>> For systems with >16G RAM, 1G is selected which exceeds 512M, so it
>>> will be reserved from high memory instead of consuming 1G of
>>> precious low memory.
>>>
>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>> ---
>>>   Documentation/admin-guide/kdump/kdump.rst     | 25 ++++++++-
>>>   .../admin-guide/kernel-parameters.txt         |  2 +-
>>>   kernel/crash_reserve.c                        | 56 
>>> ++++++++++++++++---
>>>   3 files changed, 73 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/Documentation/admin-guide/kdump/kdump.rst 
>>> b/Documentation/admin-guide/kdump/kdump.rst
>>> index 7587caadbae1..b5ae4556e9ca 100644
>>> --- a/Documentation/admin-guide/kdump/kdump.rst
>>> +++ b/Documentation/admin-guide/kdump/kdump.rst
>>> @@ -293,7 +293,28 @@ crashkernel syntax
>>>          2) if the RAM size is between 512M and 2G (exclusive), then 
>>> reserve 64M
>>>          3) if the RAM size is larger than 2G, then reserve 128M
>>>   -3) crashkernel=size,high and crashkernel=size,low
>>> +3) range1:size1[,range2:size2,...][@offset],>boundary
>>> +   Optionally, the range list can be followed by a conditional suffix
>>> +   `,>boundary`. When the selected crashkernel size matches the
>>> +   condition, the kernel will reserve memory using the same policy as
>>> +   `crashkernel=size,high` (i.e. prefer high memory first and 
>>> reserve the
>>> +   default low memory area).
>>> +
>>> +   The syntax is::
>>> +
>>> + crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset],>boundary
>>> +        range=start-[end]
>>> +
>>> +   For example::
>>> +
>>> +        crashkernel=2G-16G:512M,16G-:1G,>512M
>>> +
>>> +   This would mean:
>>> +       1) if the RAM size is between 2G and 16G (exclusive), then 
>>> reserve 512M.
>>> +       2) if the RAM size is larger than 16G, allocation will 
>>> behave like
>>> +          `crashkernel=1G,high`.
>>> +
>>> +4) crashkernel=size,high and crashkernel=size,low
>>>        If memory above 4G is preferred, crashkernel=size,high can be 
>>> used to
>>>      fulfill that. With it, physical memory is allowed to be 
>>> allocated from top,
>>> @@ -311,7 +332,7 @@ crashkernel syntax
>>>                 crashkernel=0,low
>>>   -4) crashkernel=size,cma
>>> +5) crashkernel=size,cma
>>>         Reserve additional crash kernel memory from CMA. This 
>>> reservation is
>>>       usable by the first system's userspace memory and kernel movable
>>> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
>>> b/Documentation/admin-guide/kernel-parameters.txt
>>> index 03a550630644..b2e1892ab4d8 100644
>>> --- a/Documentation/admin-guide/kernel-parameters.txt
>>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>>> @@ -1087,7 +1087,7 @@ Kernel parameters
>>>               4G when '@offset' hasn't been specified.
>>>               See Documentation/admin-guide/kdump/kdump.rst for 
>>> further details.
>>>   -    crashkernel=range1:size1[,range2:size2,...][@offset]
>>> + crashkernel=range1:size1[,range2:size2,...][@offset][,>boundary]
>>>               [KNL] Same as above, but depends on the memory
>>>               in the running system. The syntax of range is
>>>               start-[end] where start and end are both
>>> diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c
>>> index 62e60e0223cf..917738412390 100644
>>> --- a/kernel/crash_reserve.c
>>> +++ b/kernel/crash_reserve.c
>>> @@ -254,15 +254,47 @@ static __init char *get_last_crashkernel(char 
>>> *cmdline,
>>>       return ck_cmdline;
>>>   }
>>>   +/*
>>> + * This function parses command lines in the format
>>> + *
>>> + * crashkernel=ramsize-range:size[,...][@offset],>boundary
>>> + */
>>> +static void __init parse_crashkernel_boundary(char *ck_cmdline,
>>> +                    unsigned long long *boundary)
>>> +{
>>> +    char *cur = ck_cmdline, *next;
>>> +    char *first_gt = false;
>>> +
>>> +    first_gt = strchr(cur, '>');
>>> +    if (!first_gt)
>>> +        return;
>>> +
>>> +    cur = first_gt + 1;
>>> +    if (*cur == '\0' || *cur == ' ' || *cur == ',') {
>>> +        pr_warn("crashkernel: '>' specified without boundary size, 
>>> ignoring\n");
>>> +        return;
>>> +    }
>>> +
>>> +    *boundary = memparse(cur, &next);
>>> +    if (cur == next) {
>>> +        pr_warn("crashkernel: invalid boundary size after '>'\n");
>>> +        return;
>>> +    }
>>> +}
>>> +
>>>   static int __init __parse_crashkernel(char *cmdline,
>>>                    unsigned long long system_ram,
>>>                    unsigned long long *crash_size,
>>>                    unsigned long long *crash_base,
>>> -                 const char *suffix)
>>> +                 const char *suffix,
>>> +                 bool *high,
>>> +                 unsigned long long *low_size)
>>>   {
>>>       char *first_colon, *first_space;
>>>       char *ck_cmdline;
>>>       char *name = "crashkernel=";
>>> +    unsigned long long boundary = 0;
>>> +    int ret;
>>>         BUG_ON(!crash_size || !crash_base);
>>>       *crash_size = 0;
>>> @@ -283,10 +315,20 @@ static int __init __parse_crashkernel(char 
>>> *cmdline,
>>>        */
>>>       first_colon = strchr(ck_cmdline, ':');
>>>       first_space = strchr(ck_cmdline, ' ');
>>> -    if (first_colon && (!first_space || first_colon < first_space))
>>> -        return parse_crashkernel_mem(ck_cmdline, system_ram,
>>> +    if (first_colon && (!first_space || first_colon < first_space)) {
>>> +        ret = parse_crashkernel_mem(ck_cmdline, system_ram,
>>>                   crash_size, crash_base);
>>>   +        /* Handle optional ',>boundary' condition for range ':' 
>>> syntax only. */
>>> +        parse_crashkernel_boundary(ck_cmdline, &boundary);
>>> +        if (!ret && *crash_size > boundary) {
>>> +            *high = true;
>>> +            *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>>> +        }
>>> +
>>> +        return ret;
>>> +    }
>>> +
>>>       return parse_crashkernel_simple(ck_cmdline, crash_size, 
>>> crash_base);
>>>   }
>>>   @@ -310,7 +352,7 @@ int __init parse_crashkernel(char *cmdline,
>>>         /* crashkernel=X[@offset] */
>>>       ret = __parse_crashkernel(cmdline, system_ram, crash_size,
>>> -                crash_base, NULL);
>>> +                crash_base, NULL, high, low_size);
>>>   #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
>>>       /*
>>>        * If non-NULL 'high' passed in and no normal crashkernel
>>> @@ -318,7 +360,7 @@ int __init parse_crashkernel(char *cmdline,
>>>        */
>>>       if (high && ret == -ENOENT) {
>>>           ret = __parse_crashkernel(cmdline, 0, crash_size,
>>> -                crash_base, suffix_tbl[SUFFIX_HIGH]);
>>> +                crash_base, suffix_tbl[SUFFIX_HIGH], high, low_size);
>>>           if (ret || !*crash_size)
>>>               return -EINVAL;
>>>   @@ -327,7 +369,7 @@ int __init parse_crashkernel(char *cmdline,
>>>            * is not allowed.
>>>            */
>>>           ret = __parse_crashkernel(cmdline, 0, low_size,
>>> -                crash_base, suffix_tbl[SUFFIX_LOW]);
>>> +                crash_base, suffix_tbl[SUFFIX_LOW], high, low_size);
>>>           if (ret == -ENOENT) {
>>>               *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
>>>               ret = 0;
>>> @@ -344,7 +386,7 @@ int __init parse_crashkernel(char *cmdline,
>>>        */
>>>       if (cma_size)
>>>           __parse_crashkernel(cmdline, 0, cma_size,
>>> -            &cma_base, suffix_tbl[SUFFIX_CMA]);
>>> +            &cma_base, suffix_tbl[SUFFIX_CMA], high, low_size);
>>>   #endif
>>>       if (!*crash_size)
>>>           ret = -EINVAL;
>>