From patchwork Mon Apr 11 13:57:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 65521 Delivered-To: patch@linaro.org Received: by 10.112.43.237 with SMTP id z13csp1488806lbl; Mon, 11 Apr 2016 06:57:26 -0700 (PDT) X-Received: by 10.98.15.17 with SMTP id x17mr33481210pfi.52.1460383044660; Mon, 11 Apr 2016 06:57:24 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id ui8si3801978pab.38.2016.04.11.06.57.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Apr 2016 06:57:24 -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 E7F4A1A2078; Mon, 11 Apr 2016 06:57:23 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x22b.google.com (mail-wm0-x22b.google.com [IPv6:2a00:1450:400c:c09::22b]) (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 8D2871A2032 for ; Mon, 11 Apr 2016 06:57:22 -0700 (PDT) Received: by mail-wm0-x22b.google.com with SMTP id f198so146839401wme.0 for ; Mon, 11 Apr 2016 06:57:22 -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=9EBWQBKnkayj/b0VQUP+wSYHilJTNi8zA6+AEstvxk8=; b=is8fz8acKfiP4Sdz25xxsZjj8s84TD5ZAdMZmEQB8m+T9V5eCVp/FxC+bE20UdpoAK 6TW6XA+8+Cqp9AqCqaZ4F000/K9wSkiBrfzzS78+ydMCnOuqcBYcWXArWh5ELAtlErd3 AQEFgWMAAmpQ7UUNiEKyN8Ojc8Ozzs8bOFMdo= 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=9EBWQBKnkayj/b0VQUP+wSYHilJTNi8zA6+AEstvxk8=; b=UdjDUcxz9f4wK/3VRFIkyxBFrvt7/1jkLUPZx+uqGLk/4qkAxQiHoIqpjEOpZj+obR PX021tx+aY3qiSRO7NvltMuDweONKUBHjWF7of5RUiJHZQwePmgKdx2cKfuMRD6pGeH6 hZfXvqmOqn7xla+W+0etHcWOcIifhtThZZ2C9N6OnPeLH4TlWU8mJpLrE+SfFnt5pDfA 1ckyMs8cyMubpj3PV+cHlVarFQwDdyFzBpM1MRu+R5njuLAgvC0vdG2ElB/lEMVZF1j5 5qepR7NXxJJgELakSMtNCrw8IlDcGoNrZOgoEgneL5ur86DXpxZF/Bmx2C81L0a0PAoB efsQ== X-Gm-Message-State: AOPr4FW9BIeMd19LZbTEN+XsE076ZV3tfQQrxlULIYFNJunOCxL37ABFOHcH06WY9WEsiIb6 X-Received: by 10.28.131.131 with SMTP id f125mr7794077wmd.21.1460383041119; Mon, 11 Apr 2016 06:57:21 -0700 (PDT) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id u79sm17502407wmu.8.2016.04.11.06.57.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 11 Apr 2016 06:57:20 -0700 (PDT) From: Ard Biesheuvel To: edk2-devel@lists.01.org, mark.rutland@arm.com, leif.lindholm@linaro.org Date: Mon, 11 Apr 2016 15:57:15 +0200 Message-Id: <1460383035-377-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 Subject: [edk2] [PATCH] 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, and since UEFI uses an identity mapping anyway, it is far simpler to just disable the MMU, perform the page table manipulations, flush the TLBs and re-enable the MMU. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) -- 2.5.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c index b7d23c6f3286..2f8f05df8aec 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c @@ -286,6 +286,11 @@ GetBlockEntryListFromAddress ( } } else if ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) { // If we are not at the last level then we need to split this BlockEntry + // Since splitting live block entries may cause TLB conflicts, we need to + // enter this function with the MMU disabled and flush the TLBs before + // re-enabling it. This is the responsibility of the caller. + ASSERT (!ArmMmuEnabled ()); + if (IndexLevel != PageLevel) { // Retrieve the attributes from the block entry Attributes = *BlockEntry & TT_ATTRIBUTES_MASK; @@ -453,6 +458,8 @@ SetMemoryAttributes ( RETURN_STATUS Status; ARM_MEMORY_REGION_DESCRIPTOR MemoryRegion; UINT64 *TranslationTable; + UINTN SavedInterruptState; + BOOLEAN SavedMmuState; MemoryRegion.PhysicalBase = BaseAddress; MemoryRegion.VirtualBase = BaseAddress; @@ -461,6 +468,15 @@ SetMemoryAttributes ( TranslationTable = ArmGetTTBR0BaseAddress (); + SavedMmuState = ArmMmuEnabled (); + if (SavedMmuState) { + SavedInterruptState = ArmGetInterruptState (); + if (SavedInterruptState) { + ArmDisableInterrupts(); + } + ArmDisableMmu(); + } + Status = FillTranslationTable (TranslationTable, &MemoryRegion); if (RETURN_ERROR (Status)) { return Status; @@ -468,6 +484,12 @@ SetMemoryAttributes ( // Invalidate all TLB entries so changes are synced ArmInvalidateTlb (); + if (SavedMmuState) { + ArmEnableMmu(); + if (SavedInterruptState) { + ArmEnableInterrupts (); + } + } return RETURN_SUCCESS; } @@ -483,9 +505,20 @@ SetMemoryRegionAttribute ( { RETURN_STATUS Status; UINT64 *RootTable; + UINTN SavedInterruptState; + BOOLEAN SavedMmuState; RootTable = ArmGetTTBR0BaseAddress (); + SavedMmuState = ArmMmuEnabled (); + if (SavedMmuState) { + SavedInterruptState = ArmGetInterruptState (); + if (SavedInterruptState) { + ArmDisableInterrupts(); + } + ArmDisableMmu(); + } + Status = UpdateRegionMapping (RootTable, BaseAddress, Length, Attributes, BlockEntryMask); if (RETURN_ERROR (Status)) { return Status; @@ -493,6 +526,12 @@ SetMemoryRegionAttribute ( // Invalidate all TLB entries so changes are synced ArmInvalidateTlb (); + if (SavedMmuState) { + ArmEnableMmu(); + if (SavedInterruptState) { + ArmEnableInterrupts (); + } + } return RETURN_SUCCESS; }