From patchwork Mon Jul 21 15:16:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 33983 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f199.google.com (mail-pd0-f199.google.com [209.85.192.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D33C120672 for ; Mon, 21 Jul 2014 15:19:54 +0000 (UTC) Received: by mail-pd0-f199.google.com with SMTP id ft15sf51051951pdb.10 for ; Mon, 21 Jul 2014 08:19:54 -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: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=BaGi36xcZNbb6tFl3vjU/KEiO3gXW785XLu+iY9r/Fg=; b=l8sGN2xKIi/cdiu34nxRhYfmjAMk8r9kqs6tS6HKRxhNzxVulaRf4lO6J99nQ1yycJ FwHw/iouzMc6++l4Czs1Jvc7GmMS7bD8y5/PjUk7jGe2rAiDyFAn+0TK2Iz+2C2jXgy8 +9mqd8str4wqB6k5AKHhZ1GGpO/hplWvW0I2/A47gOqzhn1cRIlSypYUnYoSOX3IwWSW JMV5xSzxG06j5RhHpwafPQuOHjaI0HmZnWgvhdL3HBfBA5SpcQ1IQOCUMyzbc76wusCn 0q/2fmfk3TDyEFeedT0Be+5qShUVi7TKpT4iahXBh5BK8M0t0mp0vONXJzqC+KHi8YZh HdAA== X-Gm-Message-State: ALoCoQkXnyogMMwxlXkbzlA6BSFDsx5wISEhj/hxmGe/gRMQ5p8FubFMkoVA8kHWuK0mnzdz4P6/ X-Received: by 10.66.121.163 with SMTP id ll3mr13214679pab.26.1405955994105; Mon, 21 Jul 2014 08:19:54 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.31.139 with SMTP id f11ls1967044qgf.87.gmail; Mon, 21 Jul 2014 08:19:53 -0700 (PDT) X-Received: by 10.221.9.72 with SMTP id ov8mr30179789vcb.27.1405955993649; Mon, 21 Jul 2014 08:19:53 -0700 (PDT) Received: from mail-vc0-f176.google.com (mail-vc0-f176.google.com [209.85.220.176]) by mx.google.com with ESMTPS id k8si11544526vdv.58.2014.07.21.08.19.50 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 08:19:50 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.176 as permitted sender) client-ip=209.85.220.176; Received: by mail-vc0-f176.google.com with SMTP id id10so7673814vcb.7 for ; Mon, 21 Jul 2014 08:19:50 -0700 (PDT) X-Received: by 10.220.118.136 with SMTP id v8mr12523744vcq.50.1405955990539; Mon, 21 Jul 2014 08:19:50 -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.221.37.5 with SMTP id tc5csp121029vcb; Mon, 21 Jul 2014 08:19:50 -0700 (PDT) X-Received: by 10.68.232.2 with SMTP id tk2mr15192167pbc.65.1405955989639; Mon, 21 Jul 2014 08:19:49 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id gj8si14568008pac.127.2014.07.21.08.19.49 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Jul 2014 08:19:49 -0700 (PDT) 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 1X9FMM-0008M6-6p; Mon, 21 Jul 2014 15:18:38 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X9FLf-0007g1-DV for linux-arm-kernel@bombadil.infradead.org; Mon, 21 Jul 2014 15:17:55 +0000 Received: from mail-we0-f179.google.com ([74.125.82.179]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X9FLb-0002I0-LU for linux-arm-kernel@lists.infradead.org; Mon, 21 Jul 2014 15:17:54 +0000 Received: by mail-we0-f179.google.com with SMTP id u57so7610125wes.38 for ; Mon, 21 Jul 2014 08:17:24 -0700 (PDT) X-Received: by 10.180.80.70 with SMTP id p6mr5512513wix.22.1405955843616; Mon, 21 Jul 2014 08:17:23 -0700 (PDT) Received: from ards-macbook-pro.local ([212.91.105.246]) by mx.google.com with ESMTPSA id ft17sm38327602wjc.14.2014.07.21.08.17.20 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 08:17:22 -0700 (PDT) From: Ard Biesheuvel To: matt.fleming@intel.com, linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, leif.lindholm@linaro.org Subject: [RFC PATCH 09/10] arm64/efi: enable minimal UEFI Runtime Services for big endian Date: Mon, 21 Jul 2014 17:16:24 +0200 Message-Id: <1405955785-13477-10-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1405955785-13477-1-git-send-email-ard.biesheuvel@linaro.org> References: <1405955785-13477-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140721_111751_842181_593FCB7B X-CRM114-Status: GOOD ( 17.04 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.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.179 listed in list.dnswl.org] Cc: roy.franz@linaro.org, victor.kamensky@linaro.org, steve.capper@linaro.org, Ard Biesheuvel , msalter@redhat.com 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.220.176 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 enables the UEFI Runtime Services needed to manipulate the non-volatile variable store when running under a BE kernel. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 2 + arch/arm64/kernel/efi-be-call.S | 55 ++++++++++++++++++++ arch/arm64/kernel/efi-be-runtime.c | 104 +++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/efi.c | 15 ++++++ 4 files changed, 176 insertions(+) create mode 100644 arch/arm64/kernel/efi-be-call.S create mode 100644 arch/arm64/kernel/efi-be-runtime.c diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a34fd3b12e2b..44e642b6ab61 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -44,4 +44,6 @@ extern void efi_idmap_init(void); #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +extern void efi_be_runtime_setup(void); + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/efi-be-call.S b/arch/arm64/kernel/efi-be-call.S new file mode 100644 index 000000000000..24c92a4c352b --- /dev/null +++ b/arch/arm64/kernel/efi-be-call.S @@ -0,0 +1,55 @@ + +#include + + .text + .align 3 +ENTRY(efi_be_phys_call) + /* + * Entered at physical address with 1:1 mapping enabled. + */ + stp x29, x30, [sp, #-96]! + mov x29, sp + str x27, [sp, #16] + + ldr x8, =efi_be_phys_call // virt address of this function + adr x9, efi_be_phys_call // phys address of this function + sub x9, x8, x9 // calculate virt to phys offset in x9 + + /* preserve all inputs */ + stp x0, x1, [sp, #32] + stp x2, x3, [sp, #48] + stp x4, x5, [sp, #64] + stp x6, x7, [sp, #80] + + /* get phys address of stack */ + sub sp, sp, x9 + + /* switch to LE, disable MMU and D-cache but leave I-cache enabled */ + mrs x27, sctlr_el1 + bic x8, x27, #1 << 2 // clear SCTLR.C + msr sctlr_el1, x8 + + bl flush_cache_all + + /* restore inputs but rotated by 1 register */ + ldp x7, x0, [sp, #32] + ldp x1, x2, [sp, #48] + ldp x3, x4, [sp, #64] + ldp x5, x6, [sp, #80] + + bic x8, x27, #1 << 2 // clear SCTLR.C + bic x8, x8, #1 << 0 // clear SCTLR.M + bic x8, x8, #1 << 25 // clear SCTLR.EE + msr sctlr_el1, x8 + isb + + blr x7 + + /* switch back to BE and reenable MMU and D-cache */ + msr sctlr_el1, x27 + + mov sp, x29 + ldr x27, [sp, #16] + ldp x29, x30, [sp], #96 + ret +ENDPROC(efi_be_phys_call) diff --git a/arch/arm64/kernel/efi-be-runtime.c b/arch/arm64/kernel/efi-be-runtime.c new file mode 100644 index 000000000000..62e6c441b77b --- /dev/null +++ b/arch/arm64/kernel/efi-be-runtime.c @@ -0,0 +1,104 @@ + +#include +#include +#include +#include +#include + +static efi_runtime_services_t *runtime; +static efi_status_t (*efi_be_call)(phys_addr_t func, ...); + +static DEFINE_SPINLOCK(efi_be_rt_lock); + +static unsigned long efi_be_call_pre(void) +{ + unsigned long flags; + + kernel_neon_begin(); + spin_lock_irqsave(&efi_be_rt_lock, flags); + cpu_switch_mm(idmap_pg_dir, &init_mm); + flush_tlb_all(); + return flags; +} + +static void efi_be_call_post(unsigned long flags) +{ + cpu_switch_mm(current, current->active_mm); + flush_tlb_all(); + spin_unlock_irqrestore(&efi_be_rt_lock, flags); + kernel_neon_end(); +} + +static efi_status_t efi_be_get_variable(efi_char16_t *name, + efi_guid_t *vendor, + u32 *attr, + unsigned long *data_size, + void *data) +{ + unsigned long flags; + efi_status_t status; + + *data_size = cpu_to_le64(*data_size); + flags = efi_be_call_pre(); + status = efi_be_call(le64_to_cpu(runtime->get_variable), + virt_to_phys(name), virt_to_phys(vendor), + virt_to_phys(attr), virt_to_phys(data_size), + virt_to_phys(data)); + efi_be_call_post(flags); + *attr = le32_to_cpu(*attr); + *data_size = le64_to_cpu(*data_size); + return status; +} + +static efi_status_t efi_be_get_next_variable(unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *vendor) +{ + unsigned long flags; + efi_status_t status; + + *name_size = cpu_to_le64(*name_size); + flags = efi_be_call_pre(); + status = efi_be_call(le64_to_cpu(runtime->get_next_variable), + virt_to_phys(name_size), virt_to_phys(name), + virt_to_phys(vendor)); + efi_be_call_post(flags); + *name_size = le64_to_cpu(*name_size); + return status; +} + +static efi_status_t efi_be_set_variable(efi_char16_t *name, + efi_guid_t *vendor, + u32 attr, + unsigned long data_size, + void *data) +{ + unsigned long flags; + efi_status_t status; + + flags = efi_be_call_pre(); + status = efi_be_call(le64_to_cpu(runtime->set_variable), + virt_to_phys(name), virt_to_phys(vendor), + cpu_to_le32(attr), cpu_to_le64(data_size), + virt_to_phys(data)); + efi_be_call_post(flags); + return status; +} + +void efi_be_runtime_setup(void) +{ + extern u8 efi_be_phys_call[]; + + runtime = ioremap_cache(le64_to_cpu(efi.systab->runtime), + sizeof(efi_runtime_services_t)); + if (!runtime) { + pr_err("Failed to set up BE wrappers for UEFI Runtime Services!\n"); + return; + } + + efi_be_call = (void *)virt_to_phys(efi_be_phys_call); + + efi.get_variable = efi_be_get_variable; + efi.get_next_variable = efi_be_get_next_variable; + efi.set_variable = efi_be_set_variable; +} diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 96df58824189..21e98810c5dd 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -406,6 +406,21 @@ static int __init arm64_enter_virtual_mode(void) efi.memmap = &memmap; + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) { + efi.systab = ioremap_cache(efi_system_table, + sizeof(efi_system_table_t)); + if (!efi.systab) { + pr_err("Failed to remap EFI system table!\n"); + return -1; + } + free_boot_services(); + efi_be_runtime_setup(); + + set_bit(EFI_SYSTEM_TABLES, &efi.flags); + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); + return 0; + } + /* Map the runtime regions */ virtmap = kmalloc(mapsize, GFP_KERNEL); if (!virtmap) {