]> git.baikalelectronics.ru Git - kernel.git/commitdiff
efi/arm64: libstub: avoid SetVirtualAddressMap() when possible
authorArd Biesheuvel <ardb@kernel.org>
Fri, 16 Sep 2022 09:48:30 +0000 (11:48 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Tue, 27 Sep 2022 11:26:16 +0000 (13:26 +0200)
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>
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/efi-stub-helper.c

index cd3bea25c7628b194b8fd73e8d903ae94dd33ecc..df05c53baa234451e3213069063f04c5fa7c620e 100644 (file)
@@ -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;
index b4c2267c9502f03d3cf68d8a0f5681d9f707a966..0c493521b25b8fbc870c93c15645a707c9681be0 100644 (file)
@@ -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");