kexec.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO)
@ 2025-08-19 23:22 Evangelos Petrongonas
  2025-08-19 23:22 ` [PATCH v2 1/2] kexec: introduce is_kho_boot() Evangelos Petrongonas
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Evangelos Petrongonas @ 2025-08-19 23:22 UTC (permalink / raw)
  To: Ard Biesheuvel, Mike Rapoport
  Cc: Evangelos Petrongonas, Alexander Graf, Changyuan Lyu,
	Andrew Morton, Baoquan He, kexec, linux-mm, linux-efi,
	linux-kernel, nh-open-source

This patch series fixes a kernel panic that occurs when booting with
both EFI and KHO (Kexec HandOver) enabled.

The issue arises because EFI's `reserve_regions()` clears all memory
regions with `memblock_remove(0, PHYS_ADDR_MAX)` before rebuilding them
from EFI data. This destroys KHO scratch regions that were set up early
during device tree scanning, causing a panic as the kernel has no valid
memory regions for early allocations.

The first patch introduces `is_kho_boot()` to allow early boot
components to reliably detect if the kernel was booted via KHO-enabled
kexec. The existing `kho_is_enabled()` only checks the command line and
doesn't verify if an actual KHO FDT was passed.

The second patch modifies EFI's `reserve_regions()` to selectively
remove only non-KHO memory regions when KHO is active, preserving the
critical scratch regions while still allowing EFI to rebuild its memory
map.

The patchset was developed/tested on arm64.

On a side note, I have noticed that `kho_populate()` calls
`memblock_set_kho_scratch_only()`, but the `kho` cmdline option is
not checked until much later. Therefore, memblock will use only the
scratch regions that were passed from the outgoing kernel, even if the
incoming kernel doesn't explicitly want that. I am not sure if this is
done on purpose, but in any case we can discuss this in another patch,
as it is orthogonal to this one.

Main Changes in v2 (smaller changes can be found in individual patches):
    - Introduce is_kho_boot()
    - Replaced manual loop with for_each_mem_region macro

Evangelos Petrongonas (2):
  kexec: introduce is_kho_boot()
  efi: Support booting with kexec handover (KHO)

 drivers/firmware/efi/efi-init.c | 28 ++++++++++++++++++++++++----
 include/linux/kexec_handover.h  |  6 ++++++
 kernel/kexec_handover.c         | 20 ++++++++++++++++++++
 3 files changed, 50 insertions(+), 4 deletions(-)

-- 
2.47.3



Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597



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

* [PATCH v2 1/2] kexec: introduce is_kho_boot()
  2025-08-19 23:22 [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO) Evangelos Petrongonas
@ 2025-08-19 23:22 ` Evangelos Petrongonas
  2025-08-20  8:24   ` Mike Rapoport
  2025-08-19 23:22 ` [PATCH v2 2/2] efi: Support booting with kexec handover (KHO) Evangelos Petrongonas
  2025-08-20  8:20 ` [PATCH v2 0/2] efi: Fix EFI boot " Mike Rapoport
  2 siblings, 1 reply; 6+ messages in thread
From: Evangelos Petrongonas @ 2025-08-19 23:22 UTC (permalink / raw)
  To: Ard Biesheuvel, Mike Rapoport
  Cc: Evangelos Petrongonas, Alexander Graf, Changyuan Lyu,
	Andrew Morton, Baoquan He, kexec, linux-mm, linux-efi,
	linux-kernel, nh-open-source

During early initialisation, after a kexec, other components, like EFI
need to know if a KHO enabled kexec is performed. The `kho_is_enabled`
function is not enough as in the early stages, it only reflects
whether the cmdline has KHO enabled, not if an actual KHO FDT exists.

Extend the KHO API with `is_kho_boot()` to provide a way for components
to check if a KHO enabled kexec is performed.

Signed-off-by: Evangelos Petrongonas <epetron@amazon.de>
---
 include/linux/kexec_handover.h |  6 ++++++
 kernel/kexec_handover.c        | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 348844cffb13..559d13a3bc44 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -40,6 +40,7 @@ struct kho_serialization;
 
 #ifdef CONFIG_KEXEC_HANDOVER
 bool kho_is_enabled(void);
+bool is_kho_boot(void);
 
 int kho_preserve_folio(struct folio *folio);
 int kho_preserve_phys(phys_addr_t phys, size_t size);
@@ -60,6 +61,11 @@ static inline bool kho_is_enabled(void)
 	return false;
 }
 
+static inline bool is_kho_boot(void)
+{
+	return false;
+}
+
 static inline int kho_preserve_folio(struct folio *folio)
 {
 	return -EOPNOTSUPP;
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index 69b953551677..a1a4e76e0ff1 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -925,6 +925,26 @@ static const void *kho_get_fdt(void)
 	return kho_in.fdt_phys ? phys_to_virt(kho_in.fdt_phys) : NULL;
 }
 
+/**
+ * is_kho_boot - check if current kernel was booted via KHO-enabled
+ * kexec
+ *
+ * This function checks if the current kernel was loaded through a kexec
+ * operation with KHO enabled, by verifying both that KHO is enabled via
+ * cmdline AND that a valid KHO FDT was passed.
+ *
+ * Note: This function returns reliable results only after
+ * kho_populate() has been called during early boot. Before that,
+ * it may return false even if KHO data is present.
+ *
+ * Return: true if booted via KHO-enabled kexec, false otherwise
+ */
+bool is_kho_boot(void)
+{
+	return !!kho_get_fdt() && kho_enable;
+}
+EXPORT_SYMBOL_GPL(is_kho_boot);
+
 /**
  * kho_retrieve_subtree - retrieve a preserved sub FDT by its name.
  * @name: the name of the sub FDT passed to kho_add_subtree().
-- 
2.47.3




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597



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

* [PATCH v2 2/2] efi: Support booting with kexec handover (KHO)
  2025-08-19 23:22 [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO) Evangelos Petrongonas
  2025-08-19 23:22 ` [PATCH v2 1/2] kexec: introduce is_kho_boot() Evangelos Petrongonas
@ 2025-08-19 23:22 ` Evangelos Petrongonas
  2025-08-20  8:09   ` Mike Rapoport
  2025-08-20  8:20 ` [PATCH v2 0/2] efi: Fix EFI boot " Mike Rapoport
  2 siblings, 1 reply; 6+ messages in thread
From: Evangelos Petrongonas @ 2025-08-19 23:22 UTC (permalink / raw)
  To: Ard Biesheuvel, Mike Rapoport
  Cc: Evangelos Petrongonas, Alexander Graf, Changyuan Lyu,
	Andrew Morton, Baoquan He, kexec, linux-mm, linux-efi,
	linux-kernel, nh-open-source

When KHO (Kexec HandOver) is enabled, it sets up scratch memory regions
early during device tree scanning. After kexec, the new kernel
exclusively uses this region for memory allocations during boot up to
the initialization of the page allocator

However, when booting with EFI, EFI's reserve_regions() uses
memblock_remove(0, PHYS_ADDR_MAX) to clear all memory regions before
rebuilding them from EFI data. This destroys KHO scratch regions and
their flags, thus causing a kernel panic, as there are no scratch
memory regions.

Instead of wholesale removal, iterate through memory regions and only
remove non-KHO ones. This preserves KHO scratch regions, which are
good known memory, while still allowing EFI to rebuild its memory map.

Signed-off-by: Evangelos Petrongonas <epetron@amazon.de>
---
Changes in v2:
	- Replaced the for loop with for_each_mem_region
	- Fixed comment indentation
	- Amended commit message to specify that scratch regions
	are known good regions

 drivers/firmware/efi/efi-init.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index a00e07b853f2..99f7eecc320f 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -12,6 +12,7 @@
 #include <linux/efi.h>
 #include <linux/fwnode.h>
 #include <linux/init.h>
+#include <linux/kexec_handover.h>
 #include <linux/memblock.h>
 #include <linux/mm_types.h>
 #include <linux/of.h>
@@ -164,12 +165,31 @@ static __init void reserve_regions(void)
 		pr_info("Processing EFI memory map:\n");
 
 	/*
-	 * Discard memblocks discovered so far: if there are any at this
-	 * point, they originate from memory nodes in the DT, and UEFI
-	 * uses its own memory map instead.
+	 * Discard memblocks discovered so far except for KHO scratch
+	 * regions. Most memblocks at this point originate from memory nodes
+	 * in the DT and UEFI uses its own memory map instead. However, if
+	 * KHO is enabled, scratch regions must be preserved.
 	 */
 	memblock_dump_all();
-	memblock_remove(0, PHYS_ADDR_MAX);
+
+	if (is_kho_boot()) {
+		struct memblock_region *r;
+
+		/* Remove all non-KHO regions */
+		for_each_mem_region(r) {
+			if (!memblock_is_kho_scratch(r)) {
+				memblock_remove(r->base, r->size);
+				r--;
+			}
+		}
+	} else {
+		/*
+		 * KHO is disabled. Discard memblocks discovered so far:
+		 * if there are any at this point, they originate from memory
+		 * nodes in the DT, and UEFI uses its own memory map instead.
+		 */
+		memblock_remove(0, PHYS_ADDR_MAX);
+	}
 
 	for_each_efi_memory_desc(md) {
 		paddr = md->phys_addr;
-- 
2.47.3




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597



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

* Re: [PATCH v2 2/2] efi: Support booting with kexec handover (KHO)
  2025-08-19 23:22 ` [PATCH v2 2/2] efi: Support booting with kexec handover (KHO) Evangelos Petrongonas
