]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
UefiCpuPkg/PiSmmCpuDxeSmm: Add paging protection.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / PageTbl.c
index a871bef4e28f9c32202a32d5ea1e675cc08a6984..65f09e562228542063afdde8bc44171f12e45782 100644 (file)
@@ -58,7 +58,7 @@ SmmInitPageTable (
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
     InitializeIDTSmmStackGuard ();\r
   }\r
-  return Gen4GPageTable (0, TRUE);\r
+  return Gen4GPageTable (TRUE);\r
 }\r
 \r
 /**\r
@@ -99,7 +99,7 @@ SmiPFHandler (
   if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&\r
       (PFAddress >= mCpuHotPlugData.SmrrBase) &&\r
       (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {\r
-    DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));\r
+    DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n"));\r
     CpuDeadLoop ();\r
   }\r
 \r
@@ -109,7 +109,7 @@ SmiPFHandler (
   if ((PFAddress < mCpuHotPlugData.SmrrBase) ||\r
       (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
     if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {\r
-      DEBUG ((EFI_D_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));\r
+      DEBUG ((DEBUG_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));\r
       DEBUG_CODE (\r
         DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);\r
       );\r
@@ -128,3 +128,68 @@ SmiPFHandler (
 \r
   ReleaseSpinLock (mPFLock);\r
 }\r
+\r
+/**\r
+  This function sets memory attribute for page table.\r
+**/\r
+VOID\r
+SetPageTableAttributes (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                 Index2;\r
+  UINTN                 Index3;\r
+  UINT64                *L1PageTable;\r
+  UINT64                *L2PageTable;\r
+  UINT64                *L3PageTable;\r
+  BOOLEAN               IsSplitted;\r
+  BOOLEAN               PageTableSplitted;\r
+\r
+  DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));\r
+\r
+  //\r
+  // Disable write protection, because we need mark page table to be write protected.\r
+  // We need *write* page table memory, to mark itself to be *read only*.\r
+  //\r
+  AsmWriteCr0 (AsmReadCr0() & ~CR0_WP);\r
+\r
+  do {\r
+    DEBUG ((DEBUG_INFO, "Start...\n"));\r
+    PageTableSplitted = FALSE;\r
+\r
+    L3PageTable = (UINT64 *)GetPageTableBase ();\r
+\r
+    SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
+    PageTableSplitted = (PageTableSplitted || IsSplitted);\r
+\r
+    for (Index3 = 0; Index3 < 4; Index3++) {\r
+      L2PageTable = (UINT64 *)(UINTN)(L3PageTable[Index3] & PAGING_4K_ADDRESS_MASK_64);\r
+      if (L2PageTable == NULL) {\r
+        continue;\r
+      }\r
+\r
+      SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
+      PageTableSplitted = (PageTableSplitted || IsSplitted);\r
+\r
+      for (Index2 = 0; Index2 < SIZE_4KB/sizeof(UINT64); Index2++) {\r
+        if ((L2PageTable[Index2] & IA32_PG_PS) != 0) {\r
+          // 2M\r
+          continue;\r
+        }\r
+        L1PageTable = (UINT64 *)(UINTN)(L2PageTable[Index2] & PAGING_4K_ADDRESS_MASK_64);\r
+        if (L1PageTable == NULL) {\r
+          continue;\r
+        }\r
+        SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
+        PageTableSplitted = (PageTableSplitted || IsSplitted);\r
+      }\r
+    }\r
+  } while (PageTableSplitted);\r
+\r
+  //\r
+  // Enable write protection, after page table updated.\r
+  //\r
+  AsmWriteCr0 (AsmReadCr0() | CR0_WP);\r
+\r
+  return ;\r
+}\r