]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
UefiCpuPkg: Replace Opcode with the corresponding instructions.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmProfile.c
CommitLineData
529a5a86
MK
1/** @file\r
2Enable SMM profile.\r
3\r
3eb69b08 4Copyright (c) 2012 - 2019, 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
MK
589 SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1;\r
590 //\r
591 // Calculate the table entries of PML4E and PDPTE.\r
592 //\r
4eee0cc7
RN
593 NumberOfPml5Entries = 1;\r
594 if (SizeOfMemorySpace > 48) {\r
053e878b
MK
595 NumberOfPml5Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 48);\r
596 SizeOfMemorySpace = 48;\r
7365eb2c 597 }\r
4eee0cc7 598\r
4e78c7be 599 NumberOfPml4Entries = 1;\r
4eee0cc7 600 if (SizeOfMemorySpace > 39) {\r
053e878b
MK
601 NumberOfPml4Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 39);\r
602 SizeOfMemorySpace = 39;\r
4eee0cc7
RN
603 }\r
604\r
605 NumberOfPdptEntries = 1;\r
606 ASSERT (SizeOfMemorySpace > 30);\r
053e878b 607 NumberOfPdptEntries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 30);\r
4eee0cc7 608 } else {\r
053e878b
MK
609 Pml4Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P;\r
610 Pml4 = &Pml4Entry;\r
611 Pml5Entry = (UINTN)Pml4 | IA32_PG_P;\r
612 Pml5 = &Pml5Entry;\r
613 NumberOfPml5Entries = 1;\r
614 NumberOfPml4Entries = 1;\r
615 NumberOfPdptEntries = 4;\r
529a5a86
MK
616 }\r
617\r
618 //\r
619 // Go through page table and change 2MB-page into 4KB-page.\r
620 //\r
4eee0cc7
RN
621 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
622 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
623 //\r
624 // If PML5 entry does not exist, skip it\r
625 //\r
626 continue;\r
627 }\r
053e878b
MK
628\r
629 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 630 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
7e56f892 631 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
529a5a86 632 //\r
7e56f892 633 // If PML4 entry does not exist, skip it\r
529a5a86
MK
634 //\r
635 continue;\r
636 }\r
053e878b 637\r
7e56f892 638 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7
RN
639 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
640 if ((*Pdpt & IA32_PG_P) == 0) {\r
641 //\r
642 // If PDPT entry does not exist, skip it\r
643 //\r
644 continue;\r
645 }\r
053e878b 646\r
4eee0cc7 647 if ((*Pdpt & IA32_PG_PS) != 0) {\r
529a5a86 648 //\r
4eee0cc7 649 // This is 1G entry, skip it\r
529a5a86
MK
650 //\r
651 continue;\r
652 }\r
053e878b 653\r
4eee0cc7
RN
654 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
655 if (Pd == 0) {\r
656 continue;\r
657 }\r
053e878b 658\r
4eee0cc7
RN
659 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
660 if ((*Pd & IA32_PG_P) == 0) {\r
661 //\r
662 // If PD entry does not exist, skip it\r
663 //\r
664 continue;\r
665 }\r
053e878b
MK
666\r
667 Address = (UINTN)LShiftU64 (\r
668 LShiftU64 (\r
669 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
670 9\r
671 ) + PdIndex,\r
672 21\r
673 );\r
529a5a86 674\r
529a5a86 675 //\r
4eee0cc7 676 // If it is 2M page, check IsAddressSplit()\r
529a5a86 677 //\r
4eee0cc7
RN
678 if (((*Pd & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {\r
679 //\r
680 // Based on current page table, create 4KB page table for split area.\r
681 //\r
682 ASSERT (Address == (*Pd & PHYSICAL_ADDRESS_MASK));\r
683\r
684 Pt = AllocatePageTableMemory (1);\r
685 ASSERT (Pt != NULL);\r
529a5a86 686\r
4eee0cc7 687 // Split it\r
053e878b 688 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++) {\r
a5235562 689 Pt[PtIndex] = Address + ((PtIndex << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
4eee0cc7 690 } // end for PT\r
053e878b 691\r
4eee0cc7
RN
692 *Pd = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
693 } // end if IsAddressSplit\r
694 } // end for PD\r
695 } // end for PDPT\r
696 } // end for PML4\r
697 } // end for PML5\r
529a5a86
MK
698\r
699 //\r
700 // Go through page table and set several page table entries to absent or execute-disable.\r
701 //\r
96e1cba5 702 DEBUG ((DEBUG_INFO, "Patch page table start ...\n"));\r
4eee0cc7
RN
703 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
704 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
705 //\r
706 // If PML5 entry does not exist, skip it\r
707 //\r
708 continue;\r
709 }\r
053e878b
MK
710\r
711 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 712 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
7e56f892 713 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
529a5a86 714 //\r
7e56f892 715 // If PML4 entry does not exist, skip it\r
529a5a86
MK
716 //\r
717 continue;\r
718 }\r
053e878b 719\r
7e56f892 720 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7
RN
721 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
722 if ((*Pdpt & IA32_PG_P) == 0) {\r
723 //\r
724 // If PDPT entry does not exist, skip it\r
725 //\r
726 continue;\r
717fb604 727 }\r
053e878b 728\r
4eee0cc7 729 if ((*Pdpt & IA32_PG_PS) != 0) {\r
529a5a86 730 //\r
4eee0cc7 731 // This is 1G entry, set NX bit and skip it\r
529a5a86 732 //\r
4eee0cc7
RN
733 if (mXdSupported) {\r
734 *Pdpt = *Pdpt | IA32_PG_NX;\r
735 }\r
053e878b 736\r
529a5a86
MK
737 continue;\r
738 }\r
053e878b 739\r
4eee0cc7
RN
740 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
741 if (Pd == 0) {\r
742 continue;\r
743 }\r
053e878b 744\r
4eee0cc7
RN
745 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
746 if ((*Pd & IA32_PG_P) == 0) {\r
529a5a86 747 //\r
4eee0cc7 748 // If PD entry does not exist, skip it\r
529a5a86 749 //\r
529a5a86
MK
750 continue;\r
751 }\r
053e878b
MK
752\r
753 Address = (UINTN)LShiftU64 (\r
754 LShiftU64 (\r
755 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
756 9\r
757 ) + PdIndex,\r
758 21\r
759 );\r
4eee0cc7
RN
760\r
761 if ((*Pd & IA32_PG_PS) != 0) {\r
762 // 2MB page\r
763\r
529a5a86 764 if (!IsAddressValid (Address, &Nx)) {\r
4eee0cc7
RN
765 //\r
766 // Patch to remove Present flag and RW flag\r
767 //\r
768 *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
529a5a86 769 }\r
053e878b 770\r
529a5a86 771 if (Nx && mXdSupported) {\r
4eee0cc7
RN
772 *Pd = *Pd | IA32_PG_NX;\r
773 }\r
774 } else {\r
775 // 4KB page\r
776 Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
777 if (Pt == 0) {\r
778 continue;\r
529a5a86 779 }\r
053e878b
MK
780\r
781 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++, Pt++) {\r
4eee0cc7
RN
782 if (!IsAddressValid (Address, &Nx)) {\r
783 *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
784 }\r
053e878b 785\r
4eee0cc7
RN
786 if (Nx && mXdSupported) {\r
787 *Pt = *Pt | IA32_PG_NX;\r
788 }\r
053e878b 789\r
4eee0cc7
RN
790 Address += SIZE_4KB;\r
791 } // end for PT\r
792 } // end if PS\r
793 } // end for PD\r
794 } // end for PDPT\r
795 } // end for PML4\r
796 } // end for PML5\r
529a5a86
MK
797\r
798 //\r
799 // Flush TLB\r
800 //\r
801 CpuFlushTlb ();\r
96e1cba5 802 DEBUG ((DEBUG_INFO, "Patch page table done!\n"));\r
529a5a86
MK
803 //\r
804 // Set execute-disable flag\r
805 //\r
806 mXdEnabled = TRUE;\r
807\r
053e878b 808 return;\r
529a5a86
MK
809}\r
810\r
529a5a86
MK
811/**\r
812 To get system port address of the SMI Command Port in FADT table.\r
813\r
814**/\r
815VOID\r
816GetSmiCommandPort (\r
817 VOID\r
818 )\r
819{\r
053e878b 820 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;\r
529a5a86 821\r
053e878b
MK
822 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)EfiLocateFirstAcpiTable (\r
823 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE\r
824 );\r
529a5a86
MK
825 ASSERT (Fadt != NULL);\r
826\r
827 mSmiCommandPort = Fadt->SmiCmd;\r
96e1cba5 828 DEBUG ((DEBUG_INFO, "mSmiCommandPort = %x\n", mSmiCommandPort));\r
529a5a86
MK
829}\r
830\r
831/**\r
832 Updates page table to make some memory ranges (like system memory) absent\r
833 and make some memory ranges (like MMIO) present and execute disable. It also\r
834 update 2MB-page to 4KB-page for some memory ranges.\r
835\r
836**/\r
837VOID\r
838SmmProfileStart (\r
839 VOID\r
840 )\r
841{\r
842 //\r
843 // The flag indicates SMM profile starts to work.\r
844 //\r
845 mSmmProfileStart = TRUE;\r
846}\r
847\r
848/**\r
849 Initialize SMM profile in SmmReadyToLock protocol callback function.\r
850\r
851 @param Protocol Points to the protocol's unique identifier.\r
852 @param Interface Points to the interface instance.\r
853 @param Handle The handle on which the interface was installed.\r
854\r
855 @retval EFI_SUCCESS SmmReadyToLock protocol callback runs successfully.\r
856**/\r
857EFI_STATUS\r
858EFIAPI\r
859InitSmmProfileCallBack (\r
860 IN CONST EFI_GUID *Protocol,\r
861 IN VOID *Interface,\r
862 IN EFI_HANDLE Handle\r
863 )\r
864{\r
529a5a86
MK
865 //\r
866 // Save to variable so that SMM profile data can be found.\r
867 //\r
dc0a7143
LE
868 gRT->SetVariable (\r
869 SMM_PROFILE_NAME,\r
870 &gEfiCallerIdGuid,\r
871 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
053e878b 872 sizeof (mSmmProfileBase),\r
dc0a7143
LE
873 &mSmmProfileBase\r
874 );\r
529a5a86
MK
875\r
876 //\r
877 // Get Software SMI from FADT\r
878 //\r
879 GetSmiCommandPort ();\r
880\r
881 //\r
882 // Initialize protected memory range for patching page table later.\r
883 //\r
884 InitProtectedMemRange ();\r
885\r
886 return EFI_SUCCESS;\r
887}\r
888\r
889/**\r
890 Initialize SMM profile data structures.\r
891\r
892**/\r
893VOID\r
894InitSmmProfileInternal (\r
895 VOID\r
896 )\r
897{\r
053e878b
MK
898 EFI_STATUS Status;\r
899 EFI_PHYSICAL_ADDRESS Base;\r
900 VOID *Registration;\r
901 UINTN Index;\r
902 UINTN MsrDsAreaSizePerCpu;\r
903 UINTN TotalSize;\r
529a5a86 904\r
bb767506 905 mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus);\r
529a5a86 906 ASSERT (mPFEntryCount != NULL);\r
053e878b
MK
907 mLastPFEntryValue = (UINT64 (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
908 sizeof (mLastPFEntryValue[0]) * mMaxNumberOfCpus\r
909 );\r
529a5a86
MK
910 ASSERT (mLastPFEntryValue != NULL);\r
911 mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
053e878b
MK
912 sizeof (mLastPFEntryPointer[0]) * mMaxNumberOfCpus\r
913 );\r
529a5a86
MK
914 ASSERT (mLastPFEntryPointer != NULL);\r
915\r
916 //\r
917 // Allocate memory for SmmProfile below 4GB.\r
918 // The base address\r
919 //\r
920 mSmmProfileSize = PcdGet32 (PcdCpuSmmProfileSize);\r
921 ASSERT ((mSmmProfileSize & 0xFFF) == 0);\r
922\r
923 if (mBtsSupported) {\r
924 TotalSize = mSmmProfileSize + mMsrDsAreaSize;\r
925 } else {\r
926 TotalSize = mSmmProfileSize;\r
927 }\r
928\r
053e878b 929 Base = 0xFFFFFFFF;\r
529a5a86
MK
930 Status = gBS->AllocatePages (\r
931 AllocateMaxAddress,\r
932 EfiReservedMemoryType,\r
933 EFI_SIZE_TO_PAGES (TotalSize),\r
934 &Base\r
935 );\r
936 ASSERT_EFI_ERROR (Status);\r
937 ZeroMem ((VOID *)(UINTN)Base, TotalSize);\r
938 mSmmProfileBase = (SMM_PROFILE_HEADER *)(UINTN)Base;\r
939\r
940 //\r
941 // Initialize SMM profile data header.\r
942 //\r
943 mSmmProfileBase->HeaderSize = sizeof (SMM_PROFILE_HEADER);\r
053e878b
MK
944 mSmmProfileBase->MaxDataEntries = (UINT64)((mSmmProfileSize - sizeof (SMM_PROFILE_HEADER)) / sizeof (SMM_PROFILE_ENTRY));\r
945 mSmmProfileBase->MaxDataSize = MultU64x64 (mSmmProfileBase->MaxDataEntries, sizeof (SMM_PROFILE_ENTRY));\r
529a5a86
MK
946 mSmmProfileBase->CurDataEntries = 0;\r
947 mSmmProfileBase->CurDataSize = 0;\r
948 mSmmProfileBase->TsegStart = mCpuHotPlugData.SmrrBase;\r
949 mSmmProfileBase->TsegSize = mCpuHotPlugData.SmrrSize;\r
950 mSmmProfileBase->NumSmis = 0;\r
951 mSmmProfileBase->NumCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
952\r
953 if (mBtsSupported) {\r
bb767506 954 mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * mMaxNumberOfCpus);\r
529a5a86 955 ASSERT (mMsrDsArea != NULL);\r
bb767506 956 mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * mMaxNumberOfCpus);\r
529a5a86 957 ASSERT (mMsrBTSRecord != NULL);\r
bb767506 958 mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * mMaxNumberOfCpus);\r
529a5a86
MK
959 ASSERT (mMsrPEBSRecord != NULL);\r
960\r
053e878b 961 mMsrDsAreaBase = (MSR_DS_AREA_STRUCT *)((UINTN)Base + mSmmProfileSize);\r
bb767506 962 MsrDsAreaSizePerCpu = mMsrDsAreaSize / mMaxNumberOfCpus;\r
053e878b 963 mBTSRecordNumber = (MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof (MSR_DS_AREA_STRUCT)) / sizeof (BRANCH_TRACE_RECORD);\r
bb767506 964 for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
529a5a86 965 mMsrDsArea[Index] = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index);\r
053e878b
MK
966 mMsrBTSRecord[Index] = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof (MSR_DS_AREA_STRUCT));\r
967 mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER);\r
529a5a86 968\r
053e878b
MK
969 mMsrDsArea[Index]->BTSBufferBase = (UINTN)mMsrBTSRecord[Index];\r
970 mMsrDsArea[Index]->BTSIndex = mMsrDsArea[Index]->BTSBufferBase;\r
971 mMsrDsArea[Index]->BTSAbsoluteMaximum = mMsrDsArea[Index]->BTSBufferBase + mBTSRecordNumber * sizeof (BRANCH_TRACE_RECORD) + 1;\r
972 mMsrDsArea[Index]->BTSInterruptThreshold = mMsrDsArea[Index]->BTSAbsoluteMaximum + 1;\r
529a5a86
MK
973\r
974 mMsrDsArea[Index]->PEBSBufferBase = (UINTN)mMsrPEBSRecord[Index];\r
975 mMsrDsArea[Index]->PEBSIndex = mMsrDsArea[Index]->PEBSBufferBase;\r
053e878b 976 mMsrDsArea[Index]->PEBSAbsoluteMaximum = mMsrDsArea[Index]->PEBSBufferBase + PEBS_RECORD_NUMBER * sizeof (PEBS_RECORD) + 1;\r
529a5a86
MK
977 mMsrDsArea[Index]->PEBSInterruptThreshold = mMsrDsArea[Index]->PEBSAbsoluteMaximum + 1;\r
978 }\r
979 }\r
980\r
981 mProtectionMemRange = mProtectionMemRangeTemplate;\r
982 mProtectionMemRangeCount = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
983\r
984 //\r
985 // Update TSeg entry.\r
986 //\r
987 mProtectionMemRange[0].Range.Base = mCpuHotPlugData.SmrrBase;\r
988 mProtectionMemRange[0].Range.Top = mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize;\r
989\r
990 //\r
991 // Update SMM profile entry.\r
992 //\r
993 mProtectionMemRange[1].Range.Base = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase;\r
994 mProtectionMemRange[1].Range.Top = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase + TotalSize;\r
995\r
996 //\r
997 // Allocate memory reserved for creating 4KB pages.\r
998 //\r
999 InitPagesForPFHandler ();\r
1000\r
1001 //\r
1002 // Start SMM profile when SmmReadyToLock protocol is installed.\r
1003 //\r
1004 Status = gSmst->SmmRegisterProtocolNotify (\r
1005 &gEfiSmmReadyToLockProtocolGuid,\r
1006 InitSmmProfileCallBack,\r
1007 &Registration\r
1008 );\r
1009 ASSERT_EFI_ERROR (Status);\r
1010\r
053e878b 1011 return;\r
529a5a86
MK
1012}\r
1013\r
1014/**\r
3eb69b08 1015 Check if feature is supported by a processor.\r
529a5a86
MK
1016\r
1017**/\r
1018VOID\r
1019CheckFeatureSupported (\r
51773d49 1020 VOID\r
529a5a86
MK
1021 )\r
1022{\r
f85d3ce2 1023 UINT32 RegEax;\r
3eb69b08 1024 UINT32 RegEcx;\r
f85d3ce2
JF
1025 UINT32 RegEdx;\r
1026 MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;\r
529a5a86 1027\r
3eb69b08 1028 if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
5d34cc49
WH
1029 AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);\r
1030 if (RegEax >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {\r
1031 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, NULL);\r
1032 if ((RegEcx & CPUID_CET_SS) == 0) {\r
1033 mCetSupported = FALSE;\r
1034 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
1035 }\r
1036 } else {\r
3eb69b08
JY
1037 mCetSupported = FALSE;\r
1038 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
1039 }\r
1040 }\r
1041\r
529a5a86
MK
1042 if (mXdSupported) {\r
1043 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
1044 if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
1045 //\r
1046 // Extended CPUID functions are not supported on this processor.\r
1047 //\r
1048 mXdSupported = FALSE;\r
3c5ce64f 1049 PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
529a5a86
MK
1050 }\r
1051\r
1052 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
1053 if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {\r
1054 //\r
1055 // Execute Disable Bit feature is not supported on this processor.\r
1056 //\r
1057 mXdSupported = FALSE;\r
3c5ce64f 1058 PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
529a5a86 1059 }\r
bdafda8c
KG
1060\r
1061 if (StandardSignatureIsAuthenticAMD ()) {\r
1062 //\r
1063 // AMD processors do not support MSR_IA32_MISC_ENABLE\r
1064 //\r
1065 PatchInstructionX86 (gPatchMsrIa32MiscEnableSupported, FALSE, 1);\r
1066 }\r
529a5a86
MK
1067 }\r
1068\r
1069 if (mBtsSupported) {\r
1070 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);\r
1071 if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) {\r
1072 //\r
1073 // Per IA32 manuals:\r
1074 // When CPUID.1:EDX[21] is set, the following BTS facilities are available:\r
1075 // 1. The BTS_UNAVAILABLE flag in the IA32_MISC_ENABLE MSR indicates the\r
1076 // availability of the BTS facilities, including the ability to set the BTS and\r
1077 // BTINT bits in the MSR_DEBUGCTLA MSR.\r
1078 // 2. The IA32_DS_AREA MSR can be programmed to point to the DS save area.\r
1079 //\r
f85d3ce2
JF
1080 MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
1081 if (MiscEnableMsr.Bits.BTS == 1) {\r
529a5a86 1082 //\r
f85d3ce2 1083 // BTS facilities is not supported if MSR_IA32_MISC_ENABLE.BTS bit is set.\r
529a5a86
MK
1084 //\r
1085 mBtsSupported = FALSE;\r
1086 }\r
1087 }\r
1088 }\r
1089}\r
1090\r
529a5a86
MK
1091/**\r
1092 Enable single step.\r
1093\r
1094**/\r
1095VOID\r
1096ActivateSingleStepDB (\r
1097 VOID\r
1098 )\r
1099{\r
053e878b 1100 UINTN Dr6;\r
529a5a86
MK
1101\r
1102 Dr6 = AsmReadDr6 ();\r
1103 if ((Dr6 & DR6_SINGLE_STEP) != 0) {\r
1104 return;\r
1105 }\r
053e878b 1106\r
529a5a86
MK
1107 Dr6 |= DR6_SINGLE_STEP;\r
1108 AsmWriteDr6 (Dr6);\r
1109}\r
1110\r
1111/**\r
1112 Enable last branch.\r
1113\r
1114**/\r
1115VOID\r
1116ActivateLBR (\r
1117 VOID\r
1118 )\r
1119{\r
1120 UINT64 DebugCtl;\r
1121\r
1122 DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);\r
1123 if ((DebugCtl & MSR_DEBUG_CTL_LBR) != 0) {\r
053e878b 1124 return;\r
529a5a86 1125 }\r
053e878b 1126\r
529a5a86
MK
1127 DebugCtl |= MSR_DEBUG_CTL_LBR;\r
1128 AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);\r
1129}\r
1130\r
1131/**\r
1132 Enable branch trace store.\r
1133\r
1134 @param CpuIndex The index of the processor.\r
1135\r
1136**/\r
1137VOID\r
1138ActivateBTS (\r
053e878b 1139 IN UINTN CpuIndex\r
529a5a86
MK
1140 )\r
1141{\r
1142 UINT64 DebugCtl;\r
1143\r
1144 DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);\r
1145 if ((DebugCtl & MSR_DEBUG_CTL_BTS) != 0) {\r
053e878b 1146 return;\r
529a5a86
MK
1147 }\r
1148\r
1149 AsmWriteMsr64 (MSR_DS_AREA, (UINT64)(UINTN)mMsrDsArea[CpuIndex]);\r
1150 DebugCtl |= (UINT64)(MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR);\r
1151 DebugCtl &= ~((UINT64)MSR_DEBUG_CTL_BTINT);\r
1152 AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);\r
1153}\r
1154\r
1155/**\r
1156 Increase SMI number in each SMI entry.\r
1157\r
1158**/\r
1159VOID\r
1160SmmProfileRecordSmiNum (\r
1161 VOID\r
1162 )\r
1163{\r
1164 if (mSmmProfileStart) {\r
1165 mSmmProfileBase->NumSmis++;\r
1166 }\r
1167}\r
1168\r
1169/**\r
1170 Initialize processor environment for SMM profile.\r
1171\r
1172 @param CpuIndex The index of the processor.\r
1173\r
1174**/\r
1175VOID\r
1176ActivateSmmProfile (\r
053e878b 1177 IN UINTN CpuIndex\r
529a5a86
MK
1178 )\r
1179{\r
1180 //\r
1181 // Enable Single Step DB#\r
1182 //\r
1183 ActivateSingleStepDB ();\r
1184\r
1185 if (mBtsSupported) {\r
1186 //\r
1187 // We can not get useful information from LER, so we have to use BTS.\r
1188 //\r
1189 ActivateLBR ();\r
1190\r
1191 //\r
1192 // Enable BTS\r
1193 //\r
1194 ActivateBTS (CpuIndex);\r
1195 }\r
1196}\r
1197\r
1198/**\r
1199 Initialize SMM profile in SMM CPU entry point.\r
1200\r
1201 @param[in] Cr3 The base address of the page tables to use in SMM.\r
1202\r
1203**/\r
1204VOID\r
1205InitSmmProfile (\r
1206 UINT32 Cr3\r
1207 )\r
1208{\r
1209 //\r
1210 // Save Cr3\r
1211 //\r
1212 mSmmProfileCr3 = Cr3;\r
1213\r
1214 //\r
1215 // Skip SMM profile initialization if feature is disabled\r
1216 //\r
09afd9a4
JW
1217 if (!FeaturePcdGet (PcdCpuSmmProfileEnable) &&\r
1218 !HEAP_GUARD_NONSTOP_MODE &&\r
053e878b
MK
1219 !NULL_DETECTION_NONSTOP_MODE)\r
1220 {\r
529a5a86
MK
1221 return;\r
1222 }\r
1223\r
1224 //\r
1225 // Initialize SmmProfile here\r
1226 //\r
1227 InitSmmProfileInternal ();\r
1228\r
1229 //\r
1230 // Initialize profile IDT.\r
1231 //\r
1232 InitIdtr ();\r
09afd9a4
JW
1233\r
1234 //\r
1235 // Tell #PF handler to prepare a #DB subsequently.\r
1236 //\r
1237 mSetupDebugTrap = TRUE;\r
529a5a86
MK
1238}\r
1239\r
1240/**\r
1241 Update page table to map the memory correctly in order to make the instruction\r
1242 which caused page fault execute successfully. And it also save the original page\r
1243 table to be restored in single-step exception.\r
1244\r
1245 @param PageTable PageTable Address.\r
1246 @param PFAddress The memory address which caused page fault exception.\r
1247 @param CpuIndex The index of the processor.\r
1248 @param ErrorCode The Error code of exception.\r
1249\r
1250**/\r
1251VOID\r
1252RestorePageTableBelow4G (\r
053e878b
MK
1253 UINT64 *PageTable,\r
1254 UINT64 PFAddress,\r
1255 UINTN CpuIndex,\r
1256 UINTN ErrorCode\r
529a5a86
MK
1257 )\r
1258{\r
053e878b
MK
1259 UINTN PTIndex;\r
1260 UINTN PFIndex;\r
1261 IA32_CR4 Cr4;\r
1262 BOOLEAN Enable5LevelPaging;\r
4eee0cc7 1263\r
053e878b
MK
1264 Cr4.UintN = AsmReadCr4 ();\r
1265 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);\r
4eee0cc7
RN
1266\r
1267 //\r
1268 // PML5\r
1269 //\r
1270 if (Enable5LevelPaging) {\r
1271 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 48, 56);\r
1272 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1273 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
4eee0cc7 1274 }\r
529a5a86
MK
1275\r
1276 //\r
1277 // PML4\r
1278 //\r
053e878b 1279 if (sizeof (UINT64) == sizeof (UINTN)) {\r
529a5a86
MK
1280 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 39, 47);\r
1281 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1282 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1283 }\r
1284\r
1285 //\r
1286 // PDPTE\r
1287 //\r
1288 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 30, 38);\r
1289 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1290 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1291\r
1292 //\r
1293 // PD\r
1294 //\r
1295 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 21, 29);\r
1296 if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {\r
1297 //\r
1298 // Large page\r
1299 //\r
1300\r
1301 //\r
1302 // Record old entries with non-present status\r
1303 // Old entries include the memory which instruction is at and the memory which instruction access.\r
1304 //\r
1305 //\r
1306 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);\r
1307 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {\r
053e878b 1308 PFIndex = mPFEntryCount[CpuIndex];\r
529a5a86
MK
1309 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];\r
1310 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];\r
1311 mPFEntryCount[CpuIndex]++;\r
1312 }\r
1313\r
1314 //\r
1315 // Set new entry\r
1316 //\r
053e878b 1317 PageTable[PTIndex] = (PFAddress & ~((1ull << 21) - 1));\r
529a5a86 1318 PageTable[PTIndex] |= (UINT64)IA32_PG_PS;\r
881520ea 1319 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;\r
529a5a86
MK
1320 if ((ErrorCode & IA32_PF_EC_ID) != 0) {\r
1321 PageTable[PTIndex] &= ~IA32_PG_NX;\r
1322 }\r
1323 } else {\r
1324 //\r
1325 // Small page\r
1326 //\r
1327 ASSERT (PageTable[PTIndex] != 0);\r
053e878b 1328 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
529a5a86
MK
1329\r
1330 //\r
1331 // 4K PTE\r
1332 //\r
1333 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 12, 20);\r
1334\r
1335 //\r
1336 // Record old entries with non-present status\r
1337 // Old entries include the memory which instruction is at and the memory which instruction access.\r
1338 //\r
1339 //\r
1340 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);\r
1341 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {\r
053e878b 1342 PFIndex = mPFEntryCount[CpuIndex];\r
529a5a86
MK
1343 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];\r
1344 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];\r
1345 mPFEntryCount[CpuIndex]++;\r
1346 }\r
1347\r
1348 //\r
1349 // Set new entry\r
1350 //\r
053e878b 1351 PageTable[PTIndex] = (PFAddress & ~((1ull << 12) - 1));\r
881520ea 1352 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;\r
529a5a86
MK
1353 if ((ErrorCode & IA32_PF_EC_ID) != 0) {\r
1354 PageTable[PTIndex] &= ~IA32_PG_NX;\r
1355 }\r
1356 }\r
1357}\r
1358\r
09afd9a4
JW
1359/**\r
1360 Handler for Page Fault triggered by Guard page.\r
1361\r
1362 @param ErrorCode The Error code of exception.\r
1363\r
1364**/\r
1365VOID\r
1366GuardPagePFHandler (\r
053e878b 1367 UINTN ErrorCode\r
09afd9a4
JW
1368 )\r
1369{\r
053e878b
MK
1370 UINT64 *PageTable;\r
1371 UINT64 PFAddress;\r
1372 UINT64 RestoreAddress;\r
1373 UINTN RestorePageNumber;\r
1374 UINTN CpuIndex;\r
09afd9a4 1375\r
053e878b
MK
1376 PageTable = (UINT64 *)AsmReadCr3 ();\r
1377 PFAddress = AsmReadCr2 ();\r
1378 CpuIndex = GetCpuIndex ();\r
09afd9a4
JW
1379\r
1380 //\r
1381 // Memory operation cross pages, like "rep mov" instruction, will cause\r
1382 // infinite loop between this and Debug Trap handler. We have to make sure\r
1383 // that current page and the page followed are both in PRESENT state.\r
1384 //\r
1385 RestorePageNumber = 2;\r
053e878b 1386 RestoreAddress = PFAddress;\r
09afd9a4
JW
1387 while (RestorePageNumber > 0) {\r
1388 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
1389 RestoreAddress += EFI_PAGE_SIZE;\r
1390 RestorePageNumber--;\r
1391 }\r
1392\r
1393 //\r
1394 // Flush TLB\r
1395 //\r
1396 CpuFlushTlb ();\r
1397}\r
1398\r
529a5a86
MK
1399/**\r
1400 The Page fault handler to save SMM profile data.\r
1401\r
1402 @param Rip The RIP when exception happens.\r
1403 @param ErrorCode The Error code of exception.\r
1404\r
1405**/\r
1406VOID\r
1407SmmProfilePFHandler (\r
053e878b
MK
1408 UINTN Rip,\r
1409 UINTN ErrorCode\r
529a5a86
MK
1410 )\r
1411{\r
053e878b
MK
1412 UINT64 *PageTable;\r
1413 UINT64 PFAddress;\r
1414 UINT64 RestoreAddress;\r
1415 UINTN RestorePageNumber;\r
1416 UINTN CpuIndex;\r
1417 UINTN Index;\r
1418 UINT64 InstructionAddress;\r
1419 UINTN MaxEntryNumber;\r
1420 UINTN CurrentEntryNumber;\r
1421 BOOLEAN IsValidPFAddress;\r
1422 SMM_PROFILE_ENTRY *SmmProfileEntry;\r
1423 UINT64 SmiCommand;\r
1424 EFI_STATUS Status;\r
1425 UINT8 SoftSmiValue;\r
1426 EFI_SMM_SAVE_STATE_IO_INFO IoInfo;\r
529a5a86
MK
1427\r
1428 if (!mSmmProfileStart) {\r
1429 //\r
1430 // If SMM profile does not start, call original page fault handler.\r
1431 //\r
1432 SmiDefaultPFHandler ();\r
1433 return;\r
1434 }\r
1435\r
1436 if (mBtsSupported) {\r
1437 DisableBTS ();\r
1438 }\r
1439\r
053e878b
MK
1440 IsValidPFAddress = FALSE;\r
1441 PageTable = (UINT64 *)AsmReadCr3 ();\r
1442 PFAddress = AsmReadCr2 ();\r
1443 CpuIndex = GetCpuIndex ();\r
529a5a86 1444\r
890d9ee5
JW
1445 //\r
1446 // Memory operation cross pages, like "rep mov" instruction, will cause\r
1447 // infinite loop between this and Debug Trap handler. We have to make sure\r
1448 // that current page and the page followed are both in PRESENT state.\r
1449 //\r
1450 RestorePageNumber = 2;\r
053e878b 1451 RestoreAddress = PFAddress;\r
890d9ee5
JW
1452 while (RestorePageNumber > 0) {\r
1453 if (RestoreAddress <= 0xFFFFFFFF) {\r
1454 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
1455 } else {\r
1456 RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\r
1457 }\r
053e878b 1458\r
890d9ee5
JW
1459 RestoreAddress += EFI_PAGE_SIZE;\r
1460 RestorePageNumber--;\r
529a5a86
MK
1461 }\r
1462\r
1463 if (!IsValidPFAddress) {\r
1464 InstructionAddress = Rip;\r
053e878b 1465 if (((ErrorCode & IA32_PF_EC_ID) != 0) && (mBtsSupported)) {\r
529a5a86
MK
1466 //\r
1467 // If it is instruction fetch failure, get the correct IP from BTS.\r
1468 //\r
1469 InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip);\r
1470 if (InstructionAddress == 0) {\r
1471 //\r
1472 // It indicates the instruction which caused page fault is not a jump instruction,\r
1473 // set instruction address same as the page fault address.\r
1474 //\r
1475 InstructionAddress = PFAddress;\r
1476 }\r
1477 }\r
1478\r
529a5a86
MK
1479 //\r
1480 // Indicate it is not software SMI\r
1481 //\r
053e878b 1482 SmiCommand = 0xFFFFFFFFFFFFFFFFULL;\r
529a5a86 1483 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
053e878b 1484 Status = SmmReadSaveState (&mSmmCpu, sizeof (IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo);\r
529a5a86
MK
1485 if (EFI_ERROR (Status)) {\r
1486 continue;\r
1487 }\r
053e878b 1488\r
529a5a86 1489 if (IoInfo.IoPort == mSmiCommandPort) {\r
529a5a86
MK
1490 //\r
1491 // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port.\r
1492 //\r
1493 SoftSmiValue = IoRead8 (mSmiCommandPort);\r
053e878b 1494 SmiCommand = (UINT64)SoftSmiValue;\r
529a5a86
MK
1495 break;\r
1496 }\r
1497 }\r
1498\r
1499 SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1);\r
1500 //\r
1501 // Check if there is already a same entry in profile data.\r
1502 //\r
053e878b 1503 for (Index = 0; Index < (UINTN)mSmmProfileBase->CurDataEntries; Index++) {\r
529a5a86
MK
1504 if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) &&\r
1505 (SmmProfileEntry[Index].Address == PFAddress) &&\r
1506 (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) &&\r
1507 (SmmProfileEntry[Index].Instruction == InstructionAddress) &&\r
053e878b
MK
1508 (SmmProfileEntry[Index].SmiCmd == SmiCommand))\r
1509 {\r
529a5a86
MK
1510 //\r
1511 // Same record exist, need not save again.\r
1512 //\r
1513 break;\r
1514 }\r
1515 }\r
053e878b 1516\r
529a5a86 1517 if (Index == mSmmProfileBase->CurDataEntries) {\r
053e878b
MK
1518 CurrentEntryNumber = (UINTN)mSmmProfileBase->CurDataEntries;\r
1519 MaxEntryNumber = (UINTN)mSmmProfileBase->MaxDataEntries;\r
529a5a86
MK
1520 if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) {\r
1521 CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber;\r
1522 }\r
053e878b 1523\r
529a5a86
MK
1524 if (CurrentEntryNumber < MaxEntryNumber) {\r
1525 //\r
1526 // Log the new entry\r
1527 //\r
1528 SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis;\r
1529 SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode;\r
1530 SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId ();\r
1531 SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex;\r
1532 SmmProfileEntry[CurrentEntryNumber].Address = PFAddress;\r
1533 SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress;\r
1534 SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand;\r
1535 //\r
1536 // Update current entry index and data size in the header.\r
1537 //\r
1538 mSmmProfileBase->CurDataEntries++;\r
1539 mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY));\r
1540 }\r
1541 }\r
1542 }\r
053e878b 1543\r
529a5a86
MK
1544 //\r
1545 // Flush TLB\r
1546 //\r
1547 CpuFlushTlb ();\r
1548\r
1549 if (mBtsSupported) {\r
1550 EnableBTS ();\r
1551 }\r
1552}\r
1553\r
1554/**\r
1555 Replace INT1 exception handler to restore page table to absent/execute-disable state\r
1556 in order to trigger page fault again to save SMM profile data..\r
1557\r
1558**/\r
1559VOID\r
1560InitIdtr (\r
1561 VOID\r
1562 )\r
1563{\r
053e878b 1564 EFI_STATUS Status;\r
5c88af79
JF
1565\r
1566 Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);\r
1567 ASSERT_EFI_ERROR (Status);\r
529a5a86 1568}\r