From patchwork Tue Nov 18 12:57:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 41019 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 ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 29364241C9 for ; Tue, 18 Nov 2014 13:00:45 +0000 (UTC) Received: by mail-lb0-f199.google.com with SMTP id n15sf12675693lbi.2 for ; Tue, 18 Nov 2014 05:00:44 -0800 (PST) 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:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=vO68GFcPuIZMiG+AkjbEV9kMYx6Vhvgnv291G51PR9M=; b=NvfZzH0E6ZZFauyiGbeqTdzI1bu7LOL2gGUkJdCT2BNVqC9Vb4SPZT9EYloPl0+KsK 8YbEUjtfG+sQattdz5kebomnSogn11MVKUDk+Y1Eizqg4FaazKBfv0d7lYwvqNr3wu7q 1Q8YAyJQ3xuQE17FRojMGLIJNeAnY/+tFwa34JJwvf02vkYV2if3rxzF/GS5YJsX9mUq kdn8PukZv2yqwWQAjOjNo2iNFgdxkgHUhBuq1cLkOZgX2oK8KW+By92RjN9mIsoIp67Q JrQyJoAuqQjzffcNXRoMWG30CNp0QzRwhzA8w9x1Pxn0LQh9l0JVsb1eG0JKbZURl1hb xwVA== X-Gm-Message-State: ALoCoQmex/nVeNJopc0+wN31NfIv85riesgcyfImpW47uLAFEzBfEcUGE1JqcEUurBPhkzneTlz3 X-Received: by 10.180.182.164 with SMTP id ef4mr5672245wic.0.1416315644105; Tue, 18 Nov 2014 05:00:44 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.21.135 with SMTP id v7ls1351533lae.40.gmail; Tue, 18 Nov 2014 05:00:43 -0800 (PST) X-Received: by 10.112.133.138 with SMTP id pc10mr36250912lbb.48.1416315643679; Tue, 18 Nov 2014 05:00:43 -0800 (PST) Received: from mail-la0-f51.google.com (mail-la0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id 9si55698592lai.28.2014.11.18.05.00.43 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Nov 2014 05:00:43 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by mail-la0-f51.google.com with SMTP id mc6so2836031lab.38 for ; Tue, 18 Nov 2014 05:00:43 -0800 (PST) X-Received: by 10.152.42.226 with SMTP id r2mr35937346lal.29.1416315643576; Tue, 18 Nov 2014 05:00:43 -0800 (PST) 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.184.201 with SMTP id ew9csp1323009lbc; Tue, 18 Nov 2014 05:00:42 -0800 (PST) X-Received: by 10.70.43.8 with SMTP id s8mr37192627pdl.64.1416315641597; Tue, 18 Nov 2014 05:00:41 -0800 (PST) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id nj14si2457608pdb.184.2014.11.18.05.00.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 18 Nov 2014 05:00:41 -0800 (PST) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) 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 1XqiN7-0003G5-Ap; Tue, 18 Nov 2014 12:59:05 +0000 Received: from mail-wg0-f48.google.com ([74.125.82.48]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XqiLp-0002RM-1B for linux-arm-kernel@lists.infradead.org; Tue, 18 Nov 2014 12:57:46 +0000 Received: by mail-wg0-f48.google.com with SMTP id y19so5404955wgg.7 for ; Tue, 18 Nov 2014 04:57:22 -0800 (PST) X-Received: by 10.180.86.194 with SMTP id r2mr3632482wiz.43.1416315442574; Tue, 18 Nov 2014 04:57:22 -0800 (PST) Received: from ards-macbook-pro.local (cag06-7-83-153-85-71.fbx.proxad.net. [83.153.85.71]) by mx.google.com with ESMTPSA id cz3sm55726799wjb.23.2014.11.18.04.57.20 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Nov 2014 04:57:21 -0800 (PST) From: Ard Biesheuvel To: leif.lindholm@linaro.org, roy.franz@linaro.org, linux-arm-kernel@lists.infradead.org, mark.rutland@arm.com, msalter@redhat.com, dyoung@redhat.com, linux-efi@vger.kernel.org, matt.fleming@intel.com, will.deacon@arm.com, catalin.marinas@arm.com, grant.likely@linaro.org, geoff.levand@linaro.org Subject: [PATCH v3 05/13] efi: add common infrastructure for stub-installed virtual mapping Date: Tue, 18 Nov 2014 13:57:04 +0100 Message-Id: <1416315432-8534-6-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1416315432-8534-1-git-send-email-ard.biesheuvel@linaro.org> References: <1416315432-8534-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141118_045745_258794_19F1A18E X-CRM114-Status: GOOD ( 20.72 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.82.48 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [74.125.82.48 listed in wl.mailspike.net] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: Ard Biesheuvel X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , 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.51 as permitted sender) smtp.mail=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 introduces the common infrastructure to be shared between arm64 and ARM that wires up the UEFI memory map into system RAM discovery, virtual mappings for Runtime Services and aligning cache attributes between kernel and userland (/dev/mem) mappings for regions owned by UEFI. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/Kconfig | 3 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/virtmap.c | 134 +++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 12 +++- 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/virtmap.c diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index f712d47f30d8..c71498180e67 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -60,6 +60,9 @@ config EFI_RUNTIME_WRAPPERS config EFI_ARMSTUB bool +config EFI_VIRTMAP + bool + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index aef6a95adef5..3fd26c0ad40b 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_ARM_STUB) += libstub/ +obj-$(CONFIG_EFI_VIRTMAP) += virtmap.o diff --git a/drivers/firmware/efi/virtmap.c b/drivers/firmware/efi/virtmap.c new file mode 100644 index 000000000000..d1f1d416944f --- /dev/null +++ b/drivers/firmware/efi/virtmap.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; + +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), + .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock), + .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), + INIT_MM_CONTEXT(efi_mm) +}; + +void efi_virtmap_load(void) +{ + WARN_ON(preemptible()); + efi_set_pgd(&efi_mm); +} + +void efi_virtmap_unload(void) +{ + efi_set_pgd(current->active_mm); +} + +static pgprot_t efi_md_access_prot(efi_memory_desc_t *md, pgprot_t prot) +{ + if (md->attribute & EFI_MEMORY_WB) + return prot; + if (md->attribute & (EFI_MEMORY_WT|EFI_MEMORY_WC)) + return pgprot_writecombine(prot); + return pgprot_device(prot); +} + +void __init efi_virtmap_init(void) +{ + efi_memory_desc_t *md; + + if (!efi_enabled(EFI_BOOT)) + return; + + for_each_efi_memory_desc(&memmap, md) { + u64 paddr, npages, size; + pgprot_t prot; + + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (WARN(md->virt_addr == 0, + "UEFI virtual mapping incomplete or missing -- no entry found for 0x%llx\n", + md->phys_addr)) + return; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + pr_info(" EFI remap 0x%012llx => %p\n", + md->phys_addr, (void *)md->virt_addr); + + /* + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be + * executable, everything else can be mapped with the XN bits + * set. + */ + if (md->type == EFI_RUNTIME_SERVICES_CODE) + prot = efi_md_access_prot(md, PAGE_KERNEL_EXEC); + else + prot = efi_md_access_prot(md, PAGE_KERNEL); + + create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); + } + set_bit(EFI_VIRTMAP, &efi.flags); +} + +/* + * Return true for RAM regions that are available for general use. + */ +bool efi_mem_is_usable_region(efi_memory_desc_t *md) +{ + switch (md->type) { + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + return md->attribute & EFI_MEMORY_WB; + default: + break; + } + return false; +} + +/* + * Translate a EFI virtual address into a physical address: this is necessary, + * as some data members of the EFI system table are virtually remapped after + * SetVirtualAddressMap() has been called. + */ +phys_addr_t efi_to_phys(unsigned long addr) +{ + efi_memory_desc_t *md; + + for_each_efi_memory_desc(&memmap, md) { + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) + /* no virtual mapping has been installed by the stub */ + break; + if (md->virt_addr <= addr && + (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT)) + return md->phys_addr + addr - md->virt_addr; + } + return addr; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 2dc8577032b3..2adef3e9bf35 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -941,7 +941,8 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ #define EFI_64BIT 5 /* Is the firmware 64-bit? */ #define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ -#define EFI_ARCH_1 7 /* First arch-specific bit */ +#define EFI_VIRTMAP 7 /* Use virtmap installed by the stub */ +#define EFI_ARCH_1 8 /* First arch-specific bit */ #ifdef CONFIG_EFI /* @@ -952,6 +953,7 @@ static inline bool efi_enabled(int feature) return test_bit(feature, &efi.flags) != 0; } extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); +extern void efi_virtmap_init(void); #else static inline bool efi_enabled(int feature) { @@ -959,6 +961,7 @@ static inline bool efi_enabled(int feature) } static inline void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {} +static inline void efi_virtmap_init(void) {} #endif /* @@ -1250,4 +1253,11 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, efi_status_t efi_parse_options(char *cmdline); bool efi_runtime_disabled(void); + +phys_addr_t efi_to_phys(unsigned long addr); +bool efi_mem_is_usable_region(efi_memory_desc_t *md); + +void efi_virtmap_load(void); +void efi_virtmap_unload(void); + #endif /* _LINUX_EFI_H */