From: Ard Biesheuvel <ardb+git@google.com>
To: linux-kernel@vger.kernel.org
Cc: linux-efi@vger.kernel.org, x86@kernel.org,
Ard Biesheuvel <ardb@kernel.org>,
"Mike Rapoport (Microsoft)" <rppt@kernel.org>,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Dave Young <ruirui.yang@linux.dev>,
Gregory Price <gourry@gourry.net>
Subject: [PATCH v3 11/17] efi: Use nr_map not map_end to find the last valid memory map entry
Date: Thu, 23 Apr 2026 17:20:36 +0200 [thread overview]
Message-ID: <20260423152024.1098465-30-ardb+git@google.com> (raw)
In-Reply-To: <20260423152024.1098465-19-ardb+git@google.com>
From: Ard Biesheuvel <ardb@kernel.org>
Currently, the efi.memmap struct keeps track of the start and the end of
the EFI memory map in memory, as well as the number of entries.
Let's repaint the nr_map field as the number of *valid* entries, and
update all the iterators and other memory map traversal routines
accordingly.
This allows pruning of invalid or unneeded entries by moving the
remaining entries to the start of the map, without the need for
freeing/reallocating or unmapping and remapping. Now that entries are
never added, but only removed, it is possible to retain the same
allocation throughout the boot process, and free the part that is no
longer in use afterwards.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/platform/efi/efi.c | 18 ++++++++++++------
arch/x86/platform/efi/memmap.c | 2 +-
arch/x86/platform/efi/quirks.c | 2 +-
arch/x86/platform/efi/runtime-map.c | 4 ++--
drivers/firmware/efi/arm-runtime.c | 2 +-
drivers/firmware/efi/memmap.c | 8 +++-----
drivers/firmware/efi/riscv-runtime.c | 2 +-
include/linux/efi.h | 8 ++++----
8 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index c0195b5eab21..edbf6efe3947 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -222,7 +222,7 @@ int __init efi_memblock_x86_reserve_range(void)
"Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
efi.memmap.desc_version);
- memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
+ memblock_reserve(pmap, efi.memmap.num_valid_entries * efi.memmap.desc_size);
set_bit(EFI_PRESERVE_BS_REGIONS, &efi.flags);
return 0;
@@ -289,7 +289,7 @@ static void __init efi_clean_memmap(void)
.phys_map = efi.memmap.phys_map,
.desc_version = efi.memmap.desc_version,
.desc_size = efi.memmap.desc_size,
- .size = efi.memmap.desc_size * (efi.memmap.nr_map - n_removal),
+ .size = efi.memmap.desc_size * (efi.memmap.num_valid_entries - n_removal),
.flags = 0,
};
@@ -533,7 +533,8 @@ static inline void *efi_map_next_entry_reverse(void *entry)
{
/* Initial call */
if (!entry)
- return efi.memmap.map_end - efi.memmap.desc_size;
+ return efi_memdesc_ptr(efi.memmap.map, efi.memmap.desc_size,
+ efi.memmap.num_valid_entries - 1);
entry -= efi.memmap.desc_size;
if (entry < efi.memmap.map)
@@ -555,6 +556,9 @@ static inline void *efi_map_next_entry_reverse(void *entry)
*/
static void *efi_map_next_entry(void *entry)
{
+ if (!efi.memmap.num_valid_entries)
+ return NULL;
+
if (efi_enabled(EFI_64BIT)) {
/*
* Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
@@ -581,7 +585,9 @@ static void *efi_map_next_entry(void *entry)
return efi.memmap.map;
entry += efi.memmap.desc_size;
- if (entry >= efi.memmap.map_end)
+ if (entry >= (void *)efi_memdesc_ptr(efi.memmap.map,
+ efi.memmap.desc_size,
+ efi.memmap.num_valid_entries))
return NULL;
return entry;
@@ -712,13 +718,13 @@ static void __init kexec_enter_virtual_mode(void)
efi_memmap_unmap();
if (efi_memmap_init_late(efi.memmap.phys_map,
- efi.memmap.desc_size * efi.memmap.nr_map)) {
+ efi.memmap.desc_size * efi.memmap.num_valid_entries)) {
pr_err("Failed to remap late EFI memory map\n");
clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return;
}
- num_pages = ALIGN(efi.memmap.nr_map * efi.memmap.desc_size, PAGE_SIZE);
+ num_pages = ALIGN(efi.memmap.num_valid_entries * efi.memmap.desc_size, PAGE_SIZE);
num_pages >>= PAGE_SHIFT;
if (efi_setup_page_tables(efi.memmap.phys_map, num_pages)) {
diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c
index da7483a33d68..524e9f2ef276 100644
--- a/arch/x86/platform/efi/memmap.c
+++ b/arch/x86/platform/efi/memmap.c
@@ -90,7 +90,7 @@ int __init efi_memmap_alloc(unsigned int num_entries,
*/
int __init efi_memmap_install(struct efi_memory_map_data *data)
{
- unsigned long size = efi.memmap.desc_size * efi.memmap.nr_map;
+ unsigned long size = efi.memmap.map_end - efi.memmap.map;
unsigned long flags = efi.memmap.flags;
u64 phys = efi.memmap.phys_map;
int ret;
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index efb828b7e2ab..eb00130bcb66 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -410,7 +410,7 @@ void __init efi_unmap_boot_services(void)
if (efi_enabled(EFI_DBG))
return;
- num_to_free = efi.memmap.nr_map;
+ num_to_free = efi.memmap.num_valid_entries;
ranges_to_free = kmalloc_array(num_to_free, sizeof(ranges_to_free[0]),
GFP_KERNEL);
if (!ranges_to_free) {
diff --git a/arch/x86/platform/efi/runtime-map.c b/arch/x86/platform/efi/runtime-map.c
index 053ff161eb9a..fc8ca1974730 100644
--- a/arch/x86/platform/efi/runtime-map.c
+++ b/arch/x86/platform/efi/runtime-map.c
@@ -138,7 +138,7 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr,
int efi_get_runtime_map_size(void)
{
- return efi.memmap.nr_map * efi.memmap.desc_size;
+ return efi.memmap.num_valid_entries * efi.memmap.desc_size;
}
int efi_get_runtime_map_desc_size(void)
@@ -166,7 +166,7 @@ static int __init efi_runtime_map_init(void)
if (!efi_enabled(EFI_MEMMAP) || !efi_kobj)
return 0;
- map_entries = kzalloc_objs(entry, efi.memmap.nr_map);
+ map_entries = kzalloc_objs(entry, efi.memmap.num_valid_entries);
if (!map_entries) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 3167cab62014..e19997c09175 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -96,7 +96,7 @@ static int __init arm_enable_runtime_services(void)
efi_memmap_unmap();
- mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
+ mapsize = efi.memmap.desc_size * efi.memmap.num_valid_entries;
if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
pr_err("Failed to remap EFI memory map\n");
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index f1c04d7cfd71..035089791c93 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -49,7 +49,7 @@ int __init __efi_memmap_init(struct efi_memory_map_data *data)
}
map.phys_map = data->phys_map;
- map.nr_map = data->size / data->desc_size;
+ map.num_valid_entries = data->size / data->desc_size;
map.map_end = map.map + data->size;
map.desc_version = data->desc_version;
@@ -87,10 +87,8 @@ void __init efi_memmap_unmap(void)
return;
if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) {
- unsigned long size;
-
- size = efi.memmap.desc_size * efi.memmap.nr_map;
- early_memunmap(efi.memmap.map, size);
+ early_memunmap(efi.memmap.map,
+ efi.memmap.map_end - efi.memmap.map);
} else {
memunmap(efi.memmap.map);
}
diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c
index 60cdf7bf141f..087a7f8a74e6 100644
--- a/drivers/firmware/efi/riscv-runtime.c
+++ b/drivers/firmware/efi/riscv-runtime.c
@@ -66,7 +66,7 @@ static int __init riscv_enable_runtime_services(void)
efi_memmap_unmap();
- mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
+ mapsize = efi.memmap.desc_size * efi.memmap.num_valid_entries;
if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
pr_err("Failed to remap EFI memory map\n");
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 72e76ec54641..a8406ca92332 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -568,7 +568,7 @@ struct efi_memory_map {
phys_addr_t phys_map;
void *map;
void *map_end;
- int nr_map;
+ int num_valid_entries;
unsigned long desc_version;
unsigned long desc_size;
#define EFI_MEMMAP_LATE (1UL << 0)
@@ -803,9 +803,9 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
/* Iterate through an efi_memory_map */
#define for_each_efi_memory_desc_in_map(m, md) \
- for ((md) = (m)->map; \
- (md) && ((void *)(md) + (m)->desc_size) <= (m)->map_end; \
- (md) = (void *)(md) + (m)->desc_size)
+ for (int __idx = 0; \
+ (md) = efi_memdesc_ptr((m)->map, (m)->desc_size, __idx), \
+ __idx < (m)->num_valid_entries; ++__idx)
/**
* for_each_efi_memory_desc - iterate over descriptors in efi.memmap
--
2.54.0.rc2.544.gc7ae2d5bb8-goog
next prev parent reply other threads:[~2026-04-23 15:21 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-23 15:20 [PATCH v3 00/17] efi/x86: Avoid the need to mangle the EFI memory map Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 01/17] x86/efi: Omit redundant kernel image overlap check Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 02/17] x86/efi: Drop redundant EFI_PARAVIRT check Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 03/17] x86/efi: Only merge EFI memory map entries on 32-bit systems Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 04/17] x86/efi: Defer sub-1M check from unmap to free stage Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 05/17] x86/efi: Simplify real mode trampoline allocation quirk Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 06/17] x86/efi: Unmap kernel-reserved boot regions from EFI page tables Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 07/17] x86/efi: Drop EFI_MEMORY_RUNTIME check from __ioremap_check_other() Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 08/17] x86/efi: Allow ranges_to_free array to grow beyond initial size Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 09/17] x86/efi: Intersect ranges_to_free with MEMBLOCK_RSRV_KERN regions Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 10/17] x86/efi: Do not rely on EFI_MEMORY_RUNTIME bit and avoid entry splitting Ard Biesheuvel
2026-04-23 15:20 ` Ard Biesheuvel [this message]
2026-04-23 15:20 ` [PATCH v3 12/17] x86/efi: Clean the memory map using iterator and filter API Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 13/17] x86/efi: Update the runtime map in place Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 14/17] x86/efi: Reuse memory map instead of reallocating it Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 15/17] x86/efi: Merge two traversals of the memory map when freeing boot regions Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 16/17] x86/efi: Avoid EFI_MEMORY_RUNTIME for early EFI boot memory reservations Ard Biesheuvel
2026-04-23 15:20 ` [PATCH v3 17/17] x86/efi: Drop kexec quirk for the EFI memory attributes table Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260423152024.1098465-30-ardb+git@google.com \
--to=ardb+git@google.com \
--cc=ardb@kernel.org \
--cc=benh@kernel.crashing.org \
--cc=gourry@gourry.net \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rppt@kernel.org \
--cc=ruirui.yang@linux.dev \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox