summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi/libstub
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2022-09-16 11:48:30 +0200
committerArd Biesheuvel <ardb@kernel.org>2022-09-27 13:26:16 +0200
commitd3549a938b73f203ef522562ae9f2d38aa43d234 (patch)
tree81ef0f148991c0e999bda5bd2d3342b86cb9d4c2 /drivers/firmware/efi/libstub
parent3c6edd9034240ce9582be3392112321336bd25bb (diff)
downloadlinux-d3549a938b73f203ef522562ae9f2d38aa43d234.tar.gz
linux-d3549a938b73f203ef522562ae9f2d38aa43d234.tar.bz2
linux-d3549a938b73f203ef522562ae9f2d38aa43d234.zip
efi/arm64: libstub: avoid SetVirtualAddressMap() when possible
EFI's SetVirtualAddressMap() runtime service is a horrid hack that we'd like to avoid using, if possible. For 64-bit architectures such as arm64, the user and kernel mappings are entirely disjoint, and given that we use the user region for mapping the UEFI runtime regions when running under the OS, we don't rely on SetVirtualAddressMap() in the conventional way, i.e., to permit kernel mappings of the OS to coexist with kernel region mappings of the firmware regions. This means that, in principle, we should be able to avoid SetVirtualAddressMap() altogether, and simply use the 1:1 mapping that UEFI uses at boot time. (Note that omitting SetVirtualAddressMap() is explicitly permitted by the UEFI spec). However, there is a corner case on arm64, which, if configured for 3-level paging (or 2-level paging when using 64k pages), may not be able to cover the entire range of firmware mappings (which might contain both memory and MMIO peripheral mappings). So let's avoid SetVirtualAddressMap() on arm64, but only if the VA space is guaranteed to be of sufficient size. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'drivers/firmware/efi/libstub')
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c8
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c2
2 files changed, 9 insertions, 1 deletions
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index cd3bea25c762..df05c53baa23 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -19,6 +19,14 @@ efi_status_t check_platform_features(void)
{
u64 tg;
+ /*
+ * If we have 48 bits of VA space for TTBR0 mappings, we can map the
+ * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
+ * unnecessary.
+ */
+ if (VA_BITS_MIN >= 48)
+ efi_novamap = true;
+
/* UEFI mandates support for 4 KB granularity, no need to check */
if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
return EFI_SUCCESS;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index b4c2267c9502..0c493521b25b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -218,7 +218,7 @@ efi_status_t efi_parse_options(char const *cmdline)
efi_noinitrd = true;
} else if (!strcmp(param, "efi") && val) {
efi_nochunk = parse_option_str(val, "nochunk");
- efi_novamap = parse_option_str(val, "novamap");
+ efi_novamap |= parse_option_str(val, "novamap");
efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
parse_option_str(val, "nosoftreserve");