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>
Subject: [PATCH v2 10/19] x86/efi: Do not rely on EFI_MEMORY_RUNTIME bit and avoid entry splitting
Date: Thu, 19 Mar 2026 10:05:40 +0100 [thread overview]
Message-ID: <20260319090529.1091660-31-ardb+git@google.com> (raw)
In-Reply-To: <20260319090529.1091660-21-ardb+git@google.com>
From: Ard Biesheuvel <ardb@kernel.org>
Now that efi_mem_reserve() has been updated to rely on RSRV_KERN
memblock reservations, it is no longer needed to mark memblock reserved
boot services regions as EFI_MEMORY_RUNTIME. This means that it is no
longer needed to split existing entries in the EFI memory map, removing
the need to re-allocate/copy/remap the entire EFI memory map on every
call to efi_mem_reserve().
So drop this functionality - it is no longer needed.
Note that, for the time being, the E820 map needs to be consulted to
decide whether or not an entry with the EFI_MEMORY_RUNTIME bit cleared
needs to be preserved in the runtime map or not. However, this will be
superseded and removed by a subsequent patch, which combines the map
compaction with the actual freeing, in which case the freeing logic can
answer this question directly.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/include/asm/efi.h | 4 -
arch/x86/platform/efi/memmap.c | 138 --------------------
arch/x86/platform/efi/quirks.c | 62 +--------
3 files changed, 6 insertions(+), 198 deletions(-)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 51b4cdbea061..b01dd639bf62 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -396,10 +396,6 @@ extern int __init efi_memmap_alloc(unsigned int num_entries,
struct efi_memory_map_data *data);
extern int __init efi_memmap_install(struct efi_memory_map_data *data);
-extern int __init efi_memmap_split_count(efi_memory_desc_t *md,
- struct range *range);
-extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap,
- void *buf, struct efi_mem_range *mem);
extern enum efi_secureboot_mode __x86_ima_efi_boot_mode(void);
diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c
index 023697c88910..8ef45014c7e7 100644
--- a/arch/x86/platform/efi/memmap.c
+++ b/arch/x86/platform/efi/memmap.c
@@ -110,141 +110,3 @@ int __init efi_memmap_install(struct efi_memory_map_data *data)
__efi_memmap_free(phys, size, flags);
return 0;
}
-
-/**
- * efi_memmap_split_count - Count number of additional EFI memmap entries
- * @md: EFI memory descriptor to split
- * @range: Address range (start, end) to split around
- *
- * Returns the number of additional EFI memmap entries required to
- * accommodate @range.
- */
-int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range)
-{
- u64 m_start, m_end;
- u64 start, end;
- int count = 0;
-
- start = md->phys_addr;
- end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- /* modifying range */
- m_start = range->start;
- m_end = range->end;
-
- if (m_start <= start) {
- /* split into 2 parts */
- if (start < m_end && m_end < end)
- count++;
- }
-
- if (start < m_start && m_start < end) {
- /* split into 3 parts */
- if (m_end < end)
- count += 2;
- /* split into 2 parts */
- if (end <= m_end)
- count++;
- }
-
- return count;
-}
-
-/**
- * efi_memmap_insert - Insert a memory region in an EFI memmap
- * @old_memmap: The existing EFI memory map structure
- * @buf: Address of buffer to store new map
- * @mem: Memory map entry to insert
- *
- * It is suggested that you call efi_memmap_split_count() first
- * to see how large @buf needs to be.
- */
-void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
- struct efi_mem_range *mem)
-{
- u64 m_start, m_end, m_attr;
- efi_memory_desc_t *md;
- u64 start, end;
- void *old, *new;
-
- /* modifying range */
- m_start = mem->range.start;
- m_end = mem->range.end;
- m_attr = mem->attribute;
-
- /*
- * The EFI memory map deals with regions in EFI_PAGE_SIZE
- * units. Ensure that the region described by 'mem' is aligned
- * correctly.
- */
- if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) ||
- !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) {
- WARN_ON(1);
- return;
- }
-
- for (old = old_memmap->map, new = buf;
- old < old_memmap->map_end;
- old += old_memmap->desc_size, new += old_memmap->desc_size) {
-
- /* copy original EFI memory descriptor */
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- start = md->phys_addr;
- end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- if (m_start <= start && end <= m_end)
- md->attribute |= m_attr;
-
- if (m_start <= start &&
- (start < m_end && m_end < end)) {
- /* first part */
- md->attribute |= m_attr;
- md->num_pages = (m_end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- /* latter part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_end + 1;
- md->num_pages = (end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- }
-
- if ((start < m_start && m_start < end) && m_end < end) {
- /* first part */
- md->num_pages = (m_start - md->phys_addr) >>
- EFI_PAGE_SHIFT;
- /* middle part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->attribute |= m_attr;
- md->phys_addr = m_start;
- md->num_pages = (m_end - m_start + 1) >>
- EFI_PAGE_SHIFT;
- /* last part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_end + 1;
- md->num_pages = (end - m_end) >>
- EFI_PAGE_SHIFT;
- }
-
- if ((start < m_start && m_start < end) &&
- (end <= m_end)) {
- /* first part */
- md->num_pages = (m_start - md->phys_addr) >>
- EFI_PAGE_SHIFT;
- /* latter part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_start;
- md->num_pages = (end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- md->attribute |= m_attr;
- }
- }
-}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 13d9e036a23a..ae4ad6389f9e 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -239,63 +239,9 @@ EXPORT_SYMBOL_GPL(efi_query_variable_store);
* buggy implementations we reserve boot services region during EFI
* init and make sure it stays executable. Then, after
* SetVirtualAddressMap(), it is discarded.
- *
- * However, some boot services regions contain data that is required
- * by drivers, so we need to track which memory ranges can never be
- * freed. This is done by tagging those regions with the
- * EFI_MEMORY_RUNTIME attribute.
- *
- * Any driver that wants to mark a region as reserved must use
- * efi_mem_reserve() which will insert a new EFI memory descriptor
- * into efi.memmap (splitting existing regions if necessary) and tag
- * it with EFI_MEMORY_RUNTIME.
*/
void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
{
- struct efi_memory_map_data data = { 0 };
- struct efi_mem_range mr;
- efi_memory_desc_t md;
- int num_entries;
- void *new;
-
- if (efi_mem_desc_lookup(addr, &md) ||
- md.type != EFI_BOOT_SERVICES_DATA) {
- pr_err("Failed to lookup EFI memory descriptor for %pa\n", &addr);
- return;
- }
-
- if (addr + size > md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT)) {
- pr_err("Region spans EFI memory descriptors, %pa\n", &addr);
- return;
- }
-
- size += addr % EFI_PAGE_SIZE;
- size = round_up(size, EFI_PAGE_SIZE);
- addr = round_down(addr, EFI_PAGE_SIZE);
-
- mr.range.start = addr;
- mr.range.end = addr + size - 1;
- mr.attribute = md.attribute | EFI_MEMORY_RUNTIME;
-
- num_entries = efi_memmap_split_count(&md, &mr.range);
- num_entries += efi.memmap.nr_map;
-
- if (efi_memmap_alloc(num_entries, &data) != 0) {
- pr_err("Could not allocate boot services memmap\n");
- return;
- }
-
- new = early_memremap_prot(data.phys_map, data.size,
- pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL)));
- if (!new) {
- pr_err("Failed to map new boot services memmap\n");
- return;
- }
-
- efi_memmap_insert(&efi.memmap, new, &mr);
- early_memunmap(new, data.size);
-
- efi_memmap_install(&data);
e820__range_update(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
e820__update_table(e820_table);
}
@@ -446,7 +392,8 @@ void __init efi_unmap_boot_services(void)
efi_unmap_pages(md);
/* Do not free, someone else owns it: */
- if (md->attribute & EFI_MEMORY_RUNTIME) {
+ if ((md->attribute & EFI_MEMORY_RUNTIME) ||
+ !can_free_region(start, size)) {
num_entries++;
continue;
}
@@ -485,8 +432,11 @@ void __init efi_unmap_boot_services(void)
for_each_efi_memory_desc(md) {
if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
(md->type == EFI_BOOT_SERVICES_CODE ||
- md->type == EFI_BOOT_SERVICES_DATA))
+ md->type == EFI_BOOT_SERVICES_DATA) &&
+ can_free_region(md->phys_addr,
+ md->num_pages << EFI_PAGE_SHIFT)) {
continue;
+ }
memcpy(new_md, md, efi.memmap.desc_size);
new_md += efi.memmap.desc_size;
--
2.53.0.851.ga537e3e6e9-goog
next prev parent reply other threads:[~2026-03-19 9:06 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-19 9:05 [PATCH v2 00/19] efi/x86: Avoid the need to mangle the EFI memory map Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 01/19] memblock: Permit existing reserved regions to be marked RSRV_KERN Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 02/19] efi: Tag memblock reservations of boot services regions as RSRV_KERN Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 03/19] x86/efi: Unmap kernel-reserved boot regions from EFI page tables Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 04/19] x86/efi: Drop EFI_MEMORY_RUNTIME check from __ioremap_check_other() Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 05/19] x86/efi: Omit RSRV_KERN memblock reservations when freeing boot regions Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 06/19] x86/efi: Defer sub-1M check from unmap to free stage Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 07/19] x86/efi: Simplify real mode trampoline allocation quirk Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 08/19] x86/efi: Omit redundant kernel image overlap check Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 09/19] x86/efi: Drop redundant EFI_PARAVIRT check Ard Biesheuvel
2026-03-19 9:05 ` Ard Biesheuvel [this message]
2026-03-19 9:05 ` [PATCH v2 11/19] efi: Use nr_map not map_end to find the last valid memory map entry Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 12/19] x86/efi: Only merge EFI memory map entries on 32-bit systems Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 13/19] x86/efi: Clean the memory map using iterator and filter API Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 14/19] x86/efi: Update the runtime map in place Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 15/19] x86/efi: Use iterator API when mapping EFI regions for runtime Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 16/19] x86/efi: Reuse memory map instead of reallocating it Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 17/19] x86/efi: Defer compaction of the EFI memory map Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 18/19] x86/efi: Do not abuse RUNTIME bit to mark boot regions as reserved Ard Biesheuvel
2026-03-19 9:05 ` [PATCH v2 19/19] x86/efi: Free unused tail of the EFI memory map Ard Biesheuvel
2026-03-24 9:50 ` [PATCH v2 00/19] efi/x86: Avoid the need to mangle " 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=20260319090529.1091660-31-ardb+git@google.com \
--to=ardb+git@google.com \
--cc=ardb@kernel.org \
--cc=benh@kernel.crashing.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rppt@kernel.org \
--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 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.