From patchwork Mon Apr 11 16:08:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 65550 Delivered-To: patch@linaro.org Received: by 10.112.43.237 with SMTP id z13csp1562447lbl; Mon, 11 Apr 2016 09:08:39 -0700 (PDT) X-Received: by 10.98.9.219 with SMTP id 88mr34388071pfj.0.1460390918884; Mon, 11 Apr 2016 09:08:38 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id f90si5416032pff.83.2016.04.11.09.08.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Apr 2016 09:08:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 099FC1A22D5; Mon, 11 Apr 2016 09:08:38 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x234.google.com (mail-wm0-x234.google.com [IPv6:2a00:1450:400c:c09::234]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id B65301A22CE for ; Mon, 11 Apr 2016 09:08:36 -0700 (PDT) Received: by mail-wm0-x234.google.com with SMTP id v188so92853993wme.1 for ; Mon, 11 Apr 2016 09:08:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=dQ8wDmFgJ4O07Rop0+2xT7fxuDOQHL9rwHTqteJfD/4=; b=Eo0GjZf1qgiAQX0moH/uLyNE96O4SS94Z25MEHWP++KePdUNRjfWfbi3MczI551okp moqCLe0CvqPw62Ut5hRnYSaIlQQikhlrHzsphuDmxDYhOqx2E0FXMhiIThJV5iuU2wMi tCmfat5ym+98lnY7u39sjgu6taqURtxJPGciQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=dQ8wDmFgJ4O07Rop0+2xT7fxuDOQHL9rwHTqteJfD/4=; b=jzCyAfYPCvETxConmF+lPnDHxldXx8k+PTDKxzl5HlBAv8UIFkQEI64razPiMPKA00 Dx/Pkgb6LN7EqLWFjVZY+EpcIQjrVgh4MA5Oz0LoSYZZbZ4AVsqj0Lai7mE46k8bOoVy BvzKa9vWHw0an+Et3/DsPeFLBc1xJQpZ52P2GHeuPStpzjIqSNaoHwDcaK4YS9Q91cX0 KjMXHKrdInvB48Xao2T2hZL91CQLzmfkxxd1eIY4LQLRXFBvBOBERyM/hlcFkzan92HT bD14JG/MK13TFNQfVEu4kzamEvL8GzY0hiqUHe8xZi2X3xEq40TumLkednljs0ivNXGm 9yvA== X-Gm-Message-State: AOPr4FXlSAUx06d8QSdgcEom38ycr7jHcYowtx4T+oIx8MxHnfWmg0MntFdsQIqlbSAF9T7q X-Received: by 10.194.60.84 with SMTP id f20mr18438936wjr.57.1460390915341; Mon, 11 Apr 2016 09:08:35 -0700 (PDT) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id ks5sm28715148wjb.13.2016.04.11.09.08.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 11 Apr 2016 09:08:34 -0700 (PDT) From: Ard Biesheuvel To: edk2-devel@lists.01.org, mark.rutland@arm.com, leif.lindholm@linaro.org Date: Mon, 11 Apr 2016 18:08:29 +0200 Message-Id: <1460390909-17826-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 Subject: [edk2] [PATCH v2] ArmPkg/AArch64Mmu: disable MMU during page table manipulations X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: heyi.guo@linaro.org, ryan.harkin@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" On ARM, manipulating live page tables is cumbersome since the architecture mandates the use of break-before-make, i.e., replacing a block entry with a table entry requires an intermediate step via an invalid entry, or TLB conflicts may occur. Since it is not generally feasible to decide in the page table manipulation routines whether such an invalid entry will result in those routines themselves to become unavailable, use a function that is callable with the MMU off (i.e., a leaf function that does not access the stack) to perform the change of a block entry into a table entry. Note that the opposite should never occur, i.e., table entries are never coalesced into block entries. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- ArmPkg/Include/Library/ArmLib.h | 6 +++ ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf | 5 +- ArmPkg/Library/ArmLib/AArch64/AArch64LibConstructor.c | 36 ++++++++++++++ ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 17 ++++++- ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 51 ++++++++++++++++++++ 5 files changed, 113 insertions(+), 2 deletions(-) -- 2.5.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h index 15f610d82e1d..1689f0072db6 100644 --- a/ArmPkg/Include/Library/ArmLib.h +++ b/ArmPkg/Include/Library/ArmLib.h @@ -613,4 +613,10 @@ ArmClearMemoryRegionReadOnly ( IN UINT64 Length ); +VOID +ArmReplaceLiveTranslationEntry ( + IN UINT64 *Entry, + IN UINT64 Value + ); + #endif // __ARM_LIB__ diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf index dd585dea91fb..58684e8492f2 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf @@ -17,9 +17,10 @@ [Defines] INF_VERSION = 0x00010005 BASE_NAME = AArch64Lib FILE_GUID = ef20ddf5-b334-47b3-94cf-52ff44c29138 - MODULE_TYPE = DXE_DRIVER + MODULE_TYPE = BASE VERSION_STRING = 1.0 LIBRARY_CLASS = ArmLib + CONSTRUCTOR = AArch64LibConstructor [Sources.AARCH64] AArch64Lib.c @@ -31,6 +32,7 @@ [Sources.AARCH64] ../Common/AArch64/ArmLibSupport.S ../Common/ArmLib.c + AArch64LibConstructor.c [Packages] ArmPkg/ArmPkg.dec @@ -38,6 +40,7 @@ [Packages] [LibraryClasses] MemoryAllocationLib + CacheMaintenanceLib [Protocols] gEfiCpuArchProtocolGuid diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64LibConstructor.c b/ArmPkg/Library/ArmLib/AArch64/AArch64LibConstructor.c new file mode 100644 index 000000000000..d2d0d3c15ee3 --- /dev/null +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64LibConstructor.c @@ -0,0 +1,36 @@ +#/* @file +# +# Copyright (c) 2016, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#*/ + +#include + +#include +#include + +RETURN_STATUS +EFIAPI +AArch64LibConstructor ( + VOID + ) +{ + extern UINT32 ArmReplaceLiveTranslationEntrySize; + + // + // The ArmReplaceLiveTranslationEntry () helper function may be invoked + // with the MMU off so we have to ensure that it gets cleaned to the PoC + // + WriteBackDataCacheRange (ArmReplaceLiveTranslationEntry, + ArmReplaceLiveTranslationEntrySize); + + return RETURN_SUCCESS; +} diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c index b7d23c6f3286..2cc6fc45aecf 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c @@ -169,6 +169,20 @@ GetRootTranslationTableInfo ( STATIC VOID +ReplaceLiveEntry ( + IN UINT64 *Entry, + IN UINT64 Value + ) +{ + if (!ArmMmuEnabled ()) { + *Entry = Value; + } else { + ArmReplaceLiveTranslationEntry (Entry, Value); + } +} + +STATIC +VOID LookupAddresstoRootTable ( IN UINT64 MaxAddress, OUT UINTN *T0SZ, @@ -330,7 +344,8 @@ GetBlockEntryListFromAddress ( } // Fill the BlockEntry with the new TranslationTable - *BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY; + ReplaceLiveEntry (BlockEntry, + ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY); } } else { if (IndexLevel != PageLevel) { diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S index 1a3023b79487..789436b650df 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S @@ -56,6 +56,8 @@ GCC_ASM_EXPORT (ArmReadIdPfr1) GCC_ASM_EXPORT (ArmWriteHcr) GCC_ASM_EXPORT (ArmReadHcr) GCC_ASM_EXPORT (ArmReadCurrentEL) +GCC_ASM_EXPORT (ArmReplaceLiveTranslationEntry) +GCC_ASM_EXPORT (ArmReplaceLiveTranslationEntrySize) .set CTRL_M_BIT, (1 << 0) .set CTRL_A_BIT, (1 << 1) @@ -481,4 +483,53 @@ ASM_PFX(ArmReadCurrentEL): mrs x0, CurrentEL ret +//VOID +//ArmReplaceLiveTranslationEntry ( +// IN UINT64 *Entry, +// IN UINT64 Value +// ) +ASM_PFX(ArmReplaceLiveTranslationEntry): + .macro __replace_entry, el + mrs x8, sctlr_el\el + and x9, x8, #~CTRL_M_BIT // Clear MMU enable bit + msr sctlr_el\el, x9 + isb + + // write an invalid entry and invalidate it in the caches + str xzr, [x0] + dmb sy + dc ivac, x0 + .if \el == 1 + tlbi vmalle1 + .else + tlbi alle\el + .endif + dsb sy + msr sctlr_el\el, x8 + isb + .endm + + // disable interrupts + mrs x2, daif + msr daifset, #0xf + isb + + // clean and invalidate first so that we don't clobber adjacent entries + // that are dirty in the caches + dc civac, x0 + dsb ish + + EL1_OR_EL2_OR_EL3(x3) +1:__replace_entry 1 + b 4f +2:__replace_entry 2 + b 4f +3:__replace_entry 3 +4:msr daif, x2 + str x1, [x0] + ret + +ASM_PFX(ArmReplaceLiveTranslationEntrySize): + .long . - ArmReplaceLiveTranslationEntry + ASM_FUNCTION_REMOVE_IF_UNREFERENCED