]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmProfile.c
CommitLineData
529a5a86
MK
1/** @file\r
2Enable SMM profile.\r
3\r
13b97736 4Copyright (c) 2012 - 2023, Intel Corporation. All rights reserved.<BR>\r
bdafda8c 5Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>\r
241f9149 6\r
0acd8697 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
529a5a86
MK
8\r
9**/\r
10\r
11#include "PiSmmCpuDxeSmm.h"\r
12#include "SmmProfileInternal.h"\r
13\r
053e878b 14UINT32 mSmmProfileCr3;\r
529a5a86 15\r
053e878b
MK
16SMM_PROFILE_HEADER *mSmmProfileBase;\r
17MSR_DS_AREA_STRUCT *mMsrDsAreaBase;\r
529a5a86
MK
18//\r
19// The buffer to store SMM profile data.\r
20//\r
053e878b 21UINTN mSmmProfileSize;\r
529a5a86
MK
22\r
23//\r
24// The buffer to enable branch trace store.\r
25//\r
053e878b 26UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE;\r
529a5a86 27\r
3c5ce64f
LE
28//\r
29// The flag indicates if execute-disable is supported by processor.\r
30//\r
053e878b 31BOOLEAN mXdSupported = TRUE;\r
3c5ce64f 32\r
529a5a86
MK
33//\r
34// The flag indicates if execute-disable is enabled on processor.\r
35//\r
053e878b 36BOOLEAN mXdEnabled = FALSE;\r
529a5a86
MK
37\r
38//\r
39// The flag indicates if BTS is supported by processor.\r
40//\r
053e878b 41BOOLEAN mBtsSupported = TRUE;\r
529a5a86
MK
42\r
43//\r
44// The flag indicates if SMM profile starts to record data.\r
45//\r
053e878b 46BOOLEAN mSmmProfileStart = FALSE;\r
529a5a86 47\r
09afd9a4
JW
48//\r
49// The flag indicates if #DB will be setup in #PF handler.\r
50//\r
053e878b 51BOOLEAN mSetupDebugTrap = FALSE;\r
09afd9a4 52\r
529a5a86
MK
53//\r
54// Record the page fault exception count for one instruction execution.\r
55//\r
053e878b 56UINTN *mPFEntryCount;\r
529a5a86 57\r
053e878b 58UINT64 (*mLastPFEntryValue)[MAX_PF_ENTRY_COUNT];\r
529a5a86
MK
59UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];\r
60\r
053e878b
MK
61MSR_DS_AREA_STRUCT **mMsrDsArea;\r
62BRANCH_TRACE_RECORD **mMsrBTSRecord;\r
63UINTN mBTSRecordNumber;\r
64PEBS_RECORD **mMsrPEBSRecord;\r
529a5a86
MK
65\r
66//\r
67// These memory ranges are always present, they does not generate the access type of page fault exception,\r
68// but they possibly generate instruction fetch type of page fault exception.\r
69//\r
053e878b
MK
70MEMORY_PROTECTION_RANGE *mProtectionMemRange = NULL;\r
71UINTN mProtectionMemRangeCount = 0;\r
529a5a86
MK
72\r
73//\r
74// Some predefined memory ranges.\r
75//\r
053e878b 76MEMORY_PROTECTION_RANGE mProtectionMemRangeTemplate[] = {\r
529a5a86
MK
77 //\r
78 // SMRAM range (to be fixed in runtime).\r
79 // It is always present and instruction fetches are allowed.\r
80 //\r
053e878b
MK
81 {\r
82 { 0x00000000, 0x00000000 }, TRUE, FALSE\r
83 },\r
529a5a86
MK
84\r
85 //\r
86 // SMM profile data range( to be fixed in runtime).\r
87 // It is always present and instruction fetches are not allowed.\r
88 //\r
053e878b
MK
89 {\r
90 { 0x00000000, 0x00000000 }, TRUE, TRUE\r
91 },\r
529a5a86 92\r
ee584389
JF
93 //\r
94 // SMRAM ranges not covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz (to be fixed in runtime).\r
95 // It is always present and instruction fetches are allowed.\r
96 // {{0x00000000, 0x00000000},TRUE,FALSE},\r
97 //\r
98\r
529a5a86
MK
99 //\r
100 // Future extended range could be added here.\r
101 //\r
102\r
103 //\r
104 // PCI MMIO ranges (to be added in runtime).\r
105 // They are always present and instruction fetches are not allowed.\r
106 //\r
107};\r
108\r
109//\r
110// These memory ranges are mapped by 4KB-page instead of 2MB-page.\r
111//\r
053e878b
MK
112MEMORY_RANGE *mSplitMemRange = NULL;\r
113UINTN mSplitMemRangeCount = 0;\r
529a5a86
MK
114\r
115//\r
116// SMI command port.\r
117//\r
053e878b 118UINT32 mSmiCommandPort;\r
529a5a86
MK
119\r
120/**\r
121 Disable branch trace store.\r
122\r
123**/\r
124VOID\r
125DisableBTS (\r
126 VOID\r
127 )\r
128{\r
129 AsmMsrAnd64 (MSR_DEBUG_CTL, ~((UINT64)(MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR)));\r
130}\r
131\r
132/**\r
133 Enable branch trace store.\r
134\r
135**/\r
136VOID\r
137EnableBTS (\r
138 VOID\r
139 )\r
140{\r
141 AsmMsrOr64 (MSR_DEBUG_CTL, (MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR));\r
142}\r
143\r
144/**\r
145 Get CPU Index from APIC ID.\r
146\r
147**/\r
148UINTN\r
149GetCpuIndex (\r
150 VOID\r
151 )\r
152{\r
053e878b
MK
153 UINTN Index;\r
154 UINT32 ApicId;\r
529a5a86
MK
155\r
156 ApicId = GetApicId ();\r
157\r
bb767506 158 for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
529a5a86
MK
159 if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {\r
160 return Index;\r
161 }\r
162 }\r
053e878b 163\r
529a5a86
MK
164 ASSERT (FALSE);\r
165 return 0;\r
166}\r
167\r
168/**\r
169 Get the source of IP after execute-disable exception is triggered.\r
170\r
171 @param CpuIndex The index of CPU.\r
172 @param DestinationIP The destination address.\r
173\r
174**/\r
175UINT64\r
176GetSourceFromDestinationOnBts (\r
053e878b
MK
177 UINTN CpuIndex,\r
178 UINT64 DestinationIP\r
529a5a86
MK
179 )\r
180{\r
181 BRANCH_TRACE_RECORD *CurrentBTSRecord;\r
182 UINTN Index;\r
183 BOOLEAN FirstMatch;\r
184\r
185 FirstMatch = FALSE;\r
186\r
187 CurrentBTSRecord = (BRANCH_TRACE_RECORD *)mMsrDsArea[CpuIndex]->BTSIndex;\r
188 for (Index = 0; Index < mBTSRecordNumber; Index++) {\r
189 if ((UINTN)CurrentBTSRecord < (UINTN)mMsrBTSRecord[CpuIndex]) {\r
190 //\r
191 // Underflow\r
192 //\r
193 CurrentBTSRecord = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[CpuIndex]->BTSAbsoluteMaximum - 1);\r
053e878b 194 CurrentBTSRecord--;\r
529a5a86 195 }\r
053e878b 196\r
529a5a86
MK
197 if (CurrentBTSRecord->LastBranchTo == DestinationIP) {\r
198 //\r
199 // Good! find 1st one, then find 2nd one.\r
200 //\r
201 if (!FirstMatch) {\r
202 //\r
203 // The first one is DEBUG exception\r
204 //\r
205 FirstMatch = TRUE;\r
206 } else {\r
207 //\r
208 // Good find proper one.\r
209 //\r
210 return CurrentBTSRecord->LastBranchFrom;\r
211 }\r
212 }\r
053e878b 213\r
529a5a86
MK
214 CurrentBTSRecord--;\r
215 }\r
216\r
217 return 0;\r
218}\r
219\r
220/**\r
221 SMM profile specific INT 1 (single-step) exception handler.\r
222\r
223 @param InterruptType Defines the type of interrupt or exception that\r
224 occurred on the processor.This parameter is processor architecture specific.\r
225 @param SystemContext A pointer to the processor context when\r
226 the interrupt occurred on the processor.\r
227**/\r
228VOID\r
229EFIAPI\r
230DebugExceptionHandler (\r
053e878b
MK
231 IN EFI_EXCEPTION_TYPE InterruptType,\r
232 IN EFI_SYSTEM_CONTEXT SystemContext\r
529a5a86
MK
233 )\r
234{\r
235 UINTN CpuIndex;\r
236 UINTN PFEntry;\r
237\r
09afd9a4
JW
238 if (!mSmmProfileStart &&\r
239 !HEAP_GUARD_NONSTOP_MODE &&\r
053e878b
MK
240 !NULL_DETECTION_NONSTOP_MODE)\r
241 {\r
529a5a86
MK
242 return;\r
243 }\r
053e878b 244\r
529a5a86
MK
245 CpuIndex = GetCpuIndex ();\r
246\r
247 //\r
248 // Clear last PF entries\r
249 //\r
250 for (PFEntry = 0; PFEntry < mPFEntryCount[CpuIndex]; PFEntry++) {\r
251 *mLastPFEntryPointer[CpuIndex][PFEntry] = mLastPFEntryValue[CpuIndex][PFEntry];\r
252 }\r
253\r
254 //\r
255 // Reset page fault exception count for next page fault.\r
256 //\r
257 mPFEntryCount[CpuIndex] = 0;\r
258\r
259 //\r
260 // Flush TLB\r
261 //\r
262 CpuFlushTlb ();\r
263\r
264 //\r
265 // Clear TF in EFLAGS\r
266 //\r
267 ClearTrapFlag (SystemContext);\r
268}\r
269\r
97f1061e
JF
270/**\r
271 Check if the input address is in SMM ranges.\r
272\r
273 @param[in] Address The input address.\r
274\r
275 @retval TRUE The input address is in SMM.\r
276 @retval FALSE The input address is not in SMM.\r
277**/\r
278BOOLEAN\r
279IsInSmmRanges (\r
053e878b 280 IN EFI_PHYSICAL_ADDRESS Address\r
97f1061e
JF
281 )\r
282{\r
283 UINTN Index;\r
284\r
29dc8aa8 285 if ((Address >= mCpuHotPlugData.SmrrBase) && (Address < mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
97f1061e
JF
286 return TRUE;\r
287 }\r
053e878b 288\r
97f1061e 289 for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
053e878b
MK
290 if ((Address >= mSmmCpuSmramRanges[Index].CpuStart) &&\r
291 (Address < mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize))\r
292 {\r
97f1061e
JF
293 return TRUE;\r
294 }\r
295 }\r
053e878b 296\r
97f1061e
JF
297 return FALSE;\r
298}\r
299\r
529a5a86
MK
300/**\r
301 Check if the memory address will be mapped by 4KB-page.\r
302\r
303 @param Address The address of Memory.\r
304 @param Nx The flag indicates if the memory is execute-disable.\r
305\r
306**/\r
307BOOLEAN\r
308IsAddressValid (\r
053e878b
MK
309 IN EFI_PHYSICAL_ADDRESS Address,\r
310 IN BOOLEAN *Nx\r
529a5a86
MK
311 )\r
312{\r
313 UINTN Index;\r
314\r
529a5a86
MK
315 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
316 //\r
317 // Check configuration\r
318 //\r
319 for (Index = 0; Index < mProtectionMemRangeCount; Index++) {\r
320 if ((Address >= mProtectionMemRange[Index].Range.Base) && (Address < mProtectionMemRange[Index].Range.Top)) {\r
321 *Nx = mProtectionMemRange[Index].Nx;\r
322 return mProtectionMemRange[Index].Present;\r
323 }\r
324 }\r
053e878b 325\r
529a5a86
MK
326 *Nx = TRUE;\r
327 return FALSE;\r
529a5a86 328 } else {\r
97f1061e
JF
329 *Nx = TRUE;\r
330 if (IsInSmmRanges (Address)) {\r
331 *Nx = FALSE;\r
529a5a86 332 }\r
053e878b 333\r
529a5a86
MK
334 return TRUE;\r
335 }\r
336}\r
337\r
338/**\r
339 Check if the memory address will be mapped by 4KB-page.\r
340\r
341 @param Address The address of Memory.\r
342\r
343**/\r
344BOOLEAN\r
345IsAddressSplit (\r
053e878b 346 IN EFI_PHYSICAL_ADDRESS Address\r
529a5a86
MK
347 )\r
348{\r
349 UINTN Index;\r
350\r
351 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
352 //\r
353 // Check configuration\r
354 //\r
355 for (Index = 0; Index < mSplitMemRangeCount; Index++) {\r
356 if ((Address >= mSplitMemRange[Index].Base) && (Address < mSplitMemRange[Index].Top)) {\r
357 return TRUE;\r
358 }\r
359 }\r
360 } else {\r
361 if (Address < mCpuHotPlugData.SmrrBase) {\r
362 if ((mCpuHotPlugData.SmrrBase - Address) < BASE_2MB) {\r
363 return TRUE;\r
364 }\r
053e878b 365 } else if (Address > (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize - BASE_2MB)) {\r
529a5a86
MK
366 if ((Address - (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize - BASE_2MB)) < BASE_2MB) {\r
367 return TRUE;\r
368 }\r
369 }\r
370 }\r
053e878b 371\r
529a5a86
MK
372 //\r
373 // Return default\r
374 //\r
375 return FALSE;\r
376}\r
377\r
378/**\r
379 Initialize the protected memory ranges and the 4KB-page mapped memory ranges.\r
380\r
381**/\r
382VOID\r
383InitProtectedMemRange (\r
384 VOID\r
385 )\r
386{\r
387 UINTN Index;\r
388 UINTN NumberOfDescriptors;\r
ee584389 389 UINTN NumberOfAddedDescriptors;\r
529a5a86
MK
390 UINTN NumberOfProtectRange;\r
391 UINTN NumberOfSpliteRange;\r
392 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
393 UINTN TotalSize;\r
529a5a86
MK
394 EFI_PHYSICAL_ADDRESS ProtectBaseAddress;\r
395 EFI_PHYSICAL_ADDRESS ProtectEndAddress;\r
396 EFI_PHYSICAL_ADDRESS Top2MBAlignedAddress;\r
397 EFI_PHYSICAL_ADDRESS Base2MBAlignedAddress;\r
398 UINT64 High4KBPageSize;\r
399 UINT64 Low4KBPageSize;\r
400\r
401 NumberOfDescriptors = 0;\r
ee584389 402 NumberOfAddedDescriptors = mSmmCpuSmramRangeCount;\r
529a5a86
MK
403 NumberOfSpliteRange = 0;\r
404 MemorySpaceMap = NULL;\r
405\r
406 //\r
407 // Get MMIO ranges from GCD and add them into protected memory ranges.\r
408 //\r
dc0a7143 409 gDS->GetMemorySpaceMap (\r
053e878b
MK
410 &NumberOfDescriptors,\r
411 &MemorySpaceMap\r
412 );\r
529a5a86
MK
413 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
414 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
ee584389 415 NumberOfAddedDescriptors++;\r
529a5a86
MK
416 }\r
417 }\r
418\r
ee584389 419 if (NumberOfAddedDescriptors != 0) {\r
053e878b
MK
420 TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);\r
421 mProtectionMemRange = (MEMORY_PROTECTION_RANGE *)AllocateZeroPool (TotalSize);\r
529a5a86
MK
422 ASSERT (mProtectionMemRange != NULL);\r
423 mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE);\r
424\r
425 //\r
426 // Copy existing ranges.\r
427 //\r
428 CopyMem (mProtectionMemRange, mProtectionMemRangeTemplate, sizeof (mProtectionMemRangeTemplate));\r
429\r
430 //\r
431 // Create split ranges which come from protected ranges.\r
432 //\r
053e878b
MK
433 TotalSize = (TotalSize / sizeof (MEMORY_PROTECTION_RANGE)) * sizeof (MEMORY_RANGE);\r
434 mSplitMemRange = (MEMORY_RANGE *)AllocateZeroPool (TotalSize);\r
529a5a86
MK
435 ASSERT (mSplitMemRange != NULL);\r
436\r
ee584389
JF
437 //\r
438 // Create SMM ranges which are set to present and execution-enable.\r
439 //\r
440 NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
441 for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
053e878b
MK
442 if ((mSmmCpuSmramRanges[Index].CpuStart >= mProtectionMemRange[0].Range.Base) &&\r
443 (mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize < mProtectionMemRange[0].Range.Top))\r
444 {\r
ee584389
JF
445 //\r
446 // If the address have been already covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz\r
447 //\r
448 break;\r
449 }\r
053e878b 450\r
ee584389
JF
451 mProtectionMemRange[NumberOfProtectRange].Range.Base = mSmmCpuSmramRanges[Index].CpuStart;\r
452 mProtectionMemRange[NumberOfProtectRange].Range.Top = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;\r
453 mProtectionMemRange[NumberOfProtectRange].Present = TRUE;\r
454 mProtectionMemRange[NumberOfProtectRange].Nx = FALSE;\r
455 NumberOfProtectRange++;\r
456 }\r
457\r
529a5a86
MK
458 //\r
459 // Create MMIO ranges which are set to present and execution-disable.\r
460 //\r
529a5a86
MK
461 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
462 if (MemorySpaceMap[Index].GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {\r
463 continue;\r
464 }\r
053e878b 465\r
529a5a86
MK
466 mProtectionMemRange[NumberOfProtectRange].Range.Base = MemorySpaceMap[Index].BaseAddress;\r
467 mProtectionMemRange[NumberOfProtectRange].Range.Top = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length;\r
468 mProtectionMemRange[NumberOfProtectRange].Present = TRUE;\r
469 mProtectionMemRange[NumberOfProtectRange].Nx = TRUE;\r
470 NumberOfProtectRange++;\r
471 }\r
ee584389
JF
472\r
473 //\r
474 // Check and updated actual protected memory ranges count\r
475 //\r
476 ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount);\r
477 mProtectionMemRangeCount = NumberOfProtectRange;\r
529a5a86
MK
478 }\r
479\r
480 //\r
481 // According to protected ranges, create the ranges which will be mapped by 2KB page.\r
482 //\r
483 NumberOfSpliteRange = 0;\r
484 NumberOfProtectRange = mProtectionMemRangeCount;\r
485 for (Index = 0; Index < NumberOfProtectRange; Index++) {\r
486 //\r
487 // If MMIO base address is not 2MB alignment, make 2MB alignment for create 4KB page in page table.\r
488 //\r
489 ProtectBaseAddress = mProtectionMemRange[Index].Range.Base;\r
490 ProtectEndAddress = mProtectionMemRange[Index].Range.Top;\r
491 if (((ProtectBaseAddress & (SIZE_2MB - 1)) != 0) || ((ProtectEndAddress & (SIZE_2MB - 1)) != 0)) {\r
492 //\r
493 // Check if it is possible to create 4KB-page for not 2MB-aligned range and to create 2MB-page for 2MB-aligned range.\r
494 // A mix of 4KB and 2MB page could save SMRAM space.\r
495 //\r
496 Top2MBAlignedAddress = ProtectEndAddress & ~(SIZE_2MB - 1);\r
497 Base2MBAlignedAddress = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);\r
498 if ((Top2MBAlignedAddress > Base2MBAlignedAddress) &&\r
053e878b
MK
499 ((Top2MBAlignedAddress - Base2MBAlignedAddress) >= SIZE_2MB))\r
500 {\r
529a5a86
MK
501 //\r
502 // There is an range which could be mapped by 2MB-page.\r
503 //\r
504 High4KBPageSize = ((ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectEndAddress & ~(SIZE_2MB - 1));\r
505 Low4KBPageSize = ((ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectBaseAddress & ~(SIZE_2MB - 1));\r
506 if (High4KBPageSize != 0) {\r
507 //\r
508 // Add not 2MB-aligned range to be mapped by 4KB-page.\r
509 //\r
510 mSplitMemRange[NumberOfSpliteRange].Base = ProtectEndAddress & ~(SIZE_2MB - 1);\r
511 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);\r
512 NumberOfSpliteRange++;\r
513 }\r
053e878b 514\r
529a5a86
MK
515 if (Low4KBPageSize != 0) {\r
516 //\r
517 // Add not 2MB-aligned range to be mapped by 4KB-page.\r
518 //\r
519 mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);\r
520 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);\r
521 NumberOfSpliteRange++;\r
522 }\r
523 } else {\r
524 //\r
525 // The range could only be mapped by 4KB-page.\r
526 //\r
527 mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);\r
528 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);\r
529 NumberOfSpliteRange++;\r
530 }\r
531 }\r
532 }\r
533\r
534 mSplitMemRangeCount = NumberOfSpliteRange;\r
535\r
96e1cba5 536 DEBUG ((DEBUG_INFO, "SMM Profile Memory Ranges:\n"));\r
529a5a86 537 for (Index = 0; Index < mProtectionMemRangeCount; Index++) {\r
96e1cba5
MK
538 DEBUG ((DEBUG_INFO, "mProtectionMemRange[%d].Base = %lx\n", Index, mProtectionMemRange[Index].Range.Base));\r
539 DEBUG ((DEBUG_INFO, "mProtectionMemRange[%d].Top = %lx\n", Index, mProtectionMemRange[Index].Range.Top));\r
529a5a86 540 }\r
053e878b 541\r
529a5a86 542 for (Index = 0; Index < mSplitMemRangeCount; Index++) {\r
96e1cba5
MK
543 DEBUG ((DEBUG_INFO, "mSplitMemRange[%d].Base = %lx\n", Index, mSplitMemRange[Index].Base));\r
544 DEBUG ((DEBUG_INFO, "mSplitMemRange[%d].Top = %lx\n", Index, mSplitMemRange[Index].Top));\r
529a5a86
MK
545 }\r
546}\r
547\r
548/**\r
549 Update page table according to protected memory ranges and the 4KB-page mapped memory ranges.\r
550\r
551**/\r
552VOID\r
553InitPaging (\r
554 VOID\r
555 )\r
556{\r
053e878b
MK
557 UINT64 Pml5Entry;\r
558 UINT64 Pml4Entry;\r
559 UINT64 *Pml5;\r
560 UINT64 *Pml4;\r
561 UINT64 *Pdpt;\r
562 UINT64 *Pd;\r
563 UINT64 *Pt;\r
564 UINTN Address;\r
565 UINTN Pml5Index;\r
566 UINTN Pml4Index;\r
567 UINTN PdptIndex;\r
568 UINTN PdIndex;\r
569 UINTN PtIndex;\r
570 UINTN NumberOfPdptEntries;\r
571 UINTN NumberOfPml4Entries;\r
572 UINTN NumberOfPml5Entries;\r
573 UINTN SizeOfMemorySpace;\r
574 BOOLEAN Nx;\r
575 IA32_CR4 Cr4;\r
576 BOOLEAN Enable5LevelPaging;\r
577\r
578 Cr4.UintN = AsmReadCr4 ();\r
579 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);\r
529a5a86
MK
580\r
581 if (sizeof (UINTN) == sizeof (UINT64)) {\r
4eee0cc7 582 if (!Enable5LevelPaging) {\r
053e878b
MK
583 Pml5Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P;\r
584 Pml5 = &Pml5Entry;\r
4eee0cc7 585 } else {\r
053e878b 586 Pml5 = (UINT64 *)(UINTN)mSmmProfileCr3;\r
4eee0cc7 587 }\r
053e878b 588\r
529a5a86 589 SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1;\r
13b97736
ZL
590 ASSERT (SizeOfMemorySpace <= 52);\r
591\r
529a5a86 592 //\r
13b97736 593 // Calculate the table entries of PML5E, PML4E and PDPTE.\r
529a5a86 594 //\r
4eee0cc7
RN
595 NumberOfPml5Entries = 1;\r
596 if (SizeOfMemorySpace > 48) {\r
13b97736
ZL
597 if (Enable5LevelPaging) {\r
598 NumberOfPml5Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 48);\r
599 }\r
600\r
601 SizeOfMemorySpace = 48;\r
7365eb2c 602 }\r
4eee0cc7 603\r
4e78c7be 604 NumberOfPml4Entries = 1;\r
4eee0cc7 605 if (SizeOfMemorySpace > 39) {\r
053e878b
MK
606 NumberOfPml4Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 39);\r
607 SizeOfMemorySpace = 39;\r
4eee0cc7
RN
608 }\r
609\r
610 NumberOfPdptEntries = 1;\r
611 ASSERT (SizeOfMemorySpace > 30);\r
053e878b 612 NumberOfPdptEntries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 30);\r
4eee0cc7 613 } else {\r
053e878b
MK
614 Pml4Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P;\r
615 Pml4 = &Pml4Entry;\r
616 Pml5Entry = (UINTN)Pml4 | IA32_PG_P;\r
617 Pml5 = &Pml5Entry;\r
618 NumberOfPml5Entries = 1;\r
619 NumberOfPml4Entries = 1;\r
620 NumberOfPdptEntries = 4;\r
529a5a86
MK
621 }\r
622\r
623 //\r
624 // Go through page table and change 2MB-page into 4KB-page.\r
625 //\r
4eee0cc7
RN
626 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
627 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
628 //\r
629 // If PML5 entry does not exist, skip it\r
630 //\r
631 continue;\r
632 }\r
053e878b
MK
633\r
634 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 635 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
7e56f892 636 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
529a5a86 637 //\r
7e56f892 638 // If PML4 entry does not exist, skip it\r
529a5a86
MK
639 //\r
640 continue;\r
641 }\r
053e878b 642\r
7e56f892 643 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7
RN
644 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
645 if ((*Pdpt & IA32_PG_P) == 0) {\r
646 //\r
647 // If PDPT entry does not exist, skip it\r
648 //\r
649 continue;\r
650 }\r
053e878b 651\r
4eee0cc7 652 if ((*Pdpt & IA32_PG_PS) != 0) {\r
529a5a86 653 //\r
4eee0cc7 654 // This is 1G entry, skip it\r
529a5a86
MK
655 //\r
656 continue;\r
657 }\r
053e878b 658\r
4eee0cc7
RN
659 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
660 if (Pd == 0) {\r
661 continue;\r
662 }\r
053e878b 663\r
4eee0cc7
RN
664 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
665 if ((*Pd & IA32_PG_P) == 0) {\r
666 //\r
667 // If PD entry does not exist, skip it\r
668 //\r
669 continue;\r
670 }\r
053e878b
MK
671\r
672 Address = (UINTN)LShiftU64 (\r
673 LShiftU64 (\r
674 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
675 9\r
676 ) + PdIndex,\r
677 21\r
678 );\r
529a5a86 679\r
529a5a86 680 //\r
4eee0cc7 681 // If it is 2M page, check IsAddressSplit()\r
529a5a86 682 //\r
4eee0cc7
RN
683 if (((*Pd & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {\r
684 //\r
685 // Based on current page table, create 4KB page table for split area.\r
686 //\r
687 ASSERT (Address == (*Pd & PHYSICAL_ADDRESS_MASK));\r
688\r
689 Pt = AllocatePageTableMemory (1);\r
690 ASSERT (Pt != NULL);\r
529a5a86 691\r
4eee0cc7 692 // Split it\r
053e878b 693 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++) {\r
a5235562 694 Pt[PtIndex] = Address + ((PtIndex << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
4eee0cc7 695 } // end for PT\r
053e878b 696\r
4eee0cc7
RN
697 *Pd = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
698 } // end if IsAddressSplit\r
699 } // end for PD\r
700 } // end for PDPT\r
701 } // end for PML4\r
702 } // end for PML5\r
529a5a86
MK
703\r
704 //\r
705 // Go through page table and set several page table entries to absent or execute-disable.\r
706 //\r
96e1cba5 707 DEBUG ((DEBUG_INFO, "Patch page table start ...\n"));\r
4eee0cc7
RN
708 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
709 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
710 //\r
711 // If PML5 entry does not exist, skip it\r
712 //\r
713 continue;\r
714 }\r
053e878b
MK
715\r
716 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 717 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
7e56f892 718 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
529a5a86 719 //\r
7e56f892 720 // If PML4 entry does not exist, skip it\r
529a5a86
MK
721 //\r
722 continue;\r
723 }\r
053e878b 724\r
7e56f892 725 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7
RN
726 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
727 if ((*Pdpt & IA32_PG_P) == 0) {\r
728 //\r
729 // If PDPT entry does not exist, skip it\r
730 //\r
731 continue;\r
717fb604 732 }\r
053e878b 733\r
4eee0cc7 734 if ((*Pdpt & IA32_PG_PS) != 0) {\r
529a5a86 735 //\r
4eee0cc7 736 // This is 1G entry, set NX bit and skip it\r
529a5a86 737 //\r
4eee0cc7
RN
738 if (mXdSupported) {\r
739 *Pdpt = *Pdpt | IA32_PG_NX;\r
740 }\r
053e878b 741\r
529a5a86
MK
742 continue;\r
743 }\r
053e878b 744\r
4eee0cc7
RN
745 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
746 if (Pd == 0) {\r
747 continue;\r
748 }\r
053e878b 749\r
4eee0cc7
RN
750 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
751 if ((*Pd & IA32_PG_P) == 0) {\r
529a5a86 752 //\r
4eee0cc7 753 // If PD entry does not exist, skip it\r
529a5a86 754 //\r
529a5a86
MK
755 continue;\r
756 }\r
053e878b
MK
757\r
758 Address = (UINTN)LShiftU64 (\r
759 LShiftU64 (\r
760 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
761 9\r
762 ) + PdIndex,\r
763 21\r
764 );\r
4eee0cc7
RN
765\r
766 if ((*Pd & IA32_PG_PS) != 0) {\r
767 // 2MB page\r
768\r
529a5a86 769 if (!IsAddressValid (Address, &Nx)) {\r
4eee0cc7
RN
770 //\r
771 // Patch to remove Present flag and RW flag\r
772 //\r
773 *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
529a5a86 774 }\r
053e878b 775\r
529a5a86 776 if (Nx && mXdSupported) {\r
4eee0cc7
RN
777 *Pd = *Pd | IA32_PG_NX;\r
778 }\r
779 } else {\r
780 // 4KB page\r
781 Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
782 if (Pt == 0) {\r
783 continue;\r
529a5a86 784 }\r
053e878b
MK
785\r
786 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++, Pt++) {\r
4eee0cc7
RN
787 if (!IsAddressValid (Address, &Nx)) {\r
788 *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
789 }\r
053e878b 790\r
4eee0cc7
RN
791 if (Nx && mXdSupported) {\r
792 *Pt = *Pt | IA32_PG_NX;\r
793 }\r
053e878b 794\r
4eee0cc7
RN
795 Address += SIZE_4KB;\r
796 } // end for PT\r
797 } // end if PS\r
798 } // end for PD\r
799 } // end for PDPT\r
800 } // end for PML4\r
801 } // end for PML5\r
529a5a86
MK
802\r
803 //\r
804 // Flush TLB\r
805 //\r
806 CpuFlushTlb ();\r
96e1cba5 807 DEBUG ((DEBUG_INFO, "Patch page table done!\n"));\r
529a5a86
MK
808 //\r
809 // Set execute-disable flag\r
810 //\r
811 mXdEnabled = TRUE;\r
812\r
053e878b 813 return;\r
529a5a86
MK
814}\r
815\r
529a5a86
MK
816/**\r
817 To get system port address of the SMI Command Port in FADT table.\r
818\r
819**/\r
820VOID\r
821GetSmiCommandPort (\r
822 VOID\r
823 )\r
824{\r
053e878b 825 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;\r
529a5a86 826\r
053e878b
MK
827 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)EfiLocateFirstAcpiTable (\r
828 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE\r
829 );\r
529a5a86
MK
830 ASSERT (Fadt != NULL);\r
831\r
832 mSmiCommandPort = Fadt->SmiCmd;\r
96e1cba5 833 DEBUG ((DEBUG_INFO, "mSmiCommandPort = %x\n", mSmiCommandPort));\r
529a5a86
MK
834}\r
835\r
836/**\r
837 Updates page table to make some memory ranges (like system memory) absent\r
838 and make some memory ranges (like MMIO) present and execute disable. It also\r
839 update 2MB-page to 4KB-page for some memory ranges.\r
840\r
841**/\r
842VOID\r
843SmmProfileStart (\r
844 VOID\r
845 )\r
846{\r
847 //\r
848 // The flag indicates SMM profile starts to work.\r
849 //\r
850 mSmmProfileStart = TRUE;\r
851}\r
852\r
853/**\r
854 Initialize SMM profile in SmmReadyToLock protocol callback function.\r
855\r
856 @param Protocol Points to the protocol's unique identifier.\r
857 @param Interface Points to the interface instance.\r
858 @param Handle The handle on which the interface was installed.\r
859\r
860 @retval EFI_SUCCESS SmmReadyToLock protocol callback runs successfully.\r
861**/\r
862EFI_STATUS\r
863EFIAPI\r
864InitSmmProfileCallBack (\r
865 IN CONST EFI_GUID *Protocol,\r
866 IN VOID *Interface,\r
867 IN EFI_HANDLE Handle\r
868 )\r
869{\r
529a5a86
MK
870 //\r
871 // Save to variable so that SMM profile data can be found.\r
872 //\r
dc0a7143
LE
873 gRT->SetVariable (\r
874 SMM_PROFILE_NAME,\r
875 &gEfiCallerIdGuid,\r
876 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
053e878b 877 sizeof (mSmmProfileBase),\r
dc0a7143
LE
878 &mSmmProfileBase\r
879 );\r
529a5a86
MK
880\r
881 //\r
882 // Get Software SMI from FADT\r
883 //\r
884 GetSmiCommandPort ();\r
885\r
886 //\r
887 // Initialize protected memory range for patching page table later.\r
888 //\r
889 InitProtectedMemRange ();\r
890\r
891 return EFI_SUCCESS;\r
892}\r
893\r
894/**\r
895 Initialize SMM profile data structures.\r
896\r
897**/\r
898VOID\r
899InitSmmProfileInternal (\r
900 VOID\r
901 )\r
902{\r
053e878b
MK
903 EFI_STATUS Status;\r
904 EFI_PHYSICAL_ADDRESS Base;\r
905 VOID *Registration;\r
906 UINTN Index;\r
907 UINTN MsrDsAreaSizePerCpu;\r
908 UINTN TotalSize;\r
529a5a86 909\r
bb767506 910 mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus);\r
529a5a86 911 ASSERT (mPFEntryCount != NULL);\r
053e878b
MK
912 mLastPFEntryValue = (UINT64 (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
913 sizeof (mLastPFEntryValue[0]) * mMaxNumberOfCpus\r
914 );\r
529a5a86
MK
915 ASSERT (mLastPFEntryValue != NULL);\r
916 mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
053e878b
MK
917 sizeof (mLastPFEntryPointer[0]) * mMaxNumberOfCpus\r
918 );\r
529a5a86
MK
919 ASSERT (mLastPFEntryPointer != NULL);\r
920\r
921 //\r
922 // Allocate memory for SmmProfile below 4GB.\r
923 // The base address\r
924 //\r
925 mSmmProfileSize = PcdGet32 (PcdCpuSmmProfileSize);\r
926 ASSERT ((mSmmProfileSize & 0xFFF) == 0);\r
927\r
928 if (mBtsSupported) {\r
929 TotalSize = mSmmProfileSize + mMsrDsAreaSize;\r
930 } else {\r
931 TotalSize = mSmmProfileSize;\r
932 }\r
933\r
053e878b 934 Base = 0xFFFFFFFF;\r
529a5a86
MK
935 Status = gBS->AllocatePages (\r
936 AllocateMaxAddress,\r
937 EfiReservedMemoryType,\r
938 EFI_SIZE_TO_PAGES (TotalSize),\r
939 &Base\r
940 );\r
941 ASSERT_EFI_ERROR (Status);\r
942 ZeroMem ((VOID *)(UINTN)Base, TotalSize);\r
943 mSmmProfileBase = (SMM_PROFILE_HEADER *)(UINTN)Base;\r
944\r
945 //\r
946 // Initialize SMM profile data header.\r
947 //\r
948 mSmmProfileBase->HeaderSize = sizeof (SMM_PROFILE_HEADER);\r
053e878b
MK
949 mSmmProfileBase->MaxDataEntries = (UINT64)((mSmmProfileSize - sizeof (SMM_PROFILE_HEADER)) / sizeof (SMM_PROFILE_ENTRY));\r
950 mSmmProfileBase->MaxDataSize = MultU64x64 (mSmmProfileBase->MaxDataEntries, sizeof (SMM_PROFILE_ENTRY));\r
529a5a86
MK
951 mSmmProfileBase->CurDataEntries = 0;\r
952 mSmmProfileBase->CurDataSize = 0;\r
953 mSmmProfileBase->TsegStart = mCpuHotPlugData.SmrrBase;\r
954 mSmmProfileBase->TsegSize = mCpuHotPlugData.SmrrSize;\r
955 mSmmProfileBase->NumSmis = 0;\r
956 mSmmProfileBase->NumCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
957\r
958 if (mBtsSupported) {\r
bb767506 959 mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * mMaxNumberOfCpus);\r
529a5a86 960 ASSERT (mMsrDsArea != NULL);\r
bb767506 961 mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * mMaxNumberOfCpus);\r
529a5a86 962 ASSERT (mMsrBTSRecord != NULL);\r
bb767506 963 mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * mMaxNumberOfCpus);\r
529a5a86
MK
964 ASSERT (mMsrPEBSRecord != NULL);\r
965\r
053e878b 966 mMsrDsAreaBase = (MSR_DS_AREA_STRUCT *)((UINTN)Base + mSmmProfileSize);\r
bb767506 967 MsrDsAreaSizePerCpu = mMsrDsAreaSize / mMaxNumberOfCpus;\r
053e878b 968 mBTSRecordNumber = (MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof (MSR_DS_AREA_STRUCT)) / sizeof (BRANCH_TRACE_RECORD);\r
bb767506 969 for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
529a5a86 970 mMsrDsArea[Index] = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index);\r
053e878b
MK
971 mMsrBTSRecord[Index] = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof (MSR_DS_AREA_STRUCT));\r
972 mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER);\r
529a5a86 973\r
053e878b
MK
974 mMsrDsArea[Index]->BTSBufferBase = (UINTN)mMsrBTSRecord[Index];\r
975 mMsrDsArea[Index]->BTSIndex = mMsrDsArea[Index]->BTSBufferBase;\r
976 mMsrDsArea[Index]->BTSAbsoluteMaximum = mMsrDsArea[Index]->BTSBufferBase + mBTSRecordNumber * sizeof (BRANCH_TRACE_RECORD) + 1;\r
977 mMsrDsArea[Index]->BTSInterruptThreshold = mMsrDsArea[Index]->BTSAbsoluteMaximum + 1;\r
529a5a86
MK
978\r
979 mMsrDsArea[Index]->PEBSBufferBase = (UINTN)mMsrPEBSRecord[Index];\r
980 mMsrDsArea[Index]->PEBSIndex = mMsrDsArea[Index]->PEBSBufferBase;\r
053e878b 981 mMsrDsArea[Index]->PEBSAbsoluteMaximum = mMsrDsArea[Index]->PEBSBufferBase + PEBS_RECORD_NUMBER * sizeof (PEBS_RECORD) + 1;\r
529a5a86
MK
982 mMsrDsArea[Index]->PEBSInterruptThreshold = mMsrDsArea[Index]->PEBSAbsoluteMaximum + 1;\r
983 }\r
984 }\r
985\r
986 mProtectionMemRange = mProtectionMemRangeTemplate;\r
987 mProtectionMemRangeCount = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
988\r
989 //\r
990 // Update TSeg entry.\r
991 //\r
992 mProtectionMemRange[0].Range.Base = mCpuHotPlugData.SmrrBase;\r
993 mProtectionMemRange[0].Range.Top = mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize;\r
994\r
995 //\r
996 // Update SMM profile entry.\r
997 //\r
998 mProtectionMemRange[1].Range.Base = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase;\r
999 mProtectionMemRange[1].Range.Top = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase + TotalSize;\r
1000\r
1001 //\r
1002 // Allocate memory reserved for creating 4KB pages.\r
1003 //\r
1004 InitPagesForPFHandler ();\r
1005\r
1006 //\r
1007 // Start SMM profile when SmmReadyToLock protocol is installed.\r
1008 //\r
1009 Status = gSmst->SmmRegisterProtocolNotify (\r
1010 &gEfiSmmReadyToLockProtocolGuid,\r
1011 InitSmmProfileCallBack,\r
1012 &Registration\r
1013 );\r
1014 ASSERT_EFI_ERROR (Status);\r
1015\r
053e878b 1016 return;\r
529a5a86
MK
1017}\r
1018\r
1019/**\r
3eb69b08 1020 Check if feature is supported by a processor.\r
529a5a86
MK
1021\r
1022**/\r
1023VOID\r
1024CheckFeatureSupported (\r
51773d49 1025 VOID\r
529a5a86
MK
1026 )\r
1027{\r
f85d3ce2 1028 UINT32 RegEax;\r
3eb69b08 1029 UINT32 RegEcx;\r
f85d3ce2
JF
1030 UINT32 RegEdx;\r
1031 MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;\r
529a5a86 1032\r
3eb69b08 1033 if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
5d34cc49
WH
1034 AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);\r
1035 if (RegEax >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {\r
1036 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, NULL);\r
1037 if ((RegEcx & CPUID_CET_SS) == 0) {\r
1038 mCetSupported = FALSE;\r
1039 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
1040 }\r
1041 } else {\r
3eb69b08
JY
1042 mCetSupported = FALSE;\r
1043 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
1044 }\r
1045 }\r
1046\r
529a5a86
MK
1047 if (mXdSupported) {\r
1048 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
1049 if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
1050 //\r
1051 // Extended CPUID functions are not supported on this processor.\r
1052 //\r
1053 mXdSupported = FALSE;\r
3c5ce64f 1054 PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
529a5a86
MK
1055 }\r
1056\r
1057 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
1058 if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {\r
1059 //\r
1060 // Execute Disable Bit feature is not supported on this processor.\r
1061 //\r
1062 mXdSupported = FALSE;\r
3c5ce64f 1063 PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
529a5a86 1064 }\r
bdafda8c
KG
1065\r
1066 if (StandardSignatureIsAuthenticAMD ()) {\r
1067 //\r
1068 // AMD processors do not support MSR_IA32_MISC_ENABLE\r
1069 //\r
1070 PatchInstructionX86 (gPatchMsrIa32MiscEnableSupported, FALSE, 1);\r
1071 }\r
529a5a86
MK
1072 }\r
1073\r
1074 if (mBtsSupported) {\r
1075 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);\r
1076 if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) {\r
1077 //\r
1078 // Per IA32 manuals:\r
1079 // When CPUID.1:EDX[21] is set, the following BTS facilities are available:\r
1080 // 1. The BTS_UNAVAILABLE flag in the IA32_MISC_ENABLE MSR indicates the\r
1081 // availability of the BTS facilities, including the ability to set the BTS and\r
1082 // BTINT bits in the MSR_DEBUGCTLA MSR.\r
1083 // 2. The IA32_DS_AREA MSR can be programmed to point to the DS save area.\r
1084 //\r
f85d3ce2
JF
1085 MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
1086 if (MiscEnableMsr.Bits.BTS == 1) {\r
529a5a86 1087 //\r
f85d3ce2 1088 // BTS facilities is not supported if MSR_IA32_MISC_ENABLE.BTS bit is set.\r
529a5a86
MK
1089 //\r
1090 mBtsSupported = FALSE;\r
1091 }\r
1092 }\r
1093 }\r
1094}\r
1095\r
529a5a86
MK
1096/**\r
1097 Enable single step.\r
1098\r
1099**/\r
1100VOID\r
1101ActivateSingleStepDB (\r
1102 VOID\r
1103 )\r
1104{\r
053e878b 1105 UINTN Dr6;\r
529a5a86
MK
1106\r
1107 Dr6 = AsmReadDr6 ();\r
1108 if ((Dr6 & DR6_SINGLE_STEP) != 0) {\r
1109 return;\r
1110 }\r
053e878b 1111\r
529a5a86
MK
1112 Dr6 |= DR6_SINGLE_STEP;\r
1113 AsmWriteDr6 (Dr6);\r
1114}\r
1115\r
1116/**\r
1117 Enable last branch.\r
1118\r
1119**/\r
1120VOID\r
1121ActivateLBR (\r
1122 VOID\r
1123 )\r
1124{\r
1125 UINT64 DebugCtl;\r
1126\r
1127 DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);\r
1128 if ((DebugCtl & MSR_DEBUG_CTL_LBR) != 0) {\r
053e878b 1129 return;\r
529a5a86 1130 }\r
053e878b 1131\r
529a5a86
MK
1132 DebugCtl |= MSR_DEBUG_CTL_LBR;\r
1133 AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);\r
1134}\r
1135\r
1136/**\r
1137 Enable branch trace store.\r
1138\r
1139 @param CpuIndex The index of the processor.\r
1140\r
1141**/\r
1142VOID\r
1143ActivateBTS (\r
053e878b 1144 IN UINTN CpuIndex\r
529a5a86
MK
1145 )\r
1146{\r
1147 UINT64 DebugCtl;\r
1148\r
1149 DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);\r
1150 if ((DebugCtl & MSR_DEBUG_CTL_BTS) != 0) {\r
053e878b 1151 return;\r
529a5a86
MK
1152 }\r
1153\r
1154 AsmWriteMsr64 (MSR_DS_AREA, (UINT64)(UINTN)mMsrDsArea[CpuIndex]);\r
1155 DebugCtl |= (UINT64)(MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR);\r
1156 DebugCtl &= ~((UINT64)MSR_DEBUG_CTL_BTINT);\r
1157 AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);\r
1158}\r
1159\r
1160/**\r
1161 Increase SMI number in each SMI entry.\r
1162\r
1163**/\r
1164VOID\r
1165SmmProfileRecordSmiNum (\r
1166 VOID\r
1167 )\r
1168{\r
1169 if (mSmmProfileStart) {\r
1170 mSmmProfileBase->NumSmis++;\r
1171 }\r
1172}\r
1173\r
1174/**\r
1175 Initialize processor environment for SMM profile.\r
1176\r
1177 @param CpuIndex The index of the processor.\r
1178\r
1179**/\r
1180VOID\r
1181ActivateSmmProfile (\r
053e878b 1182 IN UINTN CpuIndex\r
529a5a86
MK
1183 )\r
1184{\r
1185 //\r
1186 // Enable Single Step DB#\r
1187 //\r
1188 ActivateSingleStepDB ();\r
1189\r
1190 if (mBtsSupported) {\r
1191 //\r
1192 // We can not get useful information from LER, so we have to use BTS.\r
1193 //\r
1194 ActivateLBR ();\r
1195\r
1196 //\r
1197 // Enable BTS\r
1198 //\r
1199 ActivateBTS (CpuIndex);\r
1200 }\r
1201}\r
1202\r
1203/**\r
1204 Initialize SMM profile in SMM CPU entry point.\r
1205\r
1206 @param[in] Cr3 The base address of the page tables to use in SMM.\r
1207\r
1208**/\r
1209VOID\r
1210InitSmmProfile (\r
1211 UINT32 Cr3\r
1212 )\r
1213{\r
1214 //\r
1215 // Save Cr3\r
1216 //\r
1217 mSmmProfileCr3 = Cr3;\r
1218\r
1219 //\r
1220 // Skip SMM profile initialization if feature is disabled\r
1221 //\r
09afd9a4
JW
1222 if (!FeaturePcdGet (PcdCpuSmmProfileEnable) &&\r
1223 !HEAP_GUARD_NONSTOP_MODE &&\r
053e878b
MK
1224 !NULL_DETECTION_NONSTOP_MODE)\r
1225 {\r
529a5a86
MK
1226 return;\r
1227 }\r
1228\r
1229 //\r
1230 // Initialize SmmProfile here\r
1231 //\r
1232 InitSmmProfileInternal ();\r
1233\r
1234 //\r
1235 // Initialize profile IDT.\r
1236 //\r
1237 InitIdtr ();\r
09afd9a4
JW
1238\r
1239 //\r
1240 // Tell #PF handler to prepare a #DB subsequently.\r
1241 //\r
1242 mSetupDebugTrap = TRUE;\r
529a5a86
MK
1243}\r
1244\r
1245/**\r
1246 Update page table to map the memory correctly in order to make the instruction\r
1247 which caused page fault execute successfully. And it also save the original page\r
1248 table to be restored in single-step exception.\r
1249\r
1250 @param PageTable PageTable Address.\r
1251 @param PFAddress The memory address which caused page fault exception.\r
1252 @param CpuIndex The index of the processor.\r
1253 @param ErrorCode The Error code of exception.\r
1254\r
1255**/\r
1256VOID\r
1257RestorePageTableBelow4G (\r
053e878b
MK
1258 UINT64 *PageTable,\r
1259 UINT64 PFAddress,\r
1260 UINTN CpuIndex,\r
1261 UINTN ErrorCode\r
529a5a86
MK
1262 )\r
1263{\r
053e878b
MK
1264 UINTN PTIndex;\r
1265 UINTN PFIndex;\r
1266 IA32_CR4 Cr4;\r
1267 BOOLEAN Enable5LevelPaging;\r
4eee0cc7 1268\r
053e878b
MK
1269 Cr4.UintN = AsmReadCr4 ();\r
1270 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);\r
4eee0cc7
RN
1271\r
1272 //\r
1273 // PML5\r
1274 //\r
1275 if (Enable5LevelPaging) {\r
1276 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 48, 56);\r
1277 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1278 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 1279 }\r
529a5a86
MK
1280\r
1281 //\r
1282 // PML4\r
1283 //\r
053e878b 1284 if (sizeof (UINT64) == sizeof (UINTN)) {\r
529a5a86
MK
1285 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 39, 47);\r
1286 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1287 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1288 }\r
1289\r
1290 //\r
1291 // PDPTE\r
1292 //\r
1293 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 30, 38);\r
1294 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1295 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1296\r
1297 //\r
1298 // PD\r
1299 //\r
1300 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 21, 29);\r
1301 if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {\r
1302 //\r
1303 // Large page\r
1304 //\r
1305\r
1306 //\r
1307 // Record old entries with non-present status\r
1308 // Old entries include the memory which instruction is at and the memory which instruction access.\r
1309 //\r
1310 //\r
1311 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);\r
1312 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {\r
053e878b 1313 PFIndex = mPFEntryCount[CpuIndex];\r
529a5a86
MK
1314 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];\r
1315 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];\r
1316 mPFEntryCount[CpuIndex]++;\r
1317 }\r
1318\r
1319 //\r
1320 // Set new entry\r
1321 //\r
053e878b 1322 PageTable[PTIndex] = (PFAddress & ~((1ull << 21) - 1));\r
529a5a86 1323 PageTable[PTIndex] |= (UINT64)IA32_PG_PS;\r
881520ea 1324 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;\r
529a5a86
MK
1325 if ((ErrorCode & IA32_PF_EC_ID) != 0) {\r
1326 PageTable[PTIndex] &= ~IA32_PG_NX;\r
1327 }\r
1328 } else {\r
1329 //\r
1330 // Small page\r
1331 //\r
1332 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1333 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1334\r
1335 //\r
1336 // 4K PTE\r
1337 //\r
1338 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 12, 20);\r
1339\r
1340 //\r
1341 // Record old entries with non-present status\r
1342 // Old entries include the memory which instruction is at and the memory which instruction access.\r
1343 //\r
1344 //\r
1345 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);\r
1346 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {\r
053e878b 1347 PFIndex = mPFEntryCount[CpuIndex];\r
529a5a86
MK
1348 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];\r
1349 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];\r
1350 mPFEntryCount[CpuIndex]++;\r
1351 }\r
1352\r
1353 //\r
1354 // Set new entry\r
1355 //\r
053e878b 1356 PageTable[PTIndex] = (PFAddress & ~((1ull << 12) - 1));\r
881520ea 1357 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;\r
529a5a86
MK
1358 if ((ErrorCode & IA32_PF_EC_ID) != 0) {\r
1359 PageTable[PTIndex] &= ~IA32_PG_NX;\r
1360 }\r
1361 }\r
1362}\r
1363\r
09afd9a4
JW
1364/**\r
1365 Handler for Page Fault triggered by Guard page.\r
1366\r
1367 @param ErrorCode The Error code of exception.\r
1368\r
1369**/\r
1370VOID\r
1371GuardPagePFHandler (\r
053e878b 1372 UINTN ErrorCode\r
09afd9a4
JW
1373 )\r
1374{\r
053e878b
MK
1375 UINT64 *PageTable;\r
1376 UINT64 PFAddress;\r
1377 UINT64 RestoreAddress;\r
1378 UINTN RestorePageNumber;\r
1379 UINTN CpuIndex;\r
09afd9a4 1380\r
053e878b
MK
1381 PageTable = (UINT64 *)AsmReadCr3 ();\r
1382 PFAddress = AsmReadCr2 ();\r
1383 CpuIndex = GetCpuIndex ();\r
09afd9a4
JW
1384\r
1385 //\r
1386 // Memory operation cross pages, like "rep mov" instruction, will cause\r
1387 // infinite loop between this and Debug Trap handler. We have to make sure\r
1388 // that current page and the page followed are both in PRESENT state.\r
1389 //\r
1390 RestorePageNumber = 2;\r
053e878b 1391 RestoreAddress = PFAddress;\r
09afd9a4
JW
1392 while (RestorePageNumber > 0) {\r
1393 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
1394 RestoreAddress += EFI_PAGE_SIZE;\r
1395 RestorePageNumber--;\r
1396 }\r
1397\r
1398 //\r
1399 // Flush TLB\r
1400 //\r
1401 CpuFlushTlb ();\r
1402}\r
1403\r
529a5a86
MK
1404/**\r
1405 The Page fault handler to save SMM profile data.\r
1406\r
1407 @param Rip The RIP when exception happens.\r
1408 @param ErrorCode The Error code of exception.\r
1409\r
1410**/\r
1411VOID\r
1412SmmProfilePFHandler (\r
053e878b
MK
1413 UINTN Rip,\r
1414 UINTN ErrorCode\r
529a5a86
MK
1415 )\r
1416{\r
053e878b
MK
1417 UINT64 *PageTable;\r
1418 UINT64 PFAddress;\r
1419 UINT64 RestoreAddress;\r
1420 UINTN RestorePageNumber;\r
1421 UINTN CpuIndex;\r
1422 UINTN Index;\r
1423 UINT64 InstructionAddress;\r
1424 UINTN MaxEntryNumber;\r
1425 UINTN CurrentEntryNumber;\r
1426 BOOLEAN IsValidPFAddress;\r
1427 SMM_PROFILE_ENTRY *SmmProfileEntry;\r
1428 UINT64 SmiCommand;\r
1429 EFI_STATUS Status;\r
1430 UINT8 SoftSmiValue;\r
1431 EFI_SMM_SAVE_STATE_IO_INFO IoInfo;\r
529a5a86
MK
1432\r
1433 if (!mSmmProfileStart) {\r
1434 //\r
1435 // If SMM profile does not start, call original page fault handler.\r
1436 //\r
1437 SmiDefaultPFHandler ();\r
1438 return;\r
1439 }\r
1440\r
1441 if (mBtsSupported) {\r
1442 DisableBTS ();\r
1443 }\r
1444\r
053e878b
MK
1445 IsValidPFAddress = FALSE;\r
1446 PageTable = (UINT64 *)AsmReadCr3 ();\r
1447 PFAddress = AsmReadCr2 ();\r
1448 CpuIndex = GetCpuIndex ();\r
529a5a86 1449\r
890d9ee5
JW
1450 //\r
1451 // Memory operation cross pages, like "rep mov" instruction, will cause\r
1452 // infinite loop between this and Debug Trap handler. We have to make sure\r
1453 // that current page and the page followed are both in PRESENT state.\r
1454 //\r
1455 RestorePageNumber = 2;\r
053e878b 1456 RestoreAddress = PFAddress;\r
890d9ee5
JW
1457 while (RestorePageNumber > 0) {\r
1458 if (RestoreAddress <= 0xFFFFFFFF) {\r
1459 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
1460 } else {\r
1461 RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\r
1462 }\r
053e878b 1463\r
890d9ee5
JW
1464 RestoreAddress += EFI_PAGE_SIZE;\r
1465 RestorePageNumber--;\r
529a5a86
MK
1466 }\r
1467\r
1468 if (!IsValidPFAddress) {\r
1469 InstructionAddress = Rip;\r
053e878b 1470 if (((ErrorCode & IA32_PF_EC_ID) != 0) && (mBtsSupported)) {\r
529a5a86
MK
1471 //\r
1472 // If it is instruction fetch failure, get the correct IP from BTS.\r
1473 //\r
1474 InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip);\r
1475 if (InstructionAddress == 0) {\r
1476 //\r
1477 // It indicates the instruction which caused page fault is not a jump instruction,\r
1478 // set instruction address same as the page fault address.\r
1479 //\r
1480 InstructionAddress = PFAddress;\r
1481 }\r
1482 }\r
1483\r
529a5a86
MK
1484 //\r
1485 // Indicate it is not software SMI\r
1486 //\r
053e878b 1487 SmiCommand = 0xFFFFFFFFFFFFFFFFULL;\r
529a5a86 1488 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
053e878b 1489 Status = SmmReadSaveState (&mSmmCpu, sizeof (IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo);\r
529a5a86
MK
1490 if (EFI_ERROR (Status)) {\r
1491 continue;\r
1492 }\r
053e878b 1493\r
529a5a86 1494 if (IoInfo.IoPort == mSmiCommandPort) {\r
529a5a86
MK
1495 //\r
1496 // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port.\r
1497 //\r
1498 SoftSmiValue = IoRead8 (mSmiCommandPort);\r
053e878b 1499 SmiCommand = (UINT64)SoftSmiValue;\r
529a5a86
MK
1500 break;\r
1501 }\r
1502 }\r
1503\r
1504 SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1);\r
1505 //\r
1506 // Check if there is already a same entry in profile data.\r
1507 //\r
053e878b 1508 for (Index = 0; Index < (UINTN)mSmmProfileBase->CurDataEntries; Index++) {\r
529a5a86
MK
1509 if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) &&\r
1510 (SmmProfileEntry[Index].Address == PFAddress) &&\r
1511 (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) &&\r
1512 (SmmProfileEntry[Index].Instruction == InstructionAddress) &&\r
053e878b
MK
1513 (SmmProfileEntry[Index].SmiCmd == SmiCommand))\r
1514 {\r
529a5a86
MK
1515 //\r
1516 // Same record exist, need not save again.\r
1517 //\r
1518 break;\r
1519 }\r
1520 }\r
053e878b 1521\r
529a5a86 1522 if (Index == mSmmProfileBase->CurDataEntries) {\r
053e878b
MK
1523 CurrentEntryNumber = (UINTN)mSmmProfileBase->CurDataEntries;\r
1524 MaxEntryNumber = (UINTN)mSmmProfileBase->MaxDataEntries;\r
529a5a86
MK
1525 if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) {\r
1526 CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber;\r
1527 }\r
053e878b 1528\r
529a5a86
MK
1529 if (CurrentEntryNumber < MaxEntryNumber) {\r
1530 //\r
1531 // Log the new entry\r
1532 //\r
1533 SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis;\r
1534 SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode;\r
1535 SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId ();\r
1536 SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex;\r
1537 SmmProfileEntry[CurrentEntryNumber].Address = PFAddress;\r
1538 SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress;\r
1539 SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand;\r
1540 //\r
1541 // Update current entry index and data size in the header.\r
1542 //\r
1543 mSmmProfileBase->CurDataEntries++;\r
1544 mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY));\r
1545 }\r
1546 }\r
1547 }\r
053e878b 1548\r
529a5a86
MK
1549 //\r
1550 // Flush TLB\r
1551 //\r
1552 CpuFlushTlb ();\r
1553\r
1554 if (mBtsSupported) {\r
1555 EnableBTS ();\r
1556 }\r
1557}\r
1558\r
1559/**\r
1560 Replace INT1 exception handler to restore page table to absent/execute-disable state\r
1561 in order to trigger page fault again to save SMM profile data..\r
1562\r
1563**/\r
1564VOID\r
1565InitIdtr (\r
1566 VOID\r
1567 )\r
1568{\r
053e878b 1569 EFI_STATUS Status;\r
5c88af79
JF
1570\r
1571 Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);\r
1572 ASSERT_EFI_ERROR (Status);\r
529a5a86 1573}\r