From patchwork Wed Aug 12 23:47:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254287 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92E44C433E1 for ; Wed, 12 Aug 2020 23:49:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6C537207DA for ; Wed, 12 Aug 2020 23:49:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="mfbtjaUr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726609AbgHLXse (ORCPT ); Wed, 12 Aug 2020 19:48:34 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52577 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726078AbgHLXse (ORCPT ); Wed, 12 Aug 2020 19:48:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1597276114; x=1628812114; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ss7v7i24RcPKHBXiHEHCAW6OY2lID7nAgTcbvPPDVXc=; b=mfbtjaUr+74jaaewgQTAtyD9HTVmII61OkX4vmL9S5ZDsGZ2HV2w7E1p wBFs3uT9AOOpcIfTQr//JB7TGVKjmb6VeO0oRG/rI1EiHRCxMCta/XxBs 9EH8YtdHX31+si/X6hRiSc4lFYsmhFie7q13czqha0pLiHNh72ZZlDLKC /1wTpXkL/uG9w1i2qLwwbRXNwYnxSUMnfKBQjzCo6f2TqnpVxlNeUVmXR d5Ee8M/JdGsyf+ihlIaFCIAsHAafrnKaC+M5N/QV8An17Auhd5VMFOR7U lOGC51A9ddMouZRi9gqNAbDlRTEMqMkq8eomt6pzfzpN2jmC04pFvPaKG Q==; IronPort-SDR: pCbwNr8RbN/p+X/hqToX9oxRIu6P3JzXouqthGb171DeHEA1bEa0FipT9PHP0OoU8A2kbupAP1 TgUA2sBgupAyw4JjF3OsrnAUzQh/2CY2qk+UrLCzaoDyEkkg6rJTBhpPbKqcfh7HcPI5OY6EJM j+a4NMz1+QyAEbQcMHK5A5ZXc/uP91C37E5EXdjc85ZfqxyB1GZ3LmaegqGi3IfgBvCpMk8cKq VaUv6H+oUHwRQNmgAi9ZogUi2/bRlh1i/vnzf8X9xjxpLTUolYhH68ACkry432F+qroOG4M2+v 2Xo= X-IronPort-AV: E=Sophos;i="5.76,305,1592841600"; d="scan'208";a="149145663" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 13 Aug 2020 07:48:34 +0800 IronPort-SDR: zoACAZgvNDeO+XKVTrXrKqyt2LxKC4EZYoGizqt3umxKHhEasd75YA9YpL2hTt9Wfei0F4z/Ey iOgs5k5Wy9VA== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 16:35:41 -0700 IronPort-SDR: /cr/S196xuexZyrwj7PKNDn3MhfMdkR8Djv0Q+hPdLHRj16wRItHsFAuGr7p6qcTIOY8a1iVh6 js0iHK39mgNw== WDCIronportException: Internal Received: from usa002576.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.59]) by uls-op-cesaip01.wdc.com with ESMTP; 12 Aug 2020 16:48:30 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Albert Ou , Alistair Francis , Andrew Morton , Anup Patel , Ard Biesheuvel , Arvind Sankar , Borislav Petkov , Greentime Hu , Ingo Molnar , Kees Cook , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, fwts-devel@lists.ubuntu.com, Mao Han , Masahiro Yamada , Michal Simek , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley , Steven Price , Waiman Long , Will Deacon , Daniel Schaefer , "abner.chang@hpe.com" Subject: [PATCH v5 2/9] RISC-V: Add early ioremap support Date: Wed, 12 Aug 2020 16:47:51 -0700 Message-Id: <20200812234758.3563-3-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200812234758.3563-1-atish.patra@wdc.com> References: <20200812234758.3563-1-atish.patra@wdc.com> MIME-Version: 1.0 Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org UEFI uses early IO or memory mappings for runtime services before normal ioremap() is usable. Add the necessary fixmap bindings and pmd mappings for generic ioremap support to work. Signed-off-by: Atish Patra --- arch/riscv/Kconfig | 1 + arch/riscv/include/asm/Kbuild | 1 + arch/riscv/include/asm/fixmap.h | 13 +++++++++++++ arch/riscv/include/asm/io.h | 1 + arch/riscv/kernel/setup.c | 1 + arch/riscv/mm/init.c | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 7b5905529146..15597f5f504f 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -37,6 +37,7 @@ config RISCV select GENERIC_ARCH_TOPOLOGY if SMP select GENERIC_ATOMIC64 if !64BIT select GENERIC_CLOCKEVENTS + select GENERIC_EARLY_IOREMAP select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO select GENERIC_IOREMAP select GENERIC_IRQ_MULTI_HANDLER diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index 3d9410bb4de0..59dd7be55005 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +generic-y += early_ioremap.h generic-y += extable.h generic-y += flat.h generic-y += kvm_para.h diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 11613f38228a..54cbf07fb4e9 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -27,6 +27,19 @@ enum fixed_addresses { FIX_TEXT_POKE1, FIX_TEXT_POKE0, FIX_EARLYCON_MEM_BASE, + + __end_of_permanent_fixed_addresses, + /* + * Temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + */ +#define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE) +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) + + FIX_BTMAP_END = __end_of_permanent_fixed_addresses, + FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1, + __end_of_fixed_addresses }; diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index 3835c3295dc5..c025a746a148 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -14,6 +14,7 @@ #include #include #include +#include /* * MMIO access functions are separated out to break dependency cycles diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 6a0ee2405813..c71788e6aff4 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -72,6 +72,7 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line; + early_ioremap_setup(); parse_early_param(); setup_bootmem(); diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 2b651f63f5c4..b75ebe8e7a92 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -403,6 +403,9 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) uintptr_t load_pa = (uintptr_t)(&_start); uintptr_t load_sz = (uintptr_t)(&_end) - load_pa; uintptr_t map_size = best_map_size(load_pa, MAX_EARLY_MAPPING_SIZE); +#ifndef __PAGETABLE_PMD_FOLDED + pmd_t fix_bmap_spmd, fix_bmap_epmd; +#endif va_pa_offset = PAGE_OFFSET - load_pa; pfn_base = PFN_DOWN(load_pa); @@ -456,6 +459,36 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL); dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1)); dtb_early_pa = dtb_pa; + + /* + * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap + * range can not span multiple pmds. + */ + BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT) + != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT)); + +#ifndef __PAGETABLE_PMD_FOLDED + /* + * Early ioremap fixmap is already created as it lies within first 2MB + * of fixmap region. We always map PMD_SIZE. Thus, both FIX_BTMAP_END + * FIX_BTMAP_BEGIN should lie in the same pmd. Verify that and warn + * the user if not. + */ + fix_bmap_spmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_BEGIN))]; + fix_bmap_epmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_END))]; + if (pmd_val(fix_bmap_spmd) != pmd_val(fix_bmap_epmd)) { + WARN_ON(1); + pr_warn("fixmap btmap start [%08lx] != end [%08lx]\n", + pmd_val(fix_bmap_spmd), pmd_val(fix_bmap_epmd)); + pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n", + fix_to_virt(FIX_BTMAP_BEGIN)); + pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n", + fix_to_virt(FIX_BTMAP_END)); + + pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END); + pr_warn("FIX_BTMAP_BEGIN: %d\n", FIX_BTMAP_BEGIN); + } +#endif } static void __init setup_vm_final(void) From patchwork Wed Aug 12 23:47:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254289 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57A23C433DF for ; Wed, 12 Aug 2020 23:48:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2F4BA2076B for ; Wed, 12 Aug 2020 23:48:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="FurpFRzZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726664AbgHLXsg (ORCPT ); Wed, 12 Aug 2020 19:48:36 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52579 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726126AbgHLXsf (ORCPT ); Wed, 12 Aug 2020 19:48:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1597276116; x=1628812116; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=M/aLmMoaf+R1cfTR4Mi4doOLt0MJCtDnvFjCl4cVqNk=; b=FurpFRzZ2ZuhQ8LvBsxFVzQdS1WLcpb9fG7TJNHQqAgpketbdIP7VPlT IzAIOHtZGOCbowaAclBa0me2gGLLIbUI5OaMvBHNXS2Xio9V0zz7TK2C1 qxXgU+PmWzaWFj0KEq0EffYOpYy+q6ewVfzf0Qb2FBOQ1aZ5DNP1Hf2ou ahRwYwuuhHWO1hj4zYOC/fHMGUuvE2AtzOpmvONNWOguxAQtcTUk93C1u h3+qvl9kbVC/bk/rMdJEGg0TpOz+KMjCJLEtlhdDgj2jyINslY/sLM9P0 E2CF7siRVFozbAEwxMJ7Y9sNPu68/hW84RzSUyDsYqe3XF4qTp25aswMV A==; IronPort-SDR: VdNjFKQlHDSRckQfSy7BZcxq8U5O7GE4e5oHtJX592fhtkGJQ0gzNsA+FQqxsTrhjRRzXaRsIu Q/4agqjSZ5F5cFuJELI7wIB9qf0toc2jjLjxdmYXXF//etrHHAL+cc+n4iK7Kzr6L2Qgk8H1Qe kfnLy6XyMJfONu5aEiuKoPg9lg3v3meWkAiTHDD4USZHPi3pE4trPDAq322w3qFecmF06I0+Fk EO6Zz9MNYQSSAsjy5sWz0hTY7eZt7BSOsMJxKga9dTxk/VZqw6kWSvlp65zJBjncToyDiMWXKp 3QA= X-IronPort-AV: E=Sophos;i="5.76,305,1592841600"; d="scan'208";a="149145669" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 13 Aug 2020 07:48:36 +0800 IronPort-SDR: FfatyBmrFppYGe30QXMu0ENmEv37kR0JnqgMHgV04Iy2MBoa2QXgy8vebztVwrNp4fsOXe57en DErI3Sip2gYQ== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 16:35:42 -0700 IronPort-SDR: P3ovugPv+fDHQa0kXG4xONb+xNMYChSxVI7c1P6E62oC4EfAS3HLQYntJ5lU99kbUACcLa5o7B X4ihSkv+Dn0w== WDCIronportException: Internal Received: from usa002576.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.59]) by uls-op-cesaip01.wdc.com with ESMTP; 12 Aug 2020 16:48:32 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Palmer Dabbelt , Ard Biesheuvel , Albert Ou , Alistair Francis , Andrew Morton , Anup Patel , Arvind Sankar , Borislav Petkov , Greentime Hu , Ingo Molnar , Kees Cook , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, fwts-devel@lists.ubuntu.com, Mao Han , Masahiro Yamada , Michal Simek , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley , Steven Price , Waiman Long , Will Deacon , Daniel Schaefer , "abner.chang@hpe.com" Subject: [PATCH v5 4/9] include: pe.h: Add RISC-V related PE definition Date: Wed, 12 Aug 2020 16:47:53 -0700 Message-Id: <20200812234758.3563-5-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200812234758.3563-1-atish.patra@wdc.com> References: <20200812234758.3563-1-atish.patra@wdc.com> MIME-Version: 1.0 Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Define RISC-V related machine types. Signed-off-by: Atish Patra Reviewed-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20200415195422.19866-3-atish.patra@wdc.com Signed-off-by: Ard Biesheuvel --- include/linux/pe.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/pe.h b/include/linux/pe.h index 8ad71d763a77..daf09ffffe38 100644 --- a/include/linux/pe.h +++ b/include/linux/pe.h @@ -55,6 +55,9 @@ #define IMAGE_FILE_MACHINE_POWERPC 0x01f0 #define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 #define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_RISCV32 0x5032 +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 +#define IMAGE_FILE_MACHINE_RISCV128 0x5128 #define IMAGE_FILE_MACHINE_SH3 0x01a2 #define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 #define IMAGE_FILE_MACHINE_SH3E 0x01a4 From patchwork Wed Aug 12 23:47:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254290 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91924C433DF for ; Wed, 12 Aug 2020 23:48:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5B88E2076B for ; Wed, 12 Aug 2020 23:48:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="SYQSODWC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726685AbgHLXsk (ORCPT ); Wed, 12 Aug 2020 19:48:40 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52585 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726673AbgHLXsi (ORCPT ); Wed, 12 Aug 2020 19:48:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1597276118; x=1628812118; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Le3ol56BMmIezgwhWxX9I0J5qDYUCuRI0AKGwqTYIEk=; b=SYQSODWC7qu63Sy10twjoIt6iKG6vdqk5MS27aRwwF3SxHAJZ1MmBb7V sZgLHcceJf74omSVxNHLdtyclLpInBLKK1b8/VNP+dMNtwAw8ye9oH65s wsIMUH7oINqkLSZo4i2za16xsnfVFATLYInUyHL3qm5U2y5bAt9iiV+r9 hduHlGkMYa+ePz2yhCduM4niszCVGXlO4wvZOy+FFs5HeStLyZi800IZ9 ib92ka/78EzwAiwiLZRlkww0t65UT+BP9DJ0zf4cILbJGEwIXMypR1bof Gtlo1EYzq6yGe6tV5jG8bGfL8D0WvnfzgiDLpvShkDQrBbrgmS3oCmRI+ Q==; IronPort-SDR: JyzvJJx5xnPlt1cM6FFgUr4/Jvk9pf/4f4mLIUtp9K6/WWCprbLkqjY7tY1Nzc+voTTTc2T/by ExTFT+c+4Hi0W8SwRjzwqq8BWo16amctWjH8qyCz2QzZyYUnmWkTNL9Gl774TUCTiBnzFy/B6r FTJJdBEVZDJakb21++ruds+wRsbZ4LCoq+vS/YMWI5wZ2uc9xHVdZRn8+TLHxQHSw8wnOyQ7ze 1ptg10LbOz399JqnMdLLSM79F85BIv8W4BGkUe+Rk5B4At0X9GEln+7jD1BSTnBNkTC+cwlviU IcY= X-IronPort-AV: E=Sophos;i="5.76,305,1592841600"; d="scan'208";a="149145676" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 13 Aug 2020 07:48:38 +0800 IronPort-SDR: GmtdontQq65Sj8/PUpfttdpYsjNdA+k3UiaQkheEm8G4ZUD8YRFNB3FYX37Sggs5u6Q3wvMlPd AWgvvjt/tDXA== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 16:35:45 -0700 IronPort-SDR: jutY+rZsosRZIQRy49vOVXUDzlKm5/DXUeR6907sWZuEbSY8yXsz+lltYdcXQBeARBF2MVrFtC Oua0uTQpglvQ== WDCIronportException: Internal Received: from usa002576.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.59]) by uls-op-cesaip01.wdc.com with ESMTP; 12 Aug 2020 16:48:34 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Ard Biesheuvel , Albert Ou , Alistair Francis , Andrew Morton , Anup Patel , Arvind Sankar , Borislav Petkov , Greentime Hu , Ingo Molnar , Kees Cook , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, fwts-devel@lists.ubuntu.com, Mao Han , Masahiro Yamada , Michal Simek , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley , Steven Price , Waiman Long , Will Deacon , Daniel Schaefer , "abner.chang@hpe.com" Subject: [PATCH v5 6/9] RISC-V: Add EFI stub support. Date: Wed, 12 Aug 2020 16:47:55 -0700 Message-Id: <20200812234758.3563-7-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200812234758.3563-1-atish.patra@wdc.com> References: <20200812234758.3563-1-atish.patra@wdc.com> MIME-Version: 1.0 Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Add a RISC-V architecture specific stub code that actually copies the actual kernel image to a valid address and jump to it after boot services are terminated. Enable UEFI related kernel configs as well for RISC-V. Signed-off-by: Atish Patra Link: https://lore.kernel.org/r/20200421033336.9663-4-atish.patra@wdc.com [ardb: - move hartid fetch into check_platform_features() - use image_size not reserve_size - select ISA_C ] Signed-off-by: Ard Biesheuvel --- arch/riscv/Kconfig | 22 +++++ arch/riscv/Makefile | 1 + arch/riscv/configs/defconfig | 1 + arch/riscv/include/asm/efi.h | 36 +++++++ drivers/firmware/efi/Kconfig | 3 +- drivers/firmware/efi/libstub/Makefile | 10 ++ drivers/firmware/efi/libstub/riscv-stub.c | 110 ++++++++++++++++++++++ 7 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/include/asm/efi.h create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 15597f5f504f..e11907cc7a43 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -401,6 +401,26 @@ config CMDLINE_FORCE endchoice +config EFI_STUB + bool + +config EFI + bool "UEFI runtime support" + depends on OF + select LIBFDT + select UCS2_STRING + select EFI_PARAMS_FROM_FDT + select EFI_STUB + select EFI_GENERIC_STUB + select RISCV_ISA_C + default y + help + This option provides support for runtime services provided + by UEFI firmware (such as non-volatile variables, realtime + clock, and platform reset). A UEFI stub is also provided to + allow the kernel to be booted as an EFI application. This + is only useful on systems that have UEFI firmware. + endmenu config BUILTIN_DTB @@ -413,3 +433,5 @@ menu "Power management options" source "kernel/power/Kconfig" endmenu + +source "drivers/firmware/Kconfig" diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index fb6e37db836d..10df59f28add 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -80,6 +80,7 @@ head-y := arch/riscv/kernel/head.o core-y += arch/riscv/ libs-y += arch/riscv/lib/ +libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a PHONY += vdso_install vdso_install: diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index d58c93efb603..d222d353d86d 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -130,3 +130,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_MEMTEST=y # CONFIG_SYSFS_SYSCALL is not set +CONFIG_EFI=y diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h new file mode 100644 index 000000000000..86da231909bb --- /dev/null +++ b/arch/riscv/include/asm/efi.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + */ +#ifndef _ASM_EFI_H +#define _ASM_EFI_H + +#include +#include +#include +#include + +/* 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) +{ + return ULONG_MAX; +} + +/* Load initrd at enough distance from DRAM start */ +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, + unsigned long image_addr) +{ + return dram_base + SZ_256M; +} + +#define alloc_screen_info(x...) (&screen_info) + +static inline void free_screen_info(struct screen_info *si) +{ +} + +static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) +{ +} + +#endif /* _ASM_EFI_H */ diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 3939699e62fe..a29fbd6e657e 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -111,7 +111,7 @@ config EFI_GENERIC_STUB config EFI_ARMSTUB_DTB_LOADER bool "Enable the DTB loader" - depends on EFI_GENERIC_STUB + depends on EFI_GENERIC_STUB && !RISCV default y help Select this config option to add support for the dtb= command @@ -128,6 +128,7 @@ config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER bool "Enable the command line initrd loader" if !X86 depends on EFI_STUB && (EFI_GENERIC_STUB || X86) default y + depends on !RISCV help Select this config option to add support for the initrd= command line parameter, allowing an initrd that resides on the same volume diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 296b18fbd7a2..e9fc2ddabd5f 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -22,6 +22,8 @@ cflags-$(CONFIG_ARM64) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fno-builtin -fpic \ $(call cc-option,-mno-single-pic-base) +cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ + -fpic cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt @@ -63,6 +65,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o lib-$(CONFIG_X86) += x86-stub.o +lib-$(CONFIG_RISCV) += riscv-stub.o CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) @@ -106,6 +109,13 @@ STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ --prefix-symbols=__efistub_ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS +# For RISC-V, we don't need anything special other than arm64. Keep all the +# symbols in .init section and make sure that no absolute symbols references +# doesn't exist. +STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \ + --prefix-symbols=__efistub_ +STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20 + $(obj)/%.stub.o: $(obj)/%.o FORCE $(call if_changed,stubcopy) diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c new file mode 100644 index 000000000000..77c3fd6f820e --- /dev/null +++ b/drivers/firmware/efi/libstub/riscv-stub.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + */ + +#include +#include + +#include +#include + +#include "efistub.h" + +/* + * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and + * 4MB for 32 bit. + */ +#ifdef CONFIG_64BIT +#define MIN_KIMG_ALIGN SZ_2M +#else +#define MIN_KIMG_ALIGN SZ_4M +#endif + +typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long); + +static u32 hartid; + +static u32 get_boot_hartid_from_fdt(void) +{ + const void *fdt; + int chosen_node, len; + const fdt32_t *prop; + + fdt = get_efi_config_table(DEVICE_TREE_GUID); + if (!fdt) + return U32_MAX; + + chosen_node = fdt_path_offset(fdt, "/chosen"); + if (chosen_node < 0) + return U32_MAX; + + prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len); + if (!prop || len != sizeof(u32)) + return U32_MAX; + + return fdt32_to_cpu(*prop); +} + +efi_status_t check_platform_features(void) +{ + hartid = get_boot_hartid_from_fdt(); + if (hartid == U32_MAX) { + efi_err("/chosen/boot-hartid missing or invalid!\n"); + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; +} + +void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, + unsigned long fdt_size) +{ + unsigned long stext_offset = _start_kernel - _start; + unsigned long kernel_entry = entrypoint + stext_offset; + jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry; + + /* + * Jump to real kernel here with following constraints. + * 1. MMU should be disabled. + * 2. a0 should contain hartid + * 3. a1 should DT address + */ + csr_write(CSR_SATP, 0); + jump_kernel(hartid, fdt); +} + +efi_status_t handle_kernel_image(unsigned long *image_addr, + unsigned long *image_size, + unsigned long *reserve_addr, + unsigned long *reserve_size, + unsigned long dram_base, + efi_loaded_image_t *image) +{ + unsigned long kernel_size = 0; + unsigned long preferred_addr; + efi_status_t status; + + kernel_size = _edata - _start; + *image_addr = (unsigned long)_start; + *image_size = kernel_size + (_end - _edata); + + /* + * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical + * address where kernel is booted. That's why kernel should boot from + * as low as possible to avoid wastage of memory. Currently, dram_base + * is occupied by the firmware. So the preferred address for kernel to + * boot is next aligned address. If preferred address is not available, + * relocate_kernel will fall back to efi_low_alloc_above to allocate + * lowest possible memory region as long as the address and size meets + * the alignment constraints. + */ + preferred_addr = round_up(dram_base, MIN_KIMG_ALIGN) + MIN_KIMG_ALIGN; + status = efi_relocate_kernel(image_addr, kernel_size, *image_size, + preferred_addr, MIN_KIMG_ALIGN, dram_base); + + if (status != EFI_SUCCESS) { + efi_err("Failed to relocate kernel\n"); + *image_size = 0; + } + return status; +} From patchwork Wed Aug 12 23:47:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254288 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7338C433E4 for ; Wed, 12 Aug 2020 23:48:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AD2D1207DA for ; Wed, 12 Aug 2020 23:48:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="XoeSXu+n" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726723AbgHLXsw (ORCPT ); Wed, 12 Aug 2020 19:48:52 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52594 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726679AbgHLXsj (ORCPT ); Wed, 12 Aug 2020 19:48:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1597276120; x=1628812120; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AyscPrTBMPEV1pFK6H6MS2gy9j/3IWx/0KXmF4ioecg=; b=XoeSXu+nbAGt9wQIpDFC9Kra+cG3ACpK/w0HUYdJUhhQG1ZFczdzbJi0 bz60H8qT/JMmK4Z5Mnzgrx6UyV/PXBedRByHgFgwJOap/iLLZI3JYNmHq Q/kQeqze/OQaA4vcs+WZu6K3g7+HrAT3+icHfdZf8ZpxfdiZEa0jj+ro0 H8eT8jDqKeJ/ldwHqK+iRSzjRGBOZACYdD9fNNVZf8EM4Gqq0Jiqf8izn TElRCqa4K0CYbOgAbkDEnGDA8h4BflZdy8L8JwOJwZNmS5ErAHwfVpzp8 g3N7DOw8QOkBzbqH59yMGi2B/CAcFO+x0OkRByRiEHIGq/1sm9JqUQ7Jz g==; IronPort-SDR: /0xJ5DCAkxiFlgoM4OG1WRFwg47ia1pVJsocPN5QQlu0aOlfaA3zU+MLu5YUcJ57KwB+R5SnSG F95QNf14ANmPrBq990Ypz4nyx9iQSH2kBvWug9Jp+kAQvUK0dmCwfh/mcpEN/2H+KceiOFRORw Ow7V3I1EyUghIpafvfoVOKjDNdFDRzQuexNMfM5qOzHTDUteKIWqdjHG1evGpIRTII0GT8qIfp eGVevKbzP+yqV7DN0c0GnTvNqpg1y7jP84cJOs0vMIhnnH+eBn3KdVVf5KYbPpSOMhUozplJ4P S5M= X-IronPort-AV: E=Sophos;i="5.76,305,1592841600"; d="scan'208";a="149145682" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 13 Aug 2020 07:48:40 +0800 IronPort-SDR: miPafaKhQgD0xJzd5LgmIVhzW+C5/Ff9tddWEI1lHrb0KX8qZ0fAe0sTNGZt+28ACUXN2bWRr9 OvWMpQtXI60g== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 16:35:47 -0700 IronPort-SDR: s3XIhzFKbWw99sBsAPO2dHMSpXFypcoMB0ov+sphPMbk/v9YzMU10loiJ1laDEj6xfgA5YFG+k oq4/SiZomxug== WDCIronportException: Internal Received: from usa002576.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.59]) by uls-op-cesaip01.wdc.com with ESMTP; 12 Aug 2020 16:48:36 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Albert Ou , Alistair Francis , Andrew Morton , Anup Patel , Ard Biesheuvel , Arvind Sankar , Borislav Petkov , Greentime Hu , Ingo Molnar , Kees Cook , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, fwts-devel@lists.ubuntu.com, Mao Han , Masahiro Yamada , Michal Simek , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley , Steven Price , Waiman Long , Will Deacon , Daniel Schaefer , "abner.chang@hpe.com" Subject: [PATCH v5 8/9] RISC-V: Add EFI runtime services Date: Wed, 12 Aug 2020 16:47:57 -0700 Message-Id: <20200812234758.3563-9-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200812234758.3563-1-atish.patra@wdc.com> References: <20200812234758.3563-1-atish.patra@wdc.com> MIME-Version: 1.0 Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.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 e11907cc7a43..b2164109483d 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -412,7 +412,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 815f8c959dd4..183f1f4b2ae6 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 eabec4dce50b..0b48059cc9da 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 c71788e6aff4..7f2a0d6dca7d 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(); #if IS_ENABLED(CONFIG_BUILTIN_DTB) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index d238cdc501ee..9fb2fe2f4a3e 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -390,7 +390,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 a5a405d8ab44..5c26725d8fd0 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(); +}