From patchwork Thu Jan 25 10:31:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 125781 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1016475ljf; Thu, 25 Jan 2018 02:31:45 -0800 (PST) X-Google-Smtp-Source: AH8x227UKCmB2652yBdj2TXJPuXMrQPrcmH0Knz3cSt3spa3tXhE8uViogiljId3R0JrpXXXIZJy X-Received: by 2002:a17:902:901:: with SMTP id 1-v6mr4933147plm.165.1516876305499; Thu, 25 Jan 2018 02:31:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516876305; cv=none; d=google.com; s=arc-20160816; b=jtNykKRwY4PgmssKD5DTSrfOPj1erJrk77PlIEFEMLykikZxQUhJZqgw4RTB2cmvLz J1ic2eRy/xJXR3MBBaHqZ08VT8Z/nWYXD86JHHk57QnU552pNscBn34z/f5IMwJG9VA2 YNsose3Yu2k+eVLHgW96oNpM4V5cASHWi4s8KAV0UdWRpcau6VT8UutB6kHnLOvgAWP4 /iiBE8ylyrRQ0E5bnexmQuB66C27vBdAO1exExF1AUWssFC3JjCaaF2cB3ZKLh1I05DV Mn6cU3DKXZTUtaA7/Xj7X5KE48rmbn7GXWJpol0JZ3aV4j34lAdB2V3dh5bEo4223nbb NC0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Xe5JmMmDwwUr5T0FCZ/VUEhhBYMAFbvH+yWUfjWsPb0=; b=duORBymbDRZ1QVFSwZiP77Ax+6WhuVNopdWDmnMDT9kQJG/NM1wnJFZ2CCX4DW6jlO Sd0Tq4oTTuKsDemAGc31+shZr2Wpol7e6BWmQohXb8ujxGspRX+wzXuWt+yK4uhHthEi dxkEIfkbP/2lsgG2OWFcVMfqregnH99862xVEHmBgK8L25H+2VJxFdWg93QfXe3QRv1B JPZbkxoOQHtbjqVPgbaf8UfoCTrRrdkXi9RC0i7Y+BmPSth0Z8cyOS/1gnRXqYaoBtQ1 OPN2k101MVlup6rHPPxHGh5Ivv3yJ/9KizjEogUOeJZIT2fd9cP3z2nc5oKurmFobtQQ IIKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=hmpUCbzy; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q7si4419852pfh.74.2018.01.25.02.31.45; Thu, 25 Jan 2018 02:31:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=hmpUCbzy; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751155AbeAYKbp (ORCPT + 2 others); Thu, 25 Jan 2018 05:31:45 -0500 Received: from mail-wm0-f65.google.com ([74.125.82.65]:38381 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750937AbeAYKbo (ORCPT ); Thu, 25 Jan 2018 05:31:44 -0500 Received: by mail-wm0-f65.google.com with SMTP id 141so13874107wme.3 for ; Thu, 25 Jan 2018 02:31:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ENyilZee9iaBr2WP0Stghq26HbxwLHoZXiP079Ty8WI=; b=hmpUCbzykVcTdH+JbOomigdSptumbmLN0we8ap5xI3OXqnufBzvTxjt2xxnIYbJkoe sBiNW488gzGspC3PMhJMRmpXSFrB7oBxLrzzziWCX/VIgQn/QuxcTPSjQTB2MS1/VB/D +CtT6oTTu6CZmftoxcY29NNm9GVMhIzFFM1jg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ENyilZee9iaBr2WP0Stghq26HbxwLHoZXiP079Ty8WI=; b=ZWnFwCcfPJbV3k5L/h8Fz/nJjlDAu3ZP2E7YtHzYWa2/70DVI2VqJGdYOVk6y3Stf6 oUmbz24SaZEY6tRRQPYsefDjY2b0QHSLR5Vz5bV6/Qf44slQstZvx/8S2LQSTIBj9u7P aUKdcSTqSJCViPIkk9bsjLAakDtLLou1MlOboAo3obmgV2Fhoeu3xGWPhmnC3dAQgFPb JgE7kaktO3/EVSrImmbSBG40OOjqcIHDF6rxWx9e6wjhcIGEXkQdLnc+LGSGrx/fL4Dl 1Rux9UG8lFA2i+Pry0mZjDsONxjG44RbpmjCvykGVY3nwqyf3QnrX02Ayh3kf1L8uH+7 vSHw== X-Gm-Message-State: AKwxytcO7sndglEzp58/cU8GXBlbAc6FyiFYiSBUR7gRJg4weCkPbfdG KpP+DV8I0jIGISBfy/7j/IpegwAFavc= X-Received: by 10.28.11.70 with SMTP id 67mr6552705wml.158.1516876302449; Thu, 25 Jan 2018 02:31:42 -0800 (PST) Received: from localhost.localdomain ([160.167.127.168]) by smtp.gmail.com with ESMTPSA id j77sm1199964wmf.37.2018.01.25.02.31.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 02:31:41 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Cc: joakim.bech@linaro.org, leif.lindholm@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel Subject: [PATCH 1/4] efi: arm64: Check whether x18 is preserved by runtime services calls Date: Thu, 25 Jan 2018 10:31:28 +0000 Message-Id: <20180125103131.19168-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180125103131.19168-1-ard.biesheuvel@linaro.org> References: <20180125103131.19168-1-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Whether or not we will ever decide to start using x18 as a platform register in Linux is uncertain, but by that time, we will need to ensure that UEFI runtime services calls don't corrupt it. So let's start issuing warnings now for this, and increase the likelihood that these firmware images have all been replaced by that time. This has been fixed on the EDK2 side in commit 6d73863b5464 ("BaseTools/tools_def AARCH64: mark register x18 as reserved")., dated July 13, 2017. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 4 +- arch/arm64/kernel/Makefile | 3 +- arch/arm64/kernel/efi-rt-wrapper.S | 41 ++++++++++++++++++++ arch/arm64/kernel/efi.c | 6 +++ 4 files changed, 52 insertions(+), 2 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Acked-by: Will Deacon diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 8389050328bb..192d791f1103 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -31,7 +31,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); ({ \ efi_##f##_t *__f; \ __f = p->f; \ - __f(args); \ + __efi_rt_asm_wrapper(__f, #f, args); \ }) #define arch_efi_call_virt_teardown() \ @@ -40,6 +40,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); efi_virtmap_unload(); \ }) +efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...); + #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT) /* arch specific definitions used by the stub code */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index b87541360f43..6a4bd80c75bd 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -38,7 +38,8 @@ arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o -arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o +arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o \ + efi-rt-wrapper.o arm64-obj-$(CONFIG_PCI) += pci.o arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_ACPI) += acpi.o diff --git a/arch/arm64/kernel/efi-rt-wrapper.S b/arch/arm64/kernel/efi-rt-wrapper.S new file mode 100644 index 000000000000..05235ebb336d --- /dev/null +++ b/arch/arm64/kernel/efi-rt-wrapper.S @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018 Linaro Ltd + * + * 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 + +ENTRY(__efi_rt_asm_wrapper) + stp x29, x30, [sp, #-32]! + mov x29, sp + + /* + * Register x18 is designated as the 'platform' register by the AAPCS, + * which means firmware running at the same exception level as the OS + * (such as UEFI) should never touch it. + */ + stp x1, x18, [sp, #16] + + /* + * We are lucky enough that no EFI runtime services take more than + * 5 arguments, so all are passed in registers rather than via the + * stack. + */ + mov x8, x0 + mov x0, x2 + mov x1, x3 + mov x2, x4 + mov x3, x5 + mov x4, x6 + blr x8 + + ldp x1, x2, [sp, #16] + cmp x2, x18 + ldp x29, x30, [sp], #32 + b.ne 0f + ret +0: b efi_handle_corrupted_x18 // tail call +ENDPROC(__efi_rt_asm_wrapper) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 82cd07592519..af4f943cffac 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -124,3 +124,9 @@ bool efi_poweroff_required(void) { return efi_enabled(EFI_RUNTIME_SERVICES); } + +asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f) +{ + pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f); + return s; +} From patchwork Thu Jan 25 10:31:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 125782 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1016518ljf; Thu, 25 Jan 2018 02:31:48 -0800 (PST) X-Google-Smtp-Source: AH8x226W5KaiTWjyeBtJnAsGAYjt3mnzFFDDFUPSxwgp52BQdTmqC2V+eOuwaQ9uW+E69XzpJM1M X-Received: by 2002:a17:902:2f41:: with SMTP id s59-v6mr11202271plb.422.1516876308693; Thu, 25 Jan 2018 02:31:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516876308; cv=none; d=google.com; s=arc-20160816; b=wvbfaSCxgcV5F0jVNae/ar+zsxxIkGCtz58HcJ097b7jIaB7jR6CRHNumtf+K3hPKe cEwqvhRoSbIpGM8Pcf4x2vFK4lH2L5Q0ZPGFc5qQpmN1VR1oLtiVTFoxhEosR8Nr2mcz jB3CNXcJdMMqBFf6nVA/Ftxax9oK2xCoozgQh/DYgq9kRtk9LXGNaYXzbeBgLH5R0Bzg M/zZ9W52n2G7F9qjFL7Dv6jIGrV1ifuLEPVuzgnfQEhFZb11mdaryy2tSGYHiIq/MY4M 09rbaXRNPj0znuLkMZ36OdY4c+1ACBWV4d3uvebo6WdVAxDrk0/GsP9VTu/PqX4ipNMS RdcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=BUq8BRuqV8cRYIGUCbSrFQcKCeTVc32Q5AKUjSSyrZ4=; b=GMukMdDR7d72VL7/D87l33a1FJZExudi4Rn02h6OwF/eu2AbA9TVET53Ht/b0PdY/d EHvpKUOx9+k4qoe3L2LDtq3FCej/YC5aL2w1kXFzVVefnoLp5Qm0+JL+1JyPLX9q9egk 5B1RasQwpjiDnekh/aZDOw1Fs4791JB8Gp9fk8VnYgUEI2abCgFhFMj21mZcsB4wMRct pqtI+KFXWYgfEIFk86b5oXp+1moS/VTI+9XoxFzflDFPkaygva4LfzFnitQ/ud49mqJl W8Zfs05R+eqRCPcWvyLuBFD4lYNlj+WKdq4pF02tUt4s3WeN7W7LEaRELMSX51SfPEcT hXxQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZvRTSsxk; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n188si1088646pga.175.2018.01.25.02.31.48; Thu, 25 Jan 2018 02:31:48 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZvRTSsxk; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751173AbeAYKbs (ORCPT + 2 others); Thu, 25 Jan 2018 05:31:48 -0500 Received: from mail-wr0-f194.google.com ([209.85.128.194]:46158 "EHLO mail-wr0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751154AbeAYKbr (ORCPT ); Thu, 25 Jan 2018 05:31:47 -0500 Received: by mail-wr0-f194.google.com with SMTP id g21so7075468wrb.13 for ; Thu, 25 Jan 2018 02:31:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=oxpKvnWnu3AzKIA2gQBJX2ShOJ2rqfrO9V0GrV28NxA=; b=ZvRTSsxkPG+Q60tHUITQujanRucBkC9Un2d6alaSTAKgKCnsA7VQDZuAI7Q56e6dzN dcH4GHTRk5dOnhjXbYKp8BZhkHTOIYHpfCGYoeUAysgQV9AfUqsJjWQYcc39QMGoCfen QtUGwZHQOKvEsmKV3SRP3R2RextP3xhVudabs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=oxpKvnWnu3AzKIA2gQBJX2ShOJ2rqfrO9V0GrV28NxA=; b=PiC68XKhM0NB0svAfbt464chBJv2f/B3bqex+6WOjA4Iwhi1lVPokVfCD2XUSmHVr3 dZZaFdejrBT+Gqry7gKxd9RseV/27YAZ+ZVRKaSS4VZafIIgX2cg0zeGo9GLMVViQLPg XM3ng1ljR74qhOYogHfPEs5oT9mHT9k2fnlpnOwHpVK68gdYvTNECM0hoe0cyzFNq6Ih t16+lLUdAWzYZi+JM1+tVWF6w/IHhNKeiBBr1WJhAny27fdCjki1gbABcu/jtUhq/X6+ fpeDJ3DlDSaIqPlU2lKf6zQxdxcP0bw8hzfPBvN0peF9IDaXJQeXd1OR+nBudK0+fQIE rGkA== X-Gm-Message-State: AKwxytfXSjua3tZZK44KONkjw/3xyZiTopfn+MtyORCd7J9OCbKzRqXi qAvSqJqklqSPQ8Ltl7jlbXQ+8ewR9YE= X-Received: by 10.223.135.187 with SMTP id b56mr8429409wrb.164.1516876305409; Thu, 25 Jan 2018 02:31:45 -0800 (PST) Received: from localhost.localdomain ([160.167.127.168]) by smtp.gmail.com with ESMTPSA id j77sm1199964wmf.37.2018.01.25.02.31.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 02:31:44 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Cc: joakim.bech@linaro.org, leif.lindholm@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel Subject: [PATCH 2/4] efi/arm64: map the stack and entry wrapper into the UEFI page tables Date: Thu, 25 Jan 2018 10:31:29 +0000 Message-Id: <20180125103131.19168-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180125103131.19168-1-ard.biesheuvel@linaro.org> References: <20180125103131.19168-1-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org As a preparatory step towards unmapping the kernel entirely while executing UEFI runtime services, move the stack and the entry wrapper routine mappings into the EFI page tables. Also, create a vector table that overrides the main one while executing in the firmware so we will be able to remap/unmap the kernel while taking interrupts. Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/efi.h | 5 ++ arch/arm64/include/asm/efi.h | 23 ++++++++- arch/arm64/include/asm/stacktrace.h | 4 ++ arch/arm64/kernel/efi-rt-wrapper.S | 51 +++++++++++++++++++- arch/arm64/kernel/efi.c | 24 +++++++++ arch/arm64/kernel/entry.S | 1 + drivers/firmware/efi/arm-runtime.c | 2 + 7 files changed, 107 insertions(+), 3 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index 17f1f1a814ff..3a63e7cc1dfa 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -99,4 +99,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, return dram_base + SZ_512M; } +static inline int efi_allocate_runtime_regions(struct mm_struct *mm) +{ + return 0; +} + #endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 192d791f1103..b9b09a734719 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -2,11 +2,13 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H +#include + +#ifndef __ASSEMBLY__ #include #include #include #include -#include #include #include #include @@ -30,8 +32,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); #define arch_efi_call_virt(p, f, args...) \ ({ \ efi_##f##_t *__f; \ + typeof(__efi_rt_asm_wrapper) *__wrap = (void *)EFI_CODE_BASE; \ __f = p->f; \ - __efi_rt_asm_wrapper(__f, #f, args); \ + __wrap(__f, #f, args); \ }) #define arch_efi_call_virt_teardown() \ @@ -146,4 +149,20 @@ static inline void efi_set_pgd(struct mm_struct *mm) void efi_virtmap_load(void); void efi_virtmap_unload(void); +int __init efi_allocate_runtime_regions(struct mm_struct *mm); + +#endif /* __ASSEMBLY__ */ + +/* + * When running with vmap'ed stacks, we need the base of the stack to be aligned + * appropriately, where the exact alignment depends on the page size. Let's just + * put the stack at address 0x0, which is guaranteed to be free and aligned. + */ +#define EFI_STACK_BASE 0x0 +#define EFI_STACK_SIZE THREAD_SIZE + +/* where to map the pivot code in the UEFI page tables */ +#define EFI_CODE_BASE 0x200000 +#define EFI_CODE_SIZE PAGE_SIZE + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index 472ef944e932..b1212b3b3df5 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -72,6 +72,8 @@ static inline bool on_overflow_stack(unsigned long sp) static inline bool on_overflow_stack(unsigned long sp) { return false; } #endif +bool on_efi_stack(unsigned long sp); + /* * We can only safely access per-cpu stacks from current in a non-preemptible * context. @@ -88,6 +90,8 @@ static inline bool on_accessible_stack(struct task_struct *tsk, unsigned long sp return true; if (on_sdei_stack(sp)) return true; + if (on_efi_stack(sp)) + return true; return false; } diff --git a/arch/arm64/kernel/efi-rt-wrapper.S b/arch/arm64/kernel/efi-rt-wrapper.S index 05235ebb336d..09e77e5edd94 100644 --- a/arch/arm64/kernel/efi-rt-wrapper.S +++ b/arch/arm64/kernel/efi-rt-wrapper.S @@ -7,7 +7,10 @@ */ #include +#include + .section ".rodata", "a" + .align PAGE_SHIFT ENTRY(__efi_rt_asm_wrapper) stp x29, x30, [sp, #-32]! mov x29, sp @@ -19,6 +22,12 @@ ENTRY(__efi_rt_asm_wrapper) */ stp x1, x18, [sp, #16] + /* switch to the EFI runtime stack and vector table */ + mov sp, #EFI_STACK_BASE + EFI_STACK_SIZE + adr x1, __efi_rt_vectors + msr vbar_el1, x1 + isb + /* * We are lucky enough that no EFI runtime services take more than * 5 arguments, so all are passed in registers rather than via the @@ -32,10 +41,50 @@ ENTRY(__efi_rt_asm_wrapper) mov x4, x6 blr x8 + /* switch back to the task stack and primary vector table */ + mov sp, x29 + ldr x1, 2f + msr vbar_el1, x1 + isb + ldp x1, x2, [sp, #16] cmp x2, x18 ldp x29, x30, [sp], #32 b.ne 0f ret -0: b efi_handle_corrupted_x18 // tail call +0: ldr x8, 1f + br x8 // tail call ENDPROC(__efi_rt_asm_wrapper) + .align 3 +1: .quad efi_handle_corrupted_x18 +2: .quad vectors + + .macro ventry + .align 7 +.Lv\@ : stp x29, x30, [sp, #-16]! // preserve x29 and x30 + mrs x29, elr_el1 // preserve ELR + adr x30, .Lret // take return address + msr elr_el1, x30 // set ELR to return address + ldr x30, 2b // take address of 'vectors' + msr vbar_el1, x30 // set VBAR to 'vectors' + isb + add x30, x30, #.Lv\@ - __efi_rt_vectors + br x30 + .endm + +.Lret: msr elr_el1, x29 + adr x30, __efi_rt_vectors + msr vbar_el1, x30 + isb + ldp x29, x30, [sp], #16 + eret + + .align 11 +__efi_rt_vectors: + .rept 8 + ventry + .endr + /* + * EFI runtime services never drop to EL0, so the + * remaining vector table entries are not needed. + */ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index af4f943cffac..68c920b2f4f0 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -130,3 +130,27 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f) pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f); return s; } + +bool on_efi_stack(unsigned long sp) +{ + return sp >= EFI_STACK_BASE && sp < (EFI_STACK_BASE + EFI_STACK_SIZE); +} + +int __init efi_allocate_runtime_regions(struct mm_struct *mm) +{ + static u8 stack[EFI_STACK_SIZE] __page_aligned_bss; + + /* map the stack */ + create_pgd_mapping(mm, __pa_symbol(stack), + EFI_STACK_BASE, EFI_STACK_SIZE, + __pgprot(pgprot_val(PAGE_KERNEL) | PTE_NG), + false); + + /* map the runtime wrapper pivot function */ + create_pgd_mapping(mm, __pa_symbol(__efi_rt_asm_wrapper), + EFI_CODE_BASE, EFI_CODE_SIZE, + __pgprot(pgprot_val(PAGE_KERNEL_ROX) | PTE_NG), + false); + + return 0; +} diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index b34e717d7597..3bab6c60a12b 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -204,6 +204,7 @@ alternative_if ARM64_HAS_PAN alternative_else_nop_endif .if \el != 0 + tbz x21, #63, 1f // skip if TTBR0 covers the stack mrs x21, ttbr0_el1 tst x21, #TTBR_ASID_MASK // Check for the reserved ASID orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 1cc41c3d6315..e84f4d961de2 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -107,6 +107,8 @@ static bool __init efi_virtmap_init(void) if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions)) return false; + efi_allocate_runtime_regions(&efi_mm); + return true; } From patchwork Thu Jan 25 10:31:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 125783 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1016548ljf; Thu, 25 Jan 2018 02:31:52 -0800 (PST) X-Google-Smtp-Source: AH8x2275dW8Oyqtr/3xfyR5hX4prMRCT10E/oF9UQCrkCWZeOzizc6Jucgw8JiDIlKLP0SXPjG9r X-Received: by 10.99.110.138 with SMTP id j132mr13111944pgc.313.1516876312275; Thu, 25 Jan 2018 02:31:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516876312; cv=none; d=google.com; s=arc-20160816; b=GTxgxn2KPvQZf+ifkdM5FRu6nmkNYYoBN0tSO9D5vgXRbbgerWqyFfuAbv7/GD//q3 YPmCO/te9IlUwli+53fHhkATcwbX9XWFZvaKLJyWsmrWSQqEEYEg4mxmwCwZjLMu3Lwi 2Bbs3CoWim0pHzt5UHq9a23ZL55jz1e/x6e6hzFIEz5ctYtIcXCDyxO07kiS03fkt0s2 iCB1LZG2qmjMWHuSJWewpomad6ykXPkzcE8759GahRGBvVUDq+4zeDP25HBEa2PnVSA9 o23Q1nUvPpiKb2CqZ+68HXNKrDh8jIIYNb5gCUSYJpwXABXIuGTUf/btaKn6KKLNBBLt 1B3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Uer7t1TLZr0EJieU1YJDWSUtTB70aCLmfgcVSEDWHp0=; b=XhFMFb8fQLK5QCAEuB1lnApE6+RMLpzl8Ynk2sYpJkfYvAhFVKwj18GzjNPLJCDF/j s/CHErO69s83ThuI+BP7lz5p3Gs5yZL7LHBFndZgGdrqphS5V601KAPCp3Ripf2Us07N P0qvJZbbNLzdaxcz5ozs4jPKPak7GKwJPbYBfbIqrAEfSH0BAlv3eAwkltGNkH4eP8uH XZVlw5mti6LBFUfHVOpnlncFzDH+MqVjV60x2A0b11FCYKXKZdvVrD5GCLHfPdW/Rtz5 LyY9MwVlQpKf4FcEIdYMVXJ9cMfZBcASfWWXHOFMSj74qT8dMKSeb7BoOoaPVrIOKxal QLeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YLyTMV5+; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n188si1088646pga.175.2018.01.25.02.31.52; Thu, 25 Jan 2018 02:31:52 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YLyTMV5+; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751184AbeAYKbv (ORCPT + 2 others); Thu, 25 Jan 2018 05:31:51 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:40645 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751154AbeAYKbu (ORCPT ); Thu, 25 Jan 2018 05:31:50 -0500 Received: by mail-wr0-f195.google.com with SMTP id 100so7104979wrb.7 for ; Thu, 25 Jan 2018 02:31:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WyBXwDXEDstE0keE/ai7u7i2exQLm/n5/KN2TdM/BEY=; b=YLyTMV5+VOu7CrvnMq+OjoK/FLp5j5wmuafCnwXcSb/YD88Hny8x9pYb3Zd7L840IG 8qXR/0hSgUq9EHfG1VHKhGH2Zy7psWrhBJhnjV3f+kHWIhCQaCKb3i3+XuQQP4Kx/qZK hmCqXEFNVhmc2Hw6oZP1+8c5/OgVZ/rWL06N0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WyBXwDXEDstE0keE/ai7u7i2exQLm/n5/KN2TdM/BEY=; b=P7n3ageHOPr/KXTORDVhjWzBCNiudfOj6GIkt8Nzx/MrAPzWU+9Qh3SIRW7/He50el HiJd+EdgRKDpOOX5lT2P25NBJWANOLf6UsuhszU5MmpyWuzzHSeLC5FZOdJ/TmTpFmLU MxQfDTWYDhgJ58EUeWJXb411o9JLKLHYyqPIa4BJEVDJP8ZTgHq26SRmajMsh1FH/FeZ ufo0E2ZgkCL3z0YzjpW7w2w001QkEeIZQzXxgaDD0rXgMBQgfjQg+ONK0fyByPEbiSMN WVPYaQKZflA7rvHG8Z4DJZaM/Ow8qUMRvj2FhUg8RnInomogU4jPKxY3rbDk701TTh17 oHEA== X-Gm-Message-State: AKwxyte6Gf2O/4mPy/6j8ZEr9l+Zn2ipqLnbp9nhNLOhV6Q0w6sQhXi1 NH5xgMkjuW9aMpkMfAIEXwsJ7yHvLlU= X-Received: by 10.223.163.134 with SMTP id l6mr8105844wrb.220.1516876309098; Thu, 25 Jan 2018 02:31:49 -0800 (PST) Received: from localhost.localdomain ([160.167.127.168]) by smtp.gmail.com with ESMTPSA id j77sm1199964wmf.37.2018.01.25.02.31.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 02:31:48 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Cc: joakim.bech@linaro.org, leif.lindholm@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel Subject: [PATCH 3/4] efi/arm64: marshall runtime services arguments via buffer in TTBR0 Date: Thu, 25 Jan 2018 10:31:30 +0000 Message-Id: <20180125103131.19168-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180125103131.19168-1-ard.biesheuvel@linaro.org> References: <20180125103131.19168-1-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org If we want to unmap the kernel while executing UEFI runtime services, we need to ensure that all arguments passed to those services are valid during that time, and this includes pointer arguments to string buffers and other data. So we have to do the rather tedious job of replacing each generic runtime wrapper with one that takes the above into account. Fortunately, UEFI runtime services are not reentrant, so we can create a static buffer with fields for each runtime service, and a separate buffer for get/set_variable. This does limit variable names to 1024 characters and the variables themselves to 64 KB, but this should not be a limitation in practice. Note that capsule update is omitted for now - this will be addressed in a subsequent patch. Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 1 - arch/arm64/include/asm/efi.h | 5 + arch/arm64/kernel/efi.c | 475 +++++++++++++++++++- 3 files changed, 479 insertions(+), 2 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index de83b53c7e19..f2224566cc75 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1196,7 +1196,6 @@ config EFI select LIBFDT select UCS2_STRING select EFI_PARAMS_FROM_FDT - select EFI_RUNTIME_WRAPPERS select EFI_STUB select EFI_ARMSTUB default y diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index b9b09a734719..b96bc4836c37 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -165,4 +165,9 @@ int __init efi_allocate_runtime_regions(struct mm_struct *mm); #define EFI_CODE_BASE 0x200000 #define EFI_CODE_SIZE PAGE_SIZE +#define EFI_VARBUFFER_BASE 0x210000 +#define EFI_VARBUFFER_SIZE SZ_64K + +#define EFI_DATA_BASE 0x220000 + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 68c920b2f4f0..cd23c20fba39 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,9 +11,15 @@ * */ +#define pr_fmt(fmt) "efi: " fmt + +#include #include #include - +#include +#include +#include +#include #include /* @@ -136,6 +142,63 @@ bool on_efi_stack(unsigned long sp) return sp >= EFI_STACK_BASE && sp < (EFI_STACK_BASE + EFI_STACK_SIZE); } +#define MAX_CAPSULES 16 +#define MAX_VARNAME_LEN 1024 + +#define EFI_ADDR(arg) (&((typeof(__efi_rt_marshall_data)*)EFI_DATA_BASE)->arg) +#define EFI_DATA(arg) (__efi_rt_marshall_data.arg) + +static union { + struct { + efi_time_t tm; + efi_time_cap_t tc; + } get_time; + + struct { + efi_time_t tm; + } set_time; + + struct { + efi_bool_t enabled; + efi_bool_t pending; + efi_time_t tm; + } get_wakeup_time; + + struct { + efi_char16_t name[MAX_VARNAME_LEN]; + efi_guid_t vendor; + u32 attr; + unsigned long data_size; + void *data; + } get_variable; + + struct { + unsigned long name_size; + efi_char16_t name[MAX_VARNAME_LEN]; + efi_guid_t vendor; + } get_next_variable; + + struct { + u64 storage_space; + u64 remaining_space; + u64 max_variable_size; + } query_variable_info; + + struct { + u32 count; + } get_next_high_mono_count; + + struct { + efi_capsule_header_t capsules[MAX_CAPSULES]; + efi_capsule_header_t *capsule_headers[MAX_CAPSULES]; + u64 max_size; + int reset_type; + } query_capsule_caps; + +} __efi_rt_marshall_data __page_aligned_bss; + +static u8 __efi_rt_varbuffer[EFI_VARBUFFER_SIZE] __page_aligned_bss; + int __init efi_allocate_runtime_regions(struct mm_struct *mm) { static u8 stack[EFI_STACK_SIZE] __page_aligned_bss; @@ -152,5 +215,415 @@ int __init efi_allocate_runtime_regions(struct mm_struct *mm) __pgprot(pgprot_val(PAGE_KERNEL_ROX) | PTE_NG), false); + /* map the marshall data struct */ + create_pgd_mapping(mm, __pa_symbol(&__efi_rt_marshall_data), + EFI_DATA_BASE, sizeof(__efi_rt_marshall_data), + __pgprot(pgprot_val(PAGE_KERNEL) | PTE_NG), + false); + + /* map the varbuffer */ + create_pgd_mapping(mm, __pa_symbol(__efi_rt_varbuffer), + EFI_VARBUFFER_BASE, EFI_VARBUFFER_SIZE, + __pgprot(pgprot_val(PAGE_KERNEL) | PTE_NG), + false); + return 0; } + +/* + * Wrap around the new efi_call_virt_generic() macros so that the + * code doesn't get too cluttered: + */ +#define efi_call_virt(f, args...) \ + efi_call_virt_pointer(efi.systab->runtime, f, args) +#define __efi_call_virt(f, args...) \ + __efi_call_virt_pointer(efi.systab->runtime, f, args) + +void efi_call_virt_check_flags(unsigned long flags, const char *call) +{ + unsigned long cur_flags, mismatch; + + local_save_flags(cur_flags); + + mismatch = flags ^ cur_flags; + if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK)) + return; + + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); + pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", + flags, cur_flags, call); + local_irq_restore(flags); +} + +static int strlen16(efi_char16_t const *name) +{ + int ret = 0; + + while (*name++) + ret++; + + return ret; +} + +static DEFINE_SEMAPHORE(efi_runtime_lock); + +static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) +{ + efi_status_t status; + + if (!tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_time, + EFI_ADDR(get_time.tm), + tc ? EFI_ADDR(get_time.tc): NULL); + + *tm = EFI_DATA(get_time.tm); + if (tc) + *tc = EFI_DATA(get_time.tc); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_time(efi_time_t *tm) +{ + efi_status_t status; + + if (!tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(set_time.tm) = *tm; + + status = efi_call_virt(set_time, + EFI_ADDR(set_time.tm)); + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, + efi_bool_t *pending, + efi_time_t *tm) +{ + efi_status_t status; + + if (!enabled || !pending || !tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_wakeup_time, + EFI_ADDR(get_wakeup_time.enabled), + EFI_ADDR(get_wakeup_time.pending), + EFI_ADDR(get_wakeup_time.tm)); + + *enabled = EFI_DATA(get_wakeup_time.enabled); + *pending = EFI_DATA(get_wakeup_time.pending); + *tm = EFI_DATA(get_wakeup_time.tm); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(set_time.tm) = *tm; + + status = efi_call_virt(set_wakeup_time, enabled, + EFI_ADDR(set_time.tm)); + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_variable(efi_char16_t *name, + efi_guid_t *vendor, + u32 *attr, + unsigned long *data_size, + void *data) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor || !data_size) + return EFI_INVALID_PARAMETER; + + if (*data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + EFI_DATA(get_variable.data_size) = *data_size; + + status = efi_call_virt(get_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr ? EFI_ADDR(get_variable.attr) : NULL, + EFI_ADDR(get_variable.data_size), + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + if (attr) + *attr = EFI_DATA(get_variable.attr); + *data_size = EFI_DATA(get_variable.data_size); + if (data) + memcpy(data, __efi_rt_varbuffer, *data_size); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *vendor) +{ + efi_status_t status; + + if (*name_size > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(get_next_variable.name_size) = *name_size; + memcpy(EFI_DATA(get_next_variable.name), name, *name_size); + EFI_DATA(get_next_variable.vendor) = *vendor; + + status = efi_call_virt(get_next_variable, + EFI_ADDR(get_next_variable.name_size), + EFI_ADDR(get_next_variable.name), + EFI_ADDR(get_next_variable.vendor)); + + *name_size = EFI_DATA(get_next_variable.name_size); + memcpy(name, EFI_DATA(get_next_variable.name), *name_size); + *vendor = EFI_DATA(get_next_variable.vendor); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_variable(efi_char16_t *name, + efi_guid_t *vendor, + u32 attr, + unsigned long data_size, + void *data) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor) + return EFI_INVALID_PARAMETER; + + if (data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + if (data) + memcpy(__efi_rt_varbuffer, data, data_size); + + status = efi_call_virt(set_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr, + data_size, + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t +virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, + u32 attr, unsigned long data_size, + void *data) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor) + return EFI_INVALID_PARAMETER; + + if (data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_trylock(&efi_runtime_lock)) + return EFI_NOT_READY; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + if (data) + memcpy(__efi_rt_varbuffer, data, data_size); + + status = efi_call_virt(set_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr, + data_size, + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + up(&efi_runtime_lock); + return status; +} + + +static efi_status_t virt_efi_query_variable_info(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + status = efi_call_virt(query_variable_info, + attr, + EFI_ADDR(query_variable_info.storage_space), + EFI_ADDR(query_variable_info.remaining_space), + EFI_ADDR(query_variable_info.max_variable_size)); + + *storage_space = EFI_DATA(query_variable_info.storage_space); + *remaining_space = EFI_DATA(query_variable_info.remaining_space); + *max_variable_size = EFI_DATA(query_variable_info.max_variable_size); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t +virt_efi_query_variable_info_nonblocking(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + efi_status_t status; + + if (down_trylock(&efi_runtime_lock)) + return EFI_NOT_READY; + + status = efi_call_virt(query_variable_info, + attr, + EFI_ADDR(query_variable_info.storage_space), + EFI_ADDR(query_variable_info.remaining_space), + EFI_ADDR(query_variable_info.max_variable_size)); + + *storage_space = EFI_DATA(query_variable_info.storage_space); + *remaining_space = EFI_DATA(query_variable_info.remaining_space); + *max_variable_size = EFI_DATA(query_variable_info.max_variable_size); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_next_high_mono_count, + EFI_ADDR(get_next_high_mono_count.count)); + + *count = EFI_DATA(get_next_high_mono_count.count); + + up(&efi_runtime_lock); + return status; +} + +static void virt_efi_reset_system(int reset_type, + efi_status_t status, + unsigned long data_size, + efi_char16_t *data) +{ + /* we don't use 'data' in the kernel */ + pr_warn("efi_reset_system: ignoring 'data' argument\n"); + + if (down_interruptible(&efi_runtime_lock)) { + pr_warn("failed to invoke the reset_system() runtime service:\n" + "could not get exclusive access to the firmware\n"); + return; + } + __efi_call_virt(reset_system, reset_type, status, 0, NULL); + up(&efi_runtime_lock); +} + +static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, + unsigned long count, + unsigned long sg_list) +{ +// efi_status_t status; + + return EFI_NOT_READY; + +// if (down_interruptible(&efi_runtime_lock)) +// return EFI_ABORTED; +// status = efi_call_virt(update_capsule, capsules, count, sg_list); +// up(&efi_runtime_lock); +// return status; +} + +static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, + unsigned long count, + u64 *max_size, + int *reset_type) +{ + efi_status_t status; + int i; + + if (count > MAX_CAPSULES) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + for (i = 0; i < count; i++) { + EFI_DATA(query_capsule_caps.capsules[i]) = *capsules[i]; + EFI_DATA(query_capsule_caps.capsule_headers[i]) = + EFI_ADDR(query_capsule_caps.capsules[i]); + } + + status = efi_call_virt(query_capsule_caps, + EFI_ADDR(query_capsule_caps.capsule_headers), + count, + EFI_ADDR(query_capsule_caps.max_size), + EFI_ADDR(query_capsule_caps.reset_type)); + + *max_size = EFI_DATA(query_capsule_caps.max_size); + *reset_type = EFI_DATA(query_capsule_caps.reset_type); + + up(&efi_runtime_lock); + return status; +} + +void efi_native_runtime_setup(void) +{ + efi.get_time = virt_efi_get_time; + efi.set_time = virt_efi_set_time; + efi.get_wakeup_time = virt_efi_get_wakeup_time; + efi.set_wakeup_time = virt_efi_set_wakeup_time; + efi.get_variable = virt_efi_get_variable; + efi.get_next_variable = virt_efi_get_next_variable; + efi.set_variable = virt_efi_set_variable; + efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking; + efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; + efi.reset_system = virt_efi_reset_system; + efi.query_variable_info = virt_efi_query_variable_info; + efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking; + efi.update_capsule = virt_efi_update_capsule; + efi.query_capsule_caps = virt_efi_query_capsule_caps; +} From patchwork Thu Jan 25 10:31:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 125784 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1016581ljf; Thu, 25 Jan 2018 02:31:54 -0800 (PST) X-Google-Smtp-Source: AH8x226NQQXPH2+qqb1/T967sS77bgKjJ76rqnhHs6lIRKgKOr+6uFVuUIqdsI2kR1Nr9Xj97jgZ X-Received: by 2002:a17:902:7046:: with SMTP id h6-v6mr10030991plt.157.1516876314448; Thu, 25 Jan 2018 02:31:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516876314; cv=none; d=google.com; s=arc-20160816; b=mSG5+UNN+ohWfZxjrBNC9B6+xP1Pj1ZRGkNq78kZTLEh1EgZLWEFHNc3S4oawi06J2 oLqKccMSnYGXO/IrK64JEUnhV+hk/+uewuuD1PJv1R0Jjynopx0LpMjHfV5vE+zjciBn lvoBs0Go9N1afzVy6Sd7fUFjzVU3eXbSmxcjMchjgEQP+aIJlISuIVsmFf4RGBtbjCi4 HU/WoPJRTJysdA5QnAmTSLSjt1LuGzSwZrc5VIjHI0klKbOFlj7E0JO5sr1MReq9Tu30 CBF4F3i0rZo3beb5xV75hsNdV5NG/QUMx0dJ2TFvz6p12leXc58VFw3BslUQ0wSZofPz oyMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=pbZxYnVS85OWHmOYfnmZv5HDdFSAeZpZGS+iGrTIW9s=; b=wrZ1bW+Iz+yNEf7WNOaqpK/AMIdGCZQXFaBqFOZn2HXPyb24XBej5rex64CvalXpvr 1yLkFtWJ7h+oNjiYZzubfLiS7dVpEvGx9+R9mY5JoTfz5VCsqXDjmksXO0oNBXSp/Atr /0/hKFcKS0IkDYIjHuUw2jdKmPUOGAM29cD+4PuKC0JSEyb2eamli4bss1aupPKJCOOE dmUPUVWsyyfO2VuHBfGjSAtqlzW4gElsGtRuBL5c5Iuzgww0M3S6UH/t4bPnmiQ77pVr vjl4RDWQqDNSwWkiHDCIrTcR8oXF3VBVhU0blmgWnsJ6sBq5Ts3XdqEVSyEpuZMLh2lF oepg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZmF4y1lb; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n188si1088646pga.175.2018.01.25.02.31.54; Thu, 25 Jan 2018 02:31:54 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZmF4y1lb; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751227AbeAYKbx (ORCPT + 2 others); Thu, 25 Jan 2018 05:31:53 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:41309 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751154AbeAYKbx (ORCPT ); Thu, 25 Jan 2018 05:31:53 -0500 Received: by mail-wm0-f67.google.com with SMTP id f71so13660457wmf.0 for ; Thu, 25 Jan 2018 02:31:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=FVMk4pC1yCOxmiUpafBID/uAYVwtcSQ+Auhgw0OZopc=; b=ZmF4y1lbljHoTqiVuGnB6LWi4yds3Gj/kuBhZBioWN/Utm+7sYb7coKHFdOD/poosS u6gv8A5Wemb8PafGj6JLkizTYzu/XupfgqsYcLYmtt4UyMzaeaGf2/tpVFvsiT2Ra0yN INLrZNT1/dqcetQsRmWdJLv35IXZMml3Fw+pw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=FVMk4pC1yCOxmiUpafBID/uAYVwtcSQ+Auhgw0OZopc=; b=ekLV8zg7tz/UT5/Pac1Uu1CUa1RPN3DcPX9x7Cqe+D0sg+SAiW8vz0Tc4/FJ0sfGEC t8tAHOAslTulkabLFfJUw/TZV3QHaUwfkDgoArDBwbna6eMU+qrH0IliJ8dPhoEOau1/ rMHzZy78aqRMohPYmnMmgdHTbQlrMScoKxX4mOmb1RGT1QqwCj8yr8zSBD8clZgA27Iu tPMiqIR1pveD8FwMvTJz9XyKk99OgUQrjF2plau140h4Vbhha+9J/ZmIp4pWLD1mZjCL DPwvsC/sZ+Zv1CansajJAvIXkPZa1WunYr8mSCGJOE3jhTsXYSLtAN9p+xJHw+TQKtou HnKw== X-Gm-Message-State: AKwxytevxfqBmq94nJ9P1qUy5tJPxZ0zI1LZ5HR3Nb92VTlM+5moMqer a5EW1QFH7AnKw203eV4t4S14CEcyBfUxnQ== X-Received: by 10.28.32.5 with SMTP id g5mr6469655wmg.62.1516876311858; Thu, 25 Jan 2018 02:31:51 -0800 (PST) Received: from localhost.localdomain ([160.167.127.168]) by smtp.gmail.com with ESMTPSA id j77sm1199964wmf.37.2018.01.25.02.31.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 02:31:51 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Cc: joakim.bech@linaro.org, leif.lindholm@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel Subject: [PATCH 4/4] efi/arm64: unmap the kernel while executing UEFI services Date: Thu, 25 Jan 2018 10:31:31 +0000 Message-Id: <20180125103131.19168-5-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180125103131.19168-1-ard.biesheuvel@linaro.org> References: <20180125103131.19168-1-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Now that all UEFI runtime service wrappers ensure that byref arguments are moved into the UEFI marshalling buffer (which is not part of the kernel mapping), we can proceed and unmap the kernel while UEFI runtime service calls are in progress. This is done by setting the EPD1 bit and flushing the TLB of the local CPU. This makes it independent of KPTI or whether non-global mappings are being used. Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/efi-rt-wrapper.S | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm64/kernel/efi-rt-wrapper.S b/arch/arm64/kernel/efi-rt-wrapper.S index 09e77e5edd94..70af90ef914c 100644 --- a/arch/arm64/kernel/efi-rt-wrapper.S +++ b/arch/arm64/kernel/efi-rt-wrapper.S @@ -9,6 +9,24 @@ #include #include + .macro sepd1, reg + mrs \reg, tcr_el1 // read Translation Control Reg + orr \reg, \reg, #1 << 23 // set EPD1 bit + msr tcr_el1, \reg // write back TCR + isb + tlbi vmalle1 + dsb nsh + .endm + + .macro cepd1, reg + mrs \reg, tcr_el1 // read Translation Control Reg + bic \reg, \reg, #1 << 23 // clear EPD1 bit + msr tcr_el1, \reg // write back TCR + isb + tlbi vmalle1 + dsb nsh + .endm + .section ".rodata", "a" .align PAGE_SHIFT ENTRY(__efi_rt_asm_wrapper) @@ -27,6 +45,7 @@ ENTRY(__efi_rt_asm_wrapper) adr x1, __efi_rt_vectors msr vbar_el1, x1 isb + sepd1 x1 /* * We are lucky enough that no EFI runtime services take more than @@ -46,6 +65,7 @@ ENTRY(__efi_rt_asm_wrapper) ldr x1, 2f msr vbar_el1, x1 isb + cepd1 x1 ldp x1, x2, [sp, #16] cmp x2, x18 @@ -63,6 +83,7 @@ ENDPROC(__efi_rt_asm_wrapper) .align 7 .Lv\@ : stp x29, x30, [sp, #-16]! // preserve x29 and x30 mrs x29, elr_el1 // preserve ELR + cepd1 x30 adr x30, .Lret // take return address msr elr_el1, x30 // set ELR to return address ldr x30, 2b // take address of 'vectors' @@ -76,6 +97,7 @@ ENDPROC(__efi_rt_asm_wrapper) adr x30, __efi_rt_vectors msr vbar_el1, x30 isb + sepd1 x30 ldp x29, x30, [sp], #16 eret