summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2017-03-14 19:52:11 +0000
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2017-03-15 19:36:10 +0000
commit0985beff2ce5e9f41e39e1900a8d19d22975d733 (patch)
treec5ae8204c0f70043edc5f906684b8a1a9b860b07
parent7e1bc8cdb387430de34cf46a3da14b09dd2e84e2 (diff)
ArmPkg/UncachedMemoryAllocationLib: set XP bit via CPU arch protocol
Commit e7b24ec9785d ("ArmPkg/UncachedMemoryAllocationLib: map uncached allocations non-executable") adds code that manipulates the GCD memory space attributes of a newly allocated uncached region without checking whether this region expose these attributes in its capabilities mask. Given that the intent is to remove executable permissions from the region, this is a fairly pointless exercise to begin with, regardless of whether it is correct or not. The reason is that RO/XP memory attributes in the GCD memory space map or the UEFI memory map are completely disconnected from the actual mapping permissions used in the page tables. So instead, invoke the CPU arch protocol directly, and add the non-exec attributes in the page tables directly. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
-rw-r--r--ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c42
-rw-r--r--ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf8
2 files changed, 42 insertions, 8 deletions
diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c
index b4fbfbcb36..fdaaf2d706 100644
--- a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c
+++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c
@@ -27,6 +27,10 @@
#include <Library/DxeServicesTableLib.h>
#include <Library/CacheMaintenanceLib.h>
+#include <Protocol/Cpu.h>
+
+STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
+
VOID *
UncachedInternalAllocatePages (
IN EFI_MEMORY_TYPE MemoryType,
@@ -150,15 +154,25 @@ AllocatePagesFromList (
Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor);
if (EFI_ERROR (Status)) {
- gBS->FreePages (Memory, Pages);
- return Status;
+ goto FreePages;
}
Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages),
- EFI_MEMORY_WC | EFI_MEMORY_XP);
+ EFI_MEMORY_WC);
if (EFI_ERROR (Status)) {
- gBS->FreePages (Memory, Pages);
- return Status;
+ goto FreePages;
+ }
+
+ //
+ // EFI_CPU_ARCH_PROTOCOL::SetMemoryAttributes() will preserve the original
+ // memory type attribute if no memory type is passed. Permission attributes
+ // will be replaced, so EFI_MEMORY_RO will be removed if present (although
+ // it would be a bug if that were the case for an AllocatePages() allocation)
+ //
+ Status = mCpu->SetMemoryAttributes (mCpu, Memory, EFI_PAGES_TO_SIZE (Pages),
+ EFI_MEMORY_XP);
+ if (EFI_ERROR (Status)) {
+ goto FreePages;
}
InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Pages));
@@ -166,8 +180,8 @@ AllocatePagesFromList (
NewNode = AllocatePool (sizeof (FREE_PAGE_NODE));
if (NewNode == NULL) {
ASSERT (FALSE);
- gBS->FreePages (Memory, Pages);
- return EFI_OUT_OF_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreePages;
}
NewNode->Base = Memory;
@@ -181,6 +195,10 @@ AllocatePagesFromList (
*Allocation = NewNode->Allocation;
return EFI_SUCCESS;
+
+FreePages:
+ gBS->FreePages (Memory, Pages);
+ return Status;
}
/**
@@ -238,6 +256,16 @@ FreePagesFromList (
*/
EFI_STATUS
EFIAPI
+UncachedMemoryAllocationLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+}
+
+EFI_STATUS
+EFIAPI
UncachedMemoryAllocationLibDestructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
index d7a0f2f792..c637430c90 100644
--- a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
+++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
@@ -22,7 +22,7 @@
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = UncachedMemoryAllocationLib
-
+ CONSTRUCTOR = UncachedMemoryAllocationLibConstructor
DESTRUCTOR = UncachedMemoryAllocationLibDestructor
[Sources.common]
@@ -42,3 +42,9 @@
[Pcd]
gArmTokenSpaceGuid.PcdArmFreeUncachedMemorySizeThreshold
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[Depex]
+ gEfiCpuArchProtocolGuid