]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuDxe.c
UefiCpuPkg/CpuDxe: Enable protection for newly added page table
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
index c5be1ff124bb5fd49e0f60d3b029b4f993b72791..6ae2dcd1c71136bd6fa364ba906dd80a6befcde6 100644 (file)
 BOOLEAN                   InterruptState = FALSE;\r
 EFI_HANDLE                mCpuHandle = NULL;\r
 BOOLEAN                   mIsFlushingGCD;\r
-UINT64                    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
-UINT64                    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
+BOOLEAN                   mIsAllocatingPageTable = FALSE;\r
+UINT64                    mValidMtrrAddressMask;\r
+UINT64                    mValidMtrrBitsMask;\r
+UINT64                    mTimerPeriod = 0;\r
 \r
 FIXED_MTRR    mFixedMtrrTable[] = {\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
+    MSR_IA32_MTRR_FIX64K_00000,\r
     0,\r
     0x10000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
+    MSR_IA32_MTRR_FIX16K_80000,\r
     0x80000,\r
     0x4000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
+    MSR_IA32_MTRR_FIX16K_A0000,\r
     0xA0000,\r
     0x4000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
+    MSR_IA32_MTRR_FIX4K_C0000,\r
     0xC0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
+    MSR_IA32_MTRR_FIX4K_C8000,\r
     0xC8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
+    MSR_IA32_MTRR_FIX4K_D0000,\r
     0xD0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
+    MSR_IA32_MTRR_FIX4K_D8000,\r
     0xD8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
+    MSR_IA32_MTRR_FIX4K_E0000,\r
     0xE0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
+    MSR_IA32_MTRR_FIX4K_E8000,\r
     0xE8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
+    MSR_IA32_MTRR_FIX4K_F0000,\r
     0xF0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
+    MSR_IA32_MTRR_FIX4K_F8000,\r
     0xF8000,\r
     0x1000\r
   },\r
@@ -297,6 +299,9 @@ CpuGetTimerValue (
   OUT UINT64                    *TimerPeriod OPTIONAL\r
   )\r
 {\r
+  UINT64          BeginValue;\r
+  UINT64          EndValue;\r
+\r
   if (TimerValue == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -308,10 +313,26 @@ CpuGetTimerValue (
   *TimerValue = AsmReadTsc ();\r
 \r
   if (TimerPeriod != NULL) {\r
+    if (mTimerPeriod == 0) {\r
+      //\r
+      // Read time stamp counter before and after delay of 100 microseconds\r
+      //\r
+      BeginValue = AsmReadTsc ();\r
+      MicroSecondDelay (100);\r
+      EndValue   = AsmReadTsc ();\r
       //\r
-      // BugBug: Hard coded. Don't know how to do this generically\r
+      // Calculate the actual frequency\r
       //\r
-      *TimerPeriod = 1000000000;\r
+      mTimerPeriod = DivU64x64Remainder (\r
+                       MultU64x32 (\r
+                         1000 * 1000 * 1000,\r
+                         100\r
+                         ),\r
+                       EndValue - BeginValue,\r
+                       NULL\r
+                       );\r
+    }\r
+    *TimerPeriod = mTimerPeriod;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -383,10 +404,24 @@ CpuSetMemoryAttributes (
   // to avoid unnecessary computing.\r
   //\r
   if (mIsFlushingGCD) {\r
-    DEBUG((EFI_D_INFO, "  Flushing GCD\n"));\r
+    DEBUG((DEBUG_INFO, "  Flushing GCD\n"));\r
     return EFI_SUCCESS;\r
   }\r
 \r
+  //\r
+  // During memory attributes updating, new pages may be allocated to setup\r
+  // smaller granularity of page table. Page allocation action might then cause\r
+  // another calling of CpuSetMemoryAttributes() recursively, due to memory\r
+  // protection policy configured (such as PcdDxeNxMemoryProtectionPolicy).\r
+  // Since this driver will always protect memory used as page table by itself,\r
+  // there's no need to apply protection policy requested from memory service.\r
+  // So it's safe to just return EFI_SUCCESS if this time of calling is caused\r
+  // by page table memory allocation.\r
+  //\r
+  if (mIsAllocatingPageTable) {\r
+    DEBUG((DEBUG_VERBOSE, "  Allocating page table memory\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
   CacheAttributes = Attributes & CACHE_ATTRIBUTE_MASK;\r
   MemoryAttributes = Attributes & MEMORY_ATTRIBUTE_MASK;\r
@@ -467,7 +502,7 @@ CpuSetMemoryAttributes (
   //\r
   // Set memory attribute by page table\r
   //\r
-  return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, AllocatePages);\r
+  return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
 }\r
 \r
 /**\r
@@ -490,13 +525,12 @@ InitializeMtrrMask (
     AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
 \r
     PhysicalAddressBits = (UINT8) RegEax;\r
-\r
-    mValidMtrrBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;\r
-    mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
   } else {\r
-    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
-    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+    PhysicalAddressBits = 36;\r
   }\r
+\r
+  mValidMtrrBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;\r
+  mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
 }\r
 \r
 /**\r
@@ -664,7 +698,7 @@ SetGcdMemorySpaceAttributes (
 \r
 **/\r
 VOID\r
-RefreshGcdMemoryAttributes (\r
+RefreshMemoryAttributesFromMtrr (\r
   VOID\r
   )\r
 {\r
@@ -685,14 +719,9 @@ RefreshGcdMemoryAttributes (
   UINT32                              FirmwareVariableMtrrCount;\r
   UINT8                               DefaultMemoryType;\r
 \r
-  if (!IsMtrrSupported ()) {\r
-    return;\r
-  }\r
-\r
   FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
   ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
-  mIsFlushingGCD = TRUE;\r
   MemorySpaceMap = NULL;\r
 \r
   //\r
@@ -843,6 +872,46 @@ RefreshGcdMemoryAttributes (
   if (MemorySpaceMap != NULL) {\r
     FreePool (MemorySpaceMap);\r
   }\r
+}\r
+\r
+/**\r
+ Check if paging is enabled or not.\r
+**/\r
+BOOLEAN\r
+IsPagingAndPageAddressExtensionsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  IA32_CR0  Cr0;\r
+  IA32_CR4  Cr4;\r
+\r
+  Cr0.UintN = AsmReadCr0 ();\r
+  Cr4.UintN = AsmReadCr4 ();\r
+\r
+  return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));\r
+}\r
+\r
+/**\r
+  Refreshes the GCD Memory Space attributes according to MTRRs and Paging.\r
+\r
+  This function refreshes the GCD Memory Space attributes according to MTRRs\r
+  and page tables.\r
+\r
+**/\r
+VOID\r
+RefreshGcdMemoryAttributes (\r
+  VOID\r
+  )\r
+{\r
+  mIsFlushingGCD = TRUE;\r
+\r
+  if (IsMtrrSupported ()) {\r
+    RefreshMemoryAttributesFromMtrr ();\r
+  }\r
+\r
+  if (IsPagingAndPageAddressExtensionsEnabled ()) {\r
+    RefreshGcdMemoryAttributesFromPaging ();\r
+  }\r
 \r
   mIsFlushingGCD = FALSE;\r
 }\r
@@ -959,13 +1028,13 @@ IntersectMemoryDescriptor (
                     IntersectionBase, IntersectionEnd - IntersectionBase,\r
                     Capabilities);\r
 \r
-    DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,\r
+    DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
       "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,\r
       IntersectionBase, IntersectionEnd, Status));\r
     return Status;\r
   }\r
 \r
-  DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
+  DEBUG ((DEBUG_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
     "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__,\r
     Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,\r
     (UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities,\r
@@ -998,7 +1067,7 @@ AddMemoryMappedIoSpace (
 \r
   Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",\r
+    DEBUG ((DEBUG_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",\r
       gEfiCallerBaseName, __FUNCTION__, Status));\r
     return Status;\r
   }\r
@@ -1055,6 +1124,11 @@ AddLocalApicMemorySpace (
   Status = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Try to allocate APIC memory mapped space, does not check return \r
+  // status because it may be allocated by other driver, or DXE Core if\r
+  // this range is built into Memory Allocation HOB.\r
+  //\r
   Status = gDS->AllocateMemorySpace (\r
                   EfiGcdAllocateAddress,\r
                   EfiGcdMemoryTypeMemoryMappedIo,\r
@@ -1064,7 +1138,10 @@ AddLocalApicMemorySpace (
                   ImageHandle,\r
                   NULL\r
                   );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_INFO, "%a: %a: AllocateMemorySpace() Status - %r\n",\r
+                         gEfiCallerBaseName, __FUNCTION__, Status));\r
+  }\r
 }\r
 \r
 /**\r
@@ -1107,11 +1184,6 @@ InitializeCpu (
   //\r
   InitInterruptDescriptorTable ();\r
 \r
-  //\r
-  // Enable the local APIC for Virtual Wire Mode.\r
-  //\r
-  ProgramVirtualWireMode ();\r
-\r
   //\r
   // Install CPU Architectural Protocol\r
   //\r