lkml.org 
[lkml]   [2019]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 089/123] efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted
    Date
    From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

    [ Upstream commit 4e46c2a956215482418d7b315749fb1b6c6bc224 ]

    The UEFI spec revision 2.7 errata A section 8.4 has the following to
    say about the virtual memory runtime services:

    "This section contains function definitions for the virtual memory
    support that may be optionally used by an operating system at runtime.
    If an operating system chooses to make EFI runtime service calls in a
    virtual addressing mode instead of the flat physical mode, then the
    operating system must use the services in this section to switch the
    EFI runtime services from flat physical addressing to virtual
    addressing."

    So it is pretty clear that calling SetVirtualAddressMap() is entirely
    optional, and so there is no point in doing so unless it achieves
    anything useful for us.

    This is not the case for 64-bit ARM. The identity mapping used by the
    firmware is arbitrarily converted into another permutation of userland
    addresses (i.e., bits [63:48] cleared), and the runtime code could easily
    deal with the original layout in exactly the same way as it deals with
    the converted layout. However, due to constraints related to page size
    differences if the OS is not running with 4k pages, and related to
    systems that may expose the individual sections of PE/COFF runtime
    modules as different memory regions, creating the virtual layout is a
    bit fiddly, and requires us to sort the memory map and reason about
    adjacent regions with identical memory types etc etc.

    So the obvious fix is to stop calling SetVirtualAddressMap() altogether
    on arm64 systems. However, to avoid surprises, which are notoriously
    hard to diagnose when it comes to OS<->firmware interactions, let's
    start by making it an opt-out feature, and implement support for the
    'efi=novamap' kernel command line parameter on ARM and arm64 systems.

    ( Note that 32-bit ARM generally does require SetVirtualAddressMap() to be
    used, given that the physical memory map and the kernel virtual address
    map are not guaranteed to be non-overlapping like on arm64. However,
    having support for efi=novamap,noruntime on 32-bit ARM, combined with
    the recently proposed support for earlycon=efifb, is likely to be useful
    to diagnose boot issues on such systems if they have no accessible serial
    port. )

    Tested-by: Jeffrey Hugo <jhugo@codeaurora.org>
    Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org>
    Tested-by: Lee Jones <lee.jones@linaro.org>
    Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
    Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
    Cc: Alexander Graf <agraf@suse.de>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
    Cc: Leif Lindholm <leif.lindholm@linaro.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Matt Fleming <matt@codeblueprint.co.uk>
    Cc: Peter Jones <pjones@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: linux-efi@vger.kernel.org
    Link: http://lkml.kernel.org/r/20190202094119.13230-8-ard.biesheuvel@linaro.org
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/firmware/efi/libstub/arm-stub.c | 5 +++++
    drivers/firmware/efi/libstub/efi-stub-helper.c | 10 ++++++++++
    drivers/firmware/efi/libstub/efistub.h | 1 +
    drivers/firmware/efi/libstub/fdt.c | 3 +++
    4 files changed, 19 insertions(+)

    diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
    index 01a9d78ee415..3b1e1dc3fb46 100644
    --- a/drivers/firmware/efi/libstub/arm-stub.c
    +++ b/drivers/firmware/efi/libstub/arm-stub.c
    @@ -364,6 +364,11 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
    paddr = in->phys_addr;
    size = in->num_pages * EFI_PAGE_SIZE;

    + if (novamap()) {
    + in->virt_addr = in->phys_addr;
    + continue;
    + }
    +
    /*
    * Make the mapping compatible with 64k pages: this allows
    * a 4k page size kernel to kexec a 64k page size kernel and
    diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
    index 50a9cab5a834..39f87e6dac5c 100644
    --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
    +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
    @@ -34,6 +34,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;

    static int __section(.data) __nokaslr;
    static int __section(.data) __quiet;
    +static int __section(.data) __novamap;

    int __pure nokaslr(void)
    {
    @@ -43,6 +44,10 @@ int __pure is_quiet(void)
    {
    return __quiet;
    }
    +int __pure novamap(void)
    +{
    + return __novamap;
    +}

    #define EFI_MMAP_NR_SLACK_SLOTS 8

    @@ -454,6 +459,11 @@ efi_status_t efi_parse_options(char const *cmdline)
    __chunk_size = -1UL;
    }

    + if (!strncmp(str, "novamap", 7)) {
    + str += strlen("novamap");
    + __novamap = 1;
    + }
    +
    /* Group words together, delimited by "," */
    while (*str && *str != ' ' && *str != ',')
    str++;
    diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
    index f59564b72ddc..2adde22b4a9f 100644
    --- a/drivers/firmware/efi/libstub/efistub.h
    +++ b/drivers/firmware/efi/libstub/efistub.h
    @@ -27,6 +27,7 @@

    extern int __pure nokaslr(void);
    extern int __pure is_quiet(void);
    +extern int __pure novamap(void);

    #define pr_efi(sys_table, msg) do { \
    if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
    diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
    index 0c0d2312f4a8..dba296a44f4e 100644
    --- a/drivers/firmware/efi/libstub/fdt.c
    +++ b/drivers/firmware/efi/libstub/fdt.c
    @@ -327,6 +327,9 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
    if (status == EFI_SUCCESS) {
    efi_set_virtual_address_map_t *svam;

    + if (novamap())
    + return EFI_SUCCESS;
    +
    /* Install the new virtual address map */
    svam = sys_table->runtime->set_virtual_address_map;
    status = svam(runtime_entry_count * desc_size, desc_size,
    --
    2.19.1
    \
     
     \ /
      Last update: 2019-03-27 19:48    [W:2.327 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site