summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2026-10-12 14:06:12 +0200
committerArd Biesheuvel <ardb@kernel.org>2026-10-15 13:53:08 +0200
commitaaf3ed0f46298e18ec8bc477cf0a37478e41f2ea (patch)
tree68493c94d47dcd52b1550281dc4aac18c88c0294
parentb49be1e7478afdb4ec96aedeb17f906253326c48 (diff)
downloadlinux-next-aaf3ed0f46298e18ec8bc477cf0a37478e41f2ea.tar.gz
linux-next-aaf3ed0f46298e18ec8bc477cf0a37478e41f2ea.zip
efi/libstub: Don't replace an existing LINUX_EFI_MEMRESERVE table
The LINUX_EFI_MEMRESERVE table is the root of a linked list of memory reservations that need to persist across kexec, such as the GICv3 LPI pending and property tables, which cannot be moved once the redistributors have been enabled. Each kernel adds its own reservations to the list that it finds via the EFI configuration table, and honours the ones made by its predecessors. The EFI stub installs a new, empty table unconditionally, replacing any existing one. This is fine on a cold boot, but not if the stub is being executed by a loader that passes on the configuration tables of an earlier kernel, e.g., a kexec loader that runs the incoming kernel's EFI stub, as the reservations made by earlier kernels would be lost. So leave an existing table in place, and only install a new one if none exists yet. Cc: <stable@vger.kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 975148f986bf..6db10590f89b 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -83,6 +83,14 @@ static void install_memreserve_table(void)
struct linux_efi_memreserve *rsv;
efi_status_t status;
+ /*
+ * If an earlier boot stage installed a memreserve table already, e.g.,
+ * a kexec loader passing on the persistent reservations made by the
+ * previous kernel, use it as is: installing a new one would replace it.
+ */
+ if (get_efi_config_table(memreserve_table_guid))
+ return;
+
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv);
if (status != EFI_SUCCESS) {