]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/CpuDxe: Moved memory mapping functions that are not architecture specific...
authorOlivier Martin <olivier.martin@arm.com>
Thu, 18 Jul 2013 06:20:33 +0000 (06:20 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 18 Jul 2013 06:20:33 +0000 (06:20 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14482 6f19259b-4bc3-4df7-8a09-765794883524

ArmPkg/Drivers/CpuDxe/ArmV6/Mmu.c
ArmPkg/Drivers/CpuDxe/CpuDxe.h
ArmPkg/Drivers/CpuDxe/CpuDxe.inf
ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c [new file with mode: 0644]

index dcc7b682c06bae25c2d9fd1a469879c525df0115..2dbdb689fe4e7f2d23bc3d046be9a57c327ba213 100644 (file)
@@ -150,133 +150,6 @@ PageToGcdAttributes (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Searches memory descriptors covered by given memory range.\r
-\r
-  This function searches into the Gcd Memory Space for descriptors\r
-  (from StartIndex to EndIndex) that contains the memory range\r
-  specified by BaseAddress and Length.\r
-\r
-  @param  MemorySpaceMap       Gcd Memory Space Map as array.\r
-  @param  NumberOfDescriptors  Number of descriptors in map.\r
-  @param  BaseAddress          BaseAddress for the requested range.\r
-  @param  Length               Length for the requested range.\r
-  @param  StartIndex           Start index into the Gcd Memory Space Map.\r
-  @param  EndIndex             End index into the Gcd Memory Space Map.\r
-\r
-  @retval EFI_SUCCESS          Search successfully.\r
-  @retval EFI_NOT_FOUND        The requested descriptors does not exist.\r
-\r
-**/\r
-EFI_STATUS\r
-SearchGcdMemorySpaces (\r
-  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,\r
-  IN UINTN                               NumberOfDescriptors,\r
-  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
-  IN UINT64                              Length,\r
-  OUT UINTN                              *StartIndex,\r
-  OUT UINTN                              *EndIndex\r
-  )\r
-{\r
-  UINTN           Index;\r
-\r
-  *StartIndex = 0;\r
-  *EndIndex   = 0;\r
-  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
-    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
-        BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
-      *StartIndex = Index;\r
-    }\r
-    if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
-        BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
-      *EndIndex = Index;\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-\r
-/**\r
-  Sets the attributes for a specified range in Gcd Memory Space Map.\r
-\r
-  This function sets the attributes for a specified range in\r
-  Gcd Memory Space Map.\r
-\r
-  @param  MemorySpaceMap       Gcd Memory Space Map as array\r
-  @param  NumberOfDescriptors  Number of descriptors in map\r
-  @param  BaseAddress          BaseAddress for the range\r
-  @param  Length               Length for the range\r
-  @param  Attributes           Attributes to set\r
-\r
-  @retval EFI_SUCCESS          Memory attributes set successfully\r
-  @retval EFI_NOT_FOUND        The specified range does not exist in Gcd Memory Space\r
-\r
-**/\r
-EFI_STATUS\r
-SetGcdMemorySpaceAttributes (\r
-  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,\r
-  IN UINTN                               NumberOfDescriptors,\r
-  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
-  IN UINT64                              Length,\r
-  IN UINT64                              Attributes\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINTN                 Index;\r
-  UINTN                 StartIndex;\r
-  UINTN                 EndIndex;\r
-  EFI_PHYSICAL_ADDRESS  RegionStart;\r
-  UINT64                RegionLength;\r
-\r
-  //\r
-  // Get all memory descriptors covered by the memory range\r
-  //\r
-  Status = SearchGcdMemorySpaces (\r
-             MemorySpaceMap,\r
-             NumberOfDescriptors,\r
-             BaseAddress,\r
-             Length,\r
-             &StartIndex,\r
-             &EndIndex\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Go through all related descriptors and set attributes accordingly\r
-  //\r
-  for (Index = StartIndex; Index <= EndIndex; Index++) {\r
-    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
-      continue;\r
-    }\r
-    //\r
-    // Calculate the start and end address of the overlapping range\r
-    //\r
-    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
-      RegionStart = BaseAddress;\r
-    } else {\r
-      RegionStart = MemorySpaceMap[Index].BaseAddress;\r
-    }\r
-    if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
-      RegionLength = BaseAddress + Length - RegionStart;\r
-    } else {\r
-      RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
-    }\r
-    //\r
-    // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
-    //\r
-    gDS->SetMemorySpaceAttributes (\r
-           RegionStart,\r
-           RegionLength,\r
-           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
-           );\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
 EFI_STATUS\r
 SyncCacheConfigPage (\r
   IN     UINT32                             SectionIndex,\r
@@ -824,121 +697,3 @@ SetMemoryAttributes (
 \r
   return Status;\r
 }\r
-\r
-\r
-/**\r
-  This function modifies the attributes for the memory region specified by BaseAddress and\r
-  Length from their current attributes to the attributes specified by Attributes.\r
-\r
-  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.\r
-  @param  BaseAddress      The physical address that is the start address of a memory region.\r
-  @param  Length           The size in bytes of the memory region.\r
-  @param  Attributes       The bit mask of attributes to set for the memory region.\r
-\r
-  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
-  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
-                                BaseAddress and Length cannot be modified.\r
-  @retval EFI_INVALID_PARAMETER Length is zero.\r
-  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
-                                the memory resource range.\r
-  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
-                                resource range specified by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for the memory resource\r
-                                range specified by BaseAddress and Length.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CpuSetMemoryAttributes (\r
-  IN EFI_CPU_ARCH_PROTOCOL     *This,\r
-  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN UINT64                    Length,\r
-  IN UINT64                    Attributes\r
-  )\r
-{\r
-  DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes));\r
-  if ( ((BaseAddress & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0) || ((Length & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0)){\r
-    // minimum granularity is SIZE_4KB (4KB on ARM)\r
-    DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx): minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes));\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-  \r
-  return SetMemoryAttributes (BaseAddress, Length, Attributes, 0);\r
-}\r
-\r
-\r
-\r
-//\r
-// Add a new protocol to support \r
-//\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CpuConvertPagesToUncachedVirtualAddress (\r
-  IN  VIRTUAL_UNCACHED_PAGES_PROTOCOL   *This,\r
-  IN  EFI_PHYSICAL_ADDRESS              Address,\r
-  IN  UINTN                             Length,\r
-  IN  EFI_PHYSICAL_ADDRESS              VirtualMask,\r
-  OUT UINT64                            *Attributes     OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
-  \r
-  \r
-  if (Attributes != NULL) {\r
-    Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor);\r
-    if (!EFI_ERROR (Status)) {\r
-      *Attributes = GcdDescriptor.Attributes;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Make this address range page fault if accessed. If it is a DMA buffer than this would \r
-  // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask\r
-  // to that address. \r
-  //\r
-  Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0);\r
-  if (!EFI_ERROR (Status)) {\r
-    Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask);\r
-  }\r
-\r
-  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ConvertPagesToUncachedVirtualAddress()\n    Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length));\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CpuReconvertPages (\r
-  IN  VIRTUAL_UNCACHED_PAGES_PROTOCOL   *This,\r
-  IN  EFI_PHYSICAL_ADDRESS              Address,\r
-  IN  UINTN                             Length,\r
-  IN  EFI_PHYSICAL_ADDRESS              VirtualMask,\r
-  IN  UINT64                            Attributes\r
-  )\r
-{\r
-  EFI_STATUS      Status;\r
-\r
-  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes));\r
-  \r
-  //\r
-  // Unmap the alaised Address\r
-  //\r
-  Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0);\r
-  if (!EFI_ERROR (Status)) {\r
-    //\r
-    // Restore atttributes\r
-    //\r
-    Status = SetMemoryAttributes (Address, Length, Attributes, 0);\r
-  }\r
-  \r
-  return Status;\r
-}\r
-\r
-\r
-VIRTUAL_UNCACHED_PAGES_PROTOCOL  gVirtualUncachedPages = {\r
-  CpuConvertPagesToUncachedVirtualAddress,\r
-  CpuReconvertPages\r
-};\r
index 6349d8087f103eb7b5c20534d8eaaa96b6c5faa1..7f59ca653c38bb1f21cde8b3b630723d577f7c42 100644 (file)
@@ -1,6 +1,7 @@
 /** @file\r
 \r
   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+  Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -139,6 +140,23 @@ PublishArmProcessorTable(
   VOID\r
   );\r
 \r
+EFI_STATUS\r
+SetMemoryAttributes (\r
+  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
+  IN UINT64                    Length,\r
+  IN UINT64                    Attributes,\r
+  IN EFI_PHYSICAL_ADDRESS      VirtualMask\r
+  );\r
+\r
+EFI_STATUS\r
+SetGcdMemorySpaceAttributes (\r
+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,\r
+  IN UINTN                               NumberOfDescriptors,\r
+  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
+  IN UINT64                              Length,\r
+  IN UINT64                              Attributes\r
+  );\r
+\r
 extern VIRTUAL_UNCACHED_PAGES_PROTOCOL  gVirtualUncachedPages;\r
 \r
 #endif // __CPU_DXE_ARM_EXCEPTION_H__\r
index 16afd0452ddcd52d14e79414d797203c085c9718..6068a0fcecaa9edbf544a3eff4e7dd0cde068bc7 100644 (file)
@@ -3,7 +3,7 @@
 #  DXE CPU driver\r
 #  \r
 #  Copyright (c) 2009, Apple Inc. All rights reserved.<BR>\r
-#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+#  Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -28,6 +28,7 @@
   CpuDxe.c\r
   CpuDxe.h\r
   CpuMpCore.c\r
+  CpuMmuCommon.c\r
 \r
 #\r
 # Prior to ARMv6 we have multiple stacks, one per mode\r
diff --git a/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c b/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c
new file mode 100644 (file)
index 0000000..b136482
--- /dev/null
@@ -0,0 +1,256 @@
+/** @file\r
+*\r
+*  Copyright (c) 2013, ARM Limited. All rights reserved.\r
+*\r
+*  This program and the accompanying materials\r
+*  are licensed and made available under the terms and conditions of the BSD License\r
+*  which accompanies this distribution.  The full text of the license may be found at\r
+*  http://opensource.org/licenses/bsd-license.php\r
+*\r
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+*\r
+**/\r
+\r
+#include "CpuDxe.h"\r
+\r
+/**\r
+  Searches memory descriptors covered by given memory range.\r
+\r
+  This function searches into the Gcd Memory Space for descriptors\r
+  (from StartIndex to EndIndex) that contains the memory range\r
+  specified by BaseAddress and Length.\r
+\r
+  @param  MemorySpaceMap       Gcd Memory Space Map as array.\r
+  @param  NumberOfDescriptors  Number of descriptors in map.\r
+  @param  BaseAddress          BaseAddress for the requested range.\r
+  @param  Length               Length for the requested range.\r
+  @param  StartIndex           Start index into the Gcd Memory Space Map.\r
+  @param  EndIndex             End index into the Gcd Memory Space Map.\r
+\r
+  @retval EFI_SUCCESS          Search successfully.\r
+  @retval EFI_NOT_FOUND        The requested descriptors does not exist.\r
+\r
+**/\r
+EFI_STATUS\r
+SearchGcdMemorySpaces (\r
+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR    *MemorySpaceMap,\r
+  IN UINTN                               NumberOfDescriptors,\r
+  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
+  IN UINT64                              Length,\r
+  OUT UINTN                             *StartIndex,\r
+  OUT UINTN                             *EndIndex\r
+  )\r
+{\r
+  UINTN           Index;\r
+\r
+  *StartIndex = 0;\r
+  *EndIndex   = 0;\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&\r
+        (BaseAddress < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))) {\r
+      *StartIndex = Index;\r
+    }\r
+    if (((BaseAddress + Length - 1) >= MemorySpaceMap[Index].BaseAddress) &&\r
+        ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))) {\r
+      *EndIndex = Index;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Sets the attributes for a specified range in Gcd Memory Space Map.\r
+\r
+  This function sets the attributes for a specified range in\r
+  Gcd Memory Space Map.\r
+\r
+  @param  MemorySpaceMap       Gcd Memory Space Map as array\r
+  @param  NumberOfDescriptors  Number of descriptors in map\r
+  @param  BaseAddress          BaseAddress for the range\r
+  @param  Length               Length for the range\r
+  @param  Attributes           Attributes to set\r
+\r
+  @retval EFI_SUCCESS          Memory attributes set successfully\r
+  @retval EFI_NOT_FOUND        The specified range does not exist in Gcd Memory Space\r
+\r
+**/\r
+EFI_STATUS\r
+SetGcdMemorySpaceAttributes (\r
+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR    *MemorySpaceMap,\r
+  IN UINTN                               NumberOfDescriptors,\r
+  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
+  IN UINT64                              Length,\r
+  IN UINT64                              Attributes\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 Index;\r
+  UINTN                 StartIndex;\r
+  UINTN                 EndIndex;\r
+  EFI_PHYSICAL_ADDRESS  RegionStart;\r
+  UINT64                RegionLength;\r
+\r
+  DEBUG ((DEBUG_GCD, "SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n",\r
+      BaseAddress, BaseAddress + Length, Attributes));\r
+\r
+  //\r
+  // Get all memory descriptors covered by the memory range\r
+  //\r
+  Status = SearchGcdMemorySpaces (\r
+             MemorySpaceMap,\r
+             NumberOfDescriptors,\r
+             BaseAddress,\r
+             Length,\r
+             &StartIndex,\r
+             &EndIndex\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Go through all related descriptors and set attributes accordingly\r
+  //\r
+  for (Index = StartIndex; Index <= EndIndex; Index++) {\r
+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+      continue;\r
+    }\r
+    //\r
+    // Calculate the start and end address of the overlapping range\r
+    //\r
+    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
+      RegionStart = BaseAddress;\r
+    } else {\r
+      RegionStart = MemorySpaceMap[Index].BaseAddress;\r
+    }\r
+    if ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)) {\r
+      RegionLength = BaseAddress + Length - RegionStart;\r
+    } else {\r
+      RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
+    }\r
+    //\r
+    // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
+    //\r
+    gDS->SetMemorySpaceAttributes (\r
+           RegionStart,\r
+           RegionLength,\r
+           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
+           );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function modifies the attributes for the memory region specified by BaseAddress and\r
+  Length from their current attributes to the attributes specified by Attributes.\r
+\r
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.\r
+  @param  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param  Length           The size in bytes of the memory region.\r
+  @param  Attributes       The bit mask of attributes to set for the memory region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
+                                BaseAddress and Length cannot be modified.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
+                                the memory resource range.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
+                                resource range specified by BaseAddress and Length.\r
+                                The bit mask of attributes is not support for the memory resource\r
+                                range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuSetMemoryAttributes (\r
+  IN EFI_CPU_ARCH_PROTOCOL    *This,\r
+  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
+  IN UINT64                    Length,\r
+  IN UINT64                    Attributes\r
+  )\r
+{\r
+  DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes));\r
+\r
+  if ((BaseAddress & (SIZE_4KB - 1)) != 0) {\r
+    // Minimum granularity is SIZE_4KB (4KB on ARM)\r
+    DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return SetMemoryAttributes (BaseAddress, Length, Attributes, 0);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuConvertPagesToUncachedVirtualAddress (\r
+  IN  VIRTUAL_UNCACHED_PAGES_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS              Address,\r
+  IN  UINTN                             Length,\r
+  IN  EFI_PHYSICAL_ADDRESS              VirtualMask,\r
+  OUT UINT64                           *Attributes     OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
+\r
+  if (Attributes != NULL) {\r
+    Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor);\r
+    if (!EFI_ERROR (Status)) {\r
+      *Attributes = GcdDescriptor.Attributes;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Make this address range page fault if accessed. If it is a DMA buffer than this would\r
+  // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask\r
+  // to that address.\r
+  //\r
+  Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask);\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuConvertPagesToUncachedVirtualAddress()\n    Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length));\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuReconvertPages (\r
+  IN  VIRTUAL_UNCACHED_PAGES_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS              Address,\r
+  IN  UINTN                             Length,\r
+  IN  EFI_PHYSICAL_ADDRESS              VirtualMask,\r
+  IN  UINT64                            Attributes\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes));\r
+\r
+  //\r
+  // Unmap the aliased Address\r
+  //\r
+  Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Restore atttributes\r
+    //\r
+    Status = SetMemoryAttributes (Address, Length, Attributes, 0);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+VIRTUAL_UNCACHED_PAGES_PROTOCOL  gVirtualUncachedPages = {\r
+  CpuConvertPagesToUncachedVirtualAddress,\r
+  CpuReconvertPages\r
+};\r