2 Page table manipulation functions for IA-32 processors
4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "PiSmmCpuDxeSmm.h"
14 Create PageTable for SMM use.
16 @return PageTable Address
24 UINTN PageFaultHandlerHookAddress
;
25 IA32_IDT_GATE_DESCRIPTOR
*IdtEntry
;
29 // Initialize spin lock
31 InitializeSpinLock (mPFLock
);
33 mPhysicalAddressBits
= 32;
35 if (FeaturePcdGet (PcdCpuSmmProfileEnable
) ||
36 HEAP_GUARD_NONSTOP_MODE
||
37 NULL_DETECTION_NONSTOP_MODE
)
40 // Set own Page Fault entry instead of the default one, because SMM Profile
41 // feature depends on IRET instruction to do Single Step
43 PageFaultHandlerHookAddress
= (UINTN
)PageFaultIdtHandlerSmmProfile
;
44 IdtEntry
= (IA32_IDT_GATE_DESCRIPTOR
*)gcSmiIdtr
.Base
;
45 IdtEntry
+= EXCEPT_IA32_PAGE_FAULT
;
46 IdtEntry
->Bits
.OffsetLow
= (UINT16
)PageFaultHandlerHookAddress
;
47 IdtEntry
->Bits
.Reserved_0
= 0;
48 IdtEntry
->Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
49 IdtEntry
->Bits
.OffsetHigh
= (UINT16
)(PageFaultHandlerHookAddress
>> 16);
52 // Register SMM Page Fault Handler
54 Status
= SmmRegisterExceptionHandler (&mSmmCpuService
, EXCEPT_IA32_PAGE_FAULT
, SmiPFHandler
);
55 ASSERT_EFI_ERROR (Status
);
59 // Additional SMM IDT initialization for SMM stack guard
61 if (FeaturePcdGet (PcdCpuSmmStackGuard
)) {
62 InitializeIDTSmmStackGuard ();
65 return Gen4GPageTable (TRUE
);
69 Page Fault handler for SMM use.
81 ThePage Fault handler wrapper for SMM use.
83 @param InterruptType Defines the type of interrupt or exception that
84 occurred on the processor.This parameter is processor architecture specific.
85 @param SystemContext A pointer to the processor context when
86 the interrupt occurred on the processor.
91 IN EFI_EXCEPTION_TYPE InterruptType
,
92 IN EFI_SYSTEM_CONTEXT SystemContext
96 UINTN GuardPageAddress
;
99 ASSERT (InterruptType
== EXCEPT_IA32_PAGE_FAULT
);
101 AcquireSpinLock (mPFLock
);
103 PFAddress
= AsmReadCr2 ();
106 // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page,
107 // or SMM page protection violation.
109 if ((PFAddress
>= mCpuHotPlugData
.SmrrBase
) &&
110 (PFAddress
< (mCpuHotPlugData
.SmrrBase
+ mCpuHotPlugData
.SmrrSize
)))
112 DumpCpuContext (InterruptType
, SystemContext
);
113 CpuIndex
= GetCpuIndex ();
114 GuardPageAddress
= (mSmmStackArrayBase
+ EFI_PAGE_SIZE
+ CpuIndex
* mSmmStackSize
);
115 if ((FeaturePcdGet (PcdCpuSmmStackGuard
)) &&
116 (PFAddress
>= GuardPageAddress
) &&
117 (PFAddress
< (GuardPageAddress
+ EFI_PAGE_SIZE
)))
119 DEBUG ((DEBUG_ERROR
, "SMM stack overflow!\n"));
121 if ((SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0) {
122 DEBUG ((DEBUG_ERROR
, "SMM exception at execution (0x%x)\n", PFAddress
));
124 DumpModuleInfoByIp (*(UINTN
*)(UINTN
)SystemContext
.SystemContextIa32
->Esp
);
127 DEBUG ((DEBUG_ERROR
, "SMM exception at access (0x%x)\n", PFAddress
));
129 DumpModuleInfoByIp ((UINTN
)SystemContext
.SystemContextIa32
->Eip
);
133 if (HEAP_GUARD_NONSTOP_MODE
) {
134 GuardPagePFHandler (SystemContext
.SystemContextIa32
->ExceptionData
);
144 // If a page fault occurs in non-SMRAM range.
146 if ((PFAddress
< mCpuHotPlugData
.SmrrBase
) ||
147 (PFAddress
>= mCpuHotPlugData
.SmrrBase
+ mCpuHotPlugData
.SmrrSize
))
149 if ((SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0) {
150 DumpCpuContext (InterruptType
, SystemContext
);
151 DEBUG ((DEBUG_ERROR
, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress
));
153 DumpModuleInfoByIp (*(UINTN
*)(UINTN
)SystemContext
.SystemContextIa32
->Esp
);
160 // If NULL pointer was just accessed
162 if (((PcdGet8 (PcdNullPointerDetectionPropertyMask
) & BIT1
) != 0) &&
163 (PFAddress
< EFI_PAGE_SIZE
))
165 DumpCpuContext (InterruptType
, SystemContext
);
166 DEBUG ((DEBUG_ERROR
, "!!! NULL pointer access !!!\n"));
168 DumpModuleInfoByIp ((UINTN
)SystemContext
.SystemContextIa32
->Eip
);
171 if (NULL_DETECTION_NONSTOP_MODE
) {
172 GuardPagePFHandler (SystemContext
.SystemContextIa32
->ExceptionData
);
180 if (IsSmmCommBufferForbiddenAddress (PFAddress
)) {
181 DumpCpuContext (InterruptType
, SystemContext
);
182 DEBUG ((DEBUG_ERROR
, "Access SMM communication forbidden address (0x%x)!\n", PFAddress
));
184 DumpModuleInfoByIp ((UINTN
)SystemContext
.SystemContextIa32
->Eip
);
191 if (FeaturePcdGet (PcdCpuSmmProfileEnable
)) {
192 SmmProfilePFHandler (
193 SystemContext
.SystemContextIa32
->Eip
,
194 SystemContext
.SystemContextIa32
->ExceptionData
197 DumpCpuContext (InterruptType
, SystemContext
);
198 SmiDefaultPFHandler ();
202 ReleaseSpinLock (mPFLock
);
206 This function returns with no action for 32 bit.
208 @param[out] *Cr2 Pointer to variable to hold CR2 register value.
219 This function returns with no action for 32 bit.
221 @param[in] Cr2 Value to write into CR2 register.
232 Return whether access to non-SMRAM is restricted.
234 @retval TRUE Access to non-SMRAM is restricted.
235 @retval FALSE Access to non-SMRAM is not restricted.
238 IsRestrictedMemoryAccess (