@ 2025-08-20  8:09   ` Mike Rapoport
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2025-08-20  8:09 UTC (permalink / raw)
  To: Evangelos Petrongonas
  Cc: Ard Biesheuvel, Alexander Graf, Changyuan Lyu, Andrew Morton,
	Baoquan He, kexec, linux-mm, linux-efi, linux-kernel,
	nh-open-source

On Tue, Aug 19, 2025 at 11:22:46PM +0000, Evangelos Petrongonas wrote:
> When KHO (Kexec HandOver) is enabled, it sets up scratch memory regions
> early during device tree scanning. After kexec, the new kernel
> exclusively uses this region for memory allocations during boot up to
> the initialization of the page allocator
> 
> However, when booting with EFI, EFI's reserve_regions() uses
> memblock_remove(0, PHYS_ADDR_MAX) to clear all memory regions before
> rebuilding them from EFI data. This destroys KHO scratch regions and
> their flags, thus causing a kernel panic, as there are no scratch
> memory regions.
> 
> Instead of wholesale removal, iterate through memory regions and only
> remove non-KHO ones. This preserves KHO scratch regions, which are
> good known memory, while still allowing EFI to rebuild its memory map.
> 
> Signed-off-by: Evangelos Petrongonas <epetron@amazon.de>
> ---
> Changes in v2:
> 	- Replaced the for loop with for_each_mem_region
> 	- Fixed comment indentation
> 	- Amended commit message to specify that scratch regions
> 	are known good regions
> 
>  drivers/firmware/efi/efi-init.c | 28 ++++++++++++++++++++++++----
>  1 file changed, 24 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
> index a00e07b853f2..99f7eecc320f 100644
> --- a/drivers/firmware/efi/efi-init.c
> +++ b/drivers/firmware/efi/efi-init.c
> @@ -12,6 +12,7 @@
>  #include <linux/efi.h>
>  #include <linux/fwnode.h>
>  #include <linux/init.h>
> +#include <linux/kexec_handover.h>
>  #include <linux/memblock.h>
>  #include <linux/mm_types.h>
>  #include <linux/of.h>
> @@ -164,12 +165,31 @@ static __init void reserve_regions(void)
>  		pr_info("Processing EFI memory map:\n");
>  
>  	/*
> -	 * Discard memblocks discovered so far: if there are any at this
> -	 * point, they originate from memory nodes in the DT, and UEFI
> -	 * uses its own memory map instead.
> +	 * Discard memblocks discovered so far except for KHO scratch
> +	 * regions. Most memblocks at this point originate from memory nodes
> +	 * in the DT and UEFI uses its own memory map instead. However, if
> +	 * KHO is enabled, scratch regions must be preserved.

I'd add that KHO scratch regions are good know memory here as well. With
that

Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

>  	 */
>  	memblock_dump_all();
> -	memblock_remove(0, PHYS_ADDR_MAX);
> +
> +	if (is_kho_boot()) {
> +		struct memblock_region *r;
> +
> +		/* Remove all non-KHO regions */
> +		for_each_mem_region(r) {
> +			if (!memblock_is_kho_scratch(r)) {
> +				memblock_remove(r->base, r->size);
> +				r--;
> +			}
> +		}
> +	} else {
> +		/*
> +		 * KHO is disabled. Discard memblocks discovered so far:
> +		 * if there are any at this point, they originate from memory
> +		 * nodes in the DT, and UEFI uses its own memory map instead.
> +		 */
> +		memblock_remove(0, PHYS_ADDR_MAX);
> +	}
>  
>  	for_each_efi_memory_desc(md) {
>  		paddr = md->phys_addr;
> -- 
> 2.47.3

-- 
Sincerely yours,
Mike.


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

* Re: [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO)
  2025-08-19 23:22 [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO) Evangelos Petrongonas
  2025-08-19 23:22 ` [PATCH v2 1/2] kexec: introduce is_kho_boot() Evangelos Petrongonas
  2025-08-19 23:22 ` [PATCH v2 2/2] efi: Support booting with kexec handover (KHO) Evangelos Petrongonas
@ 2025-08-20  8:20 ` Mike Rapoport
  2 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2025-08-20  8:20 UTC (permalink / raw)
  To: Evangelos Petrongonas
  Cc: Ard Biesheuvel, Alexander Graf, Changyuan Lyu, Andrew Morton,
	Baoquan He, kexec, linux-mm, linux-efi, linux-kernel,
	nh-open-source

On Tue, Aug 19, 2025 at 11:22:44PM +0000, Evangelos Petrongonas wrote:
> This patch series fixes a kernel panic that occurs when booting with
> both EFI and KHO (Kexec HandOver) enabled.
> 
> The issue arises because EFI's `reserve_regions()` clears all memory
> regions with `memblock_remove(0, PHYS_ADDR_MAX)` before rebuilding them
> from EFI data. This destroys KHO scratch regions that were set up early
> during device tree scanning, causing a panic as the kernel has no valid
> memory regions for early allocations.
> 
> The first patch introduces `is_kho_boot()` to allow early boot
> components to reliably detect if the kernel was booted via KHO-enabled
> kexec. The existing `kho_is_enabled()` only checks the command line and
> doesn't verify if an actual KHO FDT was passed.
> 
> The second patch modifies EFI's `reserve_regions()` to selectively
> remove only non-KHO memory regions when KHO is active, preserving the
> critical scratch regions while still allowing EFI to rebuild its memory
> map.
> 
> The patchset was developed/tested on arm64.
> 
> On a side note, I have noticed that `kho_populate()` calls
> `memblock_set_kho_scratch_only()`, but the `kho` cmdline option is
> not checked until much later. Therefore, memblock will use only the
> scratch regions that were passed from the outgoing kernel, even if the
> incoming kernel doesn't explicitly want that. I am not sure if this is
> done on purpose, but in any case we can discuss this in another patch,
> as it is orthogonal to this one.

kho_populate runs earlier than we parse the command line, so there is an
implicit assumption that we are going through KHO-enabled kexec if FDT was
passed to the new kernel.

I believe the best way is to document that and make it more explicit that
kho command line parameter only affects the "out" part.
 
> Main Changes in v2 (smaller changes can be found in individual patches):
>     - Introduce is_kho_boot()
>     - Replaced manual loop with for_each_mem_region macro
> 
> Evangelos Petrongonas (2):
>   kexec: introduce is_kho_boot()
>   efi: Support booting with kexec handover (KHO)
> 
>  drivers/firmware/efi/efi-init.c | 28 ++++++++++++++++++++++++----
>  include/linux/kexec_handover.h  |  6 ++++++
>  kernel/kexec_handover.c         | 20 ++++++++++++++++++++
>  3 files changed, 50 insertions(+), 4 deletions(-)
> 
> -- 
> 2.47.3

-- 
Sincerely yours,
Mike.


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

* Re: [PATCH v2 1/2] kexec: introduce is_kho_boot()
  2025-08-19 23:22 ` [PATCH v2 1/2] kexec: introduce is_kho_boot() Evangelos Petrongonas
@ 2025-08-20  8:24   ` Mike Rapoport
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2025-08-20  8:24 UTC (permalink / raw)
  To: Evangelos Petrongonas
  Cc: Ard Biesheuvel, Alexander Graf, Changyuan Lyu, Andrew Morton,
	Baoquan He, kexec, linux-mm, linux-efi, linux-kernel,
	nh-open-source

On Tue, Aug 19, 2025 at 11:22:45PM +0000, Evangelos Petrongonas wrote:
> During early initialisation, after a kexec, other components, like EFI
> need to know if a KHO enabled kexec is performed. The `kho_is_enabled`
> function is not enough as in the early stages, it only reflects
> whether the cmdline has KHO enabled, not if an actual KHO FDT exists.
> 
> Extend the KHO API with `is_kho_boot()` to provide a way for components
> to check if a KHO enabled kexec is performed.
> 
> Signed-off-by: Evangelos Petrongonas <epetron@amazon.de>
> ---
>  include/linux/kexec_handover.h |  6 ++++++
>  kernel/kexec_handover.c        | 20 ++++++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
> index 348844cffb13..559d13a3bc44 100644
> --- a/include/linux/kexec_handover.h
> +++ b/include/linux/kexec_handover.h
> @@ -40,6 +40,7 @@ struct kho_serialization;
>  
>  #ifdef CONFIG_KEXEC_HANDOVER
>  bool kho_is_enabled(void);
> +bool is_kho_boot(void);
>  
>  int kho_preserve_folio(struct folio *folio);
>  int kho_preserve_phys(phys_addr_t phys, size_t size);
> @@ -60,6 +61,11 @@ static inline bool kho_is_enabled(void)
>  	return false;
>  }
>  
> +static inline bool is_kho_boot(void)
> +{
> +	return false;
> +}
> +
>  static inline int kho_preserve_folio(struct folio *folio)
>  {
>  	return -EOPNOTSUPP;
> diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
> index 69b953551677..a1a4e76e0ff1 100644
> --- a/kernel/kexec_handover.c
> +++ b/kernel/kexec_handover.c
> @@ -925,6 +925,26 @@ static const void *kho_get_fdt(void)
>  	return kho_in.fdt_phys ? phys_to_virt(kho_in.fdt_phys) : NULL;
>  }
>  
> +/**
> + * is_kho_boot - check if current kernel was booted via KHO-enabled
> + * kexec
> + *
> + * This function checks if the current kernel was loaded through a kexec
> + * operation with KHO enabled, by verifying both that KHO is enabled via
> + * cmdline AND that a valid KHO FDT was passed.
> + *
> + * Note: This function returns reliable results only after
> + * kho_populate() has been called during early boot. Before that,
> + * it may return false even if KHO data is present.
> + *
> + * Return: true if booted via KHO-enabled kexec, false otherwise
> + */
> +bool is_kho_boot(void)
> +{
> +	return !!kho_get_fdt() && kho_enable;

Let's drop '&& kho_enable' and presume that a kernel that booted with KHO
FDT goes through KHO revival.

With that change feel free to add

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

> +}
> +EXPORT_SYMBOL_GPL(is_kho_boot);
> +
>  /**
>   * kho_retrieve_subtree - retrieve a preserved sub FDT by its name.
>   * @name: the name of the sub FDT passed to kho_add_subtree().
> -- 
> 2.47.3

-- 
Sincerely yours,
Mike.


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

end of thread, other threads:[~2025-08-20  9:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-19 23:22 [PATCH v2 0/2] efi: Fix EFI boot with kexec handover (KHO) Evangelos Petrongonas
2025-08-19 23:22 ` [PATCH v2 1/2] kexec: introduce is_kho_boot() Evangelos Petrongonas
2025-08-20  8:24   ` Mike Rapoport
2025-08-19 23:22 ` [PATCH v2 2/2] efi: Support booting with kexec handover (KHO) Evangelos Petrongonas
2025-08-20  8:09   ` Mike Rapoport
2025-08-20  8:20 ` [PATCH v2 0/2] efi: Fix EFI boot " Mike Rapoport

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).