The ARM architecture version 7 and later mandates that device mappings
have the XN (non-executable) bit set, to prevent speculative instruction
fetches from read-sensitive regions. This implies that we should not map
regions as device if we want to execute from them, so the NOR region that
contains our FD image should be mapped as normal memory instead.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
---
 ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c | 58 ++++++++++++++++----
 1 file changed, 47 insertions(+), 11 deletions(-)

diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c 
b/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c
index d5d288fb1b48..f5198fff9402 100644
--- a/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c
@@ -22,7 +22,7 @@
 #include <ArmPlatform.h>
 
 // Number of Virtual Memory Map Descriptors
-#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          4
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          6
 
 // DDR attributes
 #define DDR_ATTRIBUTES_CACHED    ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
@@ -52,6 +52,7 @@ ArmPlatformGetVirtualMemoryMap (
 {
   ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
   ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+  UINTN                         Index;
 
   ASSERT (VirtualMemoryMap != NULL);
 
@@ -88,20 +89,55 @@ ArmPlatformGetVirtualMemoryMap (
       VirtualMemoryTable[0].VirtualBase,
       VirtualMemoryTable[0].Length));
 
-  // Peripheral space before DRAM
-  VirtualMemoryTable[1].PhysicalBase = 0x0;
-  VirtualMemoryTable[1].VirtualBase  = 0x0;
-  VirtualMemoryTable[1].Length       = VirtualMemoryTable[0].PhysicalBase;
-  VirtualMemoryTable[1].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  //
+  // We cannot map the NOR flash that contains the FD image as a device, since
+  // that may imply XN on v7 and later, and we may still be executing from it 
at
+  // this point. So explicitly map the FD as normal memory if it does not
+  // intersect with system memory.
+  //
+
+  // Disregard the case where the FD sits above DRAM, to keep the logic simple.
+  ASSERT (FixedPcdGet64(PcdFdBaseAddress) + FixedPcdGet32(PcdFdSize) <=
+          PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize));
+
+  Index = 0;
+  if (FixedPcdGet64(PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) {
+    // FD is loaded in DRAM, map everything below DRAM as device
+    VirtualMemoryTable[++Index].PhysicalBase    = 0x0;
+    VirtualMemoryTable[Index].VirtualBase       = 0x0;
+    VirtualMemoryTable[Index].Length            = PcdGet64 
(PcdSystemMemoryBase);
+    VirtualMemoryTable[Index].Attributes        = 
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  } else {
+    // FD is loaded below DRAM, map everything except the FD as device
+    if (FixedPcdGet64(PcdFdBaseAddress) > 0) {
+      // Peripheral space before flash device
+      VirtualMemoryTable[++Index].PhysicalBase  = 0x0;
+      VirtualMemoryTable[Index].VirtualBase     = 0x0;
+      VirtualMemoryTable[Index].Length          = 
FixedPcdGet64(PcdFdBaseAddress);
+      VirtualMemoryTable[Index].Attributes      = 
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+    }
+
+    // Map the FD as normal memory
+    VirtualMemoryTable[++Index].PhysicalBase    = 
FixedPcdGet64(PcdFdBaseAddress);
+    VirtualMemoryTable[Index].VirtualBase       = 
VirtualMemoryTable[Index].PhysicalBase;
+    VirtualMemoryTable[Index].Length            = FixedPcdGet32(PcdFdSize);
+    VirtualMemoryTable[Index].Attributes        = CacheAttributes;
+
+    // Peripheral space between flash device and DRAM
+    VirtualMemoryTable[++Index].PhysicalBase    = 
FixedPcdGet64(PcdFdBaseAddress) + FixedPcdGet32(PcdFdSize);
+    VirtualMemoryTable[Index].VirtualBase       = 
VirtualMemoryTable[Index].PhysicalBase;
+    VirtualMemoryTable[Index].Length            = PcdGet64 
(PcdSystemMemoryBase) - VirtualMemoryTable[Index].PhysicalBase;
+    VirtualMemoryTable[Index].Attributes        = 
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  }
 
   // Peripheral space after DRAM
-  VirtualMemoryTable[2].PhysicalBase = VirtualMemoryTable[0].Length + 
VirtualMemoryTable[1].Length;
-  VirtualMemoryTable[2].VirtualBase  = VirtualMemoryTable[2].PhysicalBase;
-  VirtualMemoryTable[2].Length       = ArmGetPhysAddrTop () - 
VirtualMemoryTable[2].PhysicalBase;
-  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  VirtualMemoryTable[++Index].PhysicalBase      = PcdGet64 
(PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize);
+  VirtualMemoryTable[Index].VirtualBase         = 
VirtualMemoryTable[Index].PhysicalBase;
+  VirtualMemoryTable[Index].Length              = ArmGetPhysAddrTop () - 
VirtualMemoryTable[Index].PhysicalBase;
+  VirtualMemoryTable[Index].Attributes          = 
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
 
   // End of Table
-  ZeroMem (&VirtualMemoryTable[3], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+  ZeroMem (&VirtualMemoryTable[++Index], sizeof 
(ARM_MEMORY_REGION_DESCRIPTOR));
 
   *VirtualMemoryMap = VirtualMemoryTable;
 }
-- 
1.9.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to