VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 17 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 6.2 KB
Line 
1/** @file
2Page table manipulation functions for IA-32 processors
3
4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
5Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
6
7SPDX-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**/
19UINT32
20SmmInitPageTable (
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**/
73VOID
74SmiDefaultPFHandler (
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**/
89VOID
90EFIAPI
91SmiPFHandler (
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
202Exit:
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**/
211VOID
212SaveCr2 (
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**/
224VOID
225RestoreCr2 (
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**/
238BOOLEAN
239IsRestrictedMemoryAccess (
240 VOID
241 )
242{
243 return TRUE;
244}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette