summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ArmPkg/ArmPkg.dec5
-rw-r--r--ArmPkg/Drivers/CpuDxe/CpuDxe.c85
-rw-r--r--ArmPkg/Drivers/CpuDxe/CpuDxe.inf3
3 files changed, 93 insertions, 0 deletions
diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index 2444457ae5..1a16d044c9 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -144,6 +144,11 @@
# If PcdMonitorConduitHvc = TRUE, conduit = HVC
gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
+ # Whether to remap all unused memory NX before installing the CPU arch
+ # protocol driver. This is needed on platforms that map all DRAM with RWX
+ # attributes initially, and can be disabled otherwise.
+ gArmTokenSpaceGuid.PcdRemapUnusedMemoryNx|TRUE|BOOLEAN|0x00000048
+
[PcdsFeatureFlag.ARM]
# Whether to map normal memory as non-shareable. FALSE is the safe choice, but
# TRUE may be appropriate to fix performance problems if you don't care about
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c
index d04958e79e..f820f3f621 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.c
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c
@@ -11,6 +11,8 @@
#include <Guid/IdleLoopEvent.h>
+#include <Library/MemoryAllocationLib.h>
+
BOOLEAN mIsFlushingGCD;
/**
@@ -227,6 +229,75 @@ InitializeDma (
CpuArchProtocol->DmaBufferAlignment = ArmCacheWritebackGranule ();
}
+/**
+ Map all EfiConventionalMemory regions in the memory map with NX
+ attributes so that allocating or freeing EfiBootServicesData regions
+ does not result in changes to memory permission attributes.
+
+**/
+STATIC
+VOID
+RemapUnusedMemoryNx (
+ VOID
+ )
+{
+ UINT64 TestBit;
+ UINTN MemoryMapSize;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+ EFI_STATUS Status;
+
+ TestBit = LShiftU64 (1, EfiBootServicesData);
+ if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & TestBit) == 0) {
+ return;
+ }
+
+ MemoryMapSize = 0;
+ MemoryMap = NULL;
+
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ do {
+ MemoryMap = (EFI_MEMORY_DESCRIPTOR *)AllocatePool (MemoryMapSize);
+ ASSERT (MemoryMap != NULL);
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MemoryMap);
+ }
+ } while (Status == EFI_BUFFER_TOO_SMALL);
+
+ ASSERT_EFI_ERROR (Status);
+
+ MemoryMapEntry = MemoryMap;
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
+ while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
+ if (MemoryMapEntry->Type == EfiConventionalMemory) {
+ ArmSetMemoryRegionNoExec (
+ MemoryMapEntry->PhysicalStart,
+ EFI_PAGES_TO_SIZE (MemoryMapEntry->NumberOfPages)
+ );
+ }
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ }
+}
+
EFI_STATUS
CpuDxeInitialize (
IN EFI_HANDLE ImageHandle,
@@ -240,6 +311,20 @@ CpuDxeInitialize (
InitializeDma (&mCpu);
+ //
+ // Once we install the CPU arch protocol, the DXE core's memory
+ // protection routines will invoke them to manage the permissions of page
+ // allocations as they are created. Given that this includes pages
+ // allocated for page tables by this driver, we must ensure that unused
+ // memory is mapped with the same permissions as boot services data
+ // regions. Otherwise, we may end up with unbounded recursion, due to the
+ // fact that updating permissions on a newly allocated page table may trigger
+ // a block entry split, which triggers a page table allocation, etc etc
+ //
+ if (FeaturePcdGet (PcdRemapUnusedMemoryNx)) {
+ RemapUnusedMemoryNx ();
+ }
+
Status = gBS->InstallMultipleProtocolInterfaces (
&mCpuHandle,
&gEfiCpuArchProtocolGuid,
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
index e732e21cb9..7d8132200e 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
@@ -48,6 +48,7 @@
DefaultExceptionHandlerLib
DxeServicesTableLib
HobLib
+ MemoryAllocationLib
PeCoffGetEntryPointLib
UefiDriverEntryPoint
UefiLib
@@ -64,9 +65,11 @@
[Pcd.common]
gArmTokenSpaceGuid.PcdVFPEnabled
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy
[FeaturePcd.common]
gArmTokenSpaceGuid.PcdDebuggerExceptionSupport
+ gArmTokenSpaceGuid.PcdRemapUnusedMemoryNx
[Depex]
gHardwareInterruptProtocolGuid OR gHardwareInterrupt2ProtocolGuid