From patchwork Thu Jul 16 23:41:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 11668587 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 58FFE913 for ; Thu, 16 Jul 2020 23:44:03 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D1372063A for ; Thu, 16 Jul 2020 23:44:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="wN3yps8p"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="OatFTntv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1D1372063A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=wdc.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=j9u2Nay+CNwsYIcI+j2VDtvfy9QkQxSzg7R6eBLy5P4=; b=wN3yps8pUql9EnSeOXGoUrmdu PRdIeD1vtfAAu9Mz4TUuwKgCOiR1RNI7hWx3lvYcDzOUt+FgnaszKPv9pjzn8lgWzURgXcWiCofZb ex3++FGNI2CTzJwp7ZZWDx6oK8c4F6Q9WLyye1c9eNHdh6g8/DZTHMvUfQ+bkdR4F9/YGj5dSAsrW OOEPEiZHk5W9qWDsG02NWozME6mJ4GqZMtj0skRjs+M/Pn+zvrA9VFxxjNwEfZd99c/FaeGodObI+ QbyLnvUI59wDL3fidLpJNycxnEUYSTsdgYeYFvX6RyMftep/kltvGQhDZ86wQB7NDYi4OnTcWYYOw 5cG2cmtgQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwDWC-00089U-Sc; Thu, 16 Jul 2020 23:42:24 +0000 Received: from esa5.hgst.iphmx.com ([216.71.153.144]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwDVF-0007hQ-Gn; Thu, 16 Jul 2020 23:41:27 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1594942885; x=1626478885; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+dRNU0rUBy3uiPlRFMFMQL4601DHVlVc1LuPVkdO8Uk=; b=OatFTntveRLgriFgV0odewAxnmwY9SBd1uF37OpkVHO+3Stswte+G5yo 3TCrXRI+lTg2w1zlTplVqSqfbMzS8YOUFRpwSGJv57aVglZawhPxDXLMf iFuOpK7ia8rlhCkdvXvKAismpgg3Bljbhbix90vOOTxPCAl8k6t2T2U6K Krm+9p1jquFls7ZPDBbxTsKV15oBQPXg9zVIiby8APj0v57hqDY/KX7gz 2Yj4imu7Vev3qfjettqRfqlEbcL33VJG8Kt5qQNfpZvun3WbbA+kZTeAf pKKpGuJOMh7TFh+yMfAVFg/rZ5cRd7ORcDu+3cf0kuDY/tQUIvrSlhqYJ Q==; IronPort-SDR: yoOg3BzFWgktacapdSt8CPYWzXrhPee604dK5dP+90fbYEsjSJB7kzZ0+KXModDNy9VBgUg0Gc 1C/W4TTrEFCRugBViIjbsubWRH3jJctf5f7KEqhQidgEQr+q+YXekmPWSFCJlvPUQB6cA8byEj 4qYmtbFt4DMgp6UCsJOLm+ACSI41sZyJP1rHlU2yDTPyBSItvStudVyGg5VirAgicYpWq4VwQK GMmbBm3RmjUKQEFfSxivPCK5wJWeDE7g57WIVoix0aKJJfugkOHqGGwj8jMgbZMJNUg5rBQIC3 ogw= X-IronPort-AV: E=Sophos;i="5.75,360,1589212800"; d="scan'208";a="142782192" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 17 Jul 2020 07:41:25 +0800 IronPort-SDR: Kau/dZlU2hsFP9ae3pBYR6WJJDCatmJ0OCOYkkBMAX1szPeMVxhzFHXImbBxM+fg9DGuxs05H5 zafANhR6sByqS8mEYES4qeSnEZhtk//SE= Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jul 2020 16:29:48 -0700 IronPort-SDR: StdTu7g8es1+7XW7fSijIUAqaG5+s5Wei7faMCiGT/YDdtuHNIruX3EYF27rNKpUyGWYbEXHsL S2jdRhTEMnZA== WDCIronportException: Internal Received: from phd004806.ad.shared (HELO jedi-01.hgst.com) ([10.86.58.54]) by uls-op-cesaip02.wdc.com with ESMTP; 16 Jul 2020 16:41:23 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Subject: [RFT PATCH v3 8/9] RISC-V: Add EFI runtime services Date: Thu, 16 Jul 2020 16:41:03 -0700 Message-Id: <20200716234104.29049-9-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200716234104.29049-1-atish.patra@wdc.com> References: <20200716234104.29049-1-atish.patra@wdc.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200716_194125_915596_17515E4A X-CRM114-Status: GOOD ( 31.11 ) X-Spam-Score: -2.5 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-2.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [216.71.153.144 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , linux-efi@vger.kernel.org, Kees Cook , Arnd Bergmann , Heinrich Schuchardt , Masahiro Yamada , Anup Patel , Mike Rapoport , Atish Patra , Palmer Dabbelt , Zong Li , Paul Walmsley , Greentime Hu , linux-riscv@lists.infradead.org, Will Deacon , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds EFI runtime service support for RISC-V. Signed-off-by: Atish Patra --- arch/riscv/Kconfig | 2 + arch/riscv/include/asm/efi.h | 20 ++++ arch/riscv/include/asm/mmu.h | 2 + arch/riscv/include/asm/pgtable.h | 4 + arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/efi.c | 105 +++++++++++++++++ arch/riscv/kernel/setup.c | 7 +- arch/riscv/mm/init.c | 2 +- drivers/firmware/efi/Makefile | 2 + drivers/firmware/efi/libstub/efi-stub.c | 11 +- drivers/firmware/efi/riscv-runtime.c | 143 ++++++++++++++++++++++++ 11 files changed, 295 insertions(+), 4 deletions(-) create mode 100644 arch/riscv/kernel/efi.c create mode 100644 drivers/firmware/efi/riscv-runtime.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index a6569c268565..4858b19fe3a4 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -401,7 +401,9 @@ config EFI select EFI_PARAMS_FROM_FDT select EFI_STUB select EFI_GENERIC_STUB + select EFI_RUNTIME_WRAPPERS select RISCV_ISA_C + depends on MMU default y help This option provides support for runtime services provided diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h index 86da231909bb..93c305a638f4 100644 --- a/arch/riscv/include/asm/efi.h +++ b/arch/riscv/include/asm/efi.h @@ -5,11 +5,28 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H +#include #include #include #include #include +#ifdef CONFIG_EFI +extern void efi_init(void); +#else +#define efi_init() +#endif + +int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); +int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); + +#define arch_efi_call_virt_setup() efi_virtmap_load() +#define arch_efi_call_virt_teardown() efi_virtmap_unload() + +#define arch_efi_call_virt(p, f, args...) p->f(args) + +#define ARCH_EFI_IRQ_FLAGS_MASK (SR_IE | SR_SPIE) + /* on RISC-V, the FDT may be located anywhere in system RAM */ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) { @@ -33,4 +50,7 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) { } +void efi_virtmap_load(void); +void efi_virtmap_unload(void); + #endif /* _ASM_EFI_H */ diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h index 967eacb01ab5..dabcf2cfb3dc 100644 --- a/arch/riscv/include/asm/mmu.h +++ b/arch/riscv/include/asm/mmu.h @@ -20,6 +20,8 @@ typedef struct { #endif } mm_context_t; +void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, + phys_addr_t sz, pgprot_t prot); #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_MMU_H */ diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index eaea1f717010..d53ef48768ae 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -100,6 +100,10 @@ #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL | _PAGE_EXEC) +#define PAGE_KERNEL_READ __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) +#define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL | _PAGE_EXEC) +#define PAGE_KERNEL_READ_EXEC __pgprot((_PAGE_KERNEL & ~_PAGE_WRITE) \ + | _PAGE_EXEC) #define PAGE_TABLE __pgprot(_PAGE_TABLE) diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 6f7a3b3771fd..239c44c451b6 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -36,6 +36,7 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_ $(obj)/%.stub.o: $(obj)/%.o FORCE $(call if_changed,objcopy) +obj-$(CONFIG_EFI) += efi.o obj-$(CONFIG_FPU) += fpu.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/riscv/kernel/efi.c b/arch/riscv/kernel/efi.c new file mode 100644 index 000000000000..d7a723b446c3 --- /dev/null +++ b/arch/riscv/kernel/efi.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + * Adapted from arch/arm64/kernel/efi.c + */ + +#include +#include + +#include +#include +#include + +/* + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be + * executable, everything else can be mapped with the XN bits + * set. Also take the new (optional) RO/XP bits into account. + */ +static __init pgprot_t efimem_to_pgprot_map(efi_memory_desc_t *md) +{ + u64 attr = md->attribute; + u32 type = md->type; + + if (type == EFI_MEMORY_MAPPED_IO) + return PAGE_KERNEL; + + if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr), + "UEFI Runtime regions are not aligned to page size -- buggy firmware?")) + /* + * If the region is not aligned to the page size of the OS, we + * can not use strict permissions, since that would also affect + * the mapping attributes of the adjacent regions. + */ + return PAGE_EXEC; + + /* R-- */ + if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) == + (EFI_MEMORY_XP | EFI_MEMORY_RO)) + return PAGE_KERNEL_READ; + + /* R-X */ + if (attr & EFI_MEMORY_RO) + return PAGE_KERNEL_READ_EXEC; + + /* RW- */ + if (((attr & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP)) == + EFI_MEMORY_XP) || + type != EFI_RUNTIME_SERVICES_CODE) + return PAGE_KERNEL; + + /* RWX */ + return PAGE_KERNEL_EXEC; +} + +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) +{ + pgprot_t prot = __pgprot(pgprot_val(efimem_to_pgprot_map(md)) & + ~(_PAGE_GLOBAL)); + int i; + + /* RISC-V maps one page at a time */ + for (i = 0; i < md->num_pages; i++) + create_pgd_mapping(mm->pgd, md->virt_addr + i * PAGE_SIZE, + md->phys_addr + i * PAGE_SIZE, + PAGE_SIZE, prot); + return 0; +} + +static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) +{ + efi_memory_desc_t *md = data; + pte_t pte = READ_ONCE(*ptep); + unsigned long val; + + if (md->attribute & EFI_MEMORY_RO) { + val = pte_val(pte) & ~_PAGE_WRITE; + val = pte_val(pte) | _PAGE_READ; + pte = __pte(val); + } + if (md->attribute & EFI_MEMORY_XP) { + val = pte_val(pte) & ~_PAGE_EXEC; + pte = __pte(val); + } + set_pte(ptep, pte); + + return 0; +} + +int __init efi_set_mapping_permissions(struct mm_struct *mm, + efi_memory_desc_t *md) +{ + BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && + md->type != EFI_RUNTIME_SERVICES_DATA); + + /* + * Calling apply_to_page_range() is only safe on regions that are + * guaranteed to be mapped down to pages. Since we are only called + * for regions that have been mapped using efi_create_mapping() above + * (and this is checked by the generic Memory Attributes table parsing + * routines), there is no need to check that again here. + */ + return apply_to_page_range(mm, md->virt_addr, + md->num_pages << EFI_PAGE_SHIFT, + set_permissions, md); +} diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 1244b433fe7c..0a725bd8d73e 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,11 +27,12 @@ #include #include #include +#include #include "head.h" -#ifdef CONFIG_DUMMY_CONSOLE -struct screen_info screen_info = { +#if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_EFI) +struct screen_info screen_info __section(.data) = { .orig_video_lines = 30, .orig_video_cols = 80, .orig_video_mode = 0, @@ -75,6 +77,7 @@ void __init setup_arch(char **cmdline_p) early_ioremap_setup(); parse_early_param(); + efi_init(); setup_bootmem(); paging_init(); unflatten_and_copy_device_tree(); diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 9f3129c76985..2947cff5e88a 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -356,7 +356,7 @@ static void __init create_pmd_mapping(pmd_t *pmdp, #define fixmap_pgd_next fixmap_pte #endif -static void __init create_pgd_mapping(pgd_t *pgdp, +void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, phys_addr_t sz, pgprot_t prot) { diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 61fd1e8b26fb..4d628081bb2f 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -35,6 +35,8 @@ fake_map-$(CONFIG_X86) += x86_fake_mem.o arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) +riscv-obj-$(CONFIG_EFI) := efi-init.o riscv-runtime.o +obj-$(CONFIG_RISCV) += $(riscv-obj-y) obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o obj-$(CONFIG_EFI_EARLYCON) += earlycon.o obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c index 3318ec3f8e5b..6f9559a54cb3 100644 --- a/drivers/firmware/efi/libstub/efi-stub.c +++ b/drivers/firmware/efi/libstub/efi-stub.c @@ -17,7 +17,10 @@ /* * This is the base address at which to start allocating virtual memory ranges - * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use + * for UEFI Runtime Services. + * + * For ARM/ARM64: + * This is in the low TTBR0 range so that we can use * any allocation we choose, and eliminate the risk of a conflict after kexec. * The value chosen is the largest non-zero power of 2 suitable for this purpose * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can @@ -25,6 +28,12 @@ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split, * map everything below 1 GB. (512 MB is a reasonable upper bound for the * entire footprint of the UEFI runtime services memory regions) + * + * For RISC-V: + * There is no specific reason for which, this address (512MB) can't be used + * EFI runtime virtual address for RISC-V. It also helps to use EFI runtime + * services on both RV32/RV64. Keep the same runtime virtual address for RISC-V + * as well to minimize the code churn. */ #define EFI_RT_VIRTUAL_BASE SZ_512M #define EFI_RT_VIRTUAL_SIZE SZ_512M diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c new file mode 100644 index 000000000000..d28e715d2bcc --- /dev/null +++ b/drivers/firmware/efi/riscv-runtime.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Extensible Firmware Interface + * + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + * + * Based on Extensible Firmware Interface Specification version 2.4 + * Adapted from drivers/firmware/efi/arm-runtime.c + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static bool __init efi_virtmap_init(void) +{ + efi_memory_desc_t *md; + + efi_mm.pgd = pgd_alloc(&efi_mm); + mm_init_cpumask(&efi_mm); + init_new_context(NULL, &efi_mm); + + for_each_efi_memory_desc(md) { + phys_addr_t phys = md->phys_addr; + int ret; + + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) + return false; + + ret = efi_create_mapping(&efi_mm, md); + if (ret) { + pr_warn(" EFI remap %pa: failed to create mapping (%d)\n", + &phys, ret); + return false; + } + } + + if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions)) + return false; + + return true; +} + +/* + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., + * non-early mapping of the UEFI system table and virtual mappings for all + * EFI_MEMORY_RUNTIME regions. + */ +static int __init riscv_enable_runtime_services(void) +{ + u64 mapsize; + + if (!efi_enabled(EFI_BOOT)) { + pr_info("EFI services will not be available.\n"); + return 0; + } + + efi_memmap_unmap(); + + mapsize = efi.memmap.desc_size * efi.memmap.nr_map; + + if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) { + pr_err("Failed to remap EFI memory map\n"); + return 0; + } + + if (efi_soft_reserve_enabled()) { + efi_memory_desc_t *md; + + for_each_efi_memory_desc(md) { + int md_size = md->num_pages << EFI_PAGE_SHIFT; + struct resource *res; + + if (!(md->attribute & EFI_MEMORY_SP)) + continue; + + res = kzalloc(sizeof(*res), GFP_KERNEL); + if (WARN_ON(!res)) + break; + + res->start = md->phys_addr; + res->end = md->phys_addr + md_size - 1; + res->name = "Soft Reserved"; + res->flags = IORESOURCE_MEM; + res->desc = IORES_DESC_SOFT_RESERVED; + + insert_resource(&iomem_resource, res); + } + } + + if (efi_runtime_disabled()) { + pr_info("EFI runtime services will be disabled.\n"); + return 0; + } + + if (efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_info("EFI runtime services access via paravirt.\n"); + return 0; + } + + pr_info("Remapping and enabling EFI services.\n"); + + if (!efi_virtmap_init()) { + pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); + return -ENOMEM; + } + + /* Set up runtime services function pointers */ + efi_native_runtime_setup(); + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); + + return 0; +} +early_initcall(riscv_enable_runtime_services); + +void efi_virtmap_load(void) +{ + preempt_disable(); + switch_mm(current->active_mm, &efi_mm, NULL); +} + +void efi_virtmap_unload(void) +{ + switch_mm(&efi_mm, current->active_mm, NULL); + preempt_enable(); +}