From nobody Sat Nov 2 14:40:31 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1488876142517985.3437233748829; Tue, 7 Mar 2017 00:42:22 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 745F18034E; Tue, 7 Mar 2017 00:42:15 -0800 (PST) Received: from mail-wr0-x22b.google.com (mail-wr0-x22b.google.com [IPv6:2a00:1450:400c:c0c::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 E65AD8034D for ; Tue, 7 Mar 2017 00:42:13 -0800 (PST) Received: by mail-wr0-x22b.google.com with SMTP id g10so133624191wrg.2 for ; Tue, 07 Mar 2017 00:42:13 -0800 (PST) Received: from ards-macbook-pro.c.hoisthospitality.com ([109.74.56.122]) by smtp.gmail.com with ESMTPSA id u41sm30097838wrc.24.2017.03.07.00.42.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 07 Mar 2017 00:42:10 -0800 (PST) X-Original-To: edk2-devel@lists.01.org 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=cDmXFuBDhWoK75yZxpup5TSz6RkIjwNjnoBbpUhRalA=; b=YfJBspfNkUtbcJFk3ULlSn4f7mfKrkfkDOKurQ0XrHbSyPefIfqISyOFtd38/8Rola +PsGo5J+CRRp0RGYIlojzuZq/bgW2D2SLRKu+4D0oMHaRtsBuYPmPcGp1b8orrMcqgIN GY9vC36sNYWJKVJNwTCCBf+RJIFR6alrP0Ub8= 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=cDmXFuBDhWoK75yZxpup5TSz6RkIjwNjnoBbpUhRalA=; b=oiRq0UoOoimdW0xPib5ZPi6st+tvI+4Qv5B+CopWWNsxSBsILkTEhRJwfT7rnG3c4J PX/KPWuwY8VIlZRWe+xOVEX2ntznqKZFgDwJgqA+YTrNfQfgzUwfz5QzHdFWLtAapJUk dIpw4tq3SNKUwJ/lrDhO3aGYefEXnUQrEpSTF/XbHZccfsMfBwp1KxipeAQYrS7Ed8PP xpA5t4NgOcNU4fhTLtKqQQZcPNoTaD13vQgPszQW7SVQZsAvB7qfzDranVCwyenip6pT H35J9fRW98FSrji/dO1E+gTQZTOIqR2LYkGPUhH7Je73Gr9Hem/cNGqoF8lGMrbaYlXb qrCQ== X-Gm-Message-State: AMke39nWrNpVxyjyJHvU5bDPfUB0QcW7/0yEvpnsrbl0Ox2vt2/P8ol5j8jFadCJ6E/xTeps X-Received: by 10.223.172.137 with SMTP id o9mr19503005wrc.66.1488876131896; Tue, 07 Mar 2017 00:42:11 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org, leif.lindholm@linaro.org Date: Tue, 7 Mar 2017 09:42:02 +0100 Message-Id: <1488876125-24396-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488876125-24396-1-git-send-email-ard.biesheuvel@linaro.org> References: <1488876125-24396-1-git-send-email-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH v2 1/4] ArmPkg: move ARM version of SetMemoryAttributes to ArmMmuLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: lersek@redhat.com, Ard Biesheuvel MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" ... where it belongs, since AARCH64 already keeps it there, and non DXE users of ArmMmuLib (such as DxeIpl, for the non-executable stack) may need its functionality as well. While at it, rename SetMemoryAttributes to ArmSetMemoryAttributes, and make any functions that are not exported STATIC. Also, replace an explicit gBS->AllocatePages() call [which is DXE specific] with MemoryAllocationLib::AllocatePages(). Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- ArmPkg/Drivers/CpuDxe/Arm/Mmu.c | 410 -------------------- ArmPkg/Drivers/CpuDxe/CpuDxe.h | 14 +- ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c | 2 +- ArmPkg/Include/Chipset/ArmV7Mmu.h | 6 + ArmPkg/Include/Library/ArmMmuLib.h | 8 + ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 2 +- ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c | 397 +++++++++++++++++++ 7 files changed, 414 insertions(+), 425 deletions(-) diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c b/ArmPkg/Drivers/CpuDxe/Arm/Mm= u.c index d3c307f48317..12ca5b26673e 100644 --- a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c @@ -19,19 +19,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHE= R EXPRESS OR IMPLIED. #include #include "CpuDxe.h" =20 -#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \ - EFI_MEMORY_WC | \ - EFI_MEMORY_WT | \ - EFI_MEMORY_WB | \ - EFI_MEMORY_UCE | \ - EFI_MEMORY_WP) - -// First Level Descriptors -typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR; - -// Second Level Descriptors -typedef UINT32 ARM_PAGE_TABLE_ENTRY; - EFI_STATUS SectionToGcdAttributes ( IN UINT32 SectionAttributes, @@ -350,403 +337,6 @@ SyncCacheConfig ( return EFI_SUCCESS; } =20 - - -EFI_STATUS -UpdatePageEntries ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes, - IN EFI_PHYSICAL_ADDRESS VirtualMask, - OUT BOOLEAN *FlushTlbs OPTIONAL - ) -{ - EFI_STATUS Status; - UINT32 EntryValue; - UINT32 EntryMask; - UINT32 FirstLevelIdx; - UINT32 Offset; - UINT32 NumPageEntries; - UINT32 Descriptor; - UINT32 p; - UINT32 PageTableIndex; - UINT32 PageTableEntry; - UINT32 CurrentPageTableEntry; - VOID *Mva; - - volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; - volatile ARM_PAGE_TABLE_ENTRY *PageTable; - - Status =3D EFI_SUCCESS; - - // EntryMask: bitmask of values to change (1 =3D change this value, 0 = =3D leave alone) - // EntryValue: values at bit positions specified by EntryMask - EntryMask =3D TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK; - if ((Attributes & EFI_MEMORY_XP) !=3D 0) { - EntryValue =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN; - } else { - EntryValue =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE; - } - - // Although the PI spec is unclear on this, the GCD guarantees that only - // one Attribute bit is set at a time, so the order of the conditionals = below - // is irrelevant. If no memory attribute is specified, we preserve whate= ver - // memory type is set in the page tables, and update the permission attr= ibutes - // only. - if (Attributes & EFI_MEMORY_UC) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; - // map to strongly ordered - EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // T= EX[2:0] =3D 0, C=3D0, B=3D0 - } else if (Attributes & EFI_MEMORY_WC) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; - // map to normal non-cachable - EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX = [2:0]=3D 001 =3D 0x2, B=3D0, C=3D0 - } else if (Attributes & EFI_MEMORY_WT) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; - // write through with no-allocate - EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC= ; // TEX [2:0] =3D 0, C=3D1, B=3D0 - } else if (Attributes & EFI_MEMORY_WB) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; - // write back (with allocate) - EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // T= EX [2:0] =3D 001, C=3D1, B=3D1 - } else if (Attributes & CACHE_ATTRIBUTE_MASK) { - // catch unsupported memory type attributes - ASSERT (FALSE); - return EFI_UNSUPPORTED; - } - - if ((Attributes & EFI_MEMORY_RO) !=3D 0) { - EntryValue |=3D TT_DESCRIPTOR_PAGE_AP_RO_RO; - } else { - EntryValue |=3D TT_DESCRIPTOR_PAGE_AP_RW_RW; - } - - // Obtain page table base - FirstLevelTable =3D (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress= (); - - // Calculate number of 4KB page table entries to change - NumPageEntries =3D Length / TT_DESCRIPTOR_PAGE_SIZE; - - // Iterate for the number of 4KB pages to change - Offset =3D 0; - for(p =3D 0; p < NumPageEntries; p++) { - // Calculate index into first level translation table for page table v= alue - - FirstLevelIdx =3D TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Off= set) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT; - ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); - - // Read the descriptor from the first level page table - Descriptor =3D FirstLevelTable[FirstLevelIdx]; - - // Does this descriptor need to be converted from section entry to 4K = pages? - if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) { - Status =3D ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SEC= TION_BASE_SHIFT); - if (EFI_ERROR(Status)) { - // Exit for loop - break; - } - - // Re-read descriptor - Descriptor =3D FirstLevelTable[FirstLevelIdx]; - if (FlushTlbs !=3D NULL) { - *FlushTlbs =3D TRUE; - } - } - - // Obtain page table base address - PageTable =3D (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(= Descriptor); - - // Calculate index into the page table - PageTableIndex =3D ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_= MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT; - ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT); - - // Get the entry - CurrentPageTableEntry =3D PageTable[PageTableIndex]; - - // Mask off appropriate fields - PageTableEntry =3D CurrentPageTableEntry & ~EntryMask; - - // Mask in new attributes and/or permissions - PageTableEntry |=3D EntryValue; - - if (VirtualMask !=3D 0) { - // Make this virtual address point at a physical page - PageTableEntry &=3D ~VirtualMask; - } - - if (CurrentPageTableEntry !=3D PageTableEntry) { - Mva =3D (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SEC= TION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT)); - - // Only need to update if we are changing the entry - PageTable[PageTableIndex] =3D PageTableEntry; - ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], = Mva); - - // Clean/invalidate the cache for this page, but only - // if we are modifying the memory type attributes - if (((CurrentPageTableEntry ^ PageTableEntry) & TT_DESCRIPTOR_PAGE_C= ACHE_POLICY_MASK) !=3D 0) { - WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE); - } - } - - Status =3D EFI_SUCCESS; - Offset +=3D TT_DESCRIPTOR_PAGE_SIZE; - - } // End first level translation table loop - - return Status; -} - - - -EFI_STATUS -UpdateSectionEntries ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes, - IN EFI_PHYSICAL_ADDRESS VirtualMask - ) -{ - EFI_STATUS Status =3D EFI_SUCCESS; - UINT32 EntryMask; - UINT32 EntryValue; - UINT32 FirstLevelIdx; - UINT32 NumSections; - UINT32 i; - UINT32 CurrentDescriptor; - UINT32 Descriptor; - VOID *Mva; - volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; - - // EntryMask: bitmask of values to change (1 =3D change this value, 0 = =3D leave alone) - // EntryValue: values at bit positions specified by EntryMask - - // Make sure we handle a section range that is unmapped - EntryMask =3D TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN= _MASK | - TT_DESCRIPTOR_SECTION_AP_MASK; - EntryValue =3D TT_DESCRIPTOR_SECTION_TYPE_SECTION; - - // Although the PI spec is unclear on this, the GCD guarantees that only - // one Attribute bit is set at a time, so the order of the conditionals = below - // is irrelevant. If no memory attribute is specified, we preserve whate= ver - // memory type is set in the page tables, and update the permission attr= ibutes - // only. - if (Attributes & EFI_MEMORY_UC) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; - // map to strongly ordered - EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; /= / TEX[2:0] =3D 0, C=3D0, B=3D0 - } else if (Attributes & EFI_MEMORY_WC) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; - // map to normal non-cachable - EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // T= EX [2:0]=3D 001 =3D 0x2, B=3D0, C=3D0 - } else if (Attributes & EFI_MEMORY_WT) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; - // write through with no-allocate - EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_AL= LOC; // TEX [2:0] =3D 0, C=3D1, B=3D0 - } else if (Attributes & EFI_MEMORY_WB) { - // modify cacheability attributes - EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; - // write back (with allocate) - EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; /= / TEX [2:0] =3D 001, C=3D1, B=3D1 - } else if (Attributes & CACHE_ATTRIBUTE_MASK) { - // catch unsupported memory type attributes - ASSERT (FALSE); - return EFI_UNSUPPORTED; - } - - if (Attributes & EFI_MEMORY_RO) { - EntryValue |=3D TT_DESCRIPTOR_SECTION_AP_RO_RO; - } else { - EntryValue |=3D TT_DESCRIPTOR_SECTION_AP_RW_RW; - } - - if (Attributes & EFI_MEMORY_XP) { - EntryValue |=3D TT_DESCRIPTOR_SECTION_XN_MASK; - } - - // obtain page table base - FirstLevelTable =3D (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress= (); - - // calculate index into first level translation table for start of modif= ication - FirstLevelIdx =3D TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_= DESCRIPTOR_SECTION_BASE_SHIFT; - ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); - - // calculate number of 1MB first level entries this applies to - NumSections =3D Length / TT_DESCRIPTOR_SECTION_SIZE; - - // iterate through each descriptor - for(i=3D0; i> TT_= DESCRIPTOR_SECTION_BASE_SHIFT; - ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); - - // Get section attributes and convert to page attributes - SectionDescriptor =3D FirstLevelTable[FirstLevelIdx]; - PageDescriptor =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttribut= esToPageAttributes (SectionDescriptor, FALSE); - - // Allocate a page table for the 4KB entries (we use up a full page even= though we only need 1KB) - Status =3D gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 1,= &PageTableAddr); - if (EFI_ERROR(Status)) { - return Status; - } - - PageTable =3D (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr; - - // Write the page table entries out - for (Index =3D 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) { - PageTable[Index] =3D TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (In= dex << 12)) | PageDescriptor; - } - - // Flush d-cache so descriptors make it back to uncached memory for subs= equent table walks - WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)PageTableAddr, TT_DESC= RIPTOR_PAGE_SIZE); - - // Formulate page table entry, Domain=3D0, NS=3D0 - PageTableDescriptor =3D (((UINTN)PageTableAddr) & TT_DESCRIPTOR_SECTION_= PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; - - // Write the page table entry out, replacing section entry - FirstLevelTable[FirstLevelIdx] =3D PageTableDescriptor; - - return EFI_SUCCESS; -} - - - -EFI_STATUS -SetMemoryAttributes ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes, - IN EFI_PHYSICAL_ADDRESS VirtualMask - ) -{ - EFI_STATUS Status; - UINT64 ChunkLength; - BOOLEAN FlushTlbs; - - if (Length =3D=3D 0) { - return EFI_SUCCESS; - } - - FlushTlbs =3D FALSE; - while (Length > 0) { - if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE =3D=3D 0) && - Length >=3D TT_DESCRIPTOR_SECTION_SIZE) { - - ChunkLength =3D Length - Length % TT_DESCRIPTOR_SECTION_SIZE; - - DEBUG ((DEBUG_PAGE, - "SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n", - BaseAddress, ChunkLength, Attributes)); - - Status =3D UpdateSectionEntries (BaseAddress, ChunkLength, Attribute= s, - VirtualMask); - - FlushTlbs =3D TRUE; - } else { - - // - // Process page by page until the next section boundary, but only if - // we have more than a section's worth of area to deal with after th= at. - // - ChunkLength =3D TT_DESCRIPTOR_SECTION_SIZE - - (BaseAddress % TT_DESCRIPTOR_SECTION_SIZE); - if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) { - ChunkLength =3D Length; - } - - DEBUG ((DEBUG_PAGE, - "SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n", - BaseAddress, ChunkLength, Attributes)); - - Status =3D UpdatePageEntries (BaseAddress, ChunkLength, Attributes, - VirtualMask, &FlushTlbs); - } - - if (EFI_ERROR (Status)) { - break; - } - - BaseAddress +=3D ChunkLength; - Length -=3D ChunkLength; - } - - if (FlushTlbs) { - ArmInvalidateTlb (); - } - return Status; -} - UINT64 EfiAttributeToArmAttribute ( IN UINT64 EfiAttributes diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h index a46db8d25754..a0f71e69ec09 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -19,6 +19,7 @@ #include =20 #include +#include #include #include #include @@ -112,11 +113,6 @@ SyncCacheConfig ( IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol ); =20 -EFI_STATUS -ConvertSectionToPages ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ); - /** * Publish ARM Processor Data table in UEFI SYSTEM Table. * @param HobStart Pointer to the beginning of the HOB List= from PEI. @@ -132,14 +128,6 @@ PublishArmProcessorTable( VOID ); =20 -EFI_STATUS -SetMemoryAttributes ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes, - IN EFI_PHYSICAL_ADDRESS VirtualMask - ); - // The ARM Attributes might be defined on 64-bit (case of the long format = description table) UINT64 EfiAttributeToArmAttribute ( diff --git a/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c b/ArmPkg/Drivers/CpuDxe/C= puMmuCommon.c index 0f36a058407a..d0a3fedd3aa7 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c +++ b/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c @@ -210,7 +210,7 @@ CpuSetMemoryAttributes ( if (EFI_ERROR (Status) || (RegionArmAttributes !=3D ArmAttributes) || ((BaseAddress + Length) > (RegionBaseAddress + RegionLength))) { - return SetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0); + return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0); } else { return EFI_SUCCESS; } diff --git a/ArmPkg/Include/Chipset/ArmV7Mmu.h b/ArmPkg/Include/Chipset/Arm= V7Mmu.h index 549a5cd7d45a..4d913824b4ed 100644 --- a/ArmPkg/Include/Chipset/ArmV7Mmu.h +++ b/ArmPkg/Include/Chipset/ArmV7Mmu.h @@ -229,6 +229,12 @@ TT_DESCRIPTOR_PAGE= _AP_RW_RW | \ TT_DESCRIPTOR_PAGE= _CACHE_POLICY_NON_CACHEABLE) =20 +// First Level Descriptors +typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR; + +// Second Level Descriptors +typedef UINT32 ARM_PAGE_TABLE_ENTRY; + UINT32 ConvertSectionAttributesToPageAttributes ( IN UINT32 SectionAttributes, diff --git a/ArmPkg/Include/Library/ArmMmuLib.h b/ArmPkg/Include/Library/Ar= mMmuLib.h index c1d43872d548..d3a302fa8125 100644 --- a/ArmPkg/Include/Library/ArmMmuLib.h +++ b/ArmPkg/Include/Library/ArmMmuLib.h @@ -62,4 +62,12 @@ ArmReplaceLiveTranslationEntry ( IN UINT64 Value ); =20 +EFI_STATUS +ArmSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes, + IN EFI_PHYSICAL_ADDRESS VirtualMask + ); + #endif diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Libr= ary/ArmMmuLib/AArch64/ArmMmuLibCore.c index df170d20a2c2..77f108971f3e 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -447,7 +447,7 @@ GcdAttributeToPageAttribute ( } =20 EFI_STATUS -SetMemoryAttributes ( +ArmSetMemoryAttributes ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, diff --git a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c b/ArmPkg/Library/= ArmMmuLib/Arm/ArmMmuLibCore.c index f981c5bbcab6..8a472a1eb64b 100644 --- a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,13 @@ #define ID_MMFR0_SHR_IMP_HW_COHERENT 1 #define ID_MMFR0_SHR_IGNORED 0xf =20 +#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \ + EFI_MEMORY_WC | \ + EFI_MEMORY_WT | \ + EFI_MEMORY_WB | \ + EFI_MEMORY_UCE | \ + EFI_MEMORY_WP) + UINTN EFIAPI ArmReadIdMmfr0 ( @@ -406,6 +414,395 @@ ArmConfigureMmu ( return RETURN_SUCCESS; } =20 +STATIC +EFI_STATUS +ConvertSectionToPages ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + UINT32 FirstLevelIdx; + UINT32 SectionDescriptor; + UINT32 PageTableDescriptor; + UINT32 PageDescriptor; + UINT32 Index; + + volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; + volatile ARM_PAGE_TABLE_ENTRY *PageTable; + + DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)Base= Address)); + + // Obtain page table base + FirstLevelTable =3D (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress= (); + + // Calculate index into first level translation table for start of modif= ication + FirstLevelIdx =3D TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_= DESCRIPTOR_SECTION_BASE_SHIFT; + ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); + + // Get section attributes and convert to page attributes + SectionDescriptor =3D FirstLevelTable[FirstLevelIdx]; + PageDescriptor =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttribut= esToPageAttributes (SectionDescriptor, FALSE); + + // Allocate a page table for the 4KB entries (we use up a full page even= though we only need 1KB) + PageTable =3D (volatile ARM_PAGE_TABLE_ENTRY *)AllocatePages (1); + if (PageTable =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Write the page table entries out + for (Index =3D 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) { + PageTable[Index] =3D TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (In= dex << 12)) | PageDescriptor; + } + + // Flush d-cache so descriptors make it back to uncached memory for subs= equent table walks + WriteBackInvalidateDataCacheRange ((VOID *)PageTable, TT_DESCRIPTOR_PAGE= _SIZE); + + // Formulate page table entry, Domain=3D0, NS=3D0 + PageTableDescriptor =3D (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGE= TABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; + + // Write the page table entry out, replacing section entry + FirstLevelTable[FirstLevelIdx] =3D PageTableDescriptor; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +UpdatePageEntries ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes, + IN EFI_PHYSICAL_ADDRESS VirtualMask, + OUT BOOLEAN *FlushTlbs OPTIONAL + ) +{ + EFI_STATUS Status; + UINT32 EntryValue; + UINT32 EntryMask; + UINT32 FirstLevelIdx; + UINT32 Offset; + UINT32 NumPageEntries; + UINT32 Descriptor; + UINT32 p; + UINT32 PageTableIndex; + UINT32 PageTableEntry; + UINT32 CurrentPageTableEntry; + VOID *Mva; + + volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; + volatile ARM_PAGE_TABLE_ENTRY *PageTable; + + Status =3D EFI_SUCCESS; + + // EntryMask: bitmask of values to change (1 =3D change this value, 0 = =3D leave alone) + // EntryValue: values at bit positions specified by EntryMask + EntryMask =3D TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK; + if (Attributes & EFI_MEMORY_XP) { + EntryValue =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN; + } else { + EntryValue =3D TT_DESCRIPTOR_PAGE_TYPE_PAGE; + } + + // Although the PI spec is unclear on this, the GCD guarantees that only + // one Attribute bit is set at a time, so the order of the conditionals = below + // is irrelevant. If no memory attribute is specified, we preserve whate= ver + // memory type is set in the page tables, and update the permission attr= ibutes + // only. + if (Attributes & EFI_MEMORY_UC) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; + // map to strongly ordered + EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // T= EX[2:0] =3D 0, C=3D0, B=3D0 + } else if (Attributes & EFI_MEMORY_WC) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; + // map to normal non-cachable + EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX = [2:0]=3D 001 =3D 0x2, B=3D0, C=3D0 + } else if (Attributes & EFI_MEMORY_WT) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; + // write through with no-allocate + EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC= ; // TEX [2:0] =3D 0, C=3D1, B=3D0 + } else if (Attributes & EFI_MEMORY_WB) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; + // write back (with allocate) + EntryValue |=3D TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // T= EX [2:0] =3D 001, C=3D1, B=3D1 + } else if (Attributes & CACHE_ATTRIBUTE_MASK) { + // catch unsupported memory type attributes + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + if (Attributes & EFI_MEMORY_RO) { + EntryValue |=3D TT_DESCRIPTOR_PAGE_AP_RO_RO; + } else { + EntryValue |=3D TT_DESCRIPTOR_PAGE_AP_RW_RW; + } + + // Obtain page table base + FirstLevelTable =3D (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress= (); + + // Calculate number of 4KB page table entries to change + NumPageEntries =3D Length / TT_DESCRIPTOR_PAGE_SIZE; + + // Iterate for the number of 4KB pages to change + Offset =3D 0; + for(p =3D 0; p < NumPageEntries; p++) { + // Calculate index into first level translation table for page table v= alue + + FirstLevelIdx =3D TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Off= set) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT; + ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); + + // Read the descriptor from the first level page table + Descriptor =3D FirstLevelTable[FirstLevelIdx]; + + // Does this descriptor need to be converted from section entry to 4K = pages? + if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) { + Status =3D ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SEC= TION_BASE_SHIFT); + if (EFI_ERROR(Status)) { + // Exit for loop + break; + } + + // Re-read descriptor + Descriptor =3D FirstLevelTable[FirstLevelIdx]; + if (FlushTlbs !=3D NULL) { + *FlushTlbs =3D TRUE; + } + } + + // Obtain page table base address + PageTable =3D (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(= Descriptor); + + // Calculate index into the page table + PageTableIndex =3D ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_= MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT; + ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT); + + // Get the entry + CurrentPageTableEntry =3D PageTable[PageTableIndex]; + + // Mask off appropriate fields + PageTableEntry =3D CurrentPageTableEntry & ~EntryMask; + + // Mask in new attributes and/or permissions + PageTableEntry |=3D EntryValue; + + if (VirtualMask !=3D 0) { + // Make this virtual address point at a physical page + PageTableEntry &=3D ~VirtualMask; + } + + if (CurrentPageTableEntry !=3D PageTableEntry) { + Mva =3D (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SEC= TION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT)); + + // Clean/invalidate the cache for this page, but only + // if we are modifying the memory type attributes + if (((CurrentPageTableEntry ^ PageTableEntry) & TT_DESCRIPTOR_PAGE_C= ACHE_POLICY_MASK) !=3D 0) { + WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE); + } + + // Only need to update if we are changing the entry + PageTable[PageTableIndex] =3D PageTableEntry; + ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], = Mva); + } + + Status =3D EFI_SUCCESS; + Offset +=3D TT_DESCRIPTOR_PAGE_SIZE; + + } // End first level translation table loop + + return Status; +} + +STATIC +EFI_STATUS +UpdateSectionEntries ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes, + IN EFI_PHYSICAL_ADDRESS VirtualMask + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + UINT32 EntryMask; + UINT32 EntryValue; + UINT32 FirstLevelIdx; + UINT32 NumSections; + UINT32 i; + UINT32 CurrentDescriptor; + UINT32 Descriptor; + VOID *Mva; + volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; + + // EntryMask: bitmask of values to change (1 =3D change this value, 0 = =3D leave alone) + // EntryValue: values at bit positions specified by EntryMask + + // Make sure we handle a section range that is unmapped + EntryMask =3D TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN= _MASK | + TT_DESCRIPTOR_SECTION_AP_MASK; + EntryValue =3D TT_DESCRIPTOR_SECTION_TYPE_SECTION; + + // Although the PI spec is unclear on this, the GCD guarantees that only + // one Attribute bit is set at a time, so the order of the conditionals = below + // is irrelevant. If no memory attribute is specified, we preserve whate= ver + // memory type is set in the page tables, and update the permission attr= ibutes + // only. + if (Attributes & EFI_MEMORY_UC) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; + // map to strongly ordered + EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; /= / TEX[2:0] =3D 0, C=3D0, B=3D0 + } else if (Attributes & EFI_MEMORY_WC) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; + // map to normal non-cachable + EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // T= EX [2:0]=3D 001 =3D 0x2, B=3D0, C=3D0 + } else if (Attributes & EFI_MEMORY_WT) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; + // write through with no-allocate + EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_AL= LOC; // TEX [2:0] =3D 0, C=3D1, B=3D0 + } else if (Attributes & EFI_MEMORY_WB) { + // modify cacheability attributes + EntryMask |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; + // write back (with allocate) + EntryValue |=3D TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; /= / TEX [2:0] =3D 001, C=3D1, B=3D1 + } else if (Attributes & CACHE_ATTRIBUTE_MASK) { + // catch unsupported memory type attributes + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + if (Attributes & EFI_MEMORY_RO) { + EntryValue |=3D TT_DESCRIPTOR_SECTION_AP_RO_RO; + } else { + EntryValue |=3D TT_DESCRIPTOR_SECTION_AP_RW_RW; + } + + if (Attributes & EFI_MEMORY_XP) { + EntryValue |=3D TT_DESCRIPTOR_SECTION_XN_MASK; + } + + // obtain page table base + FirstLevelTable =3D (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress= (); + + // calculate index into first level translation table for start of modif= ication + FirstLevelIdx =3D TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_= DESCRIPTOR_SECTION_BASE_SHIFT; + ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT); + + // calculate number of 1MB first level entries this applies to + NumSections =3D Length / TT_DESCRIPTOR_SECTION_SIZE; + + // iterate through each descriptor + for(i=3D0; i 0) { + if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE =3D=3D 0) && + Length >=3D TT_DESCRIPTOR_SECTION_SIZE) { + + ChunkLength =3D Length - Length % TT_DESCRIPTOR_SECTION_SIZE; + + DEBUG ((DEBUG_PAGE, + "SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n", + BaseAddress, ChunkLength, Attributes)); + + Status =3D UpdateSectionEntries (BaseAddress, ChunkLength, Attribute= s, + VirtualMask); + + FlushTlbs =3D TRUE; + } else { + + // + // Process page by page until the next section boundary, but only if + // we have more than a section's worth of area to deal with after th= at. + // + ChunkLength =3D TT_DESCRIPTOR_SECTION_SIZE - + (BaseAddress % TT_DESCRIPTOR_SECTION_SIZE); + if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) { + ChunkLength =3D Length; + } + + DEBUG ((DEBUG_PAGE, + "SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n", + BaseAddress, ChunkLength, Attributes)); + + Status =3D UpdatePageEntries (BaseAddress, ChunkLength, Attributes, + VirtualMask, &FlushTlbs); + } + + if (EFI_ERROR (Status)) { + break; + } + + BaseAddress +=3D ChunkLength; + Length -=3D ChunkLength; + } + + if (FlushTlbs) { + ArmInvalidateTlb (); + } + return Status; +} =20 EFI_STATUS ArmSetMemoryRegionNoExec ( --=20 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel