Skip to contentSkip to conversation

kdump: round up the total memory size to 128M for crashkernel reservation

PATCH In review [email protected] 2 participants 5 messages Oct 24, 2017 – Nov 3, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 3/3 kdump: round up the total memory size to 128M for crashkernel reservation

The total memory size we get in kernel is usually slightly less than 2G with a 2G memory module machine. The main reason is bios/firmware reserve some area it will not export all memory as usable to Linux.

2G memory X86 kvm guest test result of the total_mem value:
UEFI boot with ovmf: 0x7ef10000
Legacy boot kvm guest: 0x7ff7cc00

An option is to use dmi/smbios to get physical memory size, but it's not reliable as well. According to Prarit hardware vendors sometimes screw this up. Thus we choose to round up total size to 128M to workaround this problem. This is a best effort workaround, will improve it when we have better way in the future.

---
 kernel/crash_core.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/crash_core.c +13 -4
@@ -42,6 +42,15 @@ static int __init parse_crashkernel_mem(
 {
 	char *cur = cmdline, *tmp;
 	bool infinite_end = false;
+	unsigned long long total_mem = system_ram;
+
+	/*
+	 * Firmware usually reserves some memory regions for it's own use.
+	 * so we get less than actual system memory size.
+	 * We workaround this by round up the total size to 128M which is
+	 * enough for most test cases.
+	 */
+	total_mem = roundup(total_mem, 0x8000000);
 
 	/* for each entry of the comma-separated list */
 	do {
@@ -86,13 +95,13 @@ static int __init parse_crashkernel_mem(
 			return -EINVAL;
 		}
 		cur = tmp;
-		if (size >= system_ram) {
+		if (size >= total_mem) {
 			pr_warn("crashkernel: invalid size\n");
 			return -EINVAL;
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram < end) {
+		if (total_mem >= start && total_mem < end) {
 			*crash_size = size;
 			if (end == ULLONG_MAX)
 				infinite_end = true;
@@ -126,9 +135,9 @@ static int __init parse_crashkernel_mem(
 				pr_warn("Memory reservation scale order expected after '^'\n");
 				return -EINVAL;
 			}
-			size = (system_ram - *crash_size) >> shift;
+			size = (total_mem - *crash_size) >> shift;
 			size = *crash_size + roundup(size, 1ULL << 20);
-			if (size < system_ram)
+			if (size < total_mem)
 				*crash_size = size;
 			cur = tmp;
 		} else
#1 lore raw

Hi Dave,

Quoted 8 lines · Dave Young

The total memory size we get in kernel is usually slightly less than 2G with a 2G memory module machine. The main reason is bios/firmware reserve some area it will not export all memory as usable to Linux.

2G memory X86 kvm guest test result of the total_mem value:
UEFI boot with ovmf: 0x7ef10000
Legacy boot kvm guest: 0x7ff7cc00

Quoted 5 lines

An option is to use dmi/smbios to get physical memory size, but it's not reliable as well. According to Prarit hardware vendors sometimes screw this up. Thus we choose to round up total size to 128M to workaround this problem. This is a best effort workaround, will improve it when we have better way in the future.

Thanks for this posting. While I don't get the point of this patch. So firmware take piece of memory, then why we need to count it into the total memory which we want to calculate a crashkernel memory based on.

Not counting that, is there anyting incorrect?

Thanks
Baoquan

Quoted 54 lines
---
 kernel/crash_core.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/crash_core.c +13 -4
@@ -42,6 +42,15 @@ static int __init parse_crashkernel_mem(
 {
 	char *cur = cmdline, *tmp;
 	bool infinite_end = false;
+	unsigned long long total_mem = system_ram;
+
+	/*
+	 * Firmware usually reserves some memory regions for it's own use.
+	 * so we get less than actual system memory size.
+	 * We workaround this by round up the total size to 128M which is
+	 * enough for most test cases.
+	 */
+	total_mem = roundup(total_mem, 0x8000000);
 
 	/* for each entry of the comma-separated list */
 	do {
@@ -86,13 +95,13 @@ static int __init parse_crashkernel_mem(
 			return -EINVAL;
 		}
 		cur = tmp;
-		if (size >= system_ram) {
+		if (size >= total_mem) {
 			pr_warn("crashkernel: invalid size\n");
 			return -EINVAL;
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram < end) {
+		if (total_mem >= start && total_mem < end) {
 			*crash_size = size;
 			if (end == ULLONG_MAX)
 				infinite_end = true;
@@ -126,9 +135,9 @@ static int __init parse_crashkernel_mem(
 				pr_warn("Memory reservation scale order expected after '^'\n");
 				return -EINVAL;
 			}
-			size = (system_ram - *crash_size) >> shift;
+			size = (total_mem - *crash_size) >> shift;
 			size = *crash_size + roundup(size, 1ULL << 20);
-			if (size < system_ram)
+			if (size < total_mem)
 				*crash_size = size;
 			cur = tmp;
 		} else
author
#2 lore raw

Hi Baoquan,

Quoted 17 lines · Baoquan He

Hi Dave,

Quoted 8 lines · Dave Young

The total memory size we get in kernel is usually slightly less than 2G with a 2G memory module machine. The main reason is bios/firmware reserve some area it will not export all memory as usable to Linux.

2G memory X86 kvm guest test result of the total_mem value:
UEFI boot with ovmf: 0x7ef10000
Legacy boot kvm guest: 0x7ff7cc00

Quoted 5 lines

An option is to use dmi/smbios to get physical memory size, but it's not reliable as well. According to Prarit hardware vendors sometimes screw this up. Thus we choose to round up total size to 128M to workaround this problem. This is a best effort workaround, will improve it when we have better way in the future.

Quoted 5 lines

Thanks for this posting. While I don't get the point of this patch. So firmware take piece of memory, then why we need to count it into the total memory which we want to calculate a crashkernel memory based on.

Not counting that, is there anyting incorrect?

Yes, considering crashkernel=1G-2G:128M, if we have a 1G memory machine, we get total size 1023M from firmware then it will not fall into 1G-2G thus no memory reserved. User will never know that, it is hard to let user to know the exact total value we get in kernel..

Quoted 50 lines

Thanks
Baoquan

Quoted 46 lines
---
 kernel/crash_core.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/crash_core.c +12 -3
@@ -42,6 +42,15 @@ static int __init parse_crashkernel_mem(
 {
 	char *cur = cmdline, *tmp;
 	bool infinite_end = false;
+	unsigned long long total_mem = system_ram;
+
+	/*
+	 * Firmware usually reserves some memory regions for it's own use.
+	 * so we get less than actual system memory size.
+	 * We workaround this by round up the total size to 128M which is
+	 * enough for most test cases.
+	 */
+	total_mem = roundup(total_mem, 0x8000000);
 
 	/* for each entry of the comma-separated list */
 	do {
@@ -86,13 +95,13 @@ static int __init parse_crashkernel_mem(
 			return -EINVAL;
 		}
 		cur = tmp;
-		if (size >= system_ram) {
+		if (size >= total_mem) {
 			pr_warn("crashkernel: invalid size\n");
 			return -EINVAL;
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram < end) {
+		if (total_mem >= start && total_mem < end) {
 			*crash_size = size;
 			if (end == ULLONG_MAX)
 				infinite_end = true;
@@ -126,9 +135,9 @@ static int __init parse_crashkernel_mem(
 				pr_warn("Memory reservation scale order expected after '^'\n");
 				return -EINVAL;
 			}
-			size = (system_ram - *crash_size) >> shift;
+			size = (total_mem - *crash_size) >> shift;
Quoted 8 lines

kernel/crash_core.c static int __init parse_crashkernel_mem( · line 143

Quoted 8 lines
kernel/crash_core.c +1 -1
 			size = *crash_size + roundup(size, 1ULL << 20);
-			if (size < system_ram)
+			if (size < total_mem)
 				*crash_size = size;
 			cur = tmp;
 		} else

Thanks
Dave

#3 lore raw
Quoted 24 lines · Dave Young

Hi Baoquan,

Quoted 21 lines · Baoquan He

Hi Dave,

Quoted 8 lines · Dave Young

The total memory size we get in kernel is usually slightly less than 2G with a 2G memory module machine. The main reason is bios/firmware reserve some area it will not export all memory as usable to Linux.

2G memory X86 kvm guest test result of the total_mem value:
UEFI boot with ovmf: 0x7ef10000
Legacy boot kvm guest: 0x7ff7cc00

Quoted 5 lines

An option is to use dmi/smbios to get physical memory size, but it's not reliable as well. According to Prarit hardware vendors sometimes screw this up. Thus we choose to round up total size to 128M to workaround this problem. This is a best effort workaround, will improve it when we have better way in the future.

Thanks for this posting. While I don't get the point of this patch. So firmware take piece of memory, then why we need to count it into the total memory which we want to calculate a crashkernel memory based on.

Quoted 6 lines
Quoted 1 line

Not counting that, is there anyting incorrect?

Yes, considering crashkernel=1G-2G:128M, if we have a 1G memory machine, we get total size 1023M from firmware then it will not fall into 1G-2G thus no memory reserved. User will never know that, it is hard to let user to know the exact total value we get in kernel..

OK, got it. Thanks.

Then I have no objection to this. See what other reviewers will say.

Thanks
Baoquan

Quoted 58 lines
Quoted 47 lines
Quoted 47 lines
---
 kernel/crash_core.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/crash_core.c +12 -3
@@ -42,6 +42,15 @@ static int __init parse_crashkernel_mem(
 {
 	char *cur = cmdline, *tmp;
 	bool infinite_end = false;
+	unsigned long long total_mem = system_ram;
+
+	/*
+	 * Firmware usually reserves some memory regions for it's own use.
+	 * so we get less than actual system memory size.
+	 * We workaround this by round up the total size to 128M which is
+	 * enough for most test cases.
+	 */
+	total_mem = roundup(total_mem, 0x8000000);
 
 	/* for each entry of the comma-separated list */
 	do {
@@ -86,13 +95,13 @@ static int __init parse_crashkernel_mem(
 			return -EINVAL;
 		}
 		cur = tmp;
-		if (size >= system_ram) {
+		if (size >= total_mem) {
 			pr_warn("crashkernel: invalid size\n");
 			return -EINVAL;
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram < end) {
+		if (total_mem >= start && total_mem < end) {
 			*crash_size = size;
 			if (end == ULLONG_MAX)
 				infinite_end = true;
@@ -126,9 +135,9 @@ static int __init parse_crashkernel_mem(
 				pr_warn("Memory reservation scale order expected after '^'\n");
 				return -EINVAL;
 			}
-			size = (system_ram - *crash_size) >> shift;
+			size = (total_mem - *crash_size) >> shift;
Quoted 8 lines

kernel/crash_core.c static int __init parse_crashkernel_mem( · line 143

Quoted 8 lines
kernel/crash_core.c +1 -1
 			size = *crash_size + roundup(size, 1ULL << 20);
-			if (size < system_ram)
+			if (size < total_mem)
 				*crash_size = size;
 			cur = tmp;
 		} else

Thanks
Dave

author
#4 lore raw

PATCH 3/3 kdump: round up the total memory size to 128M for crashkernel reservation

In reply to [email protected]

The total memory size we get in kernel is usually slightly less than 2G with a 2G memory module machine. The main reason is bios/firmware reserve some area it will not export all memory as usable to Linux.

2G memory X86 kvm guest test result of the total_mem value:
UEFI boot with ovmf: 0x7ef10000
Legacy boot kvm guest: 0x7ff7cc00
This is also a problem on arm64 UEFI booted system according to my test.

Thus for example crashkernel=1G-2G:128M, if we have a 1G memory machine, we get total size 1023M from firmware then it will not fall into 1G-2G thus no memory reserved.

An option is to use dmi/smbios to get physical memory size, but it's not reliable as well. According to Prarit hardware vendors sometimes screw this up. Thus round up total size to 128M to workaround this problem.

---
Changes from previous version of 3/3:
1. improve changelog: add examples why this is a problem (comment from Baoquan He)
2. change to use SZ_128M (comment from Bhupesh Sharma)

 kernel/crash_core.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
kernel/crash_core.c +14 -4
@@ -9,6 +9,7 @@
 #include <linux/crash_core.h>
 #include <linux/utsname.h>
 #include <linux/vmalloc.h>
+#include <linux/sizes.h>
 
 #include <asm/page.h>
 #include <asm/sections.h>
@@ -42,6 +43,15 @@ static int __init parse_crashkernel_mem(
 {
 	char *cur = cmdline, *tmp;
 	bool infinite_end = false;
+	unsigned long long total_mem = system_ram;
+
+	/*
+	 * Firmware usually reserves some memory regions for it's own use.
+	 * so we get less than actual system memory size.
+	 * We workaround this by round up the total size to 128M which is
+	 * enough for most test cases.
+	 */
+	total_mem = roundup(total_mem, SZ_128M);
 
 	/* for each entry of the comma-separated list */
 	do {
@@ -86,13 +96,13 @@ static int __init parse_crashkernel_mem(
 			return -EINVAL;
 		}
 		cur = tmp;
-		if (size >= system_ram) {
+		if (size >= total_mem) {
 			pr_warn("crashkernel: invalid size\n");
 			return -EINVAL;
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram < end) {
+		if (total_mem >= start && total_mem < end) {
 			*crash_size = size;
 			if (end == ULLONG_MAX)
 				infinite_end = true;
@@ -126,9 +136,9 @@ static int __init parse_crashkernel_mem(
 				pr_warn("Memory reservation scale order expected after '^'\n");
 				return -EINVAL;
 			}
-			size = (system_ram - *crash_size) >> shift;
+			size = (total_mem - *crash_size) >> shift;
 			size = *crash_size + roundup(size, 1ULL << 20);
-			if (size < system_ram)
+			if (size < total_mem)
 				*crash_size = size;
 			cur = tmp;
 		} else