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