All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/mm: Check return value from memblock_phys_alloc_range()
@ 2024-11-15 17:36 gldrk
  2024-11-19 11:14 ` Ingo Molnar
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: gldrk @ 2024-11-15 17:36 UTC (permalink / raw)
  To: Dave Hansen, Andy Lutomirski, Peter Zijlstra, x86; +Cc: linux-kernel

At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of contiguous
free memory available at this point, the kernel will crash and burn because
memblock_phys_alloc_range returns 0 on failure, which leads memblock_phys_free
to throw the first 4 MiB of physical memory to the wolves.  At a minimum it
should fail gracefully with a meaningful diagnostic, but in fact everything
seems to work fine without the weird reserve allocation.

---
  arch/x86/mm/init.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index eb503f5..3696770 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -640,8 +640,13 @@ static void __init memory_map_top_down(unsigned long 
map_start,
  	 */
  	addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
  					 map_end);
-	memblock_phys_free(addr, PMD_SIZE);
-	real_end = addr + PMD_SIZE;
+	if (unlikely(addr < map_start)) {
+		pr_warn("Failed to release memory for alloc_low_pages()");
+		real_end = ALIGN_DOWN(map_end, PMD_SIZE);
+	} else {
+		memblock_phys_free(addr, PMD_SIZE);
+		real_end = addr + PMD_SIZE;
+	}

  	/* step_size need to be small so pgt_buf from BRK could cover it 
*/
  	step_size = PMD_SIZE;
-- 
2.34.0


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

* Re: [PATCH] x86/mm: Check return value from memblock_phys_alloc_range()
  2024-11-15 17:36 [PATCH] x86/mm: Check return value from memblock_phys_alloc_range() gldrk
@ 2024-11-19 11:14 ` Ingo Molnar
  2024-11-19 23:56   ` gldrk
  2025-02-28 17:14 ` [tip: x86/mm] " tip-bot2 for Philip Redkin
  2025-03-19 11:04 ` [tip: x86/core] " tip-bot2 for Philip Redkin
  2 siblings, 1 reply; 5+ messages in thread
From: Ingo Molnar @ 2024-11-19 11:14 UTC (permalink / raw)
  To: gldrk; +Cc: Dave Hansen, Andy Lutomirski, Peter Zijlstra, x86, linux-kernel


* gldrk <me@rarity.fan> wrote:

> At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of contiguous
> free memory available at this point, the kernel will crash and burn because
> memblock_phys_alloc_range returns 0 on failure, which leads memblock_phys_free
> to throw the first 4 MiB of physical memory to the wolves.  At a minimum it
> should fail gracefully with a meaningful diagnostic, but in fact everything
> seems to work fine without the weird reserve allocation.
> 
> ---
>  arch/x86/mm/init.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
> index eb503f5..3696770 100644
> --- a/arch/x86/mm/init.c
> +++ b/arch/x86/mm/init.c
> @@ -640,8 +640,13 @@ static void __init memory_map_top_down(unsigned long
> map_start,
>  	 */
>  	addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
>  					 map_end);
> -	memblock_phys_free(addr, PMD_SIZE);
> -	real_end = addr + PMD_SIZE;
> +	if (unlikely(addr < map_start)) {
> +		pr_warn("Failed to release memory for alloc_low_pages()");
> +		real_end = ALIGN_DOWN(map_end, PMD_SIZE);
> +	} else {
> +		memblock_phys_free(addr, PMD_SIZE);
> +		real_end = addr + PMD_SIZE;
> +	}

Makes sense to fix this bug I suppose, but the usual error check 
pattern for memblock_phys_alloc_range() failure would not be 'addr < 
map_start' but !addr.

( If memblock_phys_alloc_range() succeeds but returns an address below 
  'map_start', that would be a different failure I guess. )

Also, no need to add the 'unlikely()' I suspect - this is early boot 
code, micro-performance of branching is immaterial.

Just curious: what type of system has < 4 MiB of contiguous free memory 
available in early boot? Or was it something intentionally constrained 
via qemu?

Thanks,

	Ingo

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

* Re: [PATCH] x86/mm: Check return value from memblock_phys_alloc_range()
  2024-11-19 11:14 ` Ingo Molnar
@ 2024-11-19 23:56   ` gldrk
  0 siblings, 0 replies; 5+ messages in thread
From: gldrk @ 2024-11-19 23:56 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Dave Hansen, Andy Lutomirski, Peter Zijlstra, x86, linux-kernel

> Just curious: what type of system has < 4 MiB of contiguous free memory
> available in early boot? Or was it something intentionally constrained
> via qemu?

Yes, I was able to boot a basic Alpine system off virtiofs with a few MiB
total and a stripped-down config.  I happen to have a memory-starved 486
machine that is technically "supported", but it's not running Linux just
yet.

Here's an updated patch.

Signed-off-by: Philip Redkin <me@rarity.fan>
---
  arch/x86/mm/init.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index eb503f5..6c4ec4f 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -640,8 +640,13 @@ static void __init memory_map_top_down(unsigned long map_start,
  	 */
  	addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
  					 map_end);
-	memblock_phys_free(addr, PMD_SIZE);
-	real_end = addr + PMD_SIZE;
+	if (!addr) {
+		pr_warn("Failed to release memory for alloc_low_pages()");
+		real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE));
+	} else {
+		memblock_phys_free(addr, PMD_SIZE);
+		real_end = addr + PMD_SIZE;
+	}

  	/* step_size need to be small so pgt_buf from BRK could cover it */
  	step_size = PMD_SIZE;
-- 
2.34.0



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

* [tip: x86/mm] x86/mm: Check return value from memblock_phys_alloc_range()
  2024-11-15 17:36 [PATCH] x86/mm: Check return value from memblock_phys_alloc_range() gldrk
  2024-11-19 11:14 ` Ingo Molnar
@ 2025-02-28 17:14 ` tip-bot2 for Philip Redkin
  2025-03-19 11:04 ` [tip: x86/core] " tip-bot2 for Philip Redkin
  2 siblings, 0 replies; 5+ messages in thread
From: tip-bot2 for Philip Redkin @ 2025-02-28 17:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Philip Redkin, Ingo Molnar, Dave Hansen, Rik van Riel,
	H. Peter Anvin, x86, linux-kernel

The following commit has been merged into the x86/mm branch of tip:

Commit-ID:     fd5935f9c20431eeadd6993fd4d2672e3e17a6b8
Gitweb:        https://git.kernel.org/tip/fd5935f9c20431eeadd6993fd4d2672e3e17a6b8
Author:        Philip Redkin <me@rarity.fan>
AuthorDate:    Fri, 15 Nov 2024 20:36:59 +03:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Fri, 28 Feb 2025 18:02:10 +01:00

x86/mm: Check return value from memblock_phys_alloc_range()

At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of
contiguous free memory available at this point, the kernel will crash
and burn because memblock_phys_alloc_range() returns 0 on failure,
which leads memblock_phys_free() to throw the first 4 MiB of physical
memory to the wolves.

At a minimum it should fail gracefully with a meaningful diagnostic,
but in fact everything seems to work fine without the weird reserve
allocation.

Signed-off-by: Philip Redkin <me@rarity.fan>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Link: https://lore.kernel.org/r/94b3e98f-96a7-3560-1f76-349eb95ccf7f@rarity.fan
---
 arch/x86/mm/init.c |  9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 62aa4d6..bfa444a 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -645,8 +645,13 @@ static void __init memory_map_top_down(unsigned long map_start,
 	 */
 	addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
 					 map_end);
-	memblock_phys_free(addr, PMD_SIZE);
-	real_end = addr + PMD_SIZE;
+	if (!addr) {
+		pr_warn("Failed to release memory for alloc_low_pages()");
+		real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE));
+	} else {
+		memblock_phys_free(addr, PMD_SIZE);
+		real_end = addr + PMD_SIZE;
+	}
 
 	/* step_size need to be small so pgt_buf from BRK could cover it */
 	step_size = PMD_SIZE;

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

* [tip: x86/core] x86/mm: Check return value from memblock_phys_alloc_range()
  2024-11-15 17:36 [PATCH] x86/mm: Check return value from memblock_phys_alloc_range() gldrk
  2024-11-19 11:14 ` Ingo Molnar
  2025-02-28 17:14 ` [tip: x86/mm] " tip-bot2 for Philip Redkin
@ 2025-03-19 11:04 ` tip-bot2 for Philip Redkin
  2 siblings, 0 replies; 5+ messages in thread
From: tip-bot2 for Philip Redkin @ 2025-03-19 11:04 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Philip Redkin, Ingo Molnar, Dave Hansen, Rik van Riel,
	H. Peter Anvin, x86, linux-kernel

The following commit has been merged into the x86/core branch of tip:

Commit-ID:     631ca8909fd5c62b9fda9edda93924311a78a9c4
Gitweb:        https://git.kernel.org/tip/631ca8909fd5c62b9fda9edda93924311a78a9c4
Author:        Philip Redkin <me@rarity.fan>
AuthorDate:    Fri, 15 Nov 2024 20:36:59 +03:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Wed, 19 Mar 2025 11:05:22 +01:00

x86/mm: Check return value from memblock_phys_alloc_range()

At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of
contiguous free memory available at this point, the kernel will crash
and burn because memblock_phys_alloc_range() returns 0 on failure,
which leads memblock_phys_free() to throw the first 4 MiB of physical
memory to the wolves.

At a minimum it should fail gracefully with a meaningful diagnostic,
but in fact everything seems to work fine without the weird reserve
allocation.

Signed-off-by: Philip Redkin <me@rarity.fan>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Link: https://lore.kernel.org/r/94b3e98f-96a7-3560-1f76-349eb95ccf7f@rarity.fan
---
 arch/x86/mm/init.c |  9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 62aa4d6..bfa444a 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -645,8 +645,13 @@ static void __init memory_map_top_down(unsigned long map_start,
 	 */
 	addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
 					 map_end);
-	memblock_phys_free(addr, PMD_SIZE);
-	real_end = addr + PMD_SIZE;
+	if (!addr) {
+		pr_warn("Failed to release memory for alloc_low_pages()");
+		real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE));
+	} else {
+		memblock_phys_free(addr, PMD_SIZE);
+		real_end = addr + PMD_SIZE;
+	}
 
 	/* step_size need to be small so pgt_buf from BRK could cover it */
 	step_size = PMD_SIZE;

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

end of thread, other threads:[~2025-03-19 11:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-15 17:36 [PATCH] x86/mm: Check return value from memblock_phys_alloc_range() gldrk
2024-11-19 11:14 ` Ingo Molnar
2024-11-19 23:56   ` gldrk
2025-02-28 17:14 ` [tip: x86/mm] " tip-bot2 for Philip Redkin
2025-03-19 11:04 ` [tip: x86/core] " tip-bot2 for Philip Redkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.