linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
@ 2019-04-02  4:10 Pingfan Liu
  2019-04-02  6:19 ` Chao Fan
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Pingfan Liu @ 2019-04-02  4:10 UTC (permalink / raw)
  To: x86
  Cc: Pingfan Liu, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Baoquan He, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, linux-kernel

crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
fail to reserve the required memory region if KASLR puts kernel into the
region. To avoid this uncertainty, asking KASLR to skip the required
region.

Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Pingfan Liu <kernelfans@gmail.com>
Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: linux-kernel@vger.kernel.org
---
v2 -> v3: adding parsing of crashkernel=range1:size1[,range2:size2,...]@offset

 arch/x86/boot/compressed/kaslr.c | 116 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 114 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 2e53c05..7f698f4 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -107,6 +107,7 @@ enum mem_avoid_index {
 	MEM_AVOID_BOOTPARAMS,
 	MEM_AVOID_MEMMAP_BEGIN,
 	MEM_AVOID_MEMMAP_END = MEM_AVOID_MEMMAP_BEGIN + MAX_MEMMAP_REGIONS - 1,
+	MEM_AVOID_CRASHKERNEL,
 	MEM_AVOID_MAX,
 };
 
@@ -238,6 +239,115 @@ static void parse_gb_huge_pages(char *param, char *val)
 	}
 }
 
+/* code heavily copied from parse_crashkernel_mem() */
+static void handle_crashkernel_mem(char *cmdline,
+					unsigned long long system_ram,
+					unsigned long long *crash_size,
+					unsigned long long *crash_base)
+{
+	char *tmp, *cur = cmdline;
+
+	/* for each entry of the comma-separated list */
+	do {
+		unsigned long long start, end = ULLONG_MAX, size;
+
+		/* get the start of the range */
+		start = memparse(cur, &tmp);
+		/* no value given */
+		if (cur == tmp)
+			return;
+		cur = tmp;
+		if (*cur != '-')
+			return;
+		cur++;
+
+		/* if no ':' is here, than we read the end */
+		if (*cur != ':') {
+			end = memparse(cur, &tmp);
+			/* no value given */
+			if (cur == tmp)
+				return;
+			cur = tmp;
+			/* invalid if crashkernel end <= start */
+			if (end <= start)
+				return;
+		}
+		/* expect ":" after range */
+		if (*cur != ':')
+			return;
+		cur++;
+
+		size = memparse(cur, &tmp);
+		/* no size value given */
+		if (cur == tmp)
+			return;
+		cur = tmp;
+		if (size >= system_ram)
+			return;
+
+		/* match ? */
+		if (system_ram >= start && system_ram < end) {
+			*crash_size = size;
+			break;
+		}
+	} while (*cur++ == ',');
+
+	if (*crash_size > 0) {
+		while (*cur && *cur != ' ' && *cur != '@')
+			cur++;
+		if (*cur == '@') {
+			cur++;
+			*crash_base = memparse(cur, &tmp);
+		}
+	}
+}
+
+/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
+static void mem_avoid_specified_crashkernel_region(char *option)
+{
+	unsigned long long crash_size, crash_base = 0;
+	char	*first_colon, *first_space, *cur = option;
+
+	first_colon = strchr(option, ':');
+	first_space = strchr(option, ' ');
+	/* if contain ":" */
+	if (first_colon && (!first_space || first_colon < first_space)) {
+		int i;
+		u64 total_sz = 0;
+		struct boot_e820_entry *entry;
+
+		for (i = 0; i < boot_params->e820_entries; i++) {
+			entry = &boot_params->e820_table[i];
+			/* Skip non-RAM entries. */
+			if (entry->type != E820_TYPE_RAM)
+				continue;
+			total_sz += entry->size;
+		}
+		handle_crashkernel_mem(option, total_sz, &crash_size,
+			&crash_base);
+	} else {
+		crash_size = memparse(option, &cur);
+		if (option == cur)
+			return;
+		while (*cur && *cur != ' ' && *cur != '@')
+			cur++;
+		if (*cur == '@') {
+			option = cur + 1;
+			crash_base = memparse(option, &cur);
+		}
+	}
+	if (crash_base) {
+		mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
+		mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
+	} else {
+		/*
+ 		 * Clearing mem_avoid if no offset is given. This is consistent
+ 		 * with kernel, which uses the last crashkernel= option.
+		 */
+		mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
+		mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
+	}
+}
 
 static void handle_mem_options(void)
 {
@@ -248,7 +358,7 @@ static void handle_mem_options(void)
 	u64 mem_size;
 
 	if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
-		!strstr(args, "hugepages"))
+		!strstr(args, "hugepages") && !strstr(args, "crashkernel="))
 		return;
 
 	tmp_cmdline = malloc(len + 1);
@@ -284,6 +394,8 @@ static void handle_mem_options(void)
 				goto out;
 
 			mem_limit = mem_size;
+		} else if (strstr(param, "crashkernel")) {
+			mem_avoid_specified_crashkernel_region(val);
 		}
 	}
 
@@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 
 	/* We don't need to set a mapping for setup_data. */
 
-	/* Mark the memmap regions we need to avoid */
+	/* Mark the regions we need to avoid */
 	handle_mem_options();
 
 	/* Enumerate the immovable memory regions */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  4:10 [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region Pingfan Liu
@ 2019-04-02  6:19 ` Chao Fan
  2019-04-02  6:52   ` Baoquan He
  2019-04-02  6:58   ` Pingfan Liu
  2019-04-02  6:46 ` Baoquan He
  2019-04-02  8:08 ` Baoquan He
  2 siblings, 2 replies; 11+ messages in thread
From: Chao Fan @ 2019-04-02  6:19 UTC (permalink / raw)
  To: Pingfan Liu
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Baoquan He, Will Deacon, Nicolas Pitre,
	Kirill A. Shutemov, Ard Biesheuvel, linux-kernel

On Tue, Apr 02, 2019 at 12:10:46PM +0800, Pingfan Liu wrote:
>crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
or or?
>fail to reserve the required memory region if KASLR puts kernel into the
>region. To avoid this uncertainty, asking KASLR to skip the required
>region.
>
>Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
>Cc: Thomas Gleixner <tglx@linutronix.de>
>Cc: Ingo Molnar <mingo@redhat.com>
>Cc: Borislav Petkov <bp@alien8.de>
>Cc: "H. Peter Anvin" <hpa@zytor.com>
>Cc: Baoquan He <bhe@redhat.com>
>Cc: Will Deacon <will.deacon@arm.com>
>Cc: Nicolas Pitre <nico@linaro.org>
>Cc: Pingfan Liu <kernelfans@gmail.com>
>Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
>Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
>Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>Cc: linux-kernel@vger.kernel.org
>---
[...]
>+
>+/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */

Before review, I want to say more about the background.
It's very hard to review the code for someone who is not so familiar
with kdump, so could you please explain more ahout
the uasge of crashkernel=range1:size1[,range2:size2,...]@offset.
And also there are so many jobs who are parsing string. So I really
need your help to understand the PATCH.

>+static void mem_avoid_specified_crashkernel_region(char *option)
>+{
>+	unsigned long long crash_size, crash_base = 0;
>+	char	*first_colon, *first_space, *cur = option;
Is there a tab after char?
>+
>+	first_colon = strchr(option, ':');
>+	first_space = strchr(option, ' ');
>+	/* if contain ":" */
>+	if (first_colon && (!first_space || first_colon < first_space)) {
>+		int i;
>+		u64 total_sz = 0;
>+		struct boot_e820_entry *entry;
>+
>+		for (i = 0; i < boot_params->e820_entries; i++) {
>+			entry = &boot_params->e820_table[i];
>+			/* Skip non-RAM entries. */
>+			if (entry->type != E820_TYPE_RAM)
>+				continue;
>+			total_sz += entry->size;
I wonder whether it's needed to consider the memory ranges here.
I think it's OK to only record the regions should to be avoid.
I remeber I ever talked with Baoquan about the similiar problems.
@Baoquan, I am not sure if I misunderstand something.

Thanks,
Chao Fan
>+		}
>+		handle_crashkernel_mem(option, total_sz, &crash_size,
>+			&crash_base);
>+	} else {
>+		crash_size = memparse(option, &cur);
>+		if (option == cur)
>+			return;
>+		while (*cur && *cur != ' ' && *cur != '@')
>+			cur++;
>+		if (*cur == '@') {
>+			option = cur + 1;
>+			crash_base = memparse(option, &cur);
>+		}
>+	}
>+	if (crash_base) {
>+		mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
>+		mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
>+	} else {
>+		/*
>+ 		 * Clearing mem_avoid if no offset is given. This is consistent
>+ 		 * with kernel, which uses the last crashkernel= option.
>+		 */
>+		mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
>+		mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
>+	}
>+}
> 
> static void handle_mem_options(void)
> {
>@@ -248,7 +358,7 @@ static void handle_mem_options(void)
> 	u64 mem_size;
> 
> 	if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
>-		!strstr(args, "hugepages"))
>+		!strstr(args, "hugepages") && !strstr(args, "crashkernel="))
> 		return;
> 
> 	tmp_cmdline = malloc(len + 1);
>@@ -284,6 +394,8 @@ static void handle_mem_options(void)
> 				goto out;
> 
> 			mem_limit = mem_size;
>+		} else if (strstr(param, "crashkernel")) {
>+			mem_avoid_specified_crashkernel_region(val);
> 		}
> 	}
> 
>@@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
> 
> 	/* We don't need to set a mapping for setup_data. */
> 
>-	/* Mark the memmap regions we need to avoid */
>+	/* Mark the regions we need to avoid */
> 	handle_mem_options();
> 
> 	/* Enumerate the immovable memory regions */
>-- 
>2.7.4
>
>
>



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  4:10 [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region Pingfan Liu
  2019-04-02  6:19 ` Chao Fan
@ 2019-04-02  6:46 ` Baoquan He
  2019-04-03  2:59   ` Pingfan Liu
  2019-04-02  8:08 ` Baoquan He
  2 siblings, 1 reply; 11+ messages in thread
From: Baoquan He @ 2019-04-02  6:46 UTC (permalink / raw)
  To: Pingfan Liu
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, linux-kernel

On 04/02/19 at 12:10pm, Pingfan Liu wrote:
> crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
> fail to reserve the required memory region if KASLR puts kernel into the
> region. To avoid this uncertainty, asking KASLR to skip the required
> region.
> 
> Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Nicolas Pitre <nico@linaro.org>
> Cc: Pingfan Liu <kernelfans@gmail.com>
> Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: linux-kernel@vger.kernel.org
> ---
> v2 -> v3: adding parsing of crashkernel=range1:size1[,range2:size2,...]@offset
> 
>  arch/x86/boot/compressed/kaslr.c | 116 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 114 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
> index 2e53c05..7f698f4 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -107,6 +107,7 @@ enum mem_avoid_index {
>  	MEM_AVOID_BOOTPARAMS,
>  	MEM_AVOID_MEMMAP_BEGIN,
>  	MEM_AVOID_MEMMAP_END = MEM_AVOID_MEMMAP_BEGIN + MAX_MEMMAP_REGIONS - 1,
> +	MEM_AVOID_CRASHKERNEL,
>  	MEM_AVOID_MAX,
>  };
>  
> @@ -238,6 +239,115 @@ static void parse_gb_huge_pages(char *param, char *val)
>  	}
>  }
>  
> +/* code heavily copied from parse_crashkernel_mem() */
> +static void handle_crashkernel_mem(char *cmdline,
> +					unsigned long long system_ram,
> +					unsigned long long *crash_size,
> +					unsigned long long *crash_base)

This version looks better and the logic is simple. It will be much better
if we can share code with parse_crashkernel_mem() since both of them look
almost the same.

> +{
> +	char *tmp, *cur = cmdline;
> +
> +	/* for each entry of the comma-separated list */
> +	do {
> +		unsigned long long start, end = ULLONG_MAX, size;
> +
> +		/* get the start of the range */
> +		start = memparse(cur, &tmp);
> +		/* no value given */
> +		if (cur == tmp)
> +			return;
> +		cur = tmp;
> +		if (*cur != '-')
> +			return;
> +		cur++;
> +
> +		/* if no ':' is here, than we read the end */
> +		if (*cur != ':') {
> +			end = memparse(cur, &tmp);
> +			/* no value given */
> +			if (cur == tmp)
> +				return;
> +			cur = tmp;
> +			/* invalid if crashkernel end <= start */
> +			if (end <= start)
> +				return;
> +		}
> +		/* expect ":" after range */
> +		if (*cur != ':')
> +			return;
> +		cur++;
> +
> +		size = memparse(cur, &tmp);
> +		/* no size value given */
> +		if (cur == tmp)
> +			return;
> +		cur = tmp;
> +		if (size >= system_ram)
> +			return;
> +
> +		/* match ? */
> +		if (system_ram >= start && system_ram < end) {
> +			*crash_size = size;
> +			break;
> +		}
> +	} while (*cur++ == ',');
> +
> +	if (*crash_size > 0) {
> +		while (*cur && *cur != ' ' && *cur != '@')
> +			cur++;
> +		if (*cur == '@') {
> +			cur++;
> +			*crash_base = memparse(cur, &tmp);
> +		}
> +	}
> +}
> +
> +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> +static void mem_avoid_specified_crashkernel_region(char *option)

Maybe just add more words to explain the specified crashkernel region
cases, but remove the 'speecified' word in function name?

> +{
> +	unsigned long long crash_size, crash_base = 0;
> +	char	*first_colon, *first_space, *cur = option;
> +
> +	first_colon = strchr(option, ':');
> +	first_space = strchr(option, ' ');
> +	/* if contain ":" */
> +	if (first_colon && (!first_space || first_colon < first_space)) {
> +		int i;
> +		u64 total_sz = 0;
> +		struct boot_e820_entry *entry;
> +
> +		for (i = 0; i < boot_params->e820_entries; i++) {
> +			entry = &boot_params->e820_table[i];
> +			/* Skip non-RAM entries. */
> +			if (entry->type != E820_TYPE_RAM)
> +				continue;
> +			total_sz += entry->size;

Wrap this for loop into a static function to calculate the system RAM
size?

Other than these, I think this adding looks good. It won't impact the
current handling, and very easy to recognize what it's doing. Thanks for
the effort.

Thanks
Baoquan
> +		}
> +		handle_crashkernel_mem(option, total_sz, &crash_size,
> +			&crash_base);
> +	} else {
> +		crash_size = memparse(option, &cur);
> +		if (option == cur)
> +			return;
> +		while (*cur && *cur != ' ' && *cur != '@')
> +			cur++;
> +		if (*cur == '@') {
> +			option = cur + 1;
> +			crash_base = memparse(option, &cur);
> +		}
> +	}
> +	if (crash_base) {
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> +	} else {
> +		/*
> + 		 * Clearing mem_avoid if no offset is given. This is consistent
> + 		 * with kernel, which uses the last crashkernel= option.
> +		 */
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> +	}
> +}
>  
>  static void handle_mem_options(void)
>  {
> @@ -248,7 +358,7 @@ static void handle_mem_options(void)
>  	u64 mem_size;
>  
>  	if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
> -		!strstr(args, "hugepages"))
> +		!strstr(args, "hugepages") && !strstr(args, "crashkernel="))
>  		return;
>  
>  	tmp_cmdline = malloc(len + 1);
> @@ -284,6 +394,8 @@ static void handle_mem_options(void)
>  				goto out;
>  
>  			mem_limit = mem_size;
> +		} else if (strstr(param, "crashkernel")) {
> +			mem_avoid_specified_crashkernel_region(val);
>  		}
>  	}
>  
> @@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
>  
>  	/* We don't need to set a mapping for setup_data. */
>  
> -	/* Mark the memmap regions we need to avoid */
> +	/* Mark the regions we need to avoid */
>  	handle_mem_options();
>  
>  	/* Enumerate the immovable memory regions */
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  6:19 ` Chao Fan
@ 2019-04-02  6:52   ` Baoquan He
  2019-04-02  6:58   ` Pingfan Liu
  1 sibling, 0 replies; 11+ messages in thread
From: Baoquan He @ 2019-04-02  6:52 UTC (permalink / raw)
  To: Chao Fan
  Cc: Pingfan Liu, x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Kirill A. Shutemov,
	Ard Biesheuvel, linux-kernel

On 04/02/19 at 02:19pm, Chao Fan wrote:
> On Tue, Apr 02, 2019 at 12:10:46PM +0800, Pingfan Liu wrote:
> >crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
> or or?
> >fail to reserve the required memory region if KASLR puts kernel into the
> >region. To avoid this uncertainty, asking KASLR to skip the required
> >region.
> >
> >Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> >Cc: Thomas Gleixner <tglx@linutronix.de>
> >Cc: Ingo Molnar <mingo@redhat.com>
> >Cc: Borislav Petkov <bp@alien8.de>
> >Cc: "H. Peter Anvin" <hpa@zytor.com>
> >Cc: Baoquan He <bhe@redhat.com>
> >Cc: Will Deacon <will.deacon@arm.com>
> >Cc: Nicolas Pitre <nico@linaro.org>
> >Cc: Pingfan Liu <kernelfans@gmail.com>
> >Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
> >Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> >Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >Cc: linux-kernel@vger.kernel.org
> >---
> [...]
> >+
> >+/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> 
> Before review, I want to say more about the background.
> It's very hard to review the code for someone who is not so familiar
> with kdump, so could you please explain more ahout
> the uasge of crashkernel=range1:size1[,range2:size2,...]@offset.
> And also there are so many jobs who are parsing string. So I really
> need your help to understand the PATCH.

The hard part may be handle_crashkernel_mem() itself. However, it's
almost copied from parse_crashkernel_mem() completely. If we can reuse
that function, thing's gonna be perfect.

> 
> >+static void mem_avoid_specified_crashkernel_region(char *option)
> >+{
> >+	unsigned long long crash_size, crash_base = 0;
> >+	char	*first_colon, *first_space, *cur = option;
> Is there a tab after char?
> >+
> >+	first_colon = strchr(option, ':');
> >+	first_space = strchr(option, ' ');
> >+	/* if contain ":" */
> >+	if (first_colon && (!first_space || first_colon < first_space)) {
> >+		int i;
> >+		u64 total_sz = 0;
> >+		struct boot_e820_entry *entry;
> >+
> >+		for (i = 0; i < boot_params->e820_entries; i++) {
> >+			entry = &boot_params->e820_table[i];
> >+			/* Skip non-RAM entries. */
> >+			if (entry->type != E820_TYPE_RAM)
> >+				continue;
> >+			total_sz += entry->size;
> I wonder whether it's needed to consider the memory ranges here.
> I think it's OK to only record the regions should to be avoid.
> I remeber I ever talked with Baoquan about the similiar problems.
> @Baoquan, I am not sure if I misunderstand something.

Not sure if I get you. Could you be more specific?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  6:19 ` Chao Fan
  2019-04-02  6:52   ` Baoquan He
@ 2019-04-02  6:58   ` Pingfan Liu
  2019-04-02  7:59     ` Chao Fan
  1 sibling, 1 reply; 11+ messages in thread
From: Pingfan Liu @ 2019-04-02  6:58 UTC (permalink / raw)
  To: Chao Fan
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Baoquan He, Will Deacon, Nicolas Pitre,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On Tue, Apr 2, 2019 at 1:20 PM Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>
> On Tue, Apr 02, 2019 at 12:10:46PM +0800, Pingfan Liu wrote:
> >crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
> or or?
> >fail to reserve the required memory region if KASLR puts kernel into the
> >region. To avoid this uncertainty, asking KASLR to skip the required
> >region.
> >
> >Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> >Cc: Thomas Gleixner <tglx@linutronix.de>
> >Cc: Ingo Molnar <mingo@redhat.com>
> >Cc: Borislav Petkov <bp@alien8.de>
> >Cc: "H. Peter Anvin" <hpa@zytor.com>
> >Cc: Baoquan He <bhe@redhat.com>
> >Cc: Will Deacon <will.deacon@arm.com>
> >Cc: Nicolas Pitre <nico@linaro.org>
> >Cc: Pingfan Liu <kernelfans@gmail.com>
> >Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
> >Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> >Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >Cc: linux-kernel@vger.kernel.org
> >---
> [...]
> >+
> >+/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
>
> Before review, I want to say more about the background.
> It's very hard to review the code for someone who is not so familiar
> with kdump, so could you please explain more ahout
> the uasge of crashkernel=range1:size1[,range2:size2,...]@offset.
> And also there are so many jobs who are parsing string. So I really
> need your help to understand the PATCH.
>
> >+static void mem_avoid_specified_crashkernel_region(char *option)
> >+{
> >+      unsigned long long crash_size, crash_base = 0;
> >+      char    *first_colon, *first_space, *cur = option;
> Is there a tab after char?
> >+
> >+      first_colon = strchr(option, ':');
> >+      first_space = strchr(option, ' ');
> >+      /* if contain ":" */
> >+      if (first_colon && (!first_space || first_colon < first_space)) {
> >+              int i;
> >+              u64 total_sz = 0;
> >+              struct boot_e820_entry *entry;
> >+
> >+              for (i = 0; i < boot_params->e820_entries; i++) {
> >+                      entry = &boot_params->e820_table[i];
> >+                      /* Skip non-RAM entries. */
> >+                      if (entry->type != E820_TYPE_RAM)
> >+                              continue;
> >+                      total_sz += entry->size;
> I wonder whether it's needed to consider the memory ranges here.
> I think it's OK to only record the regions should to be avoid.
Maybe not catch you exactly. In the case of
crashkernel=range1:size1[,range2:size2,...]@offset, the size of avoid
region depends on the size of total system ram.
> I remeber I ever talked with Baoquan about the similiar problems.
> @Baoquan, I am not sure if I misunderstand something.
>
> Thanks,
> Chao Fan
> >+              }
> >+              handle_crashkernel_mem(option, total_sz, &crash_size,
> >+                      &crash_base);
> >+      } else {
> >+              crash_size = memparse(option, &cur);
> >+              if (option == cur)
> >+                      return;
> >+              while (*cur && *cur != ' ' && *cur != '@')
> >+                      cur++;
> >+              if (*cur == '@') {
> >+                      option = cur + 1;
> >+                      crash_base = memparse(option, &cur);
> >+              }
> >+      }
> >+      if (crash_base) {
> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> >+      } else {
> >+              /*
> >+               * Clearing mem_avoid if no offset is given. This is consistent
> >+               * with kernel, which uses the last crashkernel= option.
> >+               */
> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> >+      }
> >+}
> >
> > static void handle_mem_options(void)
> > {
> >@@ -248,7 +358,7 @@ static void handle_mem_options(void)
> >       u64 mem_size;
> >
> >       if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
> >-              !strstr(args, "hugepages"))
> >+              !strstr(args, "hugepages") && !strstr(args, "crashkernel="))
> >               return;
> >
> >       tmp_cmdline = malloc(len + 1);
> >@@ -284,6 +394,8 @@ static void handle_mem_options(void)
> >                               goto out;
> >
> >                       mem_limit = mem_size;
> >+              } else if (strstr(param, "crashkernel")) {
> >+                      mem_avoid_specified_crashkernel_region(val);
> >               }
> >       }
> >
> >@@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
> >
> >       /* We don't need to set a mapping for setup_data. */
> >
> >-      /* Mark the memmap regions we need to avoid */
> >+      /* Mark the regions we need to avoid */
> >       handle_mem_options();
> >
> >       /* Enumerate the immovable memory regions */
> >--
> >2.7.4
> >
> >
> >
>
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  6:58   ` Pingfan Liu
@ 2019-04-02  7:59     ` Chao Fan
  0 siblings, 0 replies; 11+ messages in thread
From: Chao Fan @ 2019-04-02  7:59 UTC (permalink / raw)
  To: Pingfan Liu
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Baoquan He, Will Deacon, Nicolas Pitre,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On Tue, Apr 02, 2019 at 02:58:53PM +0800, Pingfan Liu wrote:
>On Tue, Apr 2, 2019 at 1:20 PM Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>>
>> On Tue, Apr 02, 2019 at 12:10:46PM +0800, Pingfan Liu wrote:
>> >crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
>> or or?
>> >fail to reserve the required memory region if KASLR puts kernel into the
>> >region. To avoid this uncertainty, asking KASLR to skip the required
>> >region.
>> >
>> >Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
>> >Cc: Thomas Gleixner <tglx@linutronix.de>
>> >Cc: Ingo Molnar <mingo@redhat.com>
>> >Cc: Borislav Petkov <bp@alien8.de>
>> >Cc: "H. Peter Anvin" <hpa@zytor.com>
>> >Cc: Baoquan He <bhe@redhat.com>
>> >Cc: Will Deacon <will.deacon@arm.com>
>> >Cc: Nicolas Pitre <nico@linaro.org>
>> >Cc: Pingfan Liu <kernelfans@gmail.com>
>> >Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
>> >Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
>> >Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> >Cc: linux-kernel@vger.kernel.org
>> >---
>> [...]
>> >+
>> >+/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
>>
>> Before review, I want to say more about the background.
>> It's very hard to review the code for someone who is not so familiar
>> with kdump, so could you please explain more ahout
>> the uasge of crashkernel=range1:size1[,range2:size2,...]@offset.
>> And also there are so many jobs who are parsing string. So I really
>> need your help to understand the PATCH.
>>
>> >+static void mem_avoid_specified_crashkernel_region(char *option)
>> >+{
>> >+      unsigned long long crash_size, crash_base = 0;
>> >+      char    *first_colon, *first_space, *cur = option;
>> Is there a tab after char?
>> >+
>> >+      first_colon = strchr(option, ':');
>> >+      first_space = strchr(option, ' ');
>> >+      /* if contain ":" */
>> >+      if (first_colon && (!first_space || first_colon < first_space)) {
>> >+              int i;
>> >+              u64 total_sz = 0;
>> >+              struct boot_e820_entry *entry;
>> >+
>> >+              for (i = 0; i < boot_params->e820_entries; i++) {
>> >+                      entry = &boot_params->e820_table[i];
>> >+                      /* Skip non-RAM entries. */
>> >+                      if (entry->type != E820_TYPE_RAM)
>> >+                              continue;
>> >+                      total_sz += entry->size;
>> I wonder whether it's needed to consider the memory ranges here.
>> I think it's OK to only record the regions should to be avoid.
>Maybe not catch you exactly. In the case of
>crashkernel=range1:size1[,range2:size2,...]@offset, the size of avoid
>region depends on the size of total system ram.

Got it, I midunderstand it.

Thanks,
Chao Fan
>> I remeber I ever talked with Baoquan about the similiar problems.
>> @Baoquan, I am not sure if I misunderstand something.
>>
>> Thanks,
>> Chao Fan
>> >+              }
>> >+              handle_crashkernel_mem(option, total_sz, &crash_size,
>> >+                      &crash_base);
>> >+      } else {
>> >+              crash_size = memparse(option, &cur);
>> >+              if (option == cur)
>> >+                      return;
>> >+              while (*cur && *cur != ' ' && *cur != '@')
>> >+                      cur++;
>> >+              if (*cur == '@') {
>> >+                      option = cur + 1;
>> >+                      crash_base = memparse(option, &cur);
>> >+              }
>> >+      }
>> >+      if (crash_base) {
>> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
>> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
>> >+      } else {
>> >+              /*
>> >+               * Clearing mem_avoid if no offset is given. This is consistent
>> >+               * with kernel, which uses the last crashkernel= option.
>> >+               */
>> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
>> >+              mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
>> >+      }
>> >+}
>> >
>> > static void handle_mem_options(void)
>> > {
>> >@@ -248,7 +358,7 @@ static void handle_mem_options(void)
>> >       u64 mem_size;
>> >
>> >       if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
>> >-              !strstr(args, "hugepages"))
>> >+              !strstr(args, "hugepages") && !strstr(args, "crashkernel="))
>> >               return;
>> >
>> >       tmp_cmdline = malloc(len + 1);
>> >@@ -284,6 +394,8 @@ static void handle_mem_options(void)
>> >                               goto out;
>> >
>> >                       mem_limit = mem_size;
>> >+              } else if (strstr(param, "crashkernel")) {
>> >+                      mem_avoid_specified_crashkernel_region(val);
>> >               }
>> >       }
>> >
>> >@@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
>> >
>> >       /* We don't need to set a mapping for setup_data. */
>> >
>> >-      /* Mark the memmap regions we need to avoid */
>> >+      /* Mark the regions we need to avoid */
>> >       handle_mem_options();
>> >
>> >       /* Enumerate the immovable memory regions */
>> >--
>> >2.7.4
>> >
>> >
>> >
>>
>>
>
>



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  4:10 [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region Pingfan Liu
  2019-04-02  6:19 ` Chao Fan
  2019-04-02  6:46 ` Baoquan He
@ 2019-04-02  8:08 ` Baoquan He
  2019-04-03  2:58   ` Pingfan Liu
  2 siblings, 1 reply; 11+ messages in thread
From: Baoquan He @ 2019-04-02  8:08 UTC (permalink / raw)
  To: Pingfan Liu
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, linux-kernel

> +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> +static void mem_avoid_specified_crashkernel_region(char *option)
> +{
> +	unsigned long long crash_size, crash_base = 0;
> +	char	*first_colon, *first_space, *cur = option;
> +

Another thing which need be noticed is that you may only need to handle
when '@' is found. Otherwise just let it go. Right?

> +	first_colon = strchr(option, ':');
> +	first_space = strchr(option, ' ');
> +	/* if contain ":" */
> +	if (first_colon && (!first_space || first_colon < first_space)) {
> +		int i;
> +		u64 total_sz = 0;
> +		struct boot_e820_entry *entry;
> +
> +		for (i = 0; i < boot_params->e820_entries; i++) {
> +			entry = &boot_params->e820_table[i];
> +			/* Skip non-RAM entries. */
> +			if (entry->type != E820_TYPE_RAM)
> +				continue;
> +			total_sz += entry->size;
> +		}
> +		handle_crashkernel_mem(option, total_sz, &crash_size,
> +			&crash_base);
> +	} else {
> +		crash_size = memparse(option, &cur);
> +		if (option == cur)
> +			return;
> +		while (*cur && *cur != ' ' && *cur != '@')
> +			cur++;
> +		if (*cur == '@') {
> +			option = cur + 1;
> +			crash_base = memparse(option, &cur);
> +		}
> +	}
> +	if (crash_base) {
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> +	} else {
> +		/*
> + 		 * Clearing mem_avoid if no offset is given. This is consistent
> + 		 * with kernel, which uses the last crashkernel= option.
> +		 */
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> +		mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> +	}
> +}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  8:08 ` Baoquan He
@ 2019-04-03  2:58   ` Pingfan Liu
  2019-04-03  3:10     ` Baoquan He
  0 siblings, 1 reply; 11+ messages in thread
From: Pingfan Liu @ 2019-04-03  2:58 UTC (permalink / raw)
  To: Baoquan He
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On Tue, Apr 2, 2019 at 4:08 PM Baoquan He <bhe@redhat.com> wrote:
>
> > +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> > +static void mem_avoid_specified_crashkernel_region(char *option)
> > +{
> > +     unsigned long long crash_size, crash_base = 0;
> > +     char    *first_colon, *first_space, *cur = option;
> > +
>
> Another thing which need be noticed is that you may only need to handle
> when '@' is found. Otherwise just let it go. Right?
>
According to kernel's behavior, only the last "crashkernel=" option
takes effect. Hence if no '@', then clearing mem_avoid

> > +     first_colon = strchr(option, ':');
> > +     first_space = strchr(option, ' ');
> > +     /* if contain ":" */
> > +     if (first_colon && (!first_space || first_colon < first_space)) {
> > +             int i;
> > +             u64 total_sz = 0;
> > +             struct boot_e820_entry *entry;
> > +
> > +             for (i = 0; i < boot_params->e820_entries; i++) {
> > +                     entry = &boot_params->e820_table[i];
> > +                     /* Skip non-RAM entries. */
> > +                     if (entry->type != E820_TYPE_RAM)
> > +                             continue;
> > +                     total_sz += entry->size;
> > +             }
> > +             handle_crashkernel_mem(option, total_sz, &crash_size,
> > +                     &crash_base);
> > +     } else {
> > +             crash_size = memparse(option, &cur);
> > +             if (option == cur)
> > +                     return;
> > +             while (*cur && *cur != ' ' && *cur != '@')
> > +                     cur++;
> > +             if (*cur == '@') {
> > +                     option = cur + 1;
> > +                     crash_base = memparse(option, &cur);
> > +             }
> > +     }
> > +     if (crash_base) {
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> > +     } else {
> > +             /*
> > +              * Clearing mem_avoid if no offset is given. This is consistent
> > +              * with kernel, which uses the last crashkernel= option.
> > +              */
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> > +     }
> > +}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-02  6:46 ` Baoquan He
@ 2019-04-03  2:59   ` Pingfan Liu
  0 siblings, 0 replies; 11+ messages in thread
From: Pingfan Liu @ 2019-04-03  2:59 UTC (permalink / raw)
  To: Baoquan He
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On Tue, Apr 2, 2019 at 2:46 PM Baoquan He <bhe@redhat.com> wrote:
>
> On 04/02/19 at 12:10pm, Pingfan Liu wrote:
> > crashkernel=x@y or or =range1:size1[,range2:size2,...]@offset option may
> > fail to reserve the required memory region if KASLR puts kernel into the
> > region. To avoid this uncertainty, asking KASLR to skip the required
> > region.
> >
> > Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Ingo Molnar <mingo@redhat.com>
> > Cc: Borislav Petkov <bp@alien8.de>
> > Cc: "H. Peter Anvin" <hpa@zytor.com>
> > Cc: Baoquan He <bhe@redhat.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Nicolas Pitre <nico@linaro.org>
> > Cc: Pingfan Liu <kernelfans@gmail.com>
> > Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
> > Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: linux-kernel@vger.kernel.org
> > ---
> > v2 -> v3: adding parsing of crashkernel=range1:size1[,range2:size2,...]@offset
> >
> >  arch/x86/boot/compressed/kaslr.c | 116 ++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 114 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
> > index 2e53c05..7f698f4 100644
> > --- a/arch/x86/boot/compressed/kaslr.c
> > +++ b/arch/x86/boot/compressed/kaslr.c
> > @@ -107,6 +107,7 @@ enum mem_avoid_index {
> >       MEM_AVOID_BOOTPARAMS,
> >       MEM_AVOID_MEMMAP_BEGIN,
> >       MEM_AVOID_MEMMAP_END = MEM_AVOID_MEMMAP_BEGIN + MAX_MEMMAP_REGIONS - 1,
> > +     MEM_AVOID_CRASHKERNEL,
> >       MEM_AVOID_MAX,
> >  };
> >
> > @@ -238,6 +239,115 @@ static void parse_gb_huge_pages(char *param, char *val)
> >       }
> >  }
> >
> > +/* code heavily copied from parse_crashkernel_mem() */
> > +static void handle_crashkernel_mem(char *cmdline,
> > +                                     unsigned long long system_ram,
> > +                                     unsigned long long *crash_size,
> > +                                     unsigned long long *crash_base)
>
> This version looks better and the logic is simple. It will be much better
> if we can share code with parse_crashkernel_mem() since both of them look
> almost the same.
>
A little hard, but I will have a try.
> > +{
> > +     char *tmp, *cur = cmdline;
> > +
> > +     /* for each entry of the comma-separated list */
> > +     do {
> > +             unsigned long long start, end = ULLONG_MAX, size;
> > +
> > +             /* get the start of the range */
> > +             start = memparse(cur, &tmp);
> > +             /* no value given */
> > +             if (cur == tmp)
> > +                     return;
> > +             cur = tmp;
> > +             if (*cur != '-')
> > +                     return;
> > +             cur++;
> > +
> > +             /* if no ':' is here, than we read the end */
> > +             if (*cur != ':') {
> > +                     end = memparse(cur, &tmp);
> > +                     /* no value given */
> > +                     if (cur == tmp)
> > +                             return;
> > +                     cur = tmp;
> > +                     /* invalid if crashkernel end <= start */
> > +                     if (end <= start)
> > +                             return;
> > +             }
> > +             /* expect ":" after range */
> > +             if (*cur != ':')
> > +                     return;
> > +             cur++;
> > +
> > +             size = memparse(cur, &tmp);
> > +             /* no size value given */
> > +             if (cur == tmp)
> > +                     return;
> > +             cur = tmp;
> > +             if (size >= system_ram)
> > +                     return;
> > +
> > +             /* match ? */
> > +             if (system_ram >= start && system_ram < end) {
> > +                     *crash_size = size;
> > +                     break;
> > +             }
> > +     } while (*cur++ == ',');
> > +
> > +     if (*crash_size > 0) {
> > +             while (*cur && *cur != ' ' && *cur != '@')
> > +                     cur++;
> > +             if (*cur == '@') {
> > +                     cur++;
> > +                     *crash_base = memparse(cur, &tmp);
> > +             }
> > +     }
> > +}
> > +
> > +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> > +static void mem_avoid_specified_crashkernel_region(char *option)
>
> Maybe just add more words to explain the specified crashkernel region
> cases, but remove the 'speecified' word in function name?
>
OK.
> > +{
> > +     unsigned long long crash_size, crash_base = 0;
> > +     char    *first_colon, *first_space, *cur = option;
> > +
> > +     first_colon = strchr(option, ':');
> > +     first_space = strchr(option, ' ');
> > +     /* if contain ":" */
> > +     if (first_colon && (!first_space || first_colon < first_space)) {
> > +             int i;
> > +             u64 total_sz = 0;
> > +             struct boot_e820_entry *entry;
> > +
> > +             for (i = 0; i < boot_params->e820_entries; i++) {
> > +                     entry = &boot_params->e820_table[i];
> > +                     /* Skip non-RAM entries. */
> > +                     if (entry->type != E820_TYPE_RAM)
> > +                             continue;
> > +                     total_sz += entry->size;
>
> Wrap this for loop into a static function to calculate the system RAM
> size?
>
OK.

Thanks for your review.

Regards,
Pingfan
> Other than these, I think this adding looks good. It won't impact the
> current handling, and very easy to recognize what it's doing. Thanks for
> the effort.
>
> Thanks
> Baoquan
> > +             }
> > +             handle_crashkernel_mem(option, total_sz, &crash_size,
> > +                     &crash_base);
> > +     } else {
> > +             crash_size = memparse(option, &cur);
> > +             if (option == cur)
> > +                     return;
> > +             while (*cur && *cur != ' ' && *cur != '@')
> > +                     cur++;
> > +             if (*cur == '@') {
> > +                     option = cur + 1;
> > +                     crash_base = memparse(option, &cur);
> > +             }
> > +     }
> > +     if (crash_base) {
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> > +     } else {
> > +             /*
> > +              * Clearing mem_avoid if no offset is given. This is consistent
> > +              * with kernel, which uses the last crashkernel= option.
> > +              */
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> > +     }
> > +}
> >
> >  static void handle_mem_options(void)
> >  {
> > @@ -248,7 +358,7 @@ static void handle_mem_options(void)
> >       u64 mem_size;
> >
> >       if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
> > -             !strstr(args, "hugepages"))
> > +             !strstr(args, "hugepages") && !strstr(args, "crashkernel="))
> >               return;
> >
> >       tmp_cmdline = malloc(len + 1);
> > @@ -284,6 +394,8 @@ static void handle_mem_options(void)
> >                               goto out;
> >
> >                       mem_limit = mem_size;
> > +             } else if (strstr(param, "crashkernel")) {
> > +                     mem_avoid_specified_crashkernel_region(val);
> >               }
> >       }
> >
> > @@ -412,7 +524,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
> >
> >       /* We don't need to set a mapping for setup_data. */
> >
> > -     /* Mark the memmap regions we need to avoid */
> > +     /* Mark the regions we need to avoid */
> >       handle_mem_options();
> >
> >       /* Enumerate the immovable memory regions */
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-03  2:58   ` Pingfan Liu
@ 2019-04-03  3:10     ` Baoquan He
  2019-04-04  9:40       ` Pingfan Liu
  0 siblings, 1 reply; 11+ messages in thread
From: Baoquan He @ 2019-04-03  3:10 UTC (permalink / raw)
  To: Pingfan Liu
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On 04/03/19 at 10:58am, Pingfan Liu wrote:
> On Tue, Apr 2, 2019 at 4:08 PM Baoquan He <bhe@redhat.com> wrote:
> >
> > > +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> > > +static void mem_avoid_specified_crashkernel_region(char *option)
> > > +{
> > > +     unsigned long long crash_size, crash_base = 0;
> > > +     char    *first_colon, *first_space, *cur = option;
> > > +
> >
> > Another thing which need be noticed is that you may only need to handle
> > when '@' is found. Otherwise just let it go. Right?
> >
> According to kernel's behavior, only the last "crashkernel=" option
> takes effect. Hence if no '@', then clearing mem_avoid

Here I mean that you can search '@' at the beginning if crashkernel is
found. Maybe no need to clear mem_avoid since it's global data, has been
initialized to 0 during loading. It's in BSS, right?

You don't have to search first colon or first space, then parse size of
crashkernel, and finally find out that it's only crashkernel=512M-2G:64M,2G-:128M
style, no '@' specified. What do you think?

> 
> > > +     first_colon = strchr(option, ':');
> > > +     first_space = strchr(option, ' ');
> > > +     /* if contain ":" */
> > > +     if (first_colon && (!first_space || first_colon < first_space)) {
> > > +             int i;
> > > +             u64 total_sz = 0;
> > > +             struct boot_e820_entry *entry;
> > > +
> > > +             for (i = 0; i < boot_params->e820_entries; i++) {
> > > +                     entry = &boot_params->e820_table[i];
> > > +                     /* Skip non-RAM entries. */
> > > +                     if (entry->type != E820_TYPE_RAM)
> > > +                             continue;
> > > +                     total_sz += entry->size;
> > > +             }
> > > +             handle_crashkernel_mem(option, total_sz, &crash_size,
> > > +                     &crash_base);
> > > +     } else {
> > > +             crash_size = memparse(option, &cur);
> > > +             if (option == cur)
> > > +                     return;
> > > +             while (*cur && *cur != ' ' && *cur != '@')
> > > +                     cur++;
> > > +             if (*cur == '@') {
> > > +                     option = cur + 1;
> > > +                     crash_base = memparse(option, &cur);
> > > +             }
> > > +     }
> > > +     if (crash_base) {
> > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> > > +     } else {
> > > +             /*
> > > +              * Clearing mem_avoid if no offset is given. This is consistent
> > > +              * with kernel, which uses the last crashkernel= option.
> > > +              */
> > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> > > +     }
> > > +}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region
  2019-04-03  3:10     ` Baoquan He
@ 2019-04-04  9:40       ` Pingfan Liu
  0 siblings, 0 replies; 11+ messages in thread
From: Pingfan Liu @ 2019-04-04  9:40 UTC (permalink / raw)
  To: Baoquan He
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Will Deacon, Nicolas Pitre, Chao Fan,
	Kirill A. Shutemov, Ard Biesheuvel, LKML

On Wed, Apr 3, 2019 at 11:10 AM Baoquan He <bhe@redhat.com> wrote:
>
> On 04/03/19 at 10:58am, Pingfan Liu wrote:
> > On Tue, Apr 2, 2019 at 4:08 PM Baoquan He <bhe@redhat.com> wrote:
> > >
> > > > +/* handle crashkernel=x@y or =range1:size1[,range2:size2,...]@offset options */
> > > > +static void mem_avoid_specified_crashkernel_region(char *option)
> > > > +{
> > > > +     unsigned long long crash_size, crash_base = 0;
> > > > +     char    *first_colon, *first_space, *cur = option;
> > > > +
> > >
> > > Another thing which need be noticed is that you may only need to handle
> > > when '@' is found. Otherwise just let it go. Right?
> > >
> > According to kernel's behavior, only the last "crashkernel=" option
> > takes effect. Hence if no '@', then clearing mem_avoid
>
> Here I mean that you can search '@' at the beginning if crashkernel is
> found. Maybe no need to clear mem_avoid since it's global data, has been
> initialized to 0 during loading. It's in BSS, right?
>
Consider the following cmdline crashkernel=256M@1G crashkernel=512M.
These two options are handled independently by handle_mem_options(),
and the later one should overwrite the previous one. This is the
behavior of current kernel's code, referring to
get_last_crashkernel().
> You don't have to search first colon or first space, then parse size of
> crashkernel, and finally find out that it's only crashkernel=512M-2G:64M,2G-:128M
> style, no '@' specified. What do you think?
>
Yes, that will be better. But I plan to reuse parse_crashkernel_mem/simple().

Thanks,
Pingfan
> >
> > > > +     first_colon = strchr(option, ':');
> > > > +     first_space = strchr(option, ' ');
> > > > +     /* if contain ":" */
> > > > +     if (first_colon && (!first_space || first_colon < first_space)) {
> > > > +             int i;
> > > > +             u64 total_sz = 0;
> > > > +             struct boot_e820_entry *entry;
> > > > +
> > > > +             for (i = 0; i < boot_params->e820_entries; i++) {
> > > > +                     entry = &boot_params->e820_table[i];
> > > > +                     /* Skip non-RAM entries. */
> > > > +                     if (entry->type != E820_TYPE_RAM)
> > > > +                             continue;
> > > > +                     total_sz += entry->size;
> > > > +             }
> > > > +             handle_crashkernel_mem(option, total_sz, &crash_size,
> > > > +                     &crash_base);
> > > > +     } else {
> > > > +             crash_size = memparse(option, &cur);
> > > > +             if (option == cur)
> > > > +                     return;
> > > > +             while (*cur && *cur != ' ' && *cur != '@')
> > > > +                     cur++;
> > > > +             if (*cur == '@') {
> > > > +                     option = cur + 1;
> > > > +                     crash_base = memparse(option, &cur);
> > > > +             }
> > > > +     }
> > > > +     if (crash_base) {
> > > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = crash_base;
> > > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = crash_size;
> > > > +     } else {
> > > > +             /*
> > > > +              * Clearing mem_avoid if no offset is given. This is consistent
> > > > +              * with kernel, which uses the last crashkernel= option.
> > > > +              */
> > > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].start = 0;
> > > > +             mem_avoid[MEM_AVOID_CRASHKERNEL].size = 0;
> > > > +     }
> > > > +}

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-04-04  9:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-02  4:10 [PATCHv3] x86/boot/KASLR: skip the specified crashkernel region Pingfan Liu
2019-04-02  6:19 ` Chao Fan
2019-04-02  6:52   ` Baoquan He
2019-04-02  6:58   ` Pingfan Liu
2019-04-02  7:59     ` Chao Fan
2019-04-02  6:46 ` Baoquan He
2019-04-03  2:59   ` Pingfan Liu
2019-04-02  8:08 ` Baoquan He
2019-04-03  2:58   ` Pingfan Liu
2019-04-03  3:10     ` Baoquan He
2019-04-04  9:40       ` Pingfan Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).