From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37B56372EC0 for ; Thu, 23 Apr 2026 15:21:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776957674; cv=none; b=sKpbGMMJctVjGk03USJBLyK1Afbu0QUJ0BaDXvhSUFzQuK9mSnMiKO7L1aJtFxKooLWsK9LcIu7A/9MYfEe7O1m27PmbBBMu0gWNCENTi1k4iWPGndI1lmSBNe696p4zulYjcEUguhmaqaZj0WENjaVjK5PGsX68MC5HhUXYm0Y= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776957674; c=relaxed/simple; bh=QJhcTCp3YWRk82k5dY7bOrapMMe8ofCD/shtK0L/ecw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dnzxQQMVvWLD4UYT+QYGAgFYP9Ofnvabxh+hYayUO+eDYT87uvnR+IJXvf2EJHBab77cnnPvK/fqjK/dgHAOnT4QAosa52EyvkCajFX/+1NXIqsOYnkzvcEcsBZJmLixv+wqQqFWKo8HdgGmaIdWHbjKXcha4xQ5cSQohNihwn0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=SEFpaJp5; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="SEFpaJp5" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-4411a36715dso3367899f8f.2 for ; Thu, 23 Apr 2026 08:21:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1776957672; x=1777562472; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Rm/hickqQysiSynTiIHCGr3FHLXl71ce3ok8oWE0Hnc=; b=SEFpaJp5cXMYQe26/f7fcQaPmbWKGJ98AdbPqKHOGt1tiddPfdogUw3jBcliCERUhm d8AG/jebqK/qUB36UqGnCzxi968xerE1d2A66Eb73M/fq/t6pavEma90byq6St/YSePC TTxDJ+YekQzH/ycEQo/42GituZJJPam6p0d+0m2YabMSLnC4tVe0OydTQ9xt+1jmY3B9 +cZHFG6PvjUf8WHuW3WsqLOBfh0e7uqBs544ST3sHGKs72GEHo1+AwRrGrkog6fkGfOR 2rKrXRCZT/jeSpAFsrMXQEQOXSe6X/zs6Q8Tx1kxR4w78tMG08mzlKrxOb+2JNVLbSR1 vJcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776957672; x=1777562472; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Rm/hickqQysiSynTiIHCGr3FHLXl71ce3ok8oWE0Hnc=; b=Ngr5d9whfEoGn9XkoU8nBMt5VMHNOY763R/1XPPiD8LOGykki8b5REuMIKiZZa4tRY efczszOQUMhiGqNEPWDxqvuTpX9xljygB4jNgnxxLk9QOveUIOyuJOMHiIM8mk005qHv BxZmjwQ9QWdkB98dhxwBPQQgjMTgPbkR/u+ov4NPfh+DcysMKXBGow/XC79MgvWJqkL3 apr7ORMWvj/flh0mJMajeLkwYCe3PINInm3a1YV55yz0uLF/xVo/Ms2Q9tMLW6ZXAQLE rTIan2HDCg1nNs9bIdelip5LkIi/JiPumqByAh+r8kJjhs4v6GgIRx/XV01XyCQoqLNf GdwA== X-Gm-Message-State: AOJu0Yz3xWmO2HBBTybqhE6nyvjHyMDmdH5ygrbXjrOaRf9FNGU2dr9q IxvNftzAANlzOgqknt3MrpBjYo96NeyPrcrTMykzGPUSjPAptW5l3zrIKNg7Ie1TXPgiP+rs3zu UKmlWmQE7bAntzN1hz1WvCfW2NJAUiXnLuugb6WPW84Z8YUQXviRmluccFuzfPUxhRksdL7eCTl Cny1HzmM/Ot8cgPx57Ugo0yoIegwOZyU/8Cg== X-Received: from wmlu21.prod.google.com ([2002:a05:600c:2115:b0:488:7c5a:b238]) (user=ardb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4707:b0:488:bfc3:efc with SMTP id 5b1f17b1804b1-488fb6e8eb5mr393522635e9.0.1776957671595; Thu, 23 Apr 2026 08:21:11 -0700 (PDT) Date: Thu, 23 Apr 2026 17:20:36 +0200 In-Reply-To: <20260423152024.1098465-19-ardb+git@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260423152024.1098465-19-ardb+git@google.com> X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=8578; i=ardb@kernel.org; h=from:subject; bh=n4XiAYaFtIBUTDvCKEmsnxORvxDae62lgJVzXOe0/QA=; b=owGbwMvMwCVmkMcZplerG8N4Wi2JIfOVxckdRn8r9L9LN2ytNX68atpX434fC/3jjoqeX9+sX MD/Lyyuo5SFQYyLQVZMkUVg9t93O09PlKp1niULM4eVCWQIAxenAEzkqCvDX7nex3fFWyv9H/J/ O2eQ1DS3/Gv4z5y0tqvGjz/fytO5YsvwP3Wylanm2tevEv9r7TD5oThvYZelZZZMZ9T+1Tt+MBU 0cgIA X-Mailer: git-send-email 2.54.0.rc2.544.gc7ae2d5bb8-goog Message-ID: <20260423152024.1098465-30-ardb+git@google.com> Subject: [PATCH v3 11/17] efi: Use nr_map not map_end to find the last valid memory map entry From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Cc: linux-efi@vger.kernel.org, x86@kernel.org, Ard Biesheuvel , "Mike Rapoport (Microsoft)" , Benjamin Herrenschmidt , Dave Young , Gregory Price Content-Type: text/plain; charset="UTF-8" From: Ard Biesheuvel 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 --- 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