From patchwork Thu Oct 1 17:04:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 54380 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f199.google.com (mail-lb0-f199.google.com [209.85.217.199]) by patches.linaro.org (Postfix) with ESMTPS id 0DB6A23010 for ; Thu, 1 Oct 2015 17:06:56 +0000 (UTC) Received: by lbcao8 with SMTP id ao8sf8633675lbc.1 for ; Thu, 01 Oct 2015 10:06:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:cc:mime-version :content-type:content-transfer-encoding:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list; bh=nW0s7vRZB47dt6ebAB5CJCwFJjlKtNEDwWjna6rcjgw=; b=Qm6oG/kACDeUgcvokBOLjK6qHAf0pcljnLAY+601N4hu6sYcjaAYSsXk4NJafPzGV2 Ah42FFDXn3Tkx0g6wMW8IlCDiH3OmmDap1WeNCIWRq9zbM6g0dLfqDgg1r+u5rOO0O9B gjVuLB7IjOldIwvUobZyBnTEtebHts2WSOZ/mqfxeEe7TL91eMVm+8QyBvRM5tDaxo9H Qtke6za6zex0BK1ELejVL+uAC8d4dfy8Kva3io8fo9efCHpPUv4yoOSO2xWpR5D1vixR VhzcLodUbDAIHq/hnnbrTJTZbjsSSbgDAmyZ5aB5kVf1tvRr12OJDKt3VeawDQnAGeoE GWRQ== X-Gm-Message-State: ALoCoQnxsmxu4p+t3QG7lTdwB1AtZJ0o8R/jKDuJahjubNt/v9vg7Stc5ewzoTZ5Zk0dExwbv7oM X-Received: by 10.112.190.65 with SMTP id go1mr1664393lbc.9.1443719213387; Thu, 01 Oct 2015 10:06:53 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.25.67 with SMTP id 64ls148660lfz.41.gmail; Thu, 01 Oct 2015 10:06:53 -0700 (PDT) X-Received: by 10.25.145.132 with SMTP id t126mr2184864lfd.88.1443719213073; Thu, 01 Oct 2015 10:06:53 -0700 (PDT) Received: from mail-la0-f49.google.com (mail-la0-f49.google.com. [209.85.215.49]) by mx.google.com with ESMTPS id sm5si3331462lbb.88.2015.10.01.10.06.53 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 01 Oct 2015 10:06:53 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) client-ip=209.85.215.49; Received: by labzv5 with SMTP id zv5so79002532lab.1 for ; Thu, 01 Oct 2015 10:06:52 -0700 (PDT) X-Received: by 10.112.180.230 with SMTP id dr6mr3314404lbc.72.1443719212668; Thu, 01 Oct 2015 10:06:52 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp729616lbq; Thu, 1 Oct 2015 10:06:51 -0700 (PDT) X-Received: by 10.180.74.47 with SMTP id q15mr4721392wiv.73.1443719211818; Thu, 01 Oct 2015 10:06:51 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id k17si8374993wjq.207.2015.10.01.10.06.51 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 01 Oct 2015 10:06:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZhhIF-0003Qq-G6; Thu, 01 Oct 2015 17:05:19 +0000 Received: from mail-wi0-f182.google.com ([209.85.212.182]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZhhHr-0001yE-R9 for linux-arm-kernel@lists.infradead.org; Thu, 01 Oct 2015 17:04:59 +0000 Received: by wicgb1 with SMTP id gb1so39118623wic.1 for ; Thu, 01 Oct 2015 10:04:34 -0700 (PDT) X-Received: by 10.194.118.5 with SMTP id ki5mr11368745wjb.94.1443719073975; Thu, 01 Oct 2015 10:04:33 -0700 (PDT) Received: from localhost.localdomain ([83.225.55.104]) by smtp.gmail.com with ESMTPSA id x9sm7036760wjf.44.2015.10.01.10.04.32 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Oct 2015 10:04:33 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org, matt.fleming@intel.com, linux@arm.linux.org.uk, will.deacon@arm.com, grant.likely@linaro.org, leif.lindholm@linaro.org, roy.franz@linaro.org, mark.rutland@arm.com, catalin.marinas@arm.com Subject: [PATCH 2/9] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM Date: Thu, 1 Oct 2015 19:04:16 +0200 Message-Id: <1443719063-6832-3-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1443719063-6832-1-git-send-email-ard.biesheuvel@linaro.org> References: <1443719063-6832-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151001_100456_352197_8C3501C5 X-CRM114-Status: GOOD ( 24.41 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.182 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [209.85.212.182 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Cc: ryan.harkin@linaro.org, Ard Biesheuvel , msalter@redhat.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ard.biesheuvel@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 This refactors the EFI init and runtime code that will be shared between arm64 and ARM so that it can be built for both archs. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 16 ++++ arch/arm64/kernel/efi.c | 51 ++++++++++ drivers/firmware/efi/arm-init.c | 11 ++- drivers/firmware/efi/arm-runtime.c | 101 ++++++-------------- drivers/firmware/efi/efi.c | 4 +- 5 files changed, 105 insertions(+), 78 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 7cc8df68c638..a16490d6ec1a 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -2,7 +2,9 @@ #define _ASM_EFI_H #include +#include #include +#include #ifdef CONFIG_EFI extern void efi_init(void); @@ -12,6 +14,8 @@ extern void efi_parse_fdt(void *fdt); #define efi_parse_fdt(x) #endif +int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); + #define efi_call_virt(f, ...) \ ({ \ efi_##f##_t *__f; \ @@ -65,6 +69,18 @@ extern void efi_parse_fdt(void *fdt); * Services are enabled and the EFI_RUNTIME_SERVICES bit set. */ +static inline void efi_set_pgd(struct mm_struct *mm) +{ + if (mm == &init_mm) + cpu_set_reserved_ttbr0(); + else + cpu_switch_mm(mm->pgd, mm); + + flush_tlb_all(); + if (icache_is_aivivt()) + __flush_icache_all(); +} + void efi_virtmap_load(void); void efi_virtmap_unload(void); diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index bd3b2f5adf0c..77df172f0e6d 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -17,6 +17,57 @@ #include +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) +{ + u64 paddr, npages, size; + pteval_t prot_val; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + /* + * Order is important here: memory regions may have all of the + * bits below set (and usually do), and any memory that has the + * EFI_MEMORY_WB bit set may be covered by the linear mapping + * and mapped write-back cacheable already. So check the + * EFI_MEMORY_WB bit first. + */ + if (md->attribute & EFI_MEMORY_WB) + prot_val = pgprot_val(PAGE_KERNEL_EXEC); + else if (md->attribute & EFI_MEMORY_WT) + prot_val = PROT_NORMAL_WT; + else if (md->attribute & EFI_MEMORY_WC) + prot_val = PROT_NORMAL_NC; + else if (md->attribute & EFI_MEMORY_UC) + prot_val = PROT_DEVICE_nGnRnE; + else + return -EINVAL; + + /* + * Since the UEFI spec requires only the type attributes to be + * identical within the same 64 KB page frame, we may encounter + * regions that are not 64 KB aligned, but whose attributes only + * differ from adjacent regions in the permission bits. + * This means we can only enforce any permission restrictions if + * the boundaries of this region are aligned to the OS page + * size. + */ + if (PAGE_SIZE == EFI_PAGE_SIZE || + (PAGE_ALIGNED(md->virt_addr) && + PAGE_ALIGNED(md->virt_addr + md->num_pages * EFI_PAGE_SIZE))) { + + if (md->attribute & EFI_MEMORY_RO) + prot_val |= PTE_RDONLY; + if (md->attribute & EFI_MEMORY_XP) + prot_val |= PTE_PXN; + } + + create_pgd_mapping(mm, paddr, md->virt_addr, size, __pgprot(prot_val)); + return 0; +} + static int __init arm64_dmi_init(void) { /* diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 56987a5b9033..235677b86e4e 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -66,7 +66,7 @@ static int __init uefi_init(void) { efi_char16_t *c16; void *config_tables; - u64 table_size; + int table_size; char vendor[100] = "unknown"; int i, retval; @@ -78,7 +78,8 @@ static int __init uefi_init(void) } set_bit(EFI_BOOT, &efi.flags); - set_bit(EFI_64BIT, &efi.flags); + if (IS_ENABLED(CONFIG_64BIT)) + set_bit(EFI_64BIT, &efi.flags); /* * Verify the EFI Table @@ -112,7 +113,7 @@ static int __init uefi_init(void) table_size); retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, - sizeof(efi_config_table_64_t), NULL); + sizeof(efi_config_table_t), NULL); early_memunmap(config_tables, table_size); out: @@ -186,7 +187,7 @@ void __init efi_parse_fdt(void *fdt) efi_system_table = params.system_table; - memmap.phys_map = (void *)params.mmap; + memmap.phys_map = (void *)(unsigned long)params.mmap; memmap.desc_size = params.desc_size; memmap.desc_version = params.desc_ver; memmap.nr_map = params.mmap_size / params.desc_size; @@ -201,7 +202,7 @@ void __init efi_init(void) if (!efi_enabled(EFI_MEMMAP)) return; - memmap.map = early_memremap((u64)memmap.phys_map, mmap_size); + memmap.map = early_memremap((unsigned long)memmap.phys_map, mmap_size); memmap.map_end = memmap.map + mmap_size; if (uefi_init() < 0) diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 5a94ea48670d..7f23f3cffb46 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -23,18 +23,19 @@ #include #include -#include -#include +#include #include +#include #include -static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; +#ifndef INIT_MM_CONTEXT +#define INIT_MM_CONTEXT(name) +#endif extern u64 efi_system_table; static struct mm_struct efi_mm = { .mm_rb = RB_ROOT, - .pgd = efi_pgd, .mm_users = ATOMIC_INIT(2), .mm_count = ATOMIC_INIT(1), .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem), @@ -47,67 +48,34 @@ static bool __init efi_virtmap_init(void) { efi_memory_desc_t *md; + efi_mm.pgd = pgd_alloc(&efi_mm); + for_each_efi_memory_desc(&memmap, md) { - u64 paddr, npages, size; - pteval_t prot_val; + phys_addr_t phys = (phys_addr_t)md->phys_addr; + int ret; if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; if (md->virt_addr == 0) return false; - paddr = md->phys_addr; - npages = md->num_pages; - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - /* - * Order is important here: memory regions may have all of the - * bits below set (and usually do), and any memory that has the - * EFI_MEMORY_WB bit set may be covered by the linear mapping - * and mapped write-back cacheable already. So check the - * EFI_MEMORY_WB bit first. - */ - if (md->attribute & EFI_MEMORY_WB) { - prot_val = pgprot_val(PAGE_KERNEL_EXEC); - } else if (md->attribute & EFI_MEMORY_WT) { - prot_val = PROT_NORMAL_WT; - } else if (md->attribute & EFI_MEMORY_WC) { - prot_val = PROT_NORMAL_NC; - } else if (md->attribute & EFI_MEMORY_UC) { - prot_val = PROT_DEVICE_nGnRnE; - } else { - pr_warn(" EFI remap 0x%012llx: not remapping due to unsupported memory attributes (0x%llx)\n", - md->phys_addr, md->attribute); - continue; - } - - /* - * Since the UEFI spec requires only the type attributes to be - * identical within the same 64 KB page frame, we may encounter - * regions that are not 64 KB aligned, but whose attributes only - * differ from adjacent regions in the permission bits. - * This means we can only enforce any permission restrictions if - * the boundaries of this region are aligned to the OS page - * size. - */ - if (PAGE_SIZE == EFI_PAGE_SIZE || - (PAGE_ALIGNED(md->virt_addr) && - PAGE_ALIGNED(md->virt_addr + md->num_pages * EFI_PAGE_SIZE))) { - - if (md->attribute & EFI_MEMORY_RO) - prot_val |= PTE_RDONLY; - if (md->attribute & EFI_MEMORY_XP) - prot_val |= PTE_PXN; + ret = efi_create_mapping(&efi_mm, md); + switch (ret) { + case 0: + pr_info(" EFI remap %pa => %p (R%c%c)\n", + &phys, (void *)(unsigned long)md->virt_addr, + md->attribute & EFI_MEMORY_RO ? '-' : 'W', + md->attribute & EFI_MEMORY_XP ? '-' : 'X'); + break; + case -EINVAL: + pr_warn(" EFI remap %pa: not remapping due to unsupported memory attributes (0x%llx)\n", + &phys, md->attribute); + return false; + default: + pr_warn(" EFI remap %pa: failed to create mapping (%d)\n", + &phys, ret); + return false; } - - pr_info(" EFI remap 0x%012llx => %p (R%c%c)\n", - md->phys_addr, (void *)md->virt_addr, - prot_val & PTE_RDONLY ? '-' : 'W', - prot_val & PTE_PXN ? '-' : 'X'); - - create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, - __pgprot(prot_val)); } return true; } @@ -117,7 +85,7 @@ static bool __init efi_virtmap_init(void) * non-early mapping of the UEFI system table and virtual mappings for all * EFI_MEMORY_RUNTIME regions. */ -static int __init arm64_enable_runtime_services(void) +static int __init arm_enable_runtime_services(void) { u64 mapsize; @@ -134,7 +102,7 @@ static int __init arm64_enable_runtime_services(void) pr_info("Remapping and enabling EFI services.\n"); mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, + memmap.map = (__force void *)ioremap_cache((unsigned long)memmap.phys_map, mapsize); if (!memmap.map) { pr_err("Failed to remap EFI memory map\n"); @@ -155,6 +123,7 @@ static int __init arm64_enable_runtime_services(void) pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); return -1; } + iounmap(memmap.map); /* Set up runtime services function pointers */ efi_native_runtime_setup(); @@ -164,19 +133,7 @@ static int __init arm64_enable_runtime_services(void) return 0; } -early_initcall(arm64_enable_runtime_services); - -static void efi_set_pgd(struct mm_struct *mm) -{ - if (mm == &init_mm) - cpu_set_reserved_ttbr0(); - else - cpu_switch_mm(mm->pgd, mm); - - flush_tlb_all(); - if (icache_is_aivivt()) - __flush_icache_all(); -} +early_initcall(arm_enable_runtime_services); void efi_virtmap_load(void) { diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index f5e586bd3b24..2eb31e28a35c 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -23,6 +23,8 @@ #include #include +#include + struct efi __read_mostly efi = { .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, @@ -286,7 +288,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) * So just always get our own virtual map on the CPU. * */ - md = early_memremap((phys_addr_t)p, sizeof (*md)); + md = early_memremap((unsigned long)p, sizeof (*md)); if (!md) { pr_err_once("early_memremap(%p, %zu) failed.\n", p, sizeof (*md));