Bug Summary

File:home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime/SmmEptHandler.c
Warning:line 150, column 7
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SmmEptHandler.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-jump-tables -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/build/StmPkg/Core -resource-dir /opt/xgcc/lib/clang/17 -include PcdData.h -D COREBOOT32 -D RELEASE -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/EDKII/BaseTools/Source/C/Include/X64 -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/EdkII/MdePkg/Include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/EdkII/MdePkg/Include/X64 -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Include/x64 -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime -I /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Init -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1715206807 -Os -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/build/StmPkg/Core -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-max-loop 10 -analyzer-output=plist-html -faddrsig -o /cb-build/coreboot_scanbuild.0/PURISM_LIBREM15_V4_STM-scanbuildtmp/2024-05-09-081252-3833419-1/report-vouhbB.plist -x c /home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime/SmmEptHandler.c
1/** @file
2 SMM EPT handler
3
4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15#include "StmRuntime.h"
16#include "PeStm.h"
17
18#define BUS_FROM_PCIE_ADDRESS(PcieAddress)(UINT8)(((UINTN)(PcieAddress) & 0x0FF00000) >> 20) (UINT8)(((UINTN)(PcieAddress) & 0x0FF00000) >> 20)
19#define DEVICE_FROM_PCIE_ADDRESS(PcieAddress)(UINT8)(((UINTN)(PcieAddress) & 0x000F8000) >> 15) (UINT8)(((UINTN)(PcieAddress) & 0x000F8000) >> 15)
20#define FUNCTION_FROM_PCIE_ADDRESS(PcieAddress)(UINT8)(((UINTN)(PcieAddress) & 0x00007000) >> 12) (UINT8)(((UINTN)(PcieAddress) & 0x00007000) >> 12)
21#define REGISTER_FROM_PCIE_ADDRESS(PcieAddress)(UINT16)((UINTN)(PcieAddress) & 0x00000FFF) (UINT16)((UINTN)(PcieAddress) & 0x00000FFF)
22
23#define PAGE_PROGATE_BITS(0x00000001 | 0x00000002 | 0x00000004 | 0x00000008 | 0x00000010
| 0x00000020)
(BIT00x00000001 | BIT10x00000002 | BIT20x00000004 | BIT30x00000008 | BIT40x00000010 | BIT50x00000020)
24
25#define PAGING_4K_MASK0xFFF 0xFFF
26#define PAGING_2M_MASK0x1FFFFF 0x1FFFFF
27#define PAGING_1G_MASK0x3FFFFFFF 0x3FFFFFFF
28
29#define PAGING_PAE_INDEX_MASK0x1FF 0x1FF
30
31#define PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull 0x000FFFFFFFFFF000ull
32#define PAGING_2M_ADDRESS_MASK_640x000FFFFFFFE00000ull 0x000FFFFFFFE00000ull
33#define PAGING_1G_ADDRESS_MASK_640x000FFFFFC0000000ull 0x000FFFFFC0000000ull
34
35typedef enum {
36 PageNone,
37 Page4K,
38 Page2M,
39 Page1G,
40} PAGE_ATTRIBUTE;
41
42typedef struct {
43 PAGE_ATTRIBUTE Attribute;
44 UINT64 Length;
45 UINT64 AddressMask;
46} PAGE_ATTRIBUTE_TABLE;
47
48PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
49 {Page4K, SIZE_4KB0x00001000, PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull},
50 {Page2M, SIZE_2MB0x00200000, PAGING_2M_ADDRESS_MASK_640x000FFFFFFFE00000ull},
51 {Page1G, SIZE_1GB0x40000000, PAGING_1G_ADDRESS_MASK_640x000FFFFFC0000000ull},
52};
53
54extern UINT64
55EptAllocatePte(
56 IN UINT64 EptPointer,
57 IN UINT64 BaseAddress,
58 IN UINT64 Length,
59 IN UINT64 PhySize
60 );
61
62extern UINT8 GetMemoryType (IN UINT64 BaseAddress);
63
64/**
65 Return length according to page attributes.
66
67 @param[in] PageAttributes The page attribute of the page entry.
68
69 @return The length of page entry.
70**/
71UINTN
72PageAttributeToLength (
73 IN PAGE_ATTRIBUTE PageAttribute
74 )
75{
76 UINTN Index;
77 for (Index = 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttributeTable[0]); Index++) {
78 if (PageAttribute == mPageAttributeTable[Index].Attribute) {
79 return (UINTN)mPageAttributeTable[Index].Length;
80 }
81 }
82 return 0;
83}
84
85/**
86 Return address mask according to page attributes.
87
88 @param[in] PageAttributes The page attribute of the page entry.
89
90 @return The address mask of page entry.
91**/
92UINTN
93PageAttributeToMask (
94 IN PAGE_ATTRIBUTE PageAttribute
95 )
96{
97 UINTN Index;
98 for (Index = 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttributeTable[0]); Index++) {
99 if (PageAttribute == mPageAttributeTable[Index].Attribute) {
100 return (UINTN)mPageAttributeTable[Index].AddressMask;
101 }
102 }
103 return 0;
104}
105
106/**
107 Return page table entry to match the address.
108
109 @param[in] Address The address to be checked.
110 @param[out] PageAttributes The page attribute of the page entry.
111
112 @return The page entry.
113**/
114EPT_ENTRY *
115GetPageTableEntry (
116 IN UINT64 EptPointer,
117 IN PHYSICAL_ADDRESS Address,
118 IN PHYSICAL_ADDRESS PhyAddress,
119 IN UINT64 PhySize,
120 OUT PAGE_ATTRIBUTE *PageAttribute
121 )
122{
123 UINTN Index1;
124 UINTN Index2;
125 UINTN Index3;
126 UINTN Index4;
127 EPT_ENTRY *L1PageTable;
128 EPT_ENTRY *L2PageTable;
129 EPT_ENTRY *L3PageTable;
130 EPT_ENTRY *L4PageTable;
131
132 //DEBUG ((EFI_D_INFO, "GetPageTableEntry: Address(guest) %llx Address(Physical) %llx Size %llx\n", (UINTN)Address, (UINTN) PhyAddress, (UINTN) PhySize));
133
134 Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK0x1FF;
135 Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK0x1FF;
136 Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK0x1FF;
137 Index1 = ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK0x1FF;
138 //DEBUG ((EFI_D_INFO, "Index: %x %x %x %x\n", Index4, Index3, Index2, Index1));
139
140 L4PageTable = (EPT_ENTRY *)(UINTN) EptPointer; //(mGuestContextCommonSmm.EptPointer.Uint64 & PAGING_4K_ADDRESS_MASK_64);
141 if (L4PageTable[Index4].Uint64 == 0) {
33
Assuming field 'Uint64' is equal to 0
34
Taking true branch
142 if(EptAllocatePte(EptPointer, Address, PhyAddress, PhySize) == 0)
35
Assuming the condition is false
36
Taking false branch
143 {
144 *PageAttribute = PageNone;
145 return NULL((void *) 0);
146 }
147 }
148
149 L3PageTable = (EPT_ENTRY *)(UINTN)(L4PageTable[Index4].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
37
Null pointer value stored to 'L3PageTable'
150 if (L3PageTable[Index3].Uint64 == 0) {
38
Dereference of null pointer
151 if(EptAllocatePte(EptPointer, Address, PhyAddress, PhySize) == 0)
152 {
153 *PageAttribute = PageNone;
154 return NULL((void *) 0);
155 }
156 }
157 if (L3PageTable[Index3].Bits32.Sp != 0) {
158 // 1G
159 *PageAttribute = Page1G;
160 return &L3PageTable[Index3];
161 }
162
163 L2PageTable = (EPT_ENTRY *)(UINTN)(L3PageTable[Index3].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
164 if (L2PageTable[Index2].Uint64 == 0) {
165 if(EptAllocatePte(EptPointer, Address, PhyAddress, PhySize) == 0)
166 {
167 *PageAttribute = PageNone;
168 return NULL((void *) 0);
169 }
170 }
171 if (L2PageTable[Index2].Bits32.Sp != 0) {
172 // 2M
173 *PageAttribute = Page2M;
174 return &L2PageTable[Index2];
175 }
176
177 // Special case where there exists a L1 Page Table and the caller wants the range to be 2M
178 // If the stars line up (both Address and PhyAddress are on 2MB boundries), then
179 // free the L1 Page table and replace it with a super page
180
181 if ((Address >= BASE_2MB0x00200000) &&
182 ((Address & PAGING_2M_MASK0x1FFFFF) == 0) &&
183 ((PhyAddress & PAGING_2M_MASK0x1FFFFF) == 0) &&
184 (PhySize > PAGING_2M_MASK0x1FFFFF))
185 {
186 //DEBUG((EFI_D_INFO, "GetPageTableEntry: replacing L1PageTable: 0x%llx with superpage\n", L2PageTable[Index2].Uint64));
187 FreePages((UINT64 *)((UINTN)(L2PageTable[Index2].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull)), 1); // free up the L2
188
189 L2PageTable[Index2].Uint64 = 0;
190 if(EptAllocatePte(EptPointer, Address, PhyAddress, PhySize) == 0)
191 {
192 *PageAttribute = PageNone;
193 return NULL((void *) 0);
194 }
195 *PageAttribute = Page2M;
196 return &L2PageTable[Index2];
197 }
198
199 // 4k
200 L1PageTable = (EPT_ENTRY *)(UINTN)(L2PageTable[Index2].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
201 if ((L1PageTable[Index1].Uint64 == 0) && (Address != 0)) {
202 if(EptAllocatePte(EptPointer, Address, PhyAddress, PhySize) == 0){
203 *PageAttribute = PageNone;
204 return NULL((void *) 0);
205 }
206 }
207 *PageAttribute = Page4K;
208 return &L1PageTable[Index1];
209}
210
211/**
212 Modify memory attributes of page entry.
213
214 @param[in] PageEntry The page entry.
215 @param[in] Attributes The bit mask of attributes to modify for the memory region.
216 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
217 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
218**/
219VOIDvoid
220ConvertPageEntryAttribute (
221 IN EPT_ENTRY *PageEntry,
222 IN UINT32 Ra,
223 IN UINT32 Wa,
224 IN UINT32 Xa,
225 IN EPT_PAGE_ATTRIBUTE_SETTING EptPageAttributeSetting,
226 IN UINT32 EMT
227 )
228{
229 UINT64 CurrentPageEntry;
230
231 CurrentPageEntry = PageEntry->Uint64;
232 switch (EptPageAttributeSetting) {
233 case EptPageAttributeSet:
234 PageEntry->Bits32.Ra = (UINT32)Ra;
235 PageEntry->Bits32.Wa = (UINT32)Wa;
236 PageEntry->Bits32.Xa = (UINT32)Xa;
237 break;
238 case EptPageAttributeAnd:
239 PageEntry->Bits32.Ra &= (UINT32)Ra;
240 PageEntry->Bits32.Wa &= (UINT32)Wa;
241 PageEntry->Bits32.Xa &= (UINT32)Xa;
242 break;
243 case EptPageAttributeOr:
244 PageEntry->Bits32.Ra |= (UINT32)Ra;
245 PageEntry->Bits32.Wa |= (UINT32)Wa;
246 PageEntry->Bits32.Xa |= (UINT32)Xa;
247 break;
248 default:
249 CpuDeadLoop ();
250 break;
251 }
252
253 if(PageEntry->Bits32.Wa == 1)
254 PageEntry->Bits.Ra = 1; // have to have read with write(vol 3c 28.2.3.1)
255 if(PageEntry->Bits32.Xa == 1)
256 PageEntry->Bits32.Ra = 1; //have to have read with execute (except for some processors)
257
258 if(EMT == -1)
259 PageEntry->Bits32.Emt = GetMemoryType((PageEntry->Uint64) & PAGING_4K_MASK0xFFF );
260 else
261 PageEntry->Bits32.Emt = EMT; // let caller set the memory type (at his own risk)
262
263#ifdef DEBUGPRINT
264 DEBUG((EFI_D_INFO, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n",do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
265 (UINT64) CurrentPageEntry,do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
266 PageEntry->Uint64,do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
267 PageEntry->Bits32.Ra,do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
268 PageEntry->Bits32.Wa,do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
269 PageEntry->Bits32.Xa,do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
270 PageEntry->Bits32.Emt))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "ConvertPageEntryAttribute - 0x%llx->0x%llx (%1x%1x%1x) Emt: %3x\n"
, (UINT64) CurrentPageEntry, PageEntry->Uint64, PageEntry->
Bits32.Ra, PageEntry->Bits32.Wa, PageEntry->Bits32.Xa, PageEntry
->Bits32.Emt); } } while (((BOOLEAN)(0==1)))
;
271#endif
272 if (CurrentPageEntry != PageEntry->Uint64) {
273 //DEBUG ((EFI_D_INFO, "ConvertPageEntryAttribute 0x%lx->0x%lx\n", CurrentPageEntry, PageEntry->Uint64));
274 }
275}
276
277/**
278 This function returns if there is need to split page entry.
279
280 @param[in] BaseAddress The base address to be checked.
281 @param[in] Length The length to be checked.
282 @param[in] PageAttribute The page attribute of the page entry.
283
284 @retval SplitAttributes on if there is need to split page entry.
285**/
286PAGE_ATTRIBUTE
287NeedSplitPage (
288 IN PHYSICAL_ADDRESS BaseAddress,
289 IN UINT64 Length,
290 IN PAGE_ATTRIBUTE PageAttribute
291 )
292{
293 UINT64 PageEntryLength;
294
295 PageEntryLength = PageAttributeToLength (PageAttribute);
296
297 if (((BaseAddress & (PageEntryLength - 1)) == 0) && (Length >= PageEntryLength)) {
298 return PageNone;
299 }
300
301 if (((BaseAddress & PAGING_2M_MASK0x1FFFFF) != 0) || (Length < SIZE_2MB0x00200000)) {
302 return Page4K;
303 }
304
305 return Page2M;
306}
307
308/**
309 This function splits one page entry to small page entries.
310
311 @param[in] PageEntry The page entry to be splitted.
312 @param[in] PageAttribute The page attribute of the page entry.
313 @param[in] SplitAttribute How to split the page entry.
314
315 @retval RETURN_SUCCESS The page entry is splitted.
316 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.
317 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.
318**/
319RETURN_STATUS
320SplitPage (
321 IN EPT_ENTRY *PageEntry,
322 IN PAGE_ATTRIBUTE PageAttribute,
323 IN PAGE_ATTRIBUTE SplitAttribute
324 )
325{
326 UINT64 BaseAddress;
327 EPT_ENTRY *NewPageEntry;
328 UINTN Index;
329
330 ASSERT (PageAttribute == Page2M || PageAttribute == Page1G)do { if (DebugAssertEnabled ()) { if (!(PageAttribute == Page2M
|| PageAttribute == Page1G)) { DebugAssert ("/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime/SmmEptHandler.c"
, 330, "PageAttribute == Page2M || PageAttribute == Page1G");
} } } while (((BOOLEAN)(0==1)))
;
331
332 if (PageAttribute == Page2M) {
333 //
334 // Split 2M to 4K
335 //
336 ASSERT (SplitAttribute == Page4K)do { if (DebugAssertEnabled ()) { if (!(SplitAttribute == Page4K
)) { DebugAssert ("/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime/SmmEptHandler.c"
, 336, "SplitAttribute == Page4K"); } } } while (((BOOLEAN)(0
==1)))
;
337 if (SplitAttribute == Page4K) {
338 NewPageEntry = (EPT_ENTRY *)AllocatePages (1);
339 //DEBUG ((EFI_D_INFO, "Split - 0x%x\n", NewPageEntry));
340 if (NewPageEntry == NULL((void *) 0)) {
341 return RETURN_OUT_OF_RESOURCES((RETURN_STATUS)(0x8000000000000000ULL | (9)));
342 }
343 BaseAddress = PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_640x000FFFFFFFE00000ull;
344 for (Index = 0; Index < SIZE_4KB0x00001000 / sizeof(UINT64); Index++) {
345 NewPageEntry[Index].Uint64 = BaseAddress + SIZE_4KB0x00001000 * Index + (PageEntry->Uint64 & PAGE_PROGATE_BITS(0x00000001 | 0x00000002 | 0x00000004 | 0x00000008 | 0x00000010
| 0x00000020)
);
346 }
347 PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;
348 PageEntry->Bits32.Ra = 1;
349 PageEntry->Bits32.Wa = 1;
350 PageEntry->Bits32.Xa = 1;
351 return RETURN_SUCCESS0;
352 } else {
353 return RETURN_UNSUPPORTED((RETURN_STATUS)(0x8000000000000000ULL | (3)));
354 }
355 } else if (PageAttribute == Page1G) {
356 //
357 // Split 1G to 2M
358 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
359 //
360 ASSERT (SplitAttribute == Page2M || SplitAttribute == Page4K)do { if (DebugAssertEnabled ()) { if (!(SplitAttribute == Page2M
|| SplitAttribute == Page4K)) { DebugAssert ("/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/stm/Stm/StmPkg/Core/Runtime/SmmEptHandler.c"
, 360, "SplitAttribute == Page2M || SplitAttribute == Page4K"
); } } } while (((BOOLEAN)(0==1)))
;
361 if ((SplitAttribute == Page2M || SplitAttribute == Page4K)) {
362 NewPageEntry = (EPT_ENTRY *)AllocatePages (1);
363 DEBUG ((EFI_D_INFO, "Split - 0x%x\n", NewPageEntry))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "Split - 0x%x\n"
, NewPageEntry); } } while (((BOOLEAN)(0==1)))
;
364 if (NewPageEntry == NULL((void *) 0)) {
365 return RETURN_OUT_OF_RESOURCES((RETURN_STATUS)(0x8000000000000000ULL | (9)));
366 }
367 BaseAddress = PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_640x000FFFFFC0000000ull;
368 for (Index = 0; Index < SIZE_4KB0x00001000 / sizeof(UINT64); Index++) {
369 NewPageEntry[Index].Uint64 = BaseAddress + SIZE_2MB0x00200000 * Index + (PageEntry->Uint64 & PAGE_PROGATE_BITS(0x00000001 | 0x00000002 | 0x00000004 | 0x00000008 | 0x00000010
| 0x00000020)
);
370 NewPageEntry[Index].Bits32.Sp = 1;
371 }
372 PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;
373 PageEntry->Bits32.Ra = 1;
374 PageEntry->Bits32.Wa = 1;
375 PageEntry->Bits32.Xa = 1;
376 return RETURN_SUCCESS0;
377 } else {
378 return RETURN_UNSUPPORTED((RETURN_STATUS)(0x8000000000000000ULL | (3)));
379 }
380 } else {
381 return RETURN_UNSUPPORTED((RETURN_STATUS)(0x8000000000000000ULL | (3)));
382 }
383}
384
385/**
386
387 This function translate guest physical address to host address.
388
389 @param Addr Guest physical address
390 @param EntryPtr EPT entry pointer
391 NULL on output means Entry not found.
392
393 @return Host physical address
394**/
395UINTN
396TranslateEPTGuestToHost (
397 IN UINT64 EptPointer,
398 IN UINTN Addr,
399 OUT EPT_ENTRY **EntryPtr OPTIONAL
400 );
401
402/**
403
404 This function translate guest physical address to host address.
405
406 @param EptPointer EPT pointer
407 @param GuestPhysicalAddress Guest physical address
408 @param HostPhysicalAddress Host physical address
409
410 @retval TRUE HostPhysicalAddress is found
411 @retval FALSE HostPhysicalAddress is not found
412 **/
413BOOLEAN
414LookupSmiGuestPhysicalToHostPhysical (
415 IN UINT64 EptPointer,
416 IN UINTN GuestPhysicalAddress,
417 OUT UINTN *HostPhysicalAddress
418 )
419{
420 EPT_ENTRY *EptEntry;
421
422 EptEntry = NULL((void *) 0);
423 *HostPhysicalAddress = TranslateEPTGuestToHost (EptPointer, GuestPhysicalAddress, &EptEntry);
424 if (EptEntry == NULL((void *) 0)) {
425 return FALSE((BOOLEAN)(0==1));
426 } else {
427 return TRUE((BOOLEAN)(1==1));
428 }
429}
430
431/**
432
433 This function translate guest linear address to host address.
434
435 @param CpuIndex CPU index
436 @param GuestLinearAddress Guest linear address
437
438 @return Host physical address
439 **/
440UINTN
441GuestLinearToHostPhysical (
442 IN UINT32 CpuIndex,
443 IN UINTN GuestLinearAddress
444 )
445{
446 UINTN GuestPhysicalAddress;
447 UINT32 VmType = mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType;
448
449 GuestPhysicalAddress = (UINTN)GuestLinearToGuestPhysical (CpuIndex, GuestLinearAddress);
450 return TranslateEPTGuestToHost (mGuestContextCommonSmm[VmType].EptPointer.Uint64, GuestPhysicalAddress, NULL((void *) 0));
451}
452
453/**
454
455 This function translate guest physical address to host address.
456
457 @param EptPointer EPT pointer
458 @param Addr Guest physical address
459 @param EntryPtr EPT entry pointer.
460 NULL on output means Entry not found.
461
462 @return Host physical address
463 **/
464UINTN
465TranslateEPTGuestToHost (
466 IN UINT64 EptPointer,
467 IN UINTN Addr,
468 OUT EPT_ENTRY **EntryPtr OPTIONAL
469 )
470{
471 EPT_ENTRY *L1PageTable;
472 EPT_ENTRY *L2PageTable;
473 EPT_ENTRY *L3PageTable;
474 EPT_ENTRY *L4PageTable;
475 UINTN Index1;
476 UINTN Index2;
477 UINTN Index3;
478 UINTN Index4;
479 UINTN Offset;
480
481 Index4 = ((UINTN)RShiftU64 (Addr, 39)) & 0x1ff;
482 Index3 = ((UINTN)Addr >> 30) & 0x1ff;
483 Index2 = ((UINTN)Addr >> 21) & 0x1ff;
484 Index1 = ((UINTN)Addr >> 12) & 0x1ff;
485 Offset = ((UINTN)Addr & 0xFFF);
486
487 if (EntryPtr != NULL((void *) 0)) {
488 *EntryPtr = NULL((void *) 0);
489 }
490 L4PageTable = (EPT_ENTRY *)(UINTN)((UINTN)EptPointer & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
491 if ((L4PageTable[Index4].Bits32.Ra == 0) &&
492 (L4PageTable[Index4].Bits32.Wa == 0) &&
493 (L4PageTable[Index4].Bits32.Xa == 0)) {
494 if (EntryPtr != NULL((void *) 0)) {
495 *EntryPtr = &L4PageTable[Index4];
496 }
497 return 0;
498 }
499 L3PageTable = (EPT_ENTRY *)(UINTN)((UINTN)L4PageTable[Index4].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
500 if ((L3PageTable[Index3].Bits32.Ra == 0) &&
501 (L3PageTable[Index3].Bits32.Wa == 0) &&
502 (L3PageTable[Index3].Bits32.Xa == 0)) {
503 if (EntryPtr != NULL((void *) 0)) {
504 *EntryPtr = &L3PageTable[Index3];
505 }
506 return 0;
507 }
508 if (L3PageTable[Index2].Bits32.Sp == 1) {
509 if (EntryPtr != NULL((void *) 0)) {
510 *EntryPtr = &L3PageTable[Index3];
511 }
512 return ((UINTN)L3PageTable[Index3].Uint64 & PAGING_1G_ADDRESS_MASK_640x000FFFFFC0000000ull) + ((UINTN)Addr & PAGING_1G_MASK0x3FFFFFFF);
513 }
514
515 L2PageTable = (EPT_ENTRY *)(UINTN)((UINTN)L3PageTable[Index3].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
516 if ((L2PageTable[Index2].Bits32.Ra == 0) &&
517 (L2PageTable[Index2].Bits32.Wa == 0) &&
518 (L2PageTable[Index2].Bits32.Xa == 0)) {
519 if (EntryPtr != NULL((void *) 0)) {
520 *EntryPtr = &L2PageTable[Index2];
521 }
522 return 0;
523 }
524
525 if (L2PageTable[Index2].Bits32.Sp == 1) {
526 if (EntryPtr != NULL((void *) 0)) {
527 *EntryPtr = &L2PageTable[Index2];
528 }
529 return ((UINTN)L2PageTable[Index2].Uint64 & PAGING_2M_ADDRESS_MASK_640x000FFFFFFFE00000ull) + ((UINTN)Addr & PAGING_2M_MASK0x1FFFFF);
530 }
531
532 L1PageTable = (EPT_ENTRY *)(UINTN)((UINTN)L2PageTable[Index2].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull);
533 if ((L1PageTable[Index1].Bits32.Ra == 0) &&
534 (L1PageTable[Index1].Bits32.Wa == 0) &&
535 (L1PageTable[Index1].Bits32.Xa == 0)) {
536 // not check last one, since user may update it
537 // return 0;
538 }
539
540 if (EntryPtr != NULL((void *) 0)) {
541 *EntryPtr = &L1PageTable[Index1];
542 }
543 return ((UINTN)L1PageTable[Index1].Uint64 & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull) + Offset;
544}
545
546/**
547
548 This function set EPT page table attribute by range.
549
550 @param Base Memory base
551 @param Length Memory length
552 @param Ra Read access
553 @param Wa Write access
554 @param Xa Execute access
555 @param EptPageAttributeSetting EPT page attribute setting
556
557 STM/PE note:
558
559 **/
560RETURN_STATUS
561EPTSetPageAttributeRange (
562 IN UINT64 EptPointerIN,
563 IN UINT64 Base,
564 IN UINT64 Length,
565 IN UINT64 PhysMem,
566 IN UINT32 Ra,
567 IN UINT32 Wa,
568 IN UINT32 Xa,
569 IN EPT_PAGE_ATTRIBUTE_SETTING EptPageAttributeSetting,
570 IN INT32 EMT
571 )
572{
573 EPT_ENTRY *PageEntry;
574 PAGE_ATTRIBUTE PageAttribute;
575 UINTN PageEntryLength;
576 PAGE_ATTRIBUTE SplitAttribute;
577 RETURN_STATUS Status;
578 UINT_128 Data128;
579 UINT64 EptPointer;
580 UINT64 Offset; // offset of address into the page
581 UINT64 OLength; // Length plus offset
582#if 0
583 DEBUG ((EFI_D_INFO, "EPTSetPageAttributeRange - Base: 0x%016lx - Length: 0x%016lx - PhysMem: 0x%016lx (%1x%1x%1x) EMT:%d\n", Base, Length, PhysMem, Ra, Wa,Xa, EMT))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "EPTSetPageAttributeRange - Base: 0x%016lx - Length: 0x%016lx - PhysMem: 0x%016lx (%1x%1x%1x) EMT:%d\n"
, Base, Length, PhysMem, Ra, Wa,Xa, EMT); } } while (((BOOLEAN
)(0==1)))
;
584#endif
585 // assumption, the user does not change PhysMem on us
586
587 EptPointer = EptPointerIN & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull; // make sure we have only the address
588
589 // Normalize the request to page boundries and lengths
590
591 Offset = Base & PAGING_4K_MASK0xFFF;
592 OLength = Length + Offset; // actual length based on the start of the page
593 Length = OLength & PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull;
594
595 if(((OLength & PAGING_4K_MASK0xFFF) > 0) ||
28
Assuming the condition is false
30
Taking false branch
596 (Length == 0))
29
Assuming 'Length' is not equal to 0
597 {
598 Length = Length + SIZE_4KB0x00001000;
599 }
600
601 Base &= PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull;
602 PhysMem &= PAGING_4K_ADDRESS_MASK_640x000FFFFFFFFFF000ull;
603
604 while (Length
30.1
'Length' is not equal to 0
!= 0) {
31
Loop condition is true. Entering loop body
605 PageEntry = GetPageTableEntry (EptPointer, Base, PhysMem, Length, &PageAttribute);
32
Calling 'GetPageTableEntry'
606// DEBUG((EFI_D_INFO, "EPTSetPageAttributeRange - received page entry: %llx\n", PageEntry->Uint64));
607 if (PageEntry == NULL((void *) 0)) {
608 DEBUG ((EFI_D_INFO, "EPTSetPageAttributeRange - PageEntry == NULL\n"))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "EPTSetPageAttributeRange - PageEntry == NULL\n"
); } } while (((BOOLEAN)(0==1)))
;
609 return RETURN_UNSUPPORTED((RETURN_STATUS)(0x8000000000000000ULL | (3)));
610 }
611 PageEntryLength = PageAttributeToLength (PageAttribute);
612 SplitAttribute = NeedSplitPage (Base, Length, PageAttribute);
613 if (SplitAttribute == PageNone) {
614 ConvertPageEntryAttribute (PageEntry, Ra, Wa, Xa, EptPageAttributeSetting, EMT);
615 //
616 // Convert success, move to next
617 //
618 Base += PageEntryLength;
619 PhysMem += PageEntryLength;
620 Length -= PageEntryLength;
621 } else {
622 Status = SplitPage (PageEntry, PageAttribute, SplitAttribute);
623 if (RETURN_ERROR (Status)(((INTN)(RETURN_STATUS)(Status)) < 0)) {
624 DEBUG ((EFI_D_INFO, "EPTSetPageAttributeRange - SplitPage Error - %r\n", Status))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "EPTSetPageAttributeRange - SplitPage Error - %r\n"
, Status); } } while (((BOOLEAN)(0==1)))
;
625 return RETURN_UNSUPPORTED((RETURN_STATUS)(0x8000000000000000ULL | (3)));
626 }
627 //
628 // Just split current page
629 // Convert success in next around
630 //
631 }
632 }
633
634 Data128.Lo = EptPointerIN;
635 Data128.Hi = 0;
636 AsmInvEpt (INVEPT_TYPE_SINGLE_CONTEXT_INVALIDATION1, &Data128);
637
638 //DEBUG ((EFI_D_INFO, "EPTSetPageAttributeRange - %r\n", RETURN_SUCCESS));
639 return RETURN_SUCCESS0;
640}
641
642/**
643
644 This function is EPT violation handler for SMM.
645
646 @param Index CPU index
647
648 **/
649
650extern unsigned int StmVmPeNmiExCount;
651VOIDvoid
652SmmEPTViolationHandler (
653 IN UINT32 Index
654 )
655{
656 VM_EXIT_QUALIFICATION Qualification;
657 STM_RSC_MEM_DESC *MemDesc;
658 UINT64 Address;
659 STM_RSC_PCI_CFG_DESC *PciCfgDesc;
660 UINT64 PciExpressAddress;
661 STM_RSC_MEM_DESC LocalMemDesc;
662 STM_RSC_PCI_CFG_DESC *LocalPciCfgDescPtr;
663 UINT8 LocalPciCfgDescBuf[STM_LOG_ENTRY_SIZE256];
664 UINT32 VmType = SMI_HANDLER0;
665
666 Qualification.UintN = VmReadN (VMCS_N_RO_EXIT_QUALIFICATION_INDEX0x6400);
667
668 DEBUG ((EFI_D_ERROR, "%ld !!!EPTViolationHandler!!!\n", (UINTN)Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld !!!EPTViolationHandler!!!\n"
, (UINTN)Index); } } while (((BOOLEAN)(0==1)))
;
1
Assuming the condition is false
2
Taking false branch
3
Loop condition is false. Exiting loop
669 DEBUG ((EFI_D_ERROR, "%ld Qualification - %016lx\n", (UINTN) Index, (UINT64)Qualification.UintN))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld Qualification - %016lx\n"
, (UINTN) Index, (UINT64)Qualification.UintN); } } while (((BOOLEAN
)(0==1)))
;
4
Assuming the condition is false
5
Taking false branch
6
Loop condition is false. Exiting loop
670 DEBUG ((EFI_D_ERROR, "%ld GuestPhysicalAddress - %016lx\n", (UINTN) Index, VmRead64 (VMCS_64_RO_GUEST_PHYSICAL_ADDR_INDEX)))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld GuestPhysicalAddress - %016lx\n"
, (UINTN) Index, VmRead64 (0x2400)); } } while (((BOOLEAN)(0==
1)))
;
7
Assuming the condition is false
8
Taking false branch
9
Loop condition is false. Exiting loop
671
672 StmVmPeNmiExCount++; // make sure there is no smi processors waiting
673
674 if (Qualification.EptViolation.GlaValid == 0) {
10
Assuming field 'GlaValid' is not equal to 0
11
Taking false branch
675 //
676 // 0=Linear address invalid.
677 //
678 DEBUG ((EFI_D_ERROR, "%ld SmmEPTViolationHandler - Linear address invalid\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld SmmEPTViolationHandler - Linear address invalid\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
679 } else {
680 if (Qualification.EptViolation.Gpa == 0) {
12
Assuming field 'Gpa' is not equal to 0
13
Taking false branch
681 //
682 // 1=Linear address valid but does not match provided physical address. EPT violation occurred while performing a guest page walk.
683 // 1) No-read EPT page encountered when trying to read from the guest IA32 page tables (e.g fetching a PML4, PDE, PTE).
684 // 2) No-write EPT page encountered when trying to write an A or D bit.
685 //
686
687 DEBUG ((EFI_D_ERROR, "%ld SmmEPTViolationHandler - EPT violation occurred while performing a guest page walk\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld SmmEPTViolationHandler - EPT violation occurred while performing a guest page walk\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
688
689 } else {
690 //
691 // 3=Linear address valid and match provided physical address. This is the normal case.
692 //
693 Address = VmRead64 (VMCS_64_RO_GUEST_PHYSICAL_ADDR_INDEX0x2400);
694 MemDesc = GetStmResourceMem (
695 mHostContextCommon.MleProtectedResource.Base,
696 Address,
697 (UINT32)(Qualification.UintN & 0x7)
698 );
699 if (MemDesc != NULL((void *) 0)) {
14
Assuming 'MemDesc' is equal to NULL
15
Taking false branch
700 DEBUG ((EFI_D_ERROR, "%ld SmmEPTViolationHandler - SMI Handler attempted to access MLE protected resource\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld SmmEPTViolationHandler - SMI Handler attempted to access MLE protected resource\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
701 AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)MemDesc);
702 SmmExceptionHandler (Index);
703 CpuDeadLoop ();
704 }
705
706 MemDesc = GetStmResourceMem (
707 (STM_RSC *)(UINTN)mGuestContextCommonSmm[VmType].BiosHwResourceRequirementsPtr,
708 Address,
709 (UINT32)(Qualification.UintN & 0x7)
710 );
711 if (MemDesc == NULL((void *) 0)) {
16
Assuming 'MemDesc' is equal to NULL
17
Taking true branch
712 DEBUG((EFI_D_ERROR, "%ld SmmEPTViolationHandler - Add unclaimed MEM_RSC!\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld SmmEPTViolationHandler - Add unclaimed MEM_RSC!\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
18
Assuming the condition is false
19
Taking false branch
20
Loop condition is false. Exiting loop
713 ZeroMem (&LocalMemDesc, sizeof(LocalMemDesc));
714 LocalMemDesc.Hdr.RscType = MEM_RANGE1;
715 LocalMemDesc.Hdr.Length = sizeof(LocalMemDesc);
716 LocalMemDesc.Base = Address;
717 LocalMemDesc.Length = 1;
718 LocalMemDesc.RWXAttributes = (UINT8)(Qualification.UintN & 0x7);
719 AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalMemDesc);
720 // BUGBUG: it should not happen?
721 // TBD: We need create EPT mapping here, if so?
722
723 if(EPTSetPageAttributeRange (
27
Calling 'EPTSetPageAttributeRange'
724 mGuestContextCommonSmm[SMI_HANDLER0].EptPointer.Uint64,
725 LocalMemDesc.Base,
726 LocalMemDesc.Length,
727 LocalMemDesc.Base,
728 ((LocalMemDesc.RWXAttributes & STM_RSC_MEM_R0x1) != 0) ? 0 : 1,
21
Assuming the condition is false
22
'?' condition is false
729 ((LocalMemDesc.RWXAttributes & STM_RSC_MEM_W0x2) != 0) ? 0 : 1,
23
Assuming the condition is false
24
'?' condition is false
730 ((LocalMemDesc.RWXAttributes & STM_RSC_MEM_X0x4) != 0) ? 0 : 1,
25
Assuming the condition is false
26
'?' condition is false
731 EptPageAttributeSet,
732 -1
733 ) != 0)
734 {
735 DEBUG((EFI_D_ERROR, "%ld SmmEPTViolationHandler - STM ERROR unable to add resource to EPT map\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld SmmEPTViolationHandler - STM ERROR unable to add resource to EPT map\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
736 CpuDeadLoop ();
737 }
738 }
739
740 // Check PCIE MMIO.
741 if ((mHostContextCommon.PciExpressBaseAddress != 0) &&
742 (Address >= mHostContextCommon.PciExpressBaseAddress) &&
743 (Address < (mHostContextCommon.PciExpressBaseAddress + mHostContextCommon.PciExpressLength))) {
744 PciExpressAddress = Address - mHostContextCommon.PciExpressBaseAddress;
745 PciCfgDesc = GetStmResourcePci (
746 mHostContextCommon.MleProtectedResource.Base,
747 BUS_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x0FF00000) >>
20)
,
748 DEVICE_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x000F8000) >>
15)
,
749 FUNCTION_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x00007000) >>
12)
,
750 REGISTER_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT16)((UINTN)(PciExpressAddress) & 0x00000FFF),
751 (UINT8)(Qualification.UintN & 0x3)
752 );
753 if (PciCfgDesc != NULL((void *) 0)) {
754 DEBUG ((EFI_D_ERROR, "%ld EPT (PCIE) violation!\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld EPT (PCIE) violation!\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
755 AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)PciCfgDesc);
756 SmmExceptionHandler (Index);
757 CpuDeadLoop ();
758 }
759
760 PciCfgDesc = GetStmResourcePci (
761 (STM_RSC *)(UINTN)mGuestContextCommonSmm[VmType].BiosHwResourceRequirementsPtr,
762 BUS_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x0FF00000) >>
20)
,
763 DEVICE_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x000F8000) >>
15)
,
764 FUNCTION_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x00007000) >>
12)
,
765 REGISTER_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT16)((UINTN)(PciExpressAddress) & 0x00000FFF),
766 (UINT8)(Qualification.UintN & 0x3)
767 );
768 if (PciCfgDesc == NULL((void *) 0)) {
769 LocalPciCfgDescPtr = (STM_RSC_PCI_CFG_DESC *)LocalPciCfgDescBuf;
770 ZeroMem (LocalPciCfgDescBuf, sizeof(LocalPciCfgDescBuf));
771 LocalPciCfgDescPtr->Hdr.RscType = PCI_CFG_RANGE5;
772 LocalPciCfgDescPtr->Hdr.Length = sizeof(STM_RSC_PCI_CFG_DESC); // BUGBUG: Just report this PCI device, it is hard to create PCI hierachy here.
773 LocalPciCfgDescPtr->RWAttributes = (UINT8)(Qualification.UintN & 0x3);
774 LocalPciCfgDescPtr->Base = REGISTER_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT16)((UINTN)(PciExpressAddress) & 0x00000FFF);
775 LocalPciCfgDescPtr->Length = 1;
776 LocalPciCfgDescPtr->OriginatingBusNumber = BUS_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x0FF00000) >>
20)
;
777 LocalPciCfgDescPtr->LastNodeIndex = 0;
778 LocalPciCfgDescPtr->PciDevicePath[0].Type = 1;
779 LocalPciCfgDescPtr->PciDevicePath[0].Subtype = 1;
780 LocalPciCfgDescPtr->PciDevicePath[0].Length = sizeof(STM_PCI_DEVICE_PATH_NODE);
781 LocalPciCfgDescPtr->PciDevicePath[0].PciFunction = FUNCTION_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x00007000) >>
12)
;
782 LocalPciCfgDescPtr->PciDevicePath[0].PciDevice = DEVICE_FROM_PCIE_ADDRESS(PciExpressAddress)(UINT8)(((UINTN)(PciExpressAddress) & 0x000F8000) >>
15)
;
783 AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)LocalPciCfgDescPtr);
784 }
785
786 }
787 }
788 }
789
790 VmWriteN (VMCS_N_GUEST_RIP_INDEX0x681E, VmReadN(VMCS_N_GUEST_RIP_INDEX0x681E) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX0x440C));
791
792 return ;
793}
794
795/**
796
797 This function is EPT misconfiguration handler for SMM.
798
799 @param Index CPU index
800
801 **/
802VOIDvoid
803SmmEPTMisconfigurationHandler (
804 IN UINT32 Index
805 )
806{
807 //
808 // Should not happen
809 //
810 DEBUG ((EFI_D_ERROR, "%ld !!!EPTMisconfigurationHandler!!!\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld !!!EPTMisconfigurationHandler!!!\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
811 DumpVmcsAllField (Index);
812
813 CpuDeadLoop ();
814
815 return ;
816}
817
818/**
819
820 This function is INVEPT handler for SMM.
821
822 @param Index CPU index
823
824 **/
825VOIDvoid
826SmmInvEPTHandler (
827 IN UINT32 Index
828 )
829{
830 DEBUG ((EFI_D_ERROR, "%ld !!!InvEPTHandler!!!\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x80000000, "%ld !!!InvEPTHandler!!!\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
831 DumpVmcsAllField (Index);
832
833 CpuDeadLoop ();
834
835 return ;
836}
837
838/**
839
840 This function sync Ia32PAE page table for EPT.
841
842 @param Index CPU index
843
844 **/
845VOIDvoid
846Ia32PAESync (
847 IN UINT32 Index
848 )
849{
850 UINTN Cr0;
851 UINTN Cr3;
852 UINTN Cr4;
853 UINT32 VmType;
854
855 DEBUG ((EFI_D_INFO, "%ld Ia32PAESync\n", Index))do { if (DebugPrintEnabled ()) { DebugPrint (0x00000040, "%ld Ia32PAESync\n"
, Index); } } while (((BOOLEAN)(0==1)))
;
856
857 VmType = mHostContextCommon.HostContextPerCpu[Index].GuestVmType; // any VmType other than SMI_HANDLER is a PeVm
858
859 if(SMI_HANDLER0 != VmType)
860 Index = 0; // PE VM index is always 0
861 //
862 // If EPT is enabled and Guest is in IA32 PAE Mode, we need to write PDPTR.
863 //
864 Cr0 = VmReadN (VMCS_N_GUEST_CR0_INDEX0x6800);
865 Cr3 = VmReadN (VMCS_N_GUEST_CR3_INDEX0x6802);
866 Cr4 = VmReadN (VMCS_N_GUEST_CR4_INDEX0x6804);
867 if (((Cr4 & CR4_PAE(1u << 5)) != 0) &&
868 ((Cr0 & CR0_PG(1u << 31)) != 0) &&
869 ((mGuestContextCommonSmm[VmType].GuestContextPerCpu[Index].Efer & IA32_EFER_MSR_MLA(1u << 10)) == 0)) {
870 VmWrite64 (VMCS_64_GUEST_PDPTE0_INDEX0x280A, *(UINT64 *)(Cr3 + sizeof(UINT64) * 0));
871 VmWrite64 (VMCS_64_GUEST_PDPTE1_INDEX0x280C, *(UINT64 *)(Cr3 + sizeof(UINT64) * 1));
872 VmWrite64 (VMCS_64_GUEST_PDPTE2_INDEX0x280E, *(UINT64 *)(Cr3 + sizeof(UINT64) * 2));
873 VmWrite64 (VMCS_64_GUEST_PDPTE3_INDEX0x2810, *(UINT64 *)(Cr3 + sizeof(UINT64) * 3));
874 }
875
876 return ;
877}