From patchwork Fri Aug 28 17:20:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254251 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.6 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 84A6EC433E6 for ; Fri, 28 Aug 2020 17:20:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 477FA207DF for ; Fri, 28 Aug 2020 17:20:55 +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="U9cfZv5G" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727003AbgH1RUy (ORCPT ); Fri, 28 Aug 2020 13:20:54 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:11689 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726266AbgH1RUp (ORCPT ); Fri, 28 Aug 2020 13:20:45 -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=1598635244; x=1630171244; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=X1EAm83Z58wS8m4kEShYGvoalHrgEcszSU1A9lCYev8=; b=U9cfZv5G3kpk/f58jriN1ApINtk1wq7i0YQ/593xCG2CQnOfaI4B9iLu 0n8q4fZlIVJHQF/mmbYzSgYY4mNNxV5EMG6eKCnwqpLvWFtHqjdWFtU+a Vkmk556JCSFNkUyTcl+V7//HzPEFC2gqPkZuGGF+1n8ssZLLZ0x4dGzr9 0D8ye20gtD5qeSCM0iTNcCOXHe3d412h/wQ/rZ+/FcdRW6qyiYNNB0aN5 gS7uCF1Zf9hqf0+e/9TqRkS4D8zF/xIFGSGwzNwe9P4m7/pSj25N7L+Ss bS9rzZHgQv9EgHoozaWt3deyXGpN6ho1VyLhEjEDTcGfufrUaE8wJNsyi Q==; IronPort-SDR: HkjE0eXiE8YuxdKdLp3w35kVsHTUOpBHmf6+3s2QSzSX2yt1LTasRuVVayqz2JRlu7iLU+TVJw iPxVrCj/GHYBxJmQO5Yp0BxHwgkkAdHhWV2pamQbcNBnhZMd0uDOGoduSywkHKRLSiG7v4LYZP c4q6wpoXGQOXmSCMCizQbmGQ6OiI3Ub/STYHSvJnB3h8mXYct4YkXf6tGTofs3ZjbtidAqZkAW o+cPQdylQR93hjDUjYQ5H6e5Ct+B5i6n4rYcPgLSMkZaTb0lfhPHvjAeAu69IZWGFRHx0LKzLM mMk= X-IronPort-AV: E=Sophos;i="5.76,364,1592841600"; d="scan'208";a="146018509" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Aug 2020 01:20:43 +0800 IronPort-SDR: eJ1ogcOq0I37o6vmFRD60TCZGDhnTIy5oBFfPXq0kA6NM8YvrMFzrT8pXMIuxOXxDqxJsjdKju ijgwxl67Zcqg== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Aug 2020 10:08:15 -0700 IronPort-SDR: WlG/c0AW18ViIX1ctKbNpx9vbHXU1Ez+YKVY2LEgu43OSrzBLhXn0KDoOl35+ldOWRMPmnAARh yaQkEMoopFhQ== WDCIronportException: Internal Received: from 6hj08h2.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.137]) by uls-op-cesaip01.wdc.com with ESMTP; 28 Aug 2020 10:20:42 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Anup Patel , Atish Patra , Palmer Dabbelt , Alistair Francis , Ard Biesheuvel , Arvind Sankar , Greentime Hu , Ingo Molnar , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, Masahiro Yamada , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley Subject: [PATCH v7 1/9] RISC-V: Move DT mapping outof fixmap Date: Fri, 28 Aug 2020 10:20:28 -0700 Message-Id: <20200828172036.8056-2-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200828172036.8056-1-atish.patra@wdc.com> References: <20200828172036.8056-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 From: Anup Patel Currently, RISC-V reserves 1MB of fixmap memory for device tree. However, it maps only single PMD (2MB) space for fixmap which leaves only < 1MB space left for other kernel features such as early ioremap which requires fixmap as well. The fixmap size can be increased by another 2MB but it brings additional complexity and changes the virtual memory layout as well. If we require some additional feature requiring fixmap again, it has to be moved again. Technically, DT doesn't need a fixmap as the memory occupied by the DT is only used during boot. That's why, We map device tree in early page table using two consecutive PGD mappings at lower addresses (< PAGE_OFFSET). This frees lot of space in fixmap and also makes maximum supported device tree size supported as PGDIR_SIZE. Thus, init memory section can be used for the same purpose as well. This simplifies fixmap implementation. Signed-off-by: Anup Patel Signed-off-by: Atish Patra Reviewed-by: Palmer Dabbelt --- arch/riscv/include/asm/fixmap.h | 3 --- arch/riscv/include/asm/pgtable.h | 1 + arch/riscv/kernel/head.S | 1 - arch/riscv/kernel/head.h | 2 -- arch/riscv/kernel/setup.c | 9 +++++++-- arch/riscv/mm/init.c | 26 ++++++++++++-------------- 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 1ff075a8dfc7..11613f38228a 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -22,9 +22,6 @@ */ enum fixed_addresses { FIX_HOLE, -#define FIX_FDT_SIZE SZ_1M - FIX_FDT_END, - FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1, FIX_PTE, FIX_PMD, FIX_TEXT_POKE1, diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index eaea1f717010..815f8c959dd4 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -464,6 +464,7 @@ static inline void __kernel_map_pages(struct page *page, int numpages, int enabl #define kern_addr_valid(addr) (1) /* FIXME */ extern void *dtb_early_va; +extern uintptr_t dtb_early_pa; void setup_bootmem(void); void paging_init(void); diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 0a4e81b8dc79..c6a37e8231a8 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -259,7 +259,6 @@ clear_bss_done: #endif /* Start the kernel */ call soc_early_init - call parse_dtb tail start_kernel .Lsecondary_start: diff --git a/arch/riscv/kernel/head.h b/arch/riscv/kernel/head.h index 105fb0496b24..b48dda3d04f6 100644 --- a/arch/riscv/kernel/head.h +++ b/arch/riscv/kernel/head.h @@ -16,6 +16,4 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa); extern void *__cpu_up_stack_pointer[]; extern void *__cpu_up_task_pointer[]; -void __init parse_dtb(void); - #endif /* __ASM_HEAD_H */ diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 2c6dd329312b..edea7ef88402 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -48,8 +48,9 @@ atomic_t hart_lottery __section(.sdata); unsigned long boot_cpu_hartid; static DEFINE_PER_CPU(struct cpu, cpu_devices); -void __init parse_dtb(void) +static void __init parse_dtb(void) { + /* Early scan of device tree from init memory */ if (early_init_dt_scan(dtb_early_va)) return; @@ -62,6 +63,7 @@ void __init parse_dtb(void) void __init setup_arch(char **cmdline_p) { + parse_dtb(); init_mm.start_code = (unsigned long) _stext; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; @@ -76,7 +78,10 @@ void __init setup_arch(char **cmdline_p) #if IS_ENABLED(CONFIG_BUILTIN_DTB) unflatten_and_copy_device_tree(); #else - unflatten_device_tree(); + if (early_init_dt_verify(__va(dtb_early_pa))) + unflatten_device_tree(); + else + pr_err("No DTB found in kernel mappings\n"); #endif #ifdef CONFIG_SWIOTLB diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 787c75f751a5..2b651f63f5c4 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -28,7 +28,9 @@ unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] EXPORT_SYMBOL(empty_zero_page); extern char _start[]; -void *dtb_early_va; +#define DTB_EARLY_BASE_VA PGDIR_SIZE +void *dtb_early_va __initdata; +uintptr_t dtb_early_pa __initdata; static void __init zone_sizes_init(void) { @@ -141,8 +143,6 @@ static void __init setup_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ -static phys_addr_t dtb_early_pa __initdata; - void __init setup_bootmem(void) { struct memblock_region *reg; @@ -399,7 +399,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) asmlinkage void __init setup_vm(uintptr_t dtb_pa) { - uintptr_t va, end_va; + uintptr_t va, pa, end_va; 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); @@ -448,16 +448,13 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) load_pa + (va - PAGE_OFFSET), map_size, PAGE_KERNEL_EXEC); - /* Create fixed mapping for early FDT parsing */ - end_va = __fix_to_virt(FIX_FDT) + FIX_FDT_SIZE; - for (va = __fix_to_virt(FIX_FDT); va < end_va; va += PAGE_SIZE) - create_pte_mapping(fixmap_pte, va, - dtb_pa + (va - __fix_to_virt(FIX_FDT)), - PAGE_SIZE, PAGE_KERNEL); - - /* Save pointer to DTB for early FDT parsing */ - dtb_early_va = (void *)fix_to_virt(FIX_FDT) + (dtb_pa & ~PAGE_MASK); - /* Save physical address for memblock reservation */ + /* Create two consecutive PGD mappings for FDT early scan */ + pa = dtb_pa & ~(PGDIR_SIZE - 1); + create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, + pa, PGDIR_SIZE, PAGE_KERNEL); + create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE, + 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; } @@ -516,6 +513,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) #else dtb_early_va = (void *)dtb_pa; #endif + dtb_early_pa = dtb_pa; } static inline void setup_vm_final(void) From patchwork Fri Aug 28 17:20:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254250 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.6 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 E5F42C43461 for ; Fri, 28 Aug 2020 17:21:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B2F3D207DF for ; Fri, 28 Aug 2020 17:21:05 +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="rUA5MOKx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726952AbgH1RVD (ORCPT ); Fri, 28 Aug 2020 13:21:03 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:11687 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726867AbgH1RUs (ORCPT ); Fri, 28 Aug 2020 13:20:48 -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=1598635246; x=1630171246; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9dzVAvMQzryRH4OY4uy0c2IA1NXr4r5gdlmIqy/4veo=; b=rUA5MOKx5oQ5CGgJQK5+hItGeXsdypoh/JsnjsXmSFMX8JCgQKmZDHfs gXEDwTby1Nxtei8kftPhIXwg7TkXEOsRiS7aVVDGxSHmqVsuFJTzJfoyC vkHEOrV0We2vv/jRSmpEtrpBesH8CMTulVhqDZfTmMt4SBa2dfJxZbJbM k4CNu02Q4Tr5rY6xaN8Si6Nk+C4PsoqVesIM0AT30ytkATivVYcFvQnhL tOwUHMxdSWtMOkOkRD9I27bIntkY9Pc1r6yBqvFc64+SHDVHtirUx3Xw2 U2sMJZkeVMULNBJznYL3CgwO2Xh3hopZrWTjcetV5nzawurQOOEZttAJD Q==; IronPort-SDR: oVB1RnvEJohTD62mkBh4XgMRZTBfVr0U9YyD4Efsh0sHCtrxQ22OdMiMWeDzd0s2LThIDH8eAH zloE0g7IFaSw4e8FdtUg1y9LSCeuJU78LeeIIS7XWg8RSo3Prvt9HJcuzeQiQVeDgkehaSL9ir TX8KRcpOobWUAz7qf3oU2R8jkTMMOcRK3hG8AwRSBDL++a1/s19XSHAqESkiALZwd7U0vtp2ya 84JBYOI+fFOGLVn09cQU0naOye0IyAfmNwUlPcsgea3ZQFmDp8I1mcd10PQeNRsbcAurbUjh6H gis= X-IronPort-AV: E=Sophos;i="5.76,364,1592841600"; d="scan'208";a="146018513" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Aug 2020 01:20:44 +0800 IronPort-SDR: 7SRYQKk9zxvE7eHLJTl7xFD+VLP0KE4VhurfnSNR5Ni0udJvFmnhNKPEvB7EeBt6h3euP/S9Yu WXPhNwFXOdVg== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Aug 2020 10:08:16 -0700 IronPort-SDR: cHEGtdZXUata0e29TqwV7pKiqsGxwZ/GjjyrOJsV4uVGyhC0xccgHd+P5yS9KgF9dMW1nvOkqH 0s8KQjCl06Cw== WDCIronportException: Internal Received: from 6hj08h2.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.137]) by uls-op-cesaip01.wdc.com with ESMTP; 28 Aug 2020 10:20:43 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Anup Patel , Mike Rapoport , Alistair Francis , Anup Patel , Ard Biesheuvel , Arvind Sankar , Greentime Hu , Ingo Molnar , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, Masahiro Yamada , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley Subject: [PATCH v7 3/9] RISC-V: Implement late mapping page table allocation functions Date: Fri, 28 Aug 2020 10:20:30 -0700 Message-Id: <20200828172036.8056-4-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200828172036.8056-1-atish.patra@wdc.com> References: <20200828172036.8056-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 Currently, page table setup is done during setup_va_final where fixmap can be used to create the temporary mappings. The physical frame is allocated from memblock_alloc_* functions. However, this won't work if page table mapping needs to be created for a different mm context (i.e. efi mm) at a later point of time. Use generic kernel page allocation function & macros for any mapping after setup_vm_final. Signed-off-by: Atish Patra Reviewed-by: Anup Patel Acked-by: Mike Rapoport --- arch/riscv/mm/init.c | 130 ++++++++++++++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 31 deletions(-) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index b75ebe8e7a92..cac2c31f8beb 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -32,6 +32,17 @@ extern char _start[]; void *dtb_early_va __initdata; uintptr_t dtb_early_pa __initdata; +struct pt_alloc_ops { + pte_t *(*get_pte_virt)(phys_addr_t pa); + phys_addr_t (*alloc_pte)(uintptr_t va); +#ifndef __PAGETABLE_PMD_FOLDED + pmd_t *(*get_pmd_virt)(phys_addr_t pa); + phys_addr_t (*alloc_pmd)(uintptr_t va); +#endif +}; + +static struct pt_alloc_ops pt_ops; + static void __init zone_sizes_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, }; @@ -211,7 +222,6 @@ EXPORT_SYMBOL(pfn_base); pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss; pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss; -static bool mmu_enabled; #define MAX_EARLY_MAPPING_SIZE SZ_128M @@ -234,27 +244,46 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) } } -static pte_t *__init get_pte_virt(phys_addr_t pa) +static inline pte_t *__init get_pte_virt_early(phys_addr_t pa) { - if (mmu_enabled) { - clear_fixmap(FIX_PTE); - return (pte_t *)set_fixmap_offset(FIX_PTE, pa); - } else { - return (pte_t *)((uintptr_t)pa); - } + return (pte_t *)((uintptr_t)pa); } -static phys_addr_t __init alloc_pte(uintptr_t va) +static inline pte_t *__init get_pte_virt_fixmap(phys_addr_t pa) +{ + clear_fixmap(FIX_PTE); + return (pte_t *)set_fixmap_offset(FIX_PTE, pa); +} + +static inline pte_t *get_pte_virt_late(phys_addr_t pa) +{ + return (pte_t *) __va(pa); +} + +static inline phys_addr_t __init alloc_pte_early(uintptr_t va) { /* * We only create PMD or PGD early mappings so we * should never reach here with MMU disabled. */ - BUG_ON(!mmu_enabled); + BUG(); +} +static inline phys_addr_t __init alloc_pte_fixmap(uintptr_t va) +{ return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); } +static phys_addr_t alloc_pte_late(uintptr_t va) +{ + unsigned long vaddr; + + vaddr = __get_free_page(GFP_KERNEL); + if (!vaddr || !pgtable_pte_page_ctor(virt_to_page(vaddr))) + BUG(); + return __pa(vaddr); +} + static void __init create_pte_mapping(pte_t *ptep, uintptr_t va, phys_addr_t pa, phys_addr_t sz, pgprot_t prot) @@ -279,28 +308,46 @@ pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss; #endif pmd_t early_pmd[PTRS_PER_PMD * NUM_EARLY_PMDS] __initdata __aligned(PAGE_SIZE); -static pmd_t *__init get_pmd_virt(phys_addr_t pa) +static pmd_t *__init get_pmd_virt_early(phys_addr_t pa) { - if (mmu_enabled) { - clear_fixmap(FIX_PMD); - return (pmd_t *)set_fixmap_offset(FIX_PMD, pa); - } else { - return (pmd_t *)((uintptr_t)pa); - } + /* Before MMU is enabled */ + return (pmd_t *)((uintptr_t)pa); } -static phys_addr_t __init alloc_pmd(uintptr_t va) +static pmd_t *__init get_pmd_virt_fixmap(phys_addr_t pa) { - uintptr_t pmd_num; + clear_fixmap(FIX_PMD); + return (pmd_t *)set_fixmap_offset(FIX_PMD, pa); +} + +static pmd_t *get_pmd_virt_late(phys_addr_t pa) +{ + return (pmd_t *) __va(pa); +} - if (mmu_enabled) - return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); +static phys_addr_t __init alloc_pmd_early(uintptr_t va) +{ + uintptr_t pmd_num; pmd_num = (va - PAGE_OFFSET) >> PGDIR_SHIFT; BUG_ON(pmd_num >= NUM_EARLY_PMDS); return (uintptr_t)&early_pmd[pmd_num * PTRS_PER_PMD]; } +static phys_addr_t __init alloc_pmd_fixmap(uintptr_t va) +{ + return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); +} + +static phys_addr_t alloc_pmd_late(uintptr_t va) +{ + unsigned long vaddr; + + vaddr = __get_free_page(GFP_KERNEL); + BUG_ON(!vaddr); + return __pa(vaddr); +} + static void __init create_pmd_mapping(pmd_t *pmdp, uintptr_t va, phys_addr_t pa, phys_addr_t sz, pgprot_t prot) @@ -316,28 +363,28 @@ static void __init create_pmd_mapping(pmd_t *pmdp, } if (pmd_none(pmdp[pmd_idx])) { - pte_phys = alloc_pte(va); + pte_phys = pt_ops.alloc_pte(va); pmdp[pmd_idx] = pfn_pmd(PFN_DOWN(pte_phys), PAGE_TABLE); - ptep = get_pte_virt(pte_phys); + ptep = pt_ops.get_pte_virt(pte_phys); memset(ptep, 0, PAGE_SIZE); } else { pte_phys = PFN_PHYS(_pmd_pfn(pmdp[pmd_idx])); - ptep = get_pte_virt(pte_phys); + ptep = pt_ops.get_pte_virt(pte_phys); } create_pte_mapping(ptep, va, pa, sz, prot); } #define pgd_next_t pmd_t -#define alloc_pgd_next(__va) alloc_pmd(__va) -#define get_pgd_next_virt(__pa) get_pmd_virt(__pa) +#define alloc_pgd_next(__va) pt_ops.alloc_pmd(__va) +#define get_pgd_next_virt(__pa) pt_ops.get_pmd_virt(__pa) #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ create_pmd_mapping(__nextp, __va, __pa, __sz, __prot) #define fixmap_pgd_next fixmap_pmd #else #define pgd_next_t pte_t -#define alloc_pgd_next(__va) alloc_pte(__va) -#define get_pgd_next_virt(__pa) get_pte_virt(__pa) +#define alloc_pgd_next(__va) pt_ops.alloc_pte(__va) +#define get_pgd_next_virt(__pa) pt_ops.get_pte_virt(__pa) #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ create_pte_mapping(__nextp, __va, __pa, __sz, __prot) #define fixmap_pgd_next fixmap_pte @@ -421,6 +468,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) BUG_ON((load_pa % map_size) != 0); BUG_ON(load_sz > MAX_EARLY_MAPPING_SIZE); + pt_ops.alloc_pte = alloc_pte_early; + pt_ops.get_pte_virt = get_pte_virt_early; +#ifndef __PAGETABLE_PMD_FOLDED + pt_ops.alloc_pmd = alloc_pmd_early; + pt_ops.get_pmd_virt = get_pmd_virt_early; +#endif /* Setup early PGD for fixmap */ create_pgd_mapping(early_pg_dir, FIXADDR_START, (uintptr_t)fixmap_pgd_next, PGDIR_SIZE, PAGE_TABLE); @@ -497,9 +550,16 @@ static void __init setup_vm_final(void) phys_addr_t pa, start, end; struct memblock_region *reg; - /* Set mmu_enabled flag */ - mmu_enabled = true; - + /** + * MMU is enabled at this point. But page table setup is not complete yet. + * fixmap page table alloc functions should be used at this point + */ + pt_ops.alloc_pte = alloc_pte_fixmap; + pt_ops.get_pte_virt = get_pte_virt_fixmap; +#ifndef __PAGETABLE_PMD_FOLDED + pt_ops.alloc_pmd = alloc_pmd_fixmap; + pt_ops.get_pmd_virt = get_pmd_virt_fixmap; +#endif /* Setup swapper PGD for fixmap */ create_pgd_mapping(swapper_pg_dir, FIXADDR_START, __pa_symbol(fixmap_pgd_next), @@ -533,6 +593,14 @@ static void __init setup_vm_final(void) /* Move to swapper page table */ csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE); local_flush_tlb_all(); + + /* generic page allocation functions must be used to setup page table */ + pt_ops.alloc_pte = alloc_pte_late; + pt_ops.get_pte_virt = get_pte_virt_late; +#ifndef __PAGETABLE_PMD_FOLDED + pt_ops.alloc_pmd = alloc_pmd_late; + pt_ops.get_pmd_virt = get_pmd_virt_late; +#endif } #else asmlinkage void __init setup_vm(uintptr_t dtb_pa) From patchwork Fri Aug 28 17:20:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254247 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.6 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 2445FC433E7 for ; Fri, 28 Aug 2020 17:22:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ED0EE207DF for ; Fri, 28 Aug 2020 17:22:22 +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="JDeXq/E/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727000AbgH1RWW (ORCPT ); Fri, 28 Aug 2020 13:22:22 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:11691 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726995AbgH1RUy (ORCPT ); Fri, 28 Aug 2020 13:20:54 -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=1598635254; x=1630171254; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZnGsRE3TMUiNQaxzR8fyngrL1GYNN0dMjoCwa6f4AaU=; b=JDeXq/E/RxCY6iwLwZOPSVeT3Tq/v+n7OtvTGTjfmy7biTAXacZmRYUy qdXVxyaKLc3fwVvCvFBYdnte/kQ5ONOA0ywNjt7uDnGiSdozDxmVdlfZd 7sFGKwjGIg5DYPSQDt8RC9x4KLEc6/vh5Mc3OyoitFwQUrtrifDuzjD02 TC4RnP7TZDy/b2gkvy6tUBEkCu9yamiSTLyjzHkRqrQg7tNrkOlIV0xM4 8CTsnWCILywmR+vwshOq7GBWCg4zSegMMqJdklprI6Ok5nMSKt6NVMpnx DLHZabyIqeGnGgC5RsFtbuaIecdmog5FCL4a/aoQ9ct7cpOaiIxn+l5OZ w==; IronPort-SDR: N5OckQJ1u1OdUtVAMIdYHmatJqy09puvnssAmIMCo12MFe1F9tUFbDQQbUoGwF27KGBzXRK13m RNDXIEdG02E56TpBH1tB7qYd66GGRdfFi90ZCJvnScDG8kQVvxlV/CqvYPnsCK8lIDB3NE+2eK +REnsjCWsOIdCyjSEXUJM9ftO2osYc6wdclaChtYsElyqPmWIceQ/6kSRku28RT2LPhcw6/nCm WZaGzC6+2LqTMGHa1jTMidVxv7ypb66GWXEAEteRh9QHwP3Z3wJhz9HwJETZr/IaFIQ1xau6YP G+w= X-IronPort-AV: E=Sophos;i="5.76,364,1592841600"; d="scan'208";a="146018518" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Aug 2020 01:20:45 +0800 IronPort-SDR: 5vlzmrE51F/Y27I0yzadWvh5zSGd8e/uarIgsM6pAihfwqFrSwf5ryrCWqf9YoxUxRdcCL+/0E vTNWviHXMJJQ== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Aug 2020 10:08:17 -0700 IronPort-SDR: 89L9wqPl3Nmj/NexeWaD+R4zvJ981nik/4d3VZU92n/3pz+AElin2t0CV1RPy0yef5/nqqhFoT kKK+zPXqAS6g== WDCIronportException: Internal Received: from 6hj08h2.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.137]) by uls-op-cesaip01.wdc.com with ESMTP; 28 Aug 2020 10:20:45 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Ard Biesheuvel , Anup Patel , Alistair Francis , Anup Patel , Arvind Sankar , Greentime Hu , Ingo Molnar , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, Masahiro Yamada , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley Subject: [PATCH v7 5/9] RISC-V: Add PE/COFF header for EFI stub Date: Fri, 28 Aug 2020 10:20:32 -0700 Message-Id: <20200828172036.8056-6-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200828172036.8056-1-atish.patra@wdc.com> References: <20200828172036.8056-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 Linux kernel Image can appear as an EFI application With appropriate PE/COFF header fields in the beginning of the Image header. An EFI application loader can directly load a Linux kernel Image and an EFI stub residing in kernel can boot Linux kernel directly. Add the necessary PE/COFF header. Signed-off-by: Atish Patra Link: https://lore.kernel.org/r/20200421033336.9663-3-atish.patra@wdc.com [ardb: - use C prefix for c.li to ensure the expected opcode is emitted - align all image sections according to PE/COFF section alignment ] Signed-off-by: Ard Biesheuvel Reviewed-by: Anup Patel --- arch/riscv/include/asm/sections.h | 13 ++++ arch/riscv/kernel/Makefile | 4 ++ arch/riscv/kernel/efi-header.S | 104 ++++++++++++++++++++++++++++++ arch/riscv/kernel/head.S | 16 +++++ arch/riscv/kernel/image-vars.h | 51 +++++++++++++++ arch/riscv/kernel/vmlinux.lds.S | 22 ++++++- 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 arch/riscv/include/asm/sections.h create mode 100644 arch/riscv/kernel/efi-header.S create mode 100644 arch/riscv/kernel/image-vars.h diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h new file mode 100644 index 000000000000..3a9971b1210f --- /dev/null +++ b/arch/riscv/include/asm/sections.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + */ +#ifndef __ASM_SECTIONS_H +#define __ASM_SECTIONS_H + +#include + +extern char _start[]; +extern char _start_kernel[]; + +#endif /* __ASM_SECTIONS_H */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index dc93710f0b2f..41e3895a3192 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -31,6 +31,10 @@ obj-y += cacheinfo.o obj-y += patch.o obj-$(CONFIG_MMU) += vdso.o vdso/ +OBJCOPYFLAGS := --prefix-symbols=__efistub_ +$(obj)/%.stub.o: $(obj)/%.o FORCE + $(call if_changed,objcopy) + obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o obj-$(CONFIG_FPU) += fpu.o obj-$(CONFIG_SMP) += smpboot.o diff --git a/arch/riscv/kernel/efi-header.S b/arch/riscv/kernel/efi-header.S new file mode 100644 index 000000000000..822b4c9ff2bb --- /dev/null +++ b/arch/riscv/kernel/efi-header.S @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + * Adapted from arch/arm64/kernel/efi-header.S + */ + +#include +#include + + .macro __EFI_PE_HEADER + .long PE_MAGIC +coff_header: +#ifdef CONFIG_64BIT + .short IMAGE_FILE_MACHINE_RISCV64 // Machine +#else + .short IMAGE_FILE_MACHINE_RISCV32 // Machine +#endif + .short section_count // NumberOfSections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 0 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short IMAGE_FILE_DEBUG_STRIPPED | \ + IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED // Characteristics + +optional_header: + .short PE_OPT_MAGIC_PE32PLUS // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long __pecoff_text_end - efi_header_end // SizeOfCode + .long __pecoff_data_virt_size // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long __efistub_efi_pe_entry - _start // AddressOfEntryPoint + .long efi_header_end - _start // BaseOfCode + +extra_header_fields: + .quad 0 // ImageBase + .long PECOFF_SECTION_ALIGNMENT // SectionAlignment + .long PECOFF_FILE_ALIGNMENT // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short LINUX_EFISTUB_MAJOR_VERSION // MajorImageVersion + .short LINUX_EFISTUB_MINOR_VERSION // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long _end - _start // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long efi_header_end - _start // SizeOfHeaders + .long 0 // CheckSum + .short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem + .short 0 // DllCharacteristics + .quad 0 // SizeOfStackReserve + .quad 0 // SizeOfStackCommit + .quad 0 // SizeOfHeapReserve + .quad 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long (section_table - .) / 8 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + .ascii ".text\0\0\0" + .long __pecoff_text_end - efi_header_end // VirtualSize + .long efi_header_end - _start // VirtualAddress + .long __pecoff_text_end - efi_header_end // SizeOfRawData + .long efi_header_end - _start // PointerToRawData + + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long IMAGE_SCN_CNT_CODE | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_EXECUTE // Characteristics + + .ascii ".data\0\0\0" + .long __pecoff_data_virt_size // VirtualSize + .long __pecoff_text_end - _start // VirtualAddress + .long __pecoff_data_raw_size // SizeOfRawData + .long __pecoff_text_end - _start // PointerToRawData + + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_WRITE // Characteristics + + .set section_count, (. - section_table) / 40 + + .balign 0x1000 +efi_header_end: + .endm diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index c6a37e8231a8..3631147732ee 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -13,6 +13,7 @@ #include #include #include +#include "efi-header.S" __HEAD ENTRY(_start) @@ -22,10 +23,18 @@ ENTRY(_start) * Do not modify it without modifying the structure and all bootloaders * that expects this header format!! */ +#ifdef CONFIG_EFI + /* + * This instruction decodes to "MZ" ASCII required by UEFI. + */ + c.li s4,-13 + j _start_kernel +#else /* jump to start kernel */ j _start_kernel /* reserved */ .word 0 +#endif .balign 8 #if __riscv_xlen == 64 /* Image load offset(2MB) from start of RAM */ @@ -43,7 +52,14 @@ ENTRY(_start) .ascii RISCV_IMAGE_MAGIC .balign 4 .ascii RISCV_IMAGE_MAGIC2 +#ifdef CONFIG_EFI + .word pe_head_start - _start +pe_head_start: + + __EFI_PE_HEADER +#else .word 0 +#endif .align 2 #ifdef CONFIG_MMU diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h new file mode 100644 index 000000000000..8c212efb37a6 --- /dev/null +++ b/arch/riscv/kernel/image-vars.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + * Linker script variables to be set after section resolution, as + * ld.lld does not like variables assigned before SECTIONS is processed. + * Based on arch/arm64/kerne/image-vars.h + */ +#ifndef __RISCV_KERNEL_IMAGE_VARS_H +#define __RISCV_KERNEL_IMAGE_VARS_H + +#ifndef LINKER_SCRIPT +#error This file should only be included in vmlinux.lds.S +#endif + +#ifdef CONFIG_EFI + +/* + * The EFI stub has its own symbol namespace prefixed by __efistub_, to + * isolate it from the kernel proper. The following symbols are legally + * accessed by the stub, so provide some aliases to make them accessible. + * Only include data symbols here, or text symbols of functions that are + * guaranteed to be safe when executed at another offset than they were + * linked at. The routines below are all implemented in assembler in a + * position independent manner + */ +__efistub_memcmp = memcmp; +__efistub_memchr = memchr; +__efistub_memcpy = memcpy; +__efistub_memmove = memmove; +__efistub_memset = memset; +__efistub_strlen = strlen; +__efistub_strnlen = strnlen; +__efistub_strcmp = strcmp; +__efistub_strncmp = strncmp; +__efistub_strrchr = strrchr; + +#ifdef CONFIG_KASAN +__efistub___memcpy = memcpy; +__efistub___memmove = memmove; +__efistub___memset = memset; +#endif + +__efistub__start = _start; +__efistub__start_kernel = _start_kernel; +__efistub__end = _end; +__efistub__edata = _edata; +__efistub_screen_info = screen_info; + +#endif + +#endif /* __RISCV_KERNEL_IMAGE_VARS_H */ diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S index f3586e31ed1e..6dcf790282dd 100644 --- a/arch/riscv/kernel/vmlinux.lds.S +++ b/arch/riscv/kernel/vmlinux.lds.S @@ -10,6 +10,7 @@ #include #include #include +#include "image-vars.h" #include OUTPUT_ARCH(riscv) @@ -17,6 +18,9 @@ ENTRY(_start) jiffies = jiffies_64; +PECOFF_SECTION_ALIGNMENT = 0x1000; +PECOFF_FILE_ALIGNMENT = 0x200; + SECTIONS { /* Beginning of code and text segment */ @@ -76,6 +80,10 @@ SECTIONS EXCEPTION_TABLE(0x10) +#ifdef CONFIG_EFI + . = ALIGN(PECOFF_SECTION_ALIGNMENT); + __pecoff_text_end = .; +#endif . = ALIGN(SECTION_ALIGN); _data = .; @@ -83,16 +91,26 @@ SECTIONS .sdata : { __global_pointer$ = . + 0x800; *(.sdata*) - /* End of data section */ - _edata = .; } +#ifdef CONFIG_EFI + .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); } + __pecoff_data_raw_size = ABSOLUTE(. - __pecoff_text_end); +#endif + + /* End of data section */ + _edata = .; + BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) .rel.dyn : { *(.rel.dyn*) } +#ifdef CONFIG_EFI + . = ALIGN(PECOFF_SECTION_ALIGNMENT); + __pecoff_data_virt_size = ABSOLUTE(. - __pecoff_text_end); +#endif _end = .; STABS_DEBUG From patchwork Fri Aug 28 17:20:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254249 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.6 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 09804C433E6 for ; Fri, 28 Aug 2020 17:21:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D7864207DF for ; Fri, 28 Aug 2020 17:21:35 +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="lt5t85F9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727781AbgH1RV1 (ORCPT ); Fri, 28 Aug 2020 13:21:27 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:11689 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727056AbgH1RVE (ORCPT ); Fri, 28 Aug 2020 13:21:04 -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=1598635263; x=1630171263; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Bk2Gh/XGM+blmye1lG7fqQWiRAnoRdaJAzm3HH3f+As=; b=lt5t85F9tqOlOR7zTKJ/sAlynrbTABWRAuVK6F4W4UPjqiwcMcJTpFtV KYFKp6+YbLzSHoGJCI7L1mafP7dfmjdgjH9oaiZHXEDb/yNJnsnVjyme+ 6SsIDf24YSTEVHZh/f2rsABelFOoNu+4BKRWx3TXKS3XVhcGUV4fqsSmq OCLI/HQvaxB/9EmUJUYKGMwXexsZCzs173RFazaWu/sqs6ebTCp4Hz8Wd Cb0F1xwrLu7Gs1N5KTR2uLctjRtRPJfMSTNNNHlt8QIIN/nqTfIaEC9Dt wWfFYySg67vTaXD2UmYViXddIfui46IXsbZKlsdJrTjlBTf+1H2SyjE7E w==; IronPort-SDR: LwfLW3dnXZrFX2+PnVyqaXQfLLySwxcCf7soLzI51S0JOVqXkPlaDfh0n3HdLTUHV7oUcKYoDY dK9Kzk7FROROlW5NUPLSeOu9u+0GHfSbYCDNIQidA9EaaH2fxHYrgk66uBI9HEKaY3z6yd+Bvo R6uHHYpLbyce3my2dLbqjgUXJfY6j6R0j5B7cVzGMMrWUfK5qwbU1S8X9JpYBQ/O+37Q3W8fRv M9OGDgDV+BW8aWpjmq/2FD+AXtNBFtg/Gc9J/BZjrgHCTh8p5LAZZ4XYKLBvqGXXWfoL1ydM07 VtQ= X-IronPort-AV: E=Sophos;i="5.76,364,1592841600"; d="scan'208";a="146018522" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Aug 2020 01:20:46 +0800 IronPort-SDR: 1fDyAO/mpt3ET0pOP0ypNlI7opAnl8mXkYl1VIftVzMhTmcM9IHjSla+pNf6o3tbEj9+WSQNzk 4xHZpL7/YIVg== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Aug 2020 10:08:19 -0700 IronPort-SDR: DMKenj1WplxHGuwNbsjHFV9MHODA2RxucJWJVYnstOrk1zE0LPtdWpDesbHuzbEc3OTdIuabKx 2Du80PCFXn3g== WDCIronportException: Internal Received: from 6hj08h2.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.137]) by uls-op-cesaip01.wdc.com with ESMTP; 28 Aug 2020 10:20:46 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Ard Biesheuvel , Alistair Francis , Anup Patel , Arvind Sankar , Greentime Hu , Ingo Molnar , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, Masahiro Yamada , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley Subject: [PATCH v7 7/9] efi: Rename arm-init to efi-init common for all arch Date: Fri, 28 Aug 2020 10:20:34 -0700 Message-Id: <20200828172036.8056-8-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200828172036.8056-1-atish.patra@wdc.com> References: <20200828172036.8056-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 arm-init is responsible for setting up efi runtime and doesn't actually do any ARM specific stuff. RISC-V can use the same source code as it is. Rename it to efi-init so that RISC-V can use it. Signed-off-by: Atish Patra Acked-by: Ard Biesheuvel --- drivers/firmware/efi/Makefile | 2 +- drivers/firmware/efi/{arm-init.c => efi-init.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/firmware/efi/{arm-init.c => efi-init.c} (100%) diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 7a216984552b..61fd1e8b26fb 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o fake_map-y += fake_mem.o fake_map-$(CONFIG_X86) += x86_fake_mem.o -arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o +arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/efi-init.c similarity index 100% rename from drivers/firmware/efi/arm-init.c rename to drivers/firmware/efi/efi-init.c From patchwork Fri Aug 28 17:20:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 254248 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.6 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 E77C1C433E6 for ; Fri, 28 Aug 2020 17:21:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A56E120848 for ; Fri, 28 Aug 2020 17:21:44 +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="R79LuVZh" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727793AbgH1RVl (ORCPT ); Fri, 28 Aug 2020 13:21:41 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:11691 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727066AbgH1RVQ (ORCPT ); Fri, 28 Aug 2020 13:21:16 -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=1598635275; x=1630171275; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DZn1zX5v4AKwiAK5OKt0fHKD9YO5xGV8inFUgUfZc6I=; b=R79LuVZhInB/sEdZJzDWeqNvrJC1Nmho3PBVmT2cWVpX2QvekLBZ5KdA da141w8FmltqSYpqZ7hHV9dvfRRdKHppIelNHPePUugVFk4zHvGV6uNAu 8pxtSC1OmoSTXHWlSSsdYgxo+Q59chZE5M7BAP/Ui5S5+lBmAx0ZKWzDw bxfG0a1zq9V4wTgK0IdV6zexUAo6O7achH1MgdpTamMq/kjmon1BunpUo Rf/eNO/YdKoEBsIVb6GYvhvjuyZCL0KWZJwmhXZwKbO0YJtV8FZUH2Df8 dvxufvWzpx0dnUdZqCISzbViS7wQlDSKn1xL50shdqGCQRJI4ibMTeSqK Q==; IronPort-SDR: gMe8JV3pxIzKbry1mGLkT+L2CG4QgJ5c8M+9U85UPiaiPtLguLignchpwPAS+F9ZNGty8Gx5O3 RA0NnTnc1KpwR8nva9cdoVY+bDiilRiMF7If5kW99trpSUHna8Y+Fn+dvclmkMMV2wgrNGMOCw F8PZypYq1UqKXyKDiYUNkPjY2p6fXsXnBwbKnvJRNdhe2DPvEjczyOlUXVj3F/0wxrLsE4NXNI ZColEypgJ7lCAqzHr0FBGrxp25xK95EMCiEBfZ7CKTRYIfjGAU1WQ1uZzMv4tQW8jJd+GvgdP1 nfU= X-IronPort-AV: E=Sophos;i="5.76,364,1592841600"; d="scan'208";a="146018526" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Aug 2020 01:20:47 +0800 IronPort-SDR: w3331GW3kr9IRFB6jqGUG/TtijeRtrJEQ5LRUeJWpcwG2uG5SnjvnHJwXNBmB0eaEVCSkJ3lQ5 eGfcJB3Agrdw== Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Aug 2020 10:08:19 -0700 IronPort-SDR: 3Gcp4bXh/V3FkFUCmqd3iPOoTBHFAPbk/T9yPoEZ1UyYOPYvKmkzdPkCVzA96v/Ym7Fr9iGW3w Ry6Dm5m9FNrg== WDCIronportException: Internal Received: from 6hj08h2.ad.shared (HELO jedi-01.hgst.com) ([10.86.59.137]) by uls-op-cesaip01.wdc.com with ESMTP; 28 Aug 2020 10:20:46 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Ard Biesheuvel , Alistair Francis , Anup Patel , Arvind Sankar , Greentime Hu , Ingo Molnar , linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, Masahiro Yamada , Mike Rapoport , Nick Desaulniers , Palmer Dabbelt , Paul Walmsley Subject: [PATCH v7 8/9] RISC-V: Add EFI runtime services Date: Fri, 28 Aug 2020 10:20:35 -0700 Message-Id: <20200828172036.8056-9-atish.patra@wdc.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200828172036.8056-1-atish.patra@wdc.com> References: <20200828172036.8056-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 Acked-by: Ard Biesheuvel --- 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 6ef2394be857..c8e57d77c144 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 41e3895a3192..e922ffe0f39e 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -35,6 +35,7 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_ $(obj)/%.stub.o: $(obj)/%.o FORCE $(call if_changed,objcopy) +obj-$(CONFIG_EFI) += efi.o obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o obj-$(CONFIG_FPU) += fpu.o obj-$(CONFIG_SMP) += smpboot.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 41ef96d0d97a..4c96ac198e14 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 cac2c31f8beb..32e7258da9bb 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(); +}