PageTbl.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /** @file
  2. Page table manipulation functions for IA-32 processors
  3. Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
  4. Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "PiSmmCpuDxeSmm.h"
  8. /**
  9. Create PageTable for SMM use.
  10. @return PageTable Address
  11. **/
  12. UINT32
  13. SmmInitPageTable (
  14. VOID
  15. )
  16. {
  17. UINTN PageFaultHandlerHookAddress;
  18. IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
  19. EFI_STATUS Status;
  20. //
  21. // Initialize spin lock
  22. //
  23. InitializeSpinLock (mPFLock);
  24. mPhysicalAddressBits = 32;
  25. if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||
  26. HEAP_GUARD_NONSTOP_MODE ||
  27. NULL_DETECTION_NONSTOP_MODE)
  28. {
  29. //
  30. // Set own Page Fault entry instead of the default one, because SMM Profile
  31. // feature depends on IRET instruction to do Single Step
  32. //
  33. PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
  34. IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)gcSmiIdtr.Base;
  35. IdtEntry += EXCEPT_IA32_PAGE_FAULT;
  36. IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
  37. IdtEntry->Bits.Reserved_0 = 0;
  38. IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
  39. IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
  40. } else {
  41. //
  42. // Register SMM Page Fault Handler
  43. //
  44. Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
  45. ASSERT_EFI_ERROR (Status);
  46. }
  47. //
  48. // Additional SMM IDT initialization for SMM stack guard
  49. //
  50. if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
  51. InitializeIDTSmmStackGuard ();
  52. }
  53. return Gen4GPageTable (TRUE);
  54. }
  55. /**
  56. Page Fault handler for SMM use.
  57. **/
  58. VOID
  59. SmiDefaultPFHandler (
  60. VOID
  61. )
  62. {
  63. CpuDeadLoop ();
  64. }
  65. /**
  66. ThePage Fault handler wrapper for SMM use.
  67. @param InterruptType Defines the type of interrupt or exception that
  68. occurred on the processor.This parameter is processor architecture specific.
  69. @param SystemContext A pointer to the processor context when
  70. the interrupt occurred on the processor.
  71. **/
  72. VOID
  73. EFIAPI
  74. SmiPFHandler (
  75. IN EFI_EXCEPTION_TYPE InterruptType,
  76. IN EFI_SYSTEM_CONTEXT SystemContext
  77. )
  78. {
  79. UINTN PFAddress;
  80. UINTN GuardPageAddress;
  81. UINTN CpuIndex;
  82. ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
  83. AcquireSpinLock (mPFLock);
  84. PFAddress = AsmReadCr2 ();
  85. //
  86. // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page,
  87. // or SMM page protection violation.
  88. //
  89. if ((PFAddress >= mCpuHotPlugData.SmrrBase) &&
  90. (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)))
  91. {
  92. DumpCpuContext (InterruptType, SystemContext);
  93. CpuIndex = GetCpuIndex ();
  94. GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize);
  95. if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
  96. (PFAddress >= GuardPageAddress) &&
  97. (PFAddress < (GuardPageAddress + EFI_PAGE_SIZE)))
  98. {
  99. DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n"));
  100. } else {
  101. if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
  102. DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%x)\n", PFAddress));
  103. DEBUG_CODE (
  104. DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
  105. );
  106. } else {
  107. DEBUG ((DEBUG_ERROR, "SMM exception at access (0x%x)\n", PFAddress));
  108. DEBUG_CODE (
  109. DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
  110. );
  111. }
  112. if (HEAP_GUARD_NONSTOP_MODE) {
  113. GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
  114. goto Exit;
  115. }
  116. }
  117. CpuDeadLoop ();
  118. goto Exit;
  119. }
  120. //
  121. // If a page fault occurs in non-SMRAM range.
  122. //
  123. if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
  124. (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))
  125. {
  126. if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
  127. DumpCpuContext (InterruptType, SystemContext);
  128. DEBUG ((DEBUG_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
  129. DEBUG_CODE (
  130. DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
  131. );
  132. CpuDeadLoop ();
  133. goto Exit;
  134. }
  135. //
  136. // If NULL pointer was just accessed
  137. //
  138. if (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) &&
  139. (PFAddress < EFI_PAGE_SIZE))
  140. {
  141. DumpCpuContext (InterruptType, SystemContext);
  142. DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));
  143. DEBUG_CODE (
  144. DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
  145. );
  146. if (NULL_DETECTION_NONSTOP_MODE) {
  147. GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
  148. goto Exit;
  149. }
  150. CpuDeadLoop ();
  151. goto Exit;
  152. }
  153. if (IsSmmCommBufferForbiddenAddress (PFAddress)) {
  154. DumpCpuContext (InterruptType, SystemContext);
  155. DEBUG ((DEBUG_ERROR, "Access SMM communication forbidden address (0x%x)!\n", PFAddress));
  156. DEBUG_CODE (
  157. DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
  158. );
  159. CpuDeadLoop ();
  160. goto Exit;
  161. }
  162. }
  163. if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
  164. SmmProfilePFHandler (
  165. SystemContext.SystemContextIa32->Eip,
  166. SystemContext.SystemContextIa32->ExceptionData
  167. );
  168. } else {
  169. DumpCpuContext (InterruptType, SystemContext);
  170. SmiDefaultPFHandler ();
  171. }
  172. Exit:
  173. ReleaseSpinLock (mPFLock);
  174. }
  175. /**
  176. This function returns with no action for 32 bit.
  177. @param[out] *Cr2 Pointer to variable to hold CR2 register value.
  178. **/
  179. VOID
  180. SaveCr2 (
  181. OUT UINTN *Cr2
  182. )
  183. {
  184. return;
  185. }
  186. /**
  187. This function returns with no action for 32 bit.
  188. @param[in] Cr2 Value to write into CR2 register.
  189. **/
  190. VOID
  191. RestoreCr2 (
  192. IN UINTN Cr2
  193. )
  194. {
  195. return;
  196. }
  197. /**
  198. Return whether access to non-SMRAM is restricted.
  199. @retval TRUE Access to non-SMRAM is restricted.
  200. @retval FALSE Access to non-SMRAM is not restricted.
  201. **/
  202. BOOLEAN
  203. IsRestrictedMemoryAccess (
  204. VOID
  205. )
  206. {
  207. return TRUE;
  208. }