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