]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
UefiCpuPkg/CpuDxe: Copy two functions from PciHostBridge
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.c
index 852b5c742688c92fc9218f1dc0f2c02dbe247f0b..fc7714a3b9f78fd0675d0263ebf076663281ba02 100644 (file)
@@ -113,6 +113,19 @@ InitializeSmmIdt (
   EFI_STATUS               Status;\r
   BOOLEAN                  InterruptState;\r
   IA32_DESCRIPTOR          DxeIdtr;\r
+\r
+  //\r
+  // There are 32 (not 255) entries in it since only processor\r
+  // generated exceptions will be handled.\r
+  //\r
+  gcSmiIdtr.Limit = (sizeof(IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;\r
+  //\r
+  // Allocate page aligned IDT, because it might be set as read only.\r
+  //\r
+  gcSmiIdtr.Base = (UINTN)AllocateCodePages (EFI_SIZE_TO_PAGES(gcSmiIdtr.Limit + 1));\r
+  ASSERT (gcSmiIdtr.Base != 0);\r
+  ZeroMem ((VOID *)gcSmiIdtr.Base, gcSmiIdtr.Limit + 1);\r
+\r
   //\r
   // Disable Interrupt and save DXE IDT table\r
   //\r
@@ -331,7 +344,7 @@ SmmInitHandler (
   AsmWriteIdtr (&gcSmiIdtr);\r
   ApicId = GetApicId ();\r
 \r
-  ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+  ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);\r
 \r
   for (Index = 0; Index < mNumberOfCpus; Index++) {\r
     if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {\r
@@ -490,6 +503,11 @@ SmmReadyToLockEventNotify (
 {\r
   GetAcpiCpuData ();\r
 \r
+  //\r
+  // Cache a copy of UEFI memory map before we start profiling feature.\r
+  //\r
+  GetUefiMemoryMap ();\r
+\r
   //\r
   // Set SMM ready to lock flag and return\r
   //\r
@@ -698,22 +716,23 @@ PiCpuSmmEntry (
 \r
   //\r
   // Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU\r
-  // specific context in a PROCESSOR_SMM_DESCRIPTOR, and the SMI entry point.  This size\r
-  // is rounded up to nearest power of 2.\r
+  // specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.\r
+  // This size is rounded up to nearest power of 2.\r
   //\r
   TileCodeSize = GetSmiHandlerSize ();\r
   TileCodeSize = ALIGN_VALUE(TileCodeSize, SIZE_4KB);\r
-  TileDataSize = sizeof (SMRAM_SAVE_STATE_MAP) + sizeof (PROCESSOR_SMM_DESCRIPTOR);\r
+  TileDataSize = (SMRAM_SAVE_STATE_MAP_OFFSET - SMM_PSD_OFFSET) + sizeof (SMRAM_SAVE_STATE_MAP);\r
   TileDataSize = ALIGN_VALUE(TileDataSize, SIZE_4KB);\r
   TileSize = TileDataSize + TileCodeSize - 1;\r
   TileSize = 2 * GetPowerOfTwo32 ((UINT32)TileSize);\r
   DEBUG ((EFI_D_INFO, "SMRAM TileSize = 0x%08x (0x%08x, 0x%08x)\n", TileSize, TileCodeSize, TileDataSize));\r
 \r
   //\r
-  // If the TileSize is larger than space available for the SMI Handler of CPU[i],\r
-  // the PROCESSOR_SMM_DESCRIPTOR of CPU[i+1] and the SMRAM Save State Map of CPU[i+1],\r
-  // the ASSERT().  If this ASSERT() is triggered, then the SMI Handler size must be\r
-  // reduced.\r
+  // If the TileSize is larger than space available for the SMI Handler of\r
+  // CPU[i], the extra CPU specific context of CPU[i+1], and the SMRAM Save\r
+  // State Map of CPU[i+1], then ASSERT().  If this ASSERT() is triggered, then\r
+  // the SMI Handler size must be reduced or the size of the extra CPU specific\r
+  // context must be reduced.\r
   //\r
   ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));\r
 \r
@@ -731,9 +750,9 @@ PiCpuSmmEntry (
   //\r
   BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));\r
   if ((FamilyId == 4) || (FamilyId == 5)) {\r
-    Buffer = AllocateAlignedPages (BufferPages, SIZE_32KB);\r
+    Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);\r
   } else {\r
-    Buffer = AllocateAlignedPages (BufferPages, SIZE_4KB);\r
+    Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);\r
   }\r
   ASSERT (Buffer != NULL);\r
   DEBUG ((EFI_D_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE(BufferPages)));\r
@@ -842,6 +861,8 @@ PiCpuSmmEntry (
   //\r
   SmmCpuFeaturesSmmRelocationComplete ();\r
 \r
+  DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));\r
+\r
   //\r
   // SMM Time initialization\r
   //\r
@@ -1004,6 +1025,7 @@ FindSmramInfo (
     }\r
   } while (Found);\r
 \r
+  FreePool (SmramRanges);\r
   DEBUG ((EFI_D_INFO, "SMRR Base: 0x%x, SMRR Size: 0x%x\n", *SmrrBase, *SmrrSize));\r
 }\r
 \r
@@ -1165,6 +1187,109 @@ AllocatePageTableMemory (
   return AllocatePages (Pages);\r
 }\r
 \r
+/**\r
+  Allocate pages for code.\r
+\r
+  @param[in]  Pages Number of pages to be allocated.\r
+\r
+  @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateCodePages (\r
+  IN UINTN           Pages\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  Memory;\r
+\r
+  if (Pages == 0) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  return (VOID *) (UINTN) Memory;\r
+}\r
+\r
+/**\r
+  Allocate aligned pages for code.\r
+\r
+  @param[in]  Pages                 Number of pages to be allocated.\r
+  @param[in]  Alignment             The requested alignment of the allocation.\r
+                                    Must be a power of two.\r
+                                    If Alignment is zero, then byte alignment is used.\r
+\r
+  @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateAlignedCodePages (\r
+  IN UINTN            Pages,\r
+  IN UINTN            Alignment\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  Memory;\r
+  UINTN                 AlignedMemory;\r
+  UINTN                 AlignmentMask;\r
+  UINTN                 UnalignedPages;\r
+  UINTN                 RealPages;\r
+\r
+  //\r
+  // Alignment must be a power of two or zero.\r
+  //\r
+  ASSERT ((Alignment & (Alignment - 1)) == 0);\r
+\r
+  if (Pages == 0) {\r
+    return NULL;\r
+  }\r
+  if (Alignment > EFI_PAGE_SIZE) {\r
+    //\r
+    // Calculate the total number of pages since alignment is larger than page size.\r
+    //\r
+    AlignmentMask  = Alignment - 1;\r
+    RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
+    //\r
+    // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
+    //\r
+    ASSERT (RealPages > Pages);\r
+\r
+    Status         = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, RealPages, &Memory);\r
+    if (EFI_ERROR (Status)) {\r
+      return NULL;\r
+    }\r
+    AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
+    UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free first unaligned page(s).\r
+      //\r
+      Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    Memory         = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
+    UnalignedPages = RealPages - Pages - UnalignedPages;\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free last unaligned page(s).\r
+      //\r
+      Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  } else {\r
+    //\r
+    // Do not over-allocate pages in this case.\r
+    //\r
+    Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+    if (EFI_ERROR (Status)) {\r
+      return NULL;\r
+    }\r
+    AlignedMemory  = (UINTN) Memory;\r
+  }\r
+  return (VOID *) AlignedMemory;\r
+}\r
+\r
 /**\r
   Perform the remaining tasks.\r
 \r
@@ -1185,6 +1310,22 @@ PerformRemainingTasks (
     // Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable.\r
     //\r
     InitPaging ();\r
+\r
+    //\r
+    // Mark critical region to be read-only in page table\r
+    //\r
+    SetMemMapAttributes ();\r
+\r
+    //\r
+    // For outside SMRAM, we only map SMM communication buffer or MMIO.\r
+    //\r
+    SetUefiMemMapAttributes ();\r
+\r
+    //\r
+    // Set page table itself to be read-only\r
+    //\r
+    SetPageTableAttributes ();\r
+\r
     //\r
     // Configure SMM Code Access Check feature if available.\r
     //\r