From patchwork Mon Oct 3 11:26:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A429EC4332F for ; Mon, 3 Oct 2022 11:26:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229830AbiJCL0m (ORCPT ); Mon, 3 Oct 2022 07:26:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229446AbiJCL0i (ORCPT ); Mon, 3 Oct 2022 07:26:38 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE5652AC66 for ; Mon, 3 Oct 2022 04:26:36 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7A161B8105A for ; Mon, 3 Oct 2022 11:26:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4010C43470; Mon, 3 Oct 2022 11:26:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796394; bh=lpQ4+WmITmtmOnKFnxuwxQHGwlCFJ4zTtvospQM9GKk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K9ID/meLYrn0iHyhvkrGaVzZES7EFVJpDW0Uw9aDg2M81HUgIx3frx0cFPJop1arF vgRUsJ37RND+bWXPfbtBFAdH5j+1mk+62cnz90JM8A40hCCp4oTwAnZyGKNkF/2dwE KBqstIRcIaoSImv4Mne7Gja/jq71Kp4NI/jjGDNpaNbzgz9oe372Ridjm0lBwXGcyr iwSpUGMJX/8UxZ2AS32VumjW87yYtxSe1Chbd1asWLgLqGyQoyz8qmXULZxXUjsIed MxkcNn1E3uEfsCTPRGFWY5eaTMnpaYyJXrS44pjrZjiba6qmhAd+2w5s9S0le4zqDP vN6tusSTeesmg== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 1/6] efi: Move EFI fake memmap support into x86 arch tree Date: Mon, 3 Oct 2022 13:26:20 +0200 Message-Id: <20221003112625.972646-2-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11648; i=ardb@kernel.org; h=from:subject; bh=lpQ4+WmITmtmOnKFnxuwxQHGwlCFJ4zTtvospQM9GKk=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbWzvxr8yONNNbEpLG35L+GKpYlawmf5lOH3UFh k0+XysqJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG1gAKCRDDTyI5ktmPJBRBDA CixbtB0CwvPLakaVceoJAQw8qQp1WDRfoHfeuCKX7ncix1T1+dYnYT7rv36evcoTla9LTIKQ+9Mkci UsRk9egPOu2Iji+te1wm5kdK5zHzh632bZ7S8hxo0DxaqPGheCnlh4ZVjht6EgSGZZYB8zvFSYQ5GU /am/hsSBLOMBjJS53c8heoJFAVYCzdZa9Q4GbxZliAE5s3So7A12gFwWpera0POthgZCzk89JQkPgE 8JFKcrU8H5uRzx2tEFQHfkaWgV+5Ce3Y4j2tFkqTYvCNkYJkyh2ndPk+eod5JVdww+/NYpYNl/Xm6p hQZI1XSSHGWqoGecrPpipl954qmi6j78R/xW9xF8prTJPNnfmHHi0EDMrOp3M3gO8M1R7oE85P7FVy JuXTKcPq5BZnsS3h8FnmGocp9kjpQuDf6rMLbCvgloMNiKNYClETqusN3AA5QXnExGnGmMnSkBGC0s 0ZodJ7yi6FzBLeCp4AaqflSxHSUCwxu5iWdHdNB+cwX+o= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The EFI fake memmap support is specific to x86, which manipulates the EFI memory map in various different ways after receiving it from the EFI stub. On other architectures, we have manages to push back on this, and the EFI memory map is kept pristine. So let's move the fake memmap code into the x86 arch tree, where it arguably belongs. Signed-off-by: Ard Biesheuvel --- arch/x86/Kconfig | 20 +++++ arch/x86/include/asm/efi.h | 5 ++ arch/x86/kernel/setup.c | 1 + arch/x86/platform/efi/Makefile | 1 + {drivers/firmware => arch/x86/platform}/efi/fake_mem.c | 79 +++++++++++++++++++- drivers/firmware/efi/Kconfig | 22 ------ drivers/firmware/efi/Makefile | 4 - drivers/firmware/efi/fake_mem.h | 10 --- drivers/firmware/efi/x86_fake_mem.c | 75 ------------------- include/linux/efi.h | 6 -- 10 files changed, 103 insertions(+), 120 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f9920f1341c8..b98941c2fec4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1978,6 +1978,26 @@ config EFI_MIXED If unsure, say N. +config EFI_FAKE_MEMMAP + bool "Enable EFI fake memory map" + depends on EFI + help + Saying Y here will enable "efi_fake_mem" boot option. By specifying + this parameter, you can add arbitrary attribute to specific memory + range by updating original (firmware provided) EFI memmap. This is + useful for debugging of EFI memmap related feature, e.g., Address + Range Mirroring feature. + +config EFI_MAX_FAKE_MEM + int "maximum allowable number of ranges in efi_fake_mem boot option" + depends on EFI_FAKE_MEMMAP + range 1 128 + default 8 + help + Maximum allowable number of ranges in efi_fake_mem boot option. + Ranges can be set up to this value using comma-separated list. + The default value is 8. + source "kernel/Kconfig.hz" config KEXEC diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 897ea4aec16e..68414d924332 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -404,10 +404,15 @@ static inline void efi_reserve_boot_services(void) #ifdef CONFIG_EFI_FAKE_MEMMAP extern void __init efi_fake_memmap_early(void); +extern void __init efi_fake_memmap(void); #else static inline void efi_fake_memmap_early(void) { } + +static inline void efi_fake_memmap(void) +{ +} #endif #define arch_ima_efi_boot_mode \ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 216fee7144ee..41ec3a69f3c7 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index a50245157685..b481719b16cc 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile @@ -4,3 +4,4 @@ GCOV_PROFILE := n obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o +obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o diff --git a/drivers/firmware/efi/fake_mem.c b/arch/x86/platform/efi/fake_mem.c similarity index 58% rename from drivers/firmware/efi/fake_mem.c rename to arch/x86/platform/efi/fake_mem.c index 6e0f34a38171..41d57cad3d84 100644 --- a/drivers/firmware/efi/fake_mem.c +++ b/arch/x86/platform/efi/fake_mem.c @@ -17,10 +17,13 @@ #include #include #include -#include "fake_mem.h" +#include +#include -struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM]; -int nr_fake_mem; +#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM + +static struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM]; +static int nr_fake_mem; static int __init cmp_fake_mem(const void *x1, const void *x2) { @@ -122,3 +125,73 @@ static int __init setup_fake_mem(char *p) } early_param("efi_fake_mem", setup_fake_mem); + +void __init efi_fake_memmap_early(void) +{ + int i; + + /* + * The late efi_fake_mem() call can handle all requests if + * EFI_MEMORY_SP support is disabled. + */ + if (!efi_soft_reserve_enabled()) + return; + + if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem) + return; + + /* + * Given that efi_fake_memmap() needs to perform memblock + * allocations it needs to run after e820__memblock_setup(). + * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given + * address range that potentially needs to mark the memory as + * reserved prior to e820__memblock_setup(). Update e820 + * directly if EFI_MEMORY_SP is specified for an + * EFI_CONVENTIONAL_MEMORY descriptor. + */ + for (i = 0; i < nr_fake_mem; i++) { + struct efi_mem_range *mem = &efi_fake_mems[i]; + efi_memory_desc_t *md; + u64 m_start, m_end; + + if ((mem->attribute & EFI_MEMORY_SP) == 0) + continue; + + m_start = mem->range.start; + m_end = mem->range.end; + for_each_efi_memory_desc(md) { + u64 start, end, size; + + if (md->type != EFI_CONVENTIONAL_MEMORY) + continue; + + start = md->phys_addr; + end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; + + if (m_start <= end && m_end >= start) + /* fake range overlaps descriptor */; + else + continue; + + /* + * Trim the boundary of the e820 update to the + * descriptor in case the fake range overlaps + * !EFI_CONVENTIONAL_MEMORY + */ + start = max(start, m_start); + end = min(end, m_end); + size = end - start + 1; + + if (end <= start) + continue; + + /* + * Ensure each efi_fake_mem instance results in + * a unique e820 resource + */ + e820__range_remove(start, size, E820_TYPE_RAM, 1); + e820__range_add(start, size, E820_TYPE_SOFT_RESERVED); + e820__update_table(e820_table); + } + } +} diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 4f7e65293297..fceeea74522e 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -37,28 +37,6 @@ config EFI_RUNTIME_MAP See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. -config EFI_FAKE_MEMMAP - bool "Enable EFI fake memory map" - depends on EFI && X86 - default n - help - Saying Y here will enable "efi_fake_mem" boot option. - By specifying this parameter, you can add arbitrary attribute - to specific memory range by updating original (firmware provided) - EFI memmap. - This is useful for debugging of EFI memmap related feature. - e.g. Address Range Mirroring feature. - -config EFI_MAX_FAKE_MEM - int "maximum allowable number of ranges in efi_fake_mem boot option" - depends on EFI_FAKE_MEMMAP - range 1 128 - default 8 - help - Maximum allowable number of ranges in efi_fake_mem boot option. - Ranges can be set up to this value using comma-separated list. - The default value is 8. - config EFI_SOFT_RESERVE bool "Reserve EFI Specific Purpose Memory" depends on EFI && EFI_STUB && ACPI_HMAT diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 8d151e332584..8e4f0d5b26e5 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o subdir-$(CONFIG_EFI_STUB) += libstub -obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_map.o obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o obj-$(CONFIG_EFI_TEST) += test/ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o @@ -32,9 +31,6 @@ obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o obj-$(CONFIG_LOAD_UEFI_KEYS) += mokvar-table.o -fake_map-y += fake_mem.o -fake_map-$(CONFIG_X86) += x86_fake_mem.o - obj-$(CONFIG_SYSFB) += sysfb_efi.o arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o diff --git a/drivers/firmware/efi/fake_mem.h b/drivers/firmware/efi/fake_mem.h deleted file mode 100644 index d52791af4b18..000000000000 --- a/drivers/firmware/efi/fake_mem.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __EFI_FAKE_MEM_H__ -#define __EFI_FAKE_MEM_H__ -#include - -#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM - -extern struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM]; -extern int nr_fake_mem; -#endif /* __EFI_FAKE_MEM_H__ */ diff --git a/drivers/firmware/efi/x86_fake_mem.c b/drivers/firmware/efi/x86_fake_mem.c deleted file mode 100644 index 0bafcc1bb0f6..000000000000 --- a/drivers/firmware/efi/x86_fake_mem.c +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2019 Intel Corporation. All rights reserved. */ -#include -#include -#include "fake_mem.h" - -void __init efi_fake_memmap_early(void) -{ - int i; - - /* - * The late efi_fake_mem() call can handle all requests if - * EFI_MEMORY_SP support is disabled. - */ - if (!efi_soft_reserve_enabled()) - return; - - if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem) - return; - - /* - * Given that efi_fake_memmap() needs to perform memblock - * allocations it needs to run after e820__memblock_setup(). - * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given - * address range that potentially needs to mark the memory as - * reserved prior to e820__memblock_setup(). Update e820 - * directly if EFI_MEMORY_SP is specified for an - * EFI_CONVENTIONAL_MEMORY descriptor. - */ - for (i = 0; i < nr_fake_mem; i++) { - struct efi_mem_range *mem = &efi_fake_mems[i]; - efi_memory_desc_t *md; - u64 m_start, m_end; - - if ((mem->attribute & EFI_MEMORY_SP) == 0) - continue; - - m_start = mem->range.start; - m_end = mem->range.end; - for_each_efi_memory_desc(md) { - u64 start, end, size; - - if (md->type != EFI_CONVENTIONAL_MEMORY) - continue; - - start = md->phys_addr; - end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; - - if (m_start <= end && m_end >= start) - /* fake range overlaps descriptor */; - else - continue; - - /* - * Trim the boundary of the e820 update to the - * descriptor in case the fake range overlaps - * !EFI_CONVENTIONAL_MEMORY - */ - start = max(start, m_start); - end = min(end, m_end); - size = end - start + 1; - - if (end <= start) - continue; - - /* - * Ensure each efi_fake_mem instance results in - * a unique e820 resource - */ - e820__range_remove(start, size, E820_TYPE_RAM, 1); - e820__range_add(start, size, E820_TYPE_SOFT_RESERVED); - e820__update_table(e820_table); - } - } -} diff --git a/include/linux/efi.h b/include/linux/efi.h index e739196ce9b2..a6dbf354d2c3 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -749,12 +749,6 @@ extern struct kobject *efi_kobj; extern int efi_reboot_quirk_mode; extern bool efi_poweroff_required(void); -#ifdef CONFIG_EFI_FAKE_MEMMAP -extern void __init efi_fake_memmap(void); -#else -static inline void efi_fake_memmap(void) { } -#endif - extern unsigned long efi_mem_attr_table; /* From patchwork Mon Oct 3 11:26:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612048 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7FC3C433FE for ; Mon, 3 Oct 2022 11:26:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229479AbiJCL0p (ORCPT ); Mon, 3 Oct 2022 07:26:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229839AbiJCL0n (ORCPT ); Mon, 3 Oct 2022 07:26:43 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0435411C16 for ; Mon, 3 Oct 2022 04:26:40 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 9E473B8105A for ; Mon, 3 Oct 2022 11:26:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AF3ECC4347C; Mon, 3 Oct 2022 11:26:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796397; bh=ZjDr14OxWTrew0/fwyFI+XUBboCoGDstHicLfif2Djw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TxY/bRfjhtxLaZp+RLCj8LsBeH7rHezBCOV0B0BosD9Voq51KCp6mICHNQZ5Ug4lI fukIwRaNQit/mbut/F+dmvt07Pbuanyh5ido7DTpsVSXiX/SGgnxx7OyTPsF1lxU2W WJ2FQ4K0Bf2lg64zbnlGBEWb8U/xZkt5fxKrmmmedFuW2CY2PpZIlZwR54Zse2l6kV wd6LXmtYDCLfh7Zd+voJ6uPiUqaHhylCrSUSomr0erOhQTtmUnvFvzLr1MmVyoMJwi bJF8A1MWl8fxpuXoc7j2iCZnP2pZmVJy8Uw4cYU25gqBrSZj9i5tQlem3iuh5mTo5j SPvnR6hX5M1jA== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 2/6] efi: memmap: Move manipulation routines into x86 arch tree Date: Mon, 3 Oct 2022 13:26:21 +0200 Message-Id: <20221003112625.972646-3-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=17368; i=ardb@kernel.org; h=from:subject; bh=ZjDr14OxWTrew0/fwyFI+XUBboCoGDstHicLfif2Djw=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbYg6dqX0FgOlAp0B3+vbe93/8K1X6EJXBcxSer Yrj6+geJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG2AAKCRDDTyI5ktmPJP2YC/ 9WT0L6a3hxPwo9zokLU/i5YXQBAxRuRvN1iiXsD2aWDn0MhaURJXR3BtmTvAOwnKdqu5D3aHBk8VZC zjpzyBOyo/dufs4+tx0LAO8RBRUU8VSHa0/UlkIG8xJXui8s2LcA/EF4ym62OyVqD5f4N+KtKVo9wL BWW+axOJ1KnRj2Su2S8XYoK4Wn0DRaUQJsfAKAmZZnRBe+gE2hXrv71b3zQErfaGF/eSOKWncDym8+ 7LKamaAPo1+dWZP7QZyURbypNI03XyQb4AuE8cUlDjqDVNrZORmTubs2PZqrkj9febHXtteZYEKuCH nr4mvsF0o+VDcOcmY5/ZMWlAjdEgQBopSt514lEBdVphFBuqoa3OA1FIbZhDUnjfOAzlY2QhWVnOrM msyBu3Wnb8obJtr7j2lbmyS48g/Mi7qTNJZa59ZzYW3J0QrwSDAGnfSke2ax4D7ayknBRkBIOq5KKC ZEahyULh4jtcvHic9eggO6E77OtHGkgR4/Ht1dgz/4bfA= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The EFI memory map is a description of the memory layout as provided by the firmware, and only x86 manipulates it in various different ways for its own memory bookkeeping. So let's move the memmap routines that are only used by x86 into the x86 arch tree. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 11 + arch/x86/platform/efi/Makefile | 3 +- arch/x86/platform/efi/memmap.c | 235 ++++++++++++++++++++ drivers/firmware/efi/memmap.c | 221 +----------------- include/linux/efi.h | 10 +- 5 files changed, 251 insertions(+), 229 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 68414d924332..1fb4686f3d12 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -415,6 +415,17 @@ static inline void efi_fake_memmap(void) } #endif +extern int __init efi_memmap_alloc(unsigned int num_entries, + struct efi_memory_map_data *data); +extern void __efi_memmap_free(u64 phys, unsigned long size, + unsigned long flags); + +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); + #define arch_ima_efi_boot_mode \ ({ extern struct boot_params boot_params; boot_params.secure_boot; }) diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index b481719b16cc..ed5502a5185d 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile @@ -2,6 +2,7 @@ KASAN_SANITIZE := n GCOV_PROFILE := n -obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o +obj-$(CONFIG_EFI) += memmap.o quirks.o efi.o efi_$(BITS).o \ + efi_stub_$(BITS).o obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c new file mode 100644 index 000000000000..44b886acf301 --- /dev/null +++ b/arch/x86/platform/efi/memmap.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Common EFI memory map functions. + */ + +#define pr_fmt(fmt) "efi: " fmt + +#include +#include +#include +#include +#include +#include +#include + +static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) +{ + return memblock_phys_alloc(size, SMP_CACHE_BYTES); +} + +static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) +{ + unsigned int order = get_order(size); + struct page *p = alloc_pages(GFP_KERNEL, order); + + if (!p) + return 0; + + return PFN_PHYS(page_to_pfn(p)); +} + +void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) +{ + if (flags & EFI_MEMMAP_MEMBLOCK) { + if (slab_is_available()) + memblock_free_late(phys, size); + else + memblock_phys_free(phys, size); + } else if (flags & EFI_MEMMAP_SLAB) { + struct page *p = pfn_to_page(PHYS_PFN(phys)); + unsigned int order = get_order(size); + + free_pages((unsigned long) page_address(p), order); + } +} + +/** + * efi_memmap_alloc - Allocate memory for the EFI memory map + * @num_entries: Number of entries in the allocated map. + * @data: efi memmap installation parameters + * + * Depending on whether mm_init() has already been invoked or not, + * either memblock or "normal" page allocation is used. + * + * Returns zero on success, a negative error code on failure. + */ +int __init efi_memmap_alloc(unsigned int num_entries, + struct efi_memory_map_data *data) +{ + /* Expect allocation parameters are zero initialized */ + WARN_ON(data->phys_map || data->size); + + data->size = num_entries * efi.memmap.desc_size; + data->desc_version = efi.memmap.desc_version; + data->desc_size = efi.memmap.desc_size; + data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK); + data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE; + + if (slab_is_available()) { + data->flags |= EFI_MEMMAP_SLAB; + data->phys_map = __efi_memmap_alloc_late(data->size); + } else { + data->flags |= EFI_MEMMAP_MEMBLOCK; + data->phys_map = __efi_memmap_alloc_early(data->size); + } + + if (!data->phys_map) + return -ENOMEM; + return 0; +} + +/** + * efi_memmap_install - Install a new EFI memory map in efi.memmap + * @ctx: map allocation parameters (address, size, flags) + * + * Unlike efi_memmap_init_*(), this function does not allow the caller + * to switch from early to late mappings. It simply uses the existing + * mapping function and installs the new memmap. + * + * Returns zero on success, a negative error code on failure. + */ +int __init efi_memmap_install(struct efi_memory_map_data *data) +{ + efi_memmap_unmap(); + + return __efi_memmap_init(data); +} + +/** + * 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/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c index 6ec7970dbd40..3501d3814f22 100644 --- a/drivers/firmware/efi/memmap.c +++ b/drivers/firmware/efi/memmap.c @@ -13,35 +13,8 @@ #include #include -static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) +void __weak __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) { - return memblock_phys_alloc(size, SMP_CACHE_BYTES); -} - -static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) -{ - unsigned int order = get_order(size); - struct page *p = alloc_pages(GFP_KERNEL, order); - - if (!p) - return 0; - - return PFN_PHYS(page_to_pfn(p)); -} - -void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) -{ - if (flags & EFI_MEMMAP_MEMBLOCK) { - if (slab_is_available()) - memblock_free_late(phys, size); - else - memblock_phys_free(phys, size); - } else if (flags & EFI_MEMMAP_SLAB) { - struct page *p = pfn_to_page(PHYS_PFN(phys)); - unsigned int order = get_order(size); - - free_pages((unsigned long) page_address(p), order); - } } static void __init efi_memmap_free(void) @@ -51,41 +24,6 @@ static void __init efi_memmap_free(void) efi.memmap.flags); } -/** - * efi_memmap_alloc - Allocate memory for the EFI memory map - * @num_entries: Number of entries in the allocated map. - * @data: efi memmap installation parameters - * - * Depending on whether mm_init() has already been invoked or not, - * either memblock or "normal" page allocation is used. - * - * Returns zero on success, a negative error code on failure. - */ -int __init efi_memmap_alloc(unsigned int num_entries, - struct efi_memory_map_data *data) -{ - /* Expect allocation parameters are zero initialized */ - WARN_ON(data->phys_map || data->size); - - data->size = num_entries * efi.memmap.desc_size; - data->desc_version = efi.memmap.desc_version; - data->desc_size = efi.memmap.desc_size; - data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK); - data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE; - - if (slab_is_available()) { - data->flags |= EFI_MEMMAP_SLAB; - data->phys_map = __efi_memmap_alloc_late(data->size); - } else { - data->flags |= EFI_MEMMAP_MEMBLOCK; - data->phys_map = __efi_memmap_alloc_early(data->size); - } - - if (!data->phys_map) - return -ENOMEM; - return 0; -} - /** * __efi_memmap_init - Common code for mapping the EFI memory map * @data: EFI memory map data @@ -101,7 +39,7 @@ int __init efi_memmap_alloc(unsigned int num_entries, * * Returns zero on success, a negative error code on failure. */ -static int __init __efi_memmap_init(struct efi_memory_map_data *data) +int __init __efi_memmap_init(struct efi_memory_map_data *data) { struct efi_memory_map map; phys_addr_t phys_map; @@ -220,158 +158,3 @@ int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size) return __efi_memmap_init(&data); } - -/** - * efi_memmap_install - Install a new EFI memory map in efi.memmap - * @ctx: map allocation parameters (address, size, flags) - * - * Unlike efi_memmap_init_*(), this function does not allow the caller - * to switch from early to late mappings. It simply uses the existing - * mapping function and installs the new memmap. - * - * Returns zero on success, a negative error code on failure. - */ -int __init efi_memmap_install(struct efi_memory_map_data *data) -{ - efi_memmap_unmap(); - - return __efi_memmap_init(data); -} - -/** - * 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/include/linux/efi.h b/include/linux/efi.h index a6dbf354d2c3..256e70e42114 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -707,18 +707,10 @@ static inline efi_status_t efi_query_variable_store(u32 attributes, #endif extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); -extern int __init efi_memmap_alloc(unsigned int num_entries, - struct efi_memory_map_data *data); -extern void __efi_memmap_free(u64 phys, unsigned long size, - unsigned long flags); +extern int __init __efi_memmap_init(struct efi_memory_map_data *data); extern int __init efi_memmap_init_early(struct efi_memory_map_data *data); extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size); extern void __init efi_memmap_unmap(void); -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); #ifdef CONFIG_EFI_ESRT extern void __init efi_esrt_init(void); From patchwork Mon Oct 3 11:26:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612408 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3D04C433F5 for ; Mon, 3 Oct 2022 11:26:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229838AbiJCL0n (ORCPT ); Mon, 3 Oct 2022 07:26:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229836AbiJCL0m (ORCPT ); Mon, 3 Oct 2022 07:26:42 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6237B2A94E for ; Mon, 3 Oct 2022 04:26:41 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D198261022 for ; Mon, 3 Oct 2022 11:26:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C25F8C433B5; Mon, 3 Oct 2022 11:26:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796400; bh=naWVhxVJzgFHTYyzbP8aferDZudNO8L5WZJcvq28kz8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BNiDIoSRsqO6SP/YjvMUB6npIWVImtY4mWHh4pvmCWYVqDtQtuHY5bBr3jdPo2inm /WfRwXzUvzpvHSn/RH0owMjbn2jYGvoOcszGqXzM65/xpvJ1CLY2fs+srTkOMfQA0m Sl4u0VnyhkuQL3/G7xKroOexeRf06KCKag0XxURSv3xsxamdKMNHzmM7rxbviila7s 0FIMpSBAkDd5YR34wQT5Q+v8Tg8V+HoYB7AB88iHGrBIGoj6XXykMrvBJDF6/Gqlcb kOGtDYhRAeA50gW7pjYE1OY7Nfrk3aZFZc7OM6CR6QSgSMD01eoC23/CcBOj+wQff7 /mNndy+5mRPWg== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 3/6] efi: xen: Set EFI_PARAVIRT for Xen dom0 boot on all architectures Date: Mon, 3 Oct 2022 13:26:22 +0200 Message-Id: <20221003112625.972646-4-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3190; i=ardb@kernel.org; h=from:subject; bh=naWVhxVJzgFHTYyzbP8aferDZudNO8L5WZJcvq28kz8=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbZUImNh+oNISz7kaell7P1ADDK/YsLUV10IJbU Cm3Ms7iJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG2QAKCRDDTyI5ktmPJChlC/ 9o6m0Iy1WpuoP8dAvEJvjXUGENSrHQz1jwTqztxBAtbc7GoxtN2OD7Yo6fcYU1htSLmDa3LtV1LVp9 hzxE4shcSNXWA3qsx0Q7kv9LuimlvTR1oYqnphlO1ArYa7K6Vv1iEw538UOR3DGgXep8hlTrdQWCxu l9S4x9xdNCP5eBLDSnNEnu2RLEwFQztbYxocM2UTZvu6p5ZIrFrZ/v/JFh2hMECJluOfJ78LFVfvLr SWti8jAOjrVPsdyXhwiFGxpgqxcJenX/ugwqvO/Zovirqc/+Saao7vAabuAlj5QxmLa8timHCLfif7 HCZy2GbDBepiQhA3JqrH5ARl1H54OQT5/wEVbwca8DTLe3wpg0gfJ1LTbScvFQhloWWFhfIEYdyYUw tPEZaeKi6iKAP1MQJAXYSb5sVSl5P8d9p/VqtN13bVvy+mf/MgKXmQSL/SOHt6jtDfY8OtqUTHRGMx ZnhVe0pgimwQIeEKMm+MLR2YT26b5k0pqVz0nruFr/1uU= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Currently, the EFI_PARAVIRT flag is only used by x86, even though other architectures also support pseudo-EFI boot, where the core kernel is invoked directly and provided with a set of data tables that resemble the ones constructed by the EFI stub, which never actually runs in that case. Let's fix this inconsistency, and always set this flag when booting dom0 via the EFI boot path. Note that Xen on x86 does not provide the EFI memory map in this case, whereas other architectures do, so move the associated EFI_PARAVIRT check into the x86 platform code. Signed-off-by: Ard Biesheuvel --- arch/x86/platform/efi/efi.c | 8 +++++--- arch/x86/platform/efi/memmap.c | 3 +++ drivers/firmware/efi/fdtparams.c | 4 ++++ drivers/firmware/efi/memmap.c | 3 --- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6e598bd78eef..6a6f2a585a3d 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -214,9 +214,11 @@ int __init efi_memblock_x86_reserve_range(void) data.desc_size = e->efi_memdesc_size; data.desc_version = e->efi_memdesc_version; - rv = efi_memmap_init_early(&data); - if (rv) - return rv; + if (!efi_enabled(EFI_PARAVIRT)) { + rv = efi_memmap_init_early(&data); + if (rv) + return rv; + } if (add_efi_memmap || do_efi_soft_reserve()) do_add_efi_memmap(); diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c index 44b886acf301..18e14ec16720 100644 --- a/arch/x86/platform/efi/memmap.c +++ b/arch/x86/platform/efi/memmap.c @@ -93,6 +93,9 @@ int __init efi_memmap_install(struct efi_memory_map_data *data) { efi_memmap_unmap(); + if (efi_enabled(EFI_PARAVIRT)) + return 0; + return __efi_memmap_init(data); } diff --git a/drivers/firmware/efi/fdtparams.c b/drivers/firmware/efi/fdtparams.c index e901f8564ca0..0ec83ba58097 100644 --- a/drivers/firmware/efi/fdtparams.c +++ b/drivers/firmware/efi/fdtparams.c @@ -30,11 +30,13 @@ static __initconst const char name[][22] = { static __initconst const struct { const char path[17]; + u8 paravirt; const char params[PARAMCOUNT][26]; } dt_params[] = { { #ifdef CONFIG_XEN // <-------17------> .path = "/hypervisor/uefi", + .paravirt = 1, .params = { [SYSTAB] = "xen,uefi-system-table", [MMBASE] = "xen,uefi-mmap-start", @@ -121,6 +123,8 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm) pr_err("Can't find property '%s' in DT!\n", pname); return 0; } + if (dt_params[i].paravirt) + set_bit(EFI_PARAVIRT, &efi.flags); return systab; } notfound: diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c index 3501d3814f22..9508082af907 100644 --- a/drivers/firmware/efi/memmap.c +++ b/drivers/firmware/efi/memmap.c @@ -44,9 +44,6 @@ int __init __efi_memmap_init(struct efi_memory_map_data *data) struct efi_memory_map map; phys_addr_t phys_map; - if (efi_enabled(EFI_PARAVIRT)) - return 0; - phys_map = data->phys_map; if (data->flags & EFI_MEMMAP_LATE) From patchwork Mon Oct 3 11:26:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612407 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9C75C4332F for ; Mon, 3 Oct 2022 11:26:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229446AbiJCL0q (ORCPT ); Mon, 3 Oct 2022 07:26:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229480AbiJCL0o (ORCPT ); Mon, 3 Oct 2022 07:26:44 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F3232A94E for ; Mon, 3 Oct 2022 04:26:44 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id BDBE46103A for ; Mon, 3 Oct 2022 11:26:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD778C433D6; Mon, 3 Oct 2022 11:26:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796403; bh=W8obWGwmcyzn5+VXhc6GfBg92Z+wLrsUyqrdMHjxep0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YTGegz+V40gx32fSy3+ERPuWauQ9SGX/uyZftYxZvb467SzxmwKVEXTMytzhQH7M4 1V2VKfiVYH7TcozRWRHaiRvjYuXJnU7IvA2olmMY0WGaftBs2Wudq34NFeznUROMkf eEKT2c2BHrvwIO56Rzxa+c2tXnHsopKi5rFQ8dcQVnCQmh0iLDqkj0BYghKh88t0pV ULDcjx0TaFehBTvC0LpqUhrWXl8AuGFXSEa+GLPK6LQT0oJW1e//vLHd+Ci6+dIj7n xxJvJpZglhpkIcm+iL9P6RnGDwu7fekz6jzPSYG5rUJjgpQsCa8Ggp2E/znkC/Nfmw X2n7ROAkqY1Aw== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 4/6] efi: memmap: Disregard bogus entries instead of returning them Date: Mon, 3 Oct 2022 13:26:23 +0200 Message-Id: <20221003112625.972646-5-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2717; i=ardb@kernel.org; h=from:subject; bh=W8obWGwmcyzn5+VXhc6GfBg92Z+wLrsUyqrdMHjxep0=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbbl+ejDPGi0x7EecnkWLLI5uBb8hfx+mNuYEHL SGFCPwKJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG2wAKCRDDTyI5ktmPJBDfC/ 9BMiukxbjQZgrq2K+4VvI3jjsxzxCI4AmtyKuHFCUBrg62qhcftHWoNGouY0pXptyDabOuNA8Tczdq x93UinMLN5X0NyKvuGmQty4oFhA8rEpRD6B2KX/VHKtu6kwGFBF8gaXmWeGfFv8ZNaQUzZCW51+Ah6 xt81Vx4p8RGFSrmoIzV6bamToULbrhLug9i/9Jsd6mg7Ggpisdj5E2rLXjTIYgtsnnoEXnwZsp9gXW PeBo+4rcj7CsYM7PfupkE6/uX6qAiYPA3UV2nJ9mBJTahiFmwKA58HVUtsv3j16lIEdROHb/bqPvTY /Iw/rmhC+gDxqBhlWoytmTnJWKB1EZpKPo3WESWHuZFKxwFAoqgMWHTFXe5dTWPeEsDBh6rC4WLY7q ylZMZsE9c0QQw1zdPhqNFcK1cGUaorxsMrxlPNm8LYO+qpRsl4HaWKrvSoGF9BMB8PI9R2X+LmbP2Y lhrKABraz+MgDmjFbkI55I1cVGbvO3j4AVGjPmERfskUM= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The ESRT code currently contains some sanity checks on the memory descriptor it obtains, but these can only trigger when the descriptor is invalid (if at all). So let's drop these checks, and instead, disregard descriptors entirely if the start address is misaligned, or the number of pages reaches beyond the end of the address space. Note that the memory map as a whole could still be inconsistent, i.e., multiple entries might cover the same area, or the address could be outside of the addressable VA space, but validating that goes beyond the scope of these helpers. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 13 +++++++------ drivers/firmware/efi/esrt.c | 18 +----------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 11857af72859..55bd3f4aab28 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -461,19 +461,20 @@ int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) efi_memory_desc_t *md; if (!efi_enabled(EFI_MEMMAP)) { - pr_err_once("EFI_MEMMAP is not enabled.\n"); + pr_warn_once("EFI_MEMMAP is not enabled.\n"); return -EINVAL; } - if (!out_md) { - pr_err_once("out_md is null.\n"); - return -EINVAL; - } - for_each_efi_memory_desc(md) { u64 size; u64 end; + /* skip bogus entries */ + if ((md->phys_addr & (EFI_PAGE_SIZE - 1)) || + (md->phys_addr > 0 && + (md->num_pages > (U64_MAX - md->phys_addr + 1) >> EFI_PAGE_SHIFT))) + continue; + size = md->num_pages << EFI_PAGE_SHIFT; end = md->phys_addr + size; if (phys_addr >= md->phys_addr && phys_addr < end) { diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 2a2f52b017e7..8f86f2b0734b 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -247,9 +247,6 @@ void __init efi_esrt_init(void) int rc; phys_addr_t end; - if (!efi_enabled(EFI_MEMMAP)) - return; - pr_debug("esrt-init: loading.\n"); if (!esrt_table_exists()) return; @@ -263,21 +260,8 @@ void __init efi_esrt_init(void) return; } - max = efi_mem_desc_end(&md); - if (max < efi.esrt) { - pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n", - (void *)efi.esrt, (void *)max); - return; - } - + max = efi_mem_desc_end(&md) - efi.esrt; size = sizeof(*esrt); - max -= efi.esrt; - - if (max < size) { - pr_err("ESRT header doesn't fit on single memory map entry. (size: %zu max: %zu)\n", - size, max); - return; - } va = early_memremap(efi.esrt, size); if (!va) { From patchwork Mon Oct 3 11:26:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612047 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16FC1C433F5 for ; Mon, 3 Oct 2022 11:26:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229515AbiJCL0s (ORCPT ); Mon, 3 Oct 2022 07:26:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33250 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229488AbiJCL0r (ORCPT ); Mon, 3 Oct 2022 07:26:47 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11F4728E13 for ; Mon, 3 Oct 2022 04:26:47 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A508961035 for ; Mon, 3 Oct 2022 11:26:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 97E0AC4347C; Mon, 3 Oct 2022 11:26:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796406; bh=WSRp6bNX/TJAZPmOt6U+CC+sxwlMaJT3eET5g/MHr2M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RUvZ35FsjQc9G8ENmYBxfeFUtDDJUFK2UMo+/cHo6gpHbn8ONmbPI3AHn8VN9L1DZ pqxSj1M/59aMOVtdAMqgPSAtTUFJ/omqlMu6l28mUHZuN4iHOB91xUSgZ1iZkJ7amJ JvcMd9Z/AxM/W1cnUQlsNR/RpGOCVARUTY1j5ke0C7GhyUdKb9Ze67VFdsmKgk7LwN Yw6TkFInATddLQqNhcAOsoeUzTuNa0pXPyvkA5KPe+9qbbBmJdMNEQTX9Qfw/tSKXp +CS79iIXCGAbyJC1T4KiK1j1JW8UiGBxSl49JnLPwrBpL7X7n2ejiwIX3WhJ3U510R oDXiacweOf8TA== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 5/6] efi: xen: Implement memory descriptor lookup based on hypercall Date: Mon, 3 Oct 2022 13:26:24 +0200 Message-Id: <20221003112625.972646-6-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3715; i=ardb@kernel.org; h=from:subject; bh=WSRp6bNX/TJAZPmOt6U+CC+sxwlMaJT3eET5g/MHr2M=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbcX3efqx7JPMOFFFmoUJQ0kqs3RTBogBvQjO3M /uoVk6+JAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG3AAKCRDDTyI5ktmPJFNIC/ 4z2IbS7WT9Pkoo7uw6cgC6n6RngdfnXEwUX3q4vv58mt2Q0iHQL4ns7hgXyPfxarD3WIISuJof/j5r cCK5/b6ZdHKAWA7hkitKX0J8CsB/0TZXv45uLpX0mLxVQmYfESgzgkxfBKgrZ+3iMOdxHiEngEMZAv jEkPD4N2LhTlYgqBcxGNnq1dPYhkTqnft5J+Aw3xsM8yj+nLvb5gcD5i+HymlThNZ1tdNIM3OByz9z 5fr/WIcJjzoS7avHP8tPVcEJnVW+rJuWJ9+HuU2QMIp2WCobQHNhvs30Q1YSp4LYFIeF68Oyf5XDG6 AI98jS6cRy055WOW8uchbDKXBvfE9g7oK8DErOjD1BNPhc+ARHEjo4hSGyT1OidxGMUXvwLAPXVxZ7 84ARkFLSx+X8GLpIohsbJODPQrBR9JASQEJpnXhQ14EMiFN10dLoN88rpIyWwHGLFdoKWqwK395xiu /dN2zr1zBiVc7Q/W6DTOo2/W5IYcvjkb7ci8y+KMYpeMI= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Xen on x86 boots dom0 in EFI mode but without providing a memory map. This means that some sanity checks we would like to perform on configuration tables or other data structures in memory are not currently possible. Xen does, however, expose EFI memory descriptor info via a Xen hypercall, so let's wire that up instead. Co-developed-by: Demi Marie Obenour Signed-off-by: Demi Marie Obenour Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 5 ++- drivers/xen/efi.c | 34 ++++++++++++++++++++ include/linux/efi.h | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 55bd3f4aab28..2c12b1a06481 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -456,7 +456,7 @@ void __init efi_find_mirror(void) * and if so, populate the supplied memory descriptor with the appropriate * data. */ -int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) +int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) { efi_memory_desc_t *md; @@ -485,6 +485,9 @@ int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) return -ENOENT; } +extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) + __weak __alias(__efi_mem_desc_lookup); + /* * Calculate the highest address of an efi memory descriptor. */ diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c index d1ff2186ebb4..74f3f6d8cdc8 100644 --- a/drivers/xen/efi.c +++ b/drivers/xen/efi.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -292,3 +293,36 @@ void __init xen_efi_runtime_setup(void) efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count; efi.reset_system = xen_efi_reset_system; } + +int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) +{ + static_assert(XEN_PAGE_SHIFT == EFI_PAGE_SHIFT, + "Mismatch between EFI_PAGE_SHIFT and XEN_PAGE_SHIFT"); + struct xen_platform_op op = { + .cmd = XENPF_firmware_info, + .u.firmware_info = { + .type = XEN_FW_EFI_INFO, + .index = XEN_FW_EFI_MEM_INFO, + .u.efi_info.mem.addr = phys_addr, + .u.efi_info.mem.size = U64_MAX - phys_addr, + } + }; + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; + int rc; + + if (!efi_enabled(EFI_PARAVIRT) || efi_enabled(EFI_MEMMAP)) + return __efi_mem_desc_lookup(phys_addr, out_md); + + rc = HYPERVISOR_platform_op(&op); + if (rc) { + pr_warn("Failed to lookup header 0x%llx in Xen memory map: error %d\n", + phys_addr, rc); + } + + out_md->phys_addr = info->mem.addr; + out_md->num_pages = info->mem.size >> EFI_PAGE_SHIFT; + out_md->type = info->mem.type; + out_md->attribute = info->mem.attr; + + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 256e70e42114..e0ee6f6da4b4 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -731,6 +731,7 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int __init efi_uart_console_only (void); extern u64 efi_mem_desc_end(efi_memory_desc_t *md); extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md); +extern int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md); extern void efi_mem_reserve(phys_addr_t addr, u64 size); extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size); extern void efi_initialize_iomem_resources(struct resource *code_resource, From patchwork Mon Oct 3 11:26:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 612406 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F571C433FE for ; Mon, 3 Oct 2022 11:26:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229567AbiJCL0x (ORCPT ); Mon, 3 Oct 2022 07:26:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229480AbiJCL0w (ORCPT ); Mon, 3 Oct 2022 07:26:52 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85CE628E13 for ; Mon, 3 Oct 2022 04:26:51 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 4371FB80DCA for ; Mon, 3 Oct 2022 11:26:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83587C433D6; Mon, 3 Oct 2022 11:26:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664796409; bh=9C7AAPmVD5BjjmNEGbxNnPMoOUW0Ie0fKwQ10Ayhy8c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ef/m3g0HgmSAdlLxc6fqIZiY6+uN5iitg2tKlqJBx2kqyn1LxQerWZsFjBQKGZPPo 5UCqsf8JYBVwYIfm0t42Hd+d2AkVCw26i1ECycyFRk8twGtzgdzIzgWc12l/6u6YF6 LH5J/jNu7aqKOutEydBgmoMzH+yaikiyc6cA7saaEgHV1A3iyLAml1itploasROBbw zlMGZ5MRNQ3RhSk4/QnAogqaAsUikGi6wXIXrS7VXzzc39CQEabYr11vCF3zMIXCFC vMYmvKSVN6NxPaW7VX5h4lWeDPKFV5OOaSAzWX7+9Psix9WpMLL3i9IWNGwX55IQYM bFfyndgoAL10w== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: xen-devel@lists.xenproject.org, Ard Biesheuvel , Demi Marie Obenour , Peter Jones , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v2 6/6] efi: Apply allowlist to EFI configuration tables when running under Xen Date: Mon, 3 Oct 2022 13:26:25 +0200 Message-Id: <20221003112625.972646-7-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221003112625.972646-1-ardb@kernel.org> References: <20221003112625.972646-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3156; i=ardb@kernel.org; h=from:subject; bh=9C7AAPmVD5BjjmNEGbxNnPMoOUW0Ie0fKwQ10Ayhy8c=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjOsbenzLnpjmFV4NFmLKMBzkM6EYzVcY2tgtXvDcv bUFOheqJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzrG3gAKCRDDTyI5ktmPJJBDC/ 43/+s+cosevfZ50pJwVpCc4I/DH7QKq7kvyhnFWKLHDPwOMJ93i8yiedrIbu95b4QIMIPJEc8tBq9y cW38DNbTE6rxfpTMb73VT4UiZ6bDN/qv+/x6zmOCHVaThg0MLBnjYO1SUCvck73IxWowiReFOO1WGA U7s9cJds+g1X15WxZf9dnt6+muhFLE2Dk5JXvjzjLPBfrXW14dHcCseM7PfBgtwrR8aSkv67OV1yTo mfZNAn3PtjxCdEsecnBhnrAytAQu4yW30XYa8DqqR6mLgjRSs7yzsdhtNCrO04A4C+eqjTpZAePYdy XXMRhHa/tIhzLLb+53o6W3/IUwm8sXP4fLwN892QVrkRXlRmwSmYcMiFf2neJxawz+DjREv9MSIa47 QJPwQvr6LGddffvkVCGaKavWwhMxpj3Q46J6qhGfbsF7f2vkS3Kso6HtD4OuXi3KVF1pcclOHbOvfT qiDRgl+P1O5UEKV58pQHT1jpiJ1EjxP/f4HUFXDu0VYmQ= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org As it turns out, Xen does not guarantee that EFI bootservices data regions in memory are preserved, which means that EFI configuration tables pointing into such memory regions may be corrupted before the dom0 OS has had a chance to inspect them. Demi Marie reports that this is causing problems for Qubes OS when it attempts to perform system firmware updates, which requires that the contents of the ESRT configuration table are valid when the fwupd user space program runs. However, other configuration tables such as the memory attributes table or the runtime properties table are equally affected, and so we need a comprehensive workaround that works for any table type. So when running under Xen, check the EFI memory descriptor covering the start of the table, and disregard the table if it does not reside in memory that is preserved by Xen. Co-developed-by: Demi Marie Obenour Signed-off-by: Demi Marie Obenour Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 7 ++++++ drivers/xen/efi.c | 24 ++++++++++++++++++++ include/linux/efi.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 2c12b1a06481..0a4583c13a40 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -560,6 +560,13 @@ static __init int match_config_table(const efi_guid_t *guid, for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { if (!efi_guidcmp(*guid, table_types[i].guid)) { + if (IS_ENABLED(CONFIG_XEN_EFI) && + !xen_efi_config_table_is_usable(guid, table)) { + if (table_types[i].name[0]) + pr_cont("(%s=0x%lx) ", + table_types[i].name, table); + return 1; + } *(table_types[i].ptr) = table; if (table_types[i].name[0]) pr_cont("%s=0x%lx ", diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c index 74f3f6d8cdc8..c275a9c377fe 100644 --- a/drivers/xen/efi.c +++ b/drivers/xen/efi.c @@ -326,3 +326,27 @@ int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) return 0; } + +bool __init xen_efi_config_table_is_usable(const efi_guid_t *guid, + unsigned long table) +{ + efi_memory_desc_t md; + int rc; + + if (!efi_enabled(EFI_PARAVIRT)) + return true; + + rc = efi_mem_desc_lookup(table, &md); + if (rc) + return false; + + switch (md.type) { + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_ACPI_RECLAIM_MEMORY: + case EFI_RESERVED_TYPE: + return true; + } + + return false; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index e0ee6f6da4b4..b0cba86352ce 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1352,4 +1352,6 @@ struct linux_efi_initrd { /* Header of a populated EFI secret area */ #define EFI_SECRET_TABLE_HEADER_GUID EFI_GUID(0x1e74f542, 0x71dd, 0x4d66, 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b) +bool xen_efi_config_table_is_usable(const efi_guid_t *, unsigned long table); + #endif /* _LINUX_EFI_H */