TianoCore EDK2 master
Loading...
Searching...
No Matches
SmmProfile.c
Go to the documentation of this file.
1
11#include "PiSmmCpuCommon.h"
12#include "SmmProfileInternal.h"
13
14UINT32 mSmmProfileCr3;
15
16SMM_PROFILE_HEADER *mSmmProfileBase;
17MSR_DS_AREA_STRUCT *mMsrDsAreaBase;
18//
19// The buffer to store SMM profile data.
20//
21UINTN mSmmProfileSize;
22
23//
24// The buffer to enable branch trace store.
25//
26UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE;
27
28//
29// The flag indicates if execute-disable is supported by processor.
30//
31BOOLEAN mXdSupported = TRUE;
32
33//
34// The flag indicates if execute-disable is enabled on processor.
35//
36BOOLEAN mXdEnabled = FALSE;
37
38//
39// The flag indicates if BTS is supported by processor.
40//
41BOOLEAN mBtsSupported = TRUE;
42
43//
44// The flag indicates if SMM profile is enabled.
45//
46BOOLEAN mSmmProfileEnabled = FALSE;
47
48//
49// The flag indicates if SMM profile starts to record data.
50//
51BOOLEAN mSmmProfileStart = FALSE;
52
53//
54// The flag indicates if #DB will be setup in #PF handler.
55//
56BOOLEAN mSetupDebugTrap = FALSE;
57
58//
59// Record the page fault exception count for one instruction execution.
60//
61UINTN *mPFEntryCount;
62
63UINT64 (*mLastPFEntryValue)[MAX_PF_ENTRY_COUNT];
64UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
65
66MSR_DS_AREA_STRUCT **mMsrDsArea;
67BRANCH_TRACE_RECORD **mMsrBTSRecord;
68UINTN mBTSRecordNumber;
69PEBS_RECORD **mMsrPEBSRecord;
70
71//
72// These memory ranges are always present, they does not generate the access type of page fault exception,
73// but they possibly generate instruction fetch type of page fault exception.
74//
75MEMORY_PROTECTION_RANGE *mProtectionMemRange = NULL;
76UINTN mProtectionMemRangeCount = 0;
77
78//
79// Some predefined memory ranges.
80//
81MEMORY_PROTECTION_RANGE mProtectionMemRangeTemplate[] = {
82 //
83 // SMRAM range (to be fixed in runtime).
84 // It is always present and instruction fetches are allowed.
85 //
86 {
87 { 0x00000000, 0x00000000 }, TRUE, FALSE
88 },
89
90 //
91 // SMM profile data range( to be fixed in runtime).
92 // It is always present and instruction fetches are not allowed.
93 //
94 {
95 { 0x00000000, 0x00000000 }, TRUE, TRUE
96 },
97
98 //
99 // SMRAM ranges not covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz (to be fixed in runtime).
100 // It is always present and instruction fetches are allowed.
101 // {{0x00000000, 0x00000000},TRUE,FALSE},
102 //
103
104 //
105 // Future extended range could be added here.
106 //
107
108 //
109 // PCI MMIO ranges (to be added in runtime).
110 // They are always present and instruction fetches are not allowed.
111 //
112};
113
114//
115// These memory ranges are mapped by 4KB-page instead of 2MB-page.
116//
117MEMORY_RANGE *mSplitMemRange = NULL;
118UINTN mSplitMemRangeCount = 0;
119
120//
121// SMI command port.
122//
123UINT32 mSmiCommandPort;
124
129VOID
131 VOID
132 )
133{
135
137 DebugCtl.Bits.BTS = 0;
138 DebugCtl.Bits.TR = 0;
139
141}
142
147VOID
149 VOID
150 )
151{
153
155 DebugCtl.Bits.BTS = 1;
156 DebugCtl.Bits.TR = 1;
157
159}
160
165UINTN
167 VOID
168 )
169{
170 UINTN Index;
171 UINT32 ApicId;
172
173 ApicId = GetApicId ();
174
175 for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
176 if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {
177 return Index;
178 }
179 }
180
181 ASSERT (FALSE);
182 return 0;
183}
184
192UINT64
194 UINTN CpuIndex,
195 UINT64 DestinationIP
196 )
197{
198 BRANCH_TRACE_RECORD *CurrentBTSRecord;
199 UINTN Index;
200 BOOLEAN FirstMatch;
201
202 FirstMatch = FALSE;
203
204 CurrentBTSRecord = (BRANCH_TRACE_RECORD *)mMsrDsArea[CpuIndex]->BTSIndex;
205 for (Index = 0; Index < mBTSRecordNumber; Index++) {
206 if ((UINTN)CurrentBTSRecord < (UINTN)mMsrBTSRecord[CpuIndex]) {
207 //
208 // Underflow
209 //
210 CurrentBTSRecord = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[CpuIndex]->BTSAbsoluteMaximum - 1);
211 CurrentBTSRecord--;
212 }
213
214 if (CurrentBTSRecord->LastBranchTo == DestinationIP) {
215 //
216 // Good! find 1st one, then find 2nd one.
217 //
218 if (!FirstMatch) {
219 //
220 // The first one is DEBUG exception
221 //
222 FirstMatch = TRUE;
223 } else {
224 //
225 // Good find proper one.
226 //
227 return CurrentBTSRecord->LastBranchFrom;
228 }
229 }
230
231 CurrentBTSRecord--;
232 }
233
234 return 0;
235}
236
245VOID
246EFIAPI
248 IN EFI_EXCEPTION_TYPE InterruptType,
249 IN EFI_SYSTEM_CONTEXT SystemContext
250 )
251{
252 UINTN CpuIndex;
253 UINTN PFEntry;
254
255 if (!mSmmProfileStart &&
256 !HEAP_GUARD_NONSTOP_MODE &&
257 !NULL_DETECTION_NONSTOP_MODE)
258 {
259 return;
260 }
261
262 CpuIndex = GetCpuIndex ();
263
264 //
265 // Clear last PF entries
266 //
267 for (PFEntry = 0; PFEntry < mPFEntryCount[CpuIndex]; PFEntry++) {
268 *mLastPFEntryPointer[CpuIndex][PFEntry] = mLastPFEntryValue[CpuIndex][PFEntry];
269 }
270
271 //
272 // Reset page fault exception count for next page fault.
273 //
274 mPFEntryCount[CpuIndex] = 0;
275
276 //
277 // Flush TLB
278 //
279 CpuFlushTlb ();
280
281 //
282 // Clear TF in EFLAGS
283 //
284 ClearTrapFlag (SystemContext);
285}
286
295BOOLEAN
298 )
299{
300 UINTN Index;
301
302 if ((Address >= mCpuHotPlugData.SmrrBase) && (Address < mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
303 return TRUE;
304 }
305
306 for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
307 if ((Address >= mSmmCpuSmramRanges[Index].CpuStart) &&
308 (Address < mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize))
309 {
310 return TRUE;
311 }
312 }
313
314 return FALSE;
315}
316
327BOOLEAN
329 IN EFI_PHYSICAL_ADDRESS Address,
330 OUT BOOLEAN *Nx
331 )
332{
333 UINTN Index;
334
335 //
336 // Check configuration
337 //
338 for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
339 if ((Address >= mProtectionMemRange[Index].Range.Base) && (Address < mProtectionMemRange[Index].Range.Top)) {
340 *Nx = mProtectionMemRange[Index].Nx;
341 return mProtectionMemRange[Index].Present;
342 }
343 }
344
345 *Nx = TRUE;
346 return FALSE;
347}
348
355BOOLEAN
358 )
359{
360 UINTN Index;
361
362 if (mSmmProfileEnabled) {
363 //
364 // Check configuration
365 //
366 for (Index = 0; Index < mSplitMemRangeCount; Index++) {
367 if ((Address >= mSplitMemRange[Index].Base) && (Address < mSplitMemRange[Index].Top)) {
368 return TRUE;
369 }
370 }
371 } else {
372 if (Address < mCpuHotPlugData.SmrrBase) {
373 if ((mCpuHotPlugData.SmrrBase - Address) < BASE_2MB) {
374 return TRUE;
375 }
376 } else if (Address > (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize - BASE_2MB)) {
377 if ((Address - (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize - BASE_2MB)) < BASE_2MB) {
378 return TRUE;
379 }
380 }
381 }
382
383 //
384 // Return default
385 //
386 return FALSE;
387}
388
399INTN
400EFIAPI
402 IN CONST VOID *Buffer1,
403 IN CONST VOID *Buffer2
404 )
405{
406 if (((MEMORY_PROTECTION_RANGE *)Buffer1)->Range.Base > ((MEMORY_PROTECTION_RANGE *)Buffer2)->Range.Base) {
407 return 1;
408 } else if (((MEMORY_PROTECTION_RANGE *)Buffer1)->Range.Base < ((MEMORY_PROTECTION_RANGE *)Buffer2)->Range.Base) {
409 return -1;
410 }
411
412 return 0;
413}
414
419VOID
421 VOID
422 )
423{
424 UINTN Index;
425 MM_CPU_MEMORY_REGION *MemoryRegion;
426 UINTN MemoryRegionCount;
427 UINTN NumberOfAddedDescriptors;
428 UINTN NumberOfProtectRange;
429 UINTN NumberOfSpliteRange;
430 UINTN TotalSize;
431 EFI_PHYSICAL_ADDRESS ProtectBaseAddress;
432 EFI_PHYSICAL_ADDRESS ProtectEndAddress;
433 EFI_PHYSICAL_ADDRESS Top2MBAlignedAddress;
434 EFI_PHYSICAL_ADDRESS Base2MBAlignedAddress;
435 UINT64 High4KBPageSize;
436 UINT64 Low4KBPageSize;
437 MEMORY_PROTECTION_RANGE MemProtectionRange;
438
439 MemoryRegion = NULL;
440 MemoryRegionCount = 0;
441 NumberOfAddedDescriptors = mSmmCpuSmramRangeCount;
442 NumberOfSpliteRange = 0;
443
444 //
445 // Create extended protection MemoryRegion and add them into protected memory ranges.
446 // Retrieve the accessible regions when SMM profile is enabled.
447 // In SMM: only MMIO is accessible.
448 // In MM: all regions described by resource HOBs are accessible.
449 //
450 CreateExtendedProtectionRange (&MemoryRegion, &MemoryRegionCount);
451 ASSERT (MemoryRegion != NULL);
452
453 NumberOfAddedDescriptors += MemoryRegionCount;
454
455 ASSERT (NumberOfAddedDescriptors != 0);
456
457 TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);
458 mProtectionMemRange = (MEMORY_PROTECTION_RANGE *)AllocateZeroPool (TotalSize);
459 ASSERT (mProtectionMemRange != NULL);
460 mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE);
461
462 //
463 // Copy existing ranges.
464 //
465 CopyMem (mProtectionMemRange, mProtectionMemRangeTemplate, sizeof (mProtectionMemRangeTemplate));
466
467 //
468 // Create split ranges which come from protected ranges.
469 //
470 TotalSize = (TotalSize / sizeof (MEMORY_PROTECTION_RANGE)) * sizeof (MEMORY_RANGE);
471 mSplitMemRange = (MEMORY_RANGE *)AllocateZeroPool (TotalSize);
472 ASSERT (mSplitMemRange != NULL);
473
474 //
475 // Create SMM ranges which are set to present and execution-enable.
476 //
477 NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);
478 for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
479 if ((mSmmCpuSmramRanges[Index].CpuStart >= mProtectionMemRange[0].Range.Base) &&
480 (mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize < mProtectionMemRange[0].Range.Top))
481 {
482 //
483 // If the address have been already covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz
484 //
485 break;
486 }
487
488 mProtectionMemRange[NumberOfProtectRange].Range.Base = mSmmCpuSmramRanges[Index].CpuStart;
489 mProtectionMemRange[NumberOfProtectRange].Range.Top = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;
490 mProtectionMemRange[NumberOfProtectRange].Present = TRUE;
491 mProtectionMemRange[NumberOfProtectRange].Nx = FALSE;
492 NumberOfProtectRange++;
493 }
494
495 //
496 // Create protection ranges which are set to present and execution-disable.
497 //
498 for (Index = 0; Index < MemoryRegionCount; Index++) {
499 mProtectionMemRange[NumberOfProtectRange].Range.Base = MemoryRegion[Index].Base;
500 mProtectionMemRange[NumberOfProtectRange].Range.Top = MemoryRegion[Index].Base + MemoryRegion[Index].Length;
501 mProtectionMemRange[NumberOfProtectRange].Present = TRUE;
502 mProtectionMemRange[NumberOfProtectRange].Nx = TRUE;
503 NumberOfProtectRange++;
504 }
505
506 //
507 // Free the MemoryRegion
508 //
509 if (MemoryRegion != NULL) {
510 FreePool (MemoryRegion);
511 }
512
513 //
514 // Check and updated actual protected memory ranges count
515 //
516 ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount);
517 mProtectionMemRangeCount = NumberOfProtectRange;
518
519 //
520 // According to protected ranges, create the ranges which will be mapped by 2KB page.
521 //
522 NumberOfSpliteRange = 0;
523 NumberOfProtectRange = mProtectionMemRangeCount;
524 for (Index = 0; Index < NumberOfProtectRange; Index++) {
525 //
526 // If base address is not 2MB alignment, make 2MB alignment for create 4KB page in page table.
527 //
528 ProtectBaseAddress = mProtectionMemRange[Index].Range.Base;
529 ProtectEndAddress = mProtectionMemRange[Index].Range.Top;
530 if (((ProtectBaseAddress & (SIZE_2MB - 1)) != 0) || ((ProtectEndAddress & (SIZE_2MB - 1)) != 0)) {
531 //
532 // Check if it is possible to create 4KB-page for not 2MB-aligned range and to create 2MB-page for 2MB-aligned range.
533 // A mix of 4KB and 2MB page could save SMRAM space.
534 //
535 Top2MBAlignedAddress = ProtectEndAddress & ~(SIZE_2MB - 1);
536 Base2MBAlignedAddress = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
537 if ((Top2MBAlignedAddress > Base2MBAlignedAddress) &&
538 ((Top2MBAlignedAddress - Base2MBAlignedAddress) >= SIZE_2MB))
539 {
540 //
541 // There is an range which could be mapped by 2MB-page.
542 //
543 High4KBPageSize = ((ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectEndAddress & ~(SIZE_2MB - 1));
544 Low4KBPageSize = ((ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectBaseAddress & ~(SIZE_2MB - 1));
545 if (High4KBPageSize != 0) {
546 //
547 // Add not 2MB-aligned range to be mapped by 4KB-page.
548 //
549 mSplitMemRange[NumberOfSpliteRange].Base = ProtectEndAddress & ~(SIZE_2MB - 1);
550 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
551 NumberOfSpliteRange++;
552 }
553
554 if (Low4KBPageSize != 0) {
555 //
556 // Add not 2MB-aligned range to be mapped by 4KB-page.
557 //
558 mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);
559 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
560 NumberOfSpliteRange++;
561 }
562 } else {
563 //
564 // The range could only be mapped by 4KB-page.
565 //
566 mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);
567 mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
568 NumberOfSpliteRange++;
569 }
570 }
571 }
572
573 mSplitMemRangeCount = NumberOfSpliteRange;
574
575 //
576 // Sort the mProtectionMemRange
577 //
578 QuickSort (mProtectionMemRange, mProtectionMemRangeCount, sizeof (MEMORY_PROTECTION_RANGE), (BASE_SORT_COMPARE)ProtectionRangeCompare, &MemProtectionRange);
579
580 DEBUG ((DEBUG_INFO, "SMM Profile Memory Ranges:\n"));
581 for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
582 DEBUG ((DEBUG_INFO, "mProtectionMemRange[%d].Base = %lx\n", Index, mProtectionMemRange[Index].Range.Base));
583 DEBUG ((DEBUG_INFO, "mProtectionMemRange[%d].Top = %lx\n", Index, mProtectionMemRange[Index].Range.Top));
584 }
585
586 for (Index = 0; Index < mSplitMemRangeCount; Index++) {
587 DEBUG ((DEBUG_INFO, "mSplitMemRange[%d].Base = %lx\n", Index, mSplitMemRange[Index].Base));
588 DEBUG ((DEBUG_INFO, "mSplitMemRange[%d].Top = %lx\n", Index, mSplitMemRange[Index].Top));
589 }
590}
591
596VOID
598 VOID
599 )
600{
601 RETURN_STATUS Status;
602 UINTN Index;
603 UINTN PageTable;
604 UINT64 Base;
605 UINT64 Length;
606 UINT64 Limit;
607 UINT64 PreviousAddress;
608 UINT64 MemoryAttrMask;
609 BOOLEAN WriteProtect;
610 BOOLEAN CetEnabled;
611
612 DEBUG ((DEBUG_INFO, "SmmProfileUpdateMemoryAttributes Start...\n"));
613
614 WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
615
616 PageTable = AsmReadCr3 ();
617 Limit = LShiftU64 (1, mPhysicalAddressBits);
618
619 //
620 // [0, 4k] may be non-present.
621 //
622 PreviousAddress = ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) ? BASE_4KB : 0;
623
624 for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
625 MemoryAttrMask = 0;
626 if (mProtectionMemRange[Index].Nx == TRUE) {
627 MemoryAttrMask = EFI_MEMORY_XP;
628 }
629
630 if (mProtectionMemRange[Index].Present == FALSE) {
631 MemoryAttrMask = EFI_MEMORY_RP;
632 }
633
634 Base = mProtectionMemRange[Index].Range.Base;
635 Length = mProtectionMemRange[Index].Range.Top - Base;
636 if (MemoryAttrMask != 0) {
637 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, Base, Length, MemoryAttrMask, TRUE, NULL);
638 ASSERT_RETURN_ERROR (Status);
639 }
640
641 if (Base > PreviousAddress) {
642 //
643 // Mark the ranges not in mProtectionMemRange as non-present.
644 //
645 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, EFI_MEMORY_RP, TRUE, NULL);
646 ASSERT_RETURN_ERROR (Status);
647 }
648
649 PreviousAddress = Base + Length;
650 }
651
652 //
653 // Set the last remaining range
654 //
655 if (PreviousAddress < Limit) {
656 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Limit - PreviousAddress, EFI_MEMORY_RP, TRUE, NULL);
657 ASSERT_RETURN_ERROR (Status);
658 }
659
660 //
661 // Flush TLB
662 //
663 CpuFlushTlb ();
664
665 //
666 // Set execute-disable flag
667 //
668 mXdEnabled = TRUE;
669
670 WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
671
672 DEBUG ((DEBUG_INFO, "SmmProfileUpdateMemoryAttributes Done.\n"));
673}
674
681VOID
683 VOID
684 )
685{
686 //
687 // The flag indicates SMM profile starts to work.
688 //
689 mSmmProfileStart = TRUE;
690
691 //
692 // Tell #PF handler to prepare a #DB subsequently.
693 //
694 mSetupDebugTrap = TRUE;
695}
696
707EFIAPI
709 IN CONST EFI_GUID *Protocol,
710 IN VOID *Interface,
711 IN EFI_HANDLE Handle
712 )
713{
714 EFI_STATUS Status;
715 EFI_SMM_VARIABLE_PROTOCOL *SmmProfileVariable;
716
717 //
718 // Locate SmmVariableProtocol.
719 //
720 Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&SmmProfileVariable);
721 ASSERT_EFI_ERROR (Status);
722
723 //
724 // Save to variable so that SMM profile data can be found.
725 //
726 SmmProfileVariable->SmmSetVariable (
727 SMM_PROFILE_NAME,
728 &gEfiCallerIdGuid,
729 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
730 sizeof (mSmmProfileBase),
731 &mSmmProfileBase
732 );
733
734 return EFI_SUCCESS;
735}
736
741VOID
743 VOID
744 )
745{
746 EFI_STATUS Status;
747 VOID *Registration;
748 UINTN Index;
749 UINTN MsrDsAreaSizePerCpu;
750 UINT64 SmmProfileSize;
751
752 mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus);
753 ASSERT (mPFEntryCount != NULL);
754 mLastPFEntryValue = (UINT64 (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (
755 sizeof (mLastPFEntryValue[0]) * mMaxNumberOfCpus
756 );
757 ASSERT (mLastPFEntryValue != NULL);
758 mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (
759 sizeof (mLastPFEntryPointer[0]) * mMaxNumberOfCpus
760 );
761 ASSERT (mLastPFEntryPointer != NULL);
762
763 //
764 // Get Smm Profile Base
765 //
766 mSmmProfileBase = (SMM_PROFILE_HEADER *)(UINTN)GetSmmProfileData (&SmmProfileSize);
767 DEBUG ((DEBUG_ERROR, "SmmProfileBase = 0x%016x.\n", (UINTN)mSmmProfileBase));
768 DEBUG ((DEBUG_ERROR, "SmmProfileSize = 0x%016x.\n", (UINTN)SmmProfileSize));
769
770 if (mBtsSupported) {
771 ASSERT (SmmProfileSize > mMsrDsAreaSize);
772 mSmmProfileSize = (UINTN)SmmProfileSize - mMsrDsAreaSize;
773 } else {
774 mSmmProfileSize = (UINTN)SmmProfileSize;
775 }
776
777 ASSERT ((mSmmProfileSize & 0xFFF) == 0);
778
779 //
780 // Initialize SMM profile data header.
781 //
782 mSmmProfileBase->HeaderSize = sizeof (SMM_PROFILE_HEADER);
783 mSmmProfileBase->MaxDataEntries = (UINT64)((mSmmProfileSize - sizeof (SMM_PROFILE_HEADER)) / sizeof (SMM_PROFILE_ENTRY));
784 mSmmProfileBase->MaxDataSize = MultU64x64 (mSmmProfileBase->MaxDataEntries, sizeof (SMM_PROFILE_ENTRY));
785 mSmmProfileBase->CurDataEntries = 0;
786 mSmmProfileBase->CurDataSize = 0;
787 mSmmProfileBase->TsegStart = mCpuHotPlugData.SmrrBase;
788 mSmmProfileBase->TsegSize = mCpuHotPlugData.SmrrSize;
789 mSmmProfileBase->NumSmis = 0;
790 mSmmProfileBase->NumCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
791
792 if (mBtsSupported) {
793 mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * mMaxNumberOfCpus);
794 ASSERT (mMsrDsArea != NULL);
795 mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * mMaxNumberOfCpus);
796 ASSERT (mMsrBTSRecord != NULL);
797 mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * mMaxNumberOfCpus);
798 ASSERT (mMsrPEBSRecord != NULL);
799
800 mMsrDsAreaBase = (MSR_DS_AREA_STRUCT *)((UINTN)mSmmProfileBase + mSmmProfileSize);
801 MsrDsAreaSizePerCpu = mMsrDsAreaSize / mMaxNumberOfCpus;
802 mBTSRecordNumber = (MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof (MSR_DS_AREA_STRUCT)) / sizeof (BRANCH_TRACE_RECORD);
803 for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
804 mMsrDsArea[Index] = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index);
805 mMsrBTSRecord[Index] = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof (MSR_DS_AREA_STRUCT));
806 mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof (PEBS_RECORD) * PEBS_RECORD_NUMBER);
807
808 mMsrDsArea[Index]->BTSBufferBase = (UINTN)mMsrBTSRecord[Index];
809 mMsrDsArea[Index]->BTSIndex = mMsrDsArea[Index]->BTSBufferBase;
810 mMsrDsArea[Index]->BTSAbsoluteMaximum = mMsrDsArea[Index]->BTSBufferBase + mBTSRecordNumber * sizeof (BRANCH_TRACE_RECORD) + 1;
811 mMsrDsArea[Index]->BTSInterruptThreshold = mMsrDsArea[Index]->BTSAbsoluteMaximum + 1;
812
813 mMsrDsArea[Index]->PEBSBufferBase = (UINTN)mMsrPEBSRecord[Index];
814 mMsrDsArea[Index]->PEBSIndex = mMsrDsArea[Index]->PEBSBufferBase;
815 mMsrDsArea[Index]->PEBSAbsoluteMaximum = mMsrDsArea[Index]->PEBSBufferBase + PEBS_RECORD_NUMBER * sizeof (PEBS_RECORD) + 1;
816 mMsrDsArea[Index]->PEBSInterruptThreshold = mMsrDsArea[Index]->PEBSAbsoluteMaximum + 1;
817 }
818 }
819
820 mProtectionMemRange = mProtectionMemRangeTemplate;
821 mProtectionMemRangeCount = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);
822
823 //
824 // Update TSeg entry.
825 //
826 mProtectionMemRange[0].Range.Base = mCpuHotPlugData.SmrrBase;
827 mProtectionMemRange[0].Range.Top = mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize;
828
829 //
830 // Update SMM profile entry.
831 //
832 mProtectionMemRange[1].Range.Base = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase;
833 mProtectionMemRange[1].Range.Top = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase + SmmProfileSize;
834
835 //
836 // Allocate memory reserved for creating 4KB pages.
837 //
839
840 //
841 // Start SMM profile when SmmReadyToLock protocol is installed.
842 //
843 Status = gMmst->MmRegisterProtocolNotify (
844 &gEfiSmmReadyToLockProtocolGuid,
846 &Registration
847 );
848 ASSERT_EFI_ERROR (Status);
849
850 return;
851}
852
858VOID
860 IN UINTN CpuIndex
861 )
862{
863 UINT32 RegEax;
864 UINT32 RegEcx;
865 UINT32 RegEdx;
866 MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;
867
868 if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
869 AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);
872 if ((RegEcx & CPUID_CET_SS) == 0) {
873 mCetSupported = FALSE;
874 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
875 }
876 } else {
877 mCetSupported = FALSE;
878 PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
879 }
880 }
881
882 if (mBtsSupported) {
884 if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) {
885 //
886 // Per IA32 manuals:
887 // When CPUID.1:EDX[21] is set, the following BTS facilities are available:
888 // 1. The BTS_UNAVAILABLE flag in the IA32_MISC_ENABLE MSR indicates the
889 // availability of the BTS facilities, including the ability to set the BTS and
890 // BTINT bits in the MSR_DEBUGCTLA MSR.
891 // 2. The IA32_DS_AREA MSR can be programmed to point to the DS save area.
892 //
893 MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
894 if (MiscEnableMsr.Bits.BTS == 1) {
895 //
896 // BTS facilities is not supported if MSR_IA32_MISC_ENABLE.BTS bit is set.
897 //
898 mBtsSupported = FALSE;
899 }
900 }
901 }
902
903 if (mSmmCodeAccessCheckEnable) {
904 //
905 // Check to see if the CPU supports the SMM Code Access Check feature
906 // Do not access this MSR unless the CPU supports the SmmRegFeatureControl
907 //
909 ((AsmReadMsr64 (EFI_MSR_SMM_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) == 0))
910 {
911 mSmmCodeAccessCheckEnable = FALSE;
912 }
913 }
914}
915
920VOID
922 VOID
923 )
924{
925 UINTN Dr6;
926
927 Dr6 = AsmReadDr6 ();
928 if ((Dr6 & DR6_SINGLE_STEP) != 0) {
929 return;
930 }
931
932 Dr6 |= DR6_SINGLE_STEP;
933 AsmWriteDr6 (Dr6);
934}
935
940VOID
942 VOID
943 )
944{
946
948 if (DebugCtl.Bits.LBR) {
949 return;
950 }
951
952 DebugCtl.Bits.LBR = 1;
954}
955
962VOID
964 IN UINTN CpuIndex
965 )
966{
968
970 if ((DebugCtl.Bits.BTS)) {
971 return;
972 }
973
974 AsmWriteMsr64 (MSR_DS_AREA, (UINT64)(UINTN)mMsrDsArea[CpuIndex]);
975
976 //
977 // Enable BTS
978 //
979 DebugCtl.Bits.BTS = 1;
980 DebugCtl.Bits.TR = 1;
981
982 DebugCtl.Bits.BTINT = 0;
984}
985
990VOID
992 VOID
993 )
994{
995 if (mSmmProfileStart) {
996 mSmmProfileBase->NumSmis++;
997 }
998}
999
1006VOID
1008 IN UINTN CpuIndex
1009 )
1010{
1011 //
1012 // Enable Single Step DB#
1013 //
1015
1016 if (mBtsSupported) {
1017 //
1018 // We can not get useful information from LER, so we have to use BTS.
1019 //
1020 ActivateLBR ();
1021
1022 //
1023 // Enable BTS
1024 //
1025 ActivateBTS (CpuIndex);
1026 }
1027}
1028
1035VOID
1037 UINT32 Cr3
1038 )
1039{
1040 //
1041 // Save Cr3
1042 //
1043 mSmmProfileCr3 = Cr3;
1044
1045 //
1046 // Skip SMM profile initialization if feature is disabled
1047 //
1048 if (!mSmmProfileEnabled &&
1049 !HEAP_GUARD_NONSTOP_MODE &&
1050 !NULL_DETECTION_NONSTOP_MODE)
1051 {
1052 return;
1053 }
1054
1055 //
1056 // Initialize SmmProfile here
1057 //
1059
1060 //
1061 // Initialize profile IDT.
1062 //
1063 InitIdtr ();
1064}
1065
1077VOID
1079 UINT64 *PageTable,
1080 UINT64 PFAddress,
1081 UINTN CpuIndex,
1082 UINTN ErrorCode
1083 )
1084{
1085 UINTN PTIndex;
1086 UINTN PFIndex;
1087 IA32_CR4 Cr4;
1088 BOOLEAN Enable5LevelPaging;
1089
1090 Cr4.UintN = AsmReadCr4 ();
1091 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
1092
1093 //
1094 // PML5
1095 //
1096 if (Enable5LevelPaging) {
1097 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 48, 56);
1098 ASSERT (PageTable[PTIndex] != 0);
1099 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
1100 }
1101
1102 //
1103 // PML4
1104 //
1105 if (sizeof (UINT64) == sizeof (UINTN)) {
1106 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 39, 47);
1107 ASSERT (PageTable[PTIndex] != 0);
1108 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
1109 }
1110
1111 //
1112 // PDPTE
1113 //
1114 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 30, 38);
1115
1116 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
1117 //
1118 // For 32-bit case, because a full map page table for 0-4G is created by default,
1119 // and since the PDPTE must be one non-leaf entry, the PDPTE must always be present.
1120 // So, ASSERT it must be the 64-bit case running here.
1121 //
1122 ASSERT (sizeof (UINT64) == sizeof (UINTN));
1123
1124 //
1125 // If the entry is not present, allocate one page from page pool for it
1126 //
1127 PageTable[PTIndex] = AllocPage () | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
1128 }
1129
1130 ASSERT (PageTable[PTIndex] != 0);
1131 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
1132
1133 //
1134 // PD
1135 //
1136 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 21, 29);
1137 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
1138 //
1139 // A 2M page size will be used directly when the 2M entry is marked as non-present.
1140 //
1141
1142 //
1143 // Record old entries with non-present status
1144 // Old entries include the memory which instruction is at and the memory which instruction access.
1145 //
1146 //
1147 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);
1148 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {
1149 PFIndex = mPFEntryCount[CpuIndex];
1150 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];
1151 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];
1152 mPFEntryCount[CpuIndex]++;
1153 }
1154
1155 //
1156 // Set new entry
1157 //
1158 PageTable[PTIndex] = (PFAddress & ~((1ull << 21) - 1));
1159 PageTable[PTIndex] |= (UINT64)IA32_PG_PS;
1160 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;
1161 if ((ErrorCode & IA32_PF_EC_ID) != 0) {
1162 PageTable[PTIndex] &= ~IA32_PG_NX;
1163 }
1164 } else {
1165 //
1166 // If the 2M entry is marked as present, a 4K page size will be utilized.
1167 // In this scenario, the 2M entry must be a non-leaf entry.
1168 //
1169 ASSERT (PageTable[PTIndex] != 0);
1170 PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
1171
1172 //
1173 // 4K PTE
1174 //
1175 PTIndex = (UINTN)BitFieldRead64 (PFAddress, 12, 20);
1176
1177 //
1178 // Record old entries with non-present status
1179 // Old entries include the memory which instruction is at and the memory which instruction access.
1180 //
1181 //
1182 ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);
1183 if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {
1184 PFIndex = mPFEntryCount[CpuIndex];
1185 mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];
1186 mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];
1187 mPFEntryCount[CpuIndex]++;
1188 }
1189
1190 //
1191 // Set new entry
1192 //
1193 PageTable[PTIndex] = (PFAddress & ~((1ull << 12) - 1));
1194 PageTable[PTIndex] |= (UINT64)PAGE_ATTRIBUTE_BITS;
1195 if ((ErrorCode & IA32_PF_EC_ID) != 0) {
1196 PageTable[PTIndex] &= ~IA32_PG_NX;
1197 }
1198 }
1199}
1200
1207VOID
1209 UINTN ErrorCode
1210 )
1211{
1212 UINT64 *PageTable;
1213 UINT64 PFAddress;
1214 UINT64 RestoreAddress;
1215 UINTN RestorePageNumber;
1216 UINTN CpuIndex;
1217
1218 PageTable = (UINT64 *)AsmReadCr3 ();
1219 PFAddress = AsmReadCr2 ();
1220 CpuIndex = GetCpuIndex ();
1221
1222 //
1223 // Memory operation cross pages, like "rep mov" instruction, will cause
1224 // infinite loop between this and Debug Trap handler. We have to make sure
1225 // that current page and the page followed are both in PRESENT state.
1226 //
1227 RestorePageNumber = 2;
1228 RestoreAddress = PFAddress;
1229 while (RestorePageNumber > 0) {
1230 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);
1231 RestoreAddress += EFI_PAGE_SIZE;
1232 RestorePageNumber--;
1233 }
1234
1235 //
1236 // Flush TLB
1237 //
1238 CpuFlushTlb ();
1239}
1240
1248VOID
1250 UINTN Rip,
1251 UINTN ErrorCode
1252 )
1253{
1254 UINT64 *PageTable;
1255 UINT64 PFAddress;
1256 UINT64 RestoreAddress;
1257 UINTN RestorePageNumber;
1258 UINTN CpuIndex;
1259 UINTN Index;
1260 UINT64 InstructionAddress;
1261 UINTN MaxEntryNumber;
1262 UINTN CurrentEntryNumber;
1263 BOOLEAN IsValidPFAddress;
1264 SMM_PROFILE_ENTRY *SmmProfileEntry;
1265 UINT64 SmiCommand;
1266 EFI_STATUS Status;
1267 UINT8 SoftSmiValue;
1269
1270 if (mBtsSupported) {
1271 DisableBTS ();
1272 }
1273
1274 IsValidPFAddress = FALSE;
1275 PageTable = (UINT64 *)AsmReadCr3 ();
1276 PFAddress = AsmReadCr2 ();
1277 CpuIndex = GetCpuIndex ();
1278
1279 //
1280 // Memory operation cross pages, like "rep mov" instruction, will cause
1281 // infinite loop between this and Debug Trap handler. We have to make sure
1282 // that current page and the page followed are both in PRESENT state.
1283 //
1284 RestorePageNumber = 2;
1285 RestoreAddress = PFAddress;
1286 while (RestorePageNumber > 0) {
1287 if (RestoreAddress <= 0xFFFFFFFF) {
1288 RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);
1289 } else {
1290 RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
1291 }
1292
1293 RestoreAddress += EFI_PAGE_SIZE;
1294 RestorePageNumber--;
1295 }
1296
1297 if (!IsValidPFAddress) {
1298 InstructionAddress = Rip;
1299 if (((ErrorCode & IA32_PF_EC_ID) != 0) && (mBtsSupported)) {
1300 //
1301 // If it is instruction fetch failure, get the correct IP from BTS.
1302 //
1303 InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip);
1304 if (InstructionAddress == 0) {
1305 //
1306 // It indicates the instruction which caused page fault is not a jump instruction,
1307 // set instruction address same as the page fault address.
1308 //
1309 InstructionAddress = PFAddress;
1310 }
1311 }
1312
1313 //
1314 // Indicate it is not software SMI
1315 //
1316 SmiCommand = 0xFFFFFFFFFFFFFFFFULL;
1317 for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
1318 Status = SmmReadSaveState (&mSmmCpu, sizeof (IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo);
1319 if (EFI_ERROR (Status)) {
1320 continue;
1321 }
1322
1323 if (IoInfo.IoPort == mSmiCommandPort) {
1324 //
1325 // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port.
1326 //
1327 SoftSmiValue = IoRead8 (mSmiCommandPort);
1328 SmiCommand = (UINT64)SoftSmiValue;
1329 break;
1330 }
1331 }
1332
1333 SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1);
1334 //
1335 // Check if there is already a same entry in profile data.
1336 //
1337 for (Index = 0; Index < (UINTN)mSmmProfileBase->CurDataEntries; Index++) {
1338 if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) &&
1339 (SmmProfileEntry[Index].Address == PFAddress) &&
1340 (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) &&
1341 (SmmProfileEntry[Index].Instruction == InstructionAddress) &&
1342 (SmmProfileEntry[Index].SmiCmd == SmiCommand))
1343 {
1344 //
1345 // Same record exist, need not save again.
1346 //
1347 break;
1348 }
1349 }
1350
1351 if (Index == mSmmProfileBase->CurDataEntries) {
1352 CurrentEntryNumber = (UINTN)mSmmProfileBase->CurDataEntries;
1353 MaxEntryNumber = (UINTN)mSmmProfileBase->MaxDataEntries;
1354 if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) {
1355 CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber;
1356 }
1357
1358 if (CurrentEntryNumber < MaxEntryNumber) {
1359 //
1360 // Log the new entry
1361 //
1362 SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis;
1363 SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode;
1364 SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId ();
1365 SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex;
1366 SmmProfileEntry[CurrentEntryNumber].Address = PFAddress;
1367 SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress;
1368 SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand;
1369 //
1370 // Update current entry index and data size in the header.
1371 //
1372 mSmmProfileBase->CurDataEntries++;
1373 mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY));
1374 }
1375 }
1376 }
1377
1378 //
1379 // Flush TLB
1380 //
1381 CpuFlushTlb ();
1382
1383 if (mBtsSupported) {
1384 EnableBTS ();
1385 }
1386}
1387
1393VOID
1395 VOID
1396 )
1397{
1398 EFI_STATUS Status;
1399
1400 Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);
1401 ASSERT_EFI_ERROR (Status);
1402}
UINT64 UINTN
INT64 INTN
UINT64 EFIAPI MultU64x64(IN UINT64 Multiplicand, IN UINT64 Multiplier)
Definition: MultU64x64.c:27
INTN(EFIAPI * BASE_SORT_COMPARE)(IN CONST VOID *Buffer1, IN CONST VOID *Buffer2)
Definition: BaseLib.h:3285
VOID EFIAPI QuickSort(IN OUT VOID *BufferToSort, IN CONST UINTN Count, IN CONST UINTN ElementSize, IN BASE_SORT_COMPARE CompareFunction, OUT VOID *BufferOneElement)
Definition: QuickSort.c:36
UINT64 EFIAPI BitFieldRead64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit)
Definition: BitField.c:719
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINT32 EFIAPI AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuIdEx.c:43
VOID EFIAPI CpuFlushTlb(VOID)
RETURN_STATUS ConvertMemoryPageAttributes(IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN PAGE_ACTION PageAction, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL, OUT BOOLEAN *IsSplitted OPTIONAL, OUT BOOLEAN *IsModified OPTIONAL)
Definition: CpuPageTable.c:719
EFI_STATUS EFIAPI SmmRegisterExceptionHandler(IN EFI_SMM_CPU_SERVICE_PROTOCOL *This, IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
Definition: CpuService.c:353
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINTN EFIAPI AsmReadCr3(VOID)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
UINTN EFIAPI AsmReadCr2(VOID)
UINT64 EFIAPI AsmWriteMsr64(IN UINT32 Index, IN UINT64 Value)
UINTN EFIAPI AsmReadCr4(VOID)
UINTN EFIAPI AsmReadDr6(VOID)
UINTN EFIAPI AsmWriteDr6(UINTN Dr6)
UINT64 AllocPage(VOID)
Definition: PageTbl.c:76
VOID ClearTrapFlag(IN OUT EFI_SYSTEM_CONTEXT SystemContext)
VOID InitPagesForPFHandler(VOID)
VOID RestorePageTableAbove4G(UINT64 *PageTable, UINT64 PFAddress, UINTN CpuIndex, UINTN ErrorCode, BOOLEAN *IsValidPFAddress)
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
UINT32 EFIAPI GetApicId(VOID)
Definition: BaseXApicLib.c:337
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_RETURN_ERROR(StatusParameter)
Definition: DebugLib.h:493
#define DEBUG(Expression)
Definition: DebugLib.h:434
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
#define MSR_IA32_DEBUGCTL
#define MSR_IA32_MISC_ENABLE
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
Definition: Cpuid.h:1301
#define CPUID_SIGNATURE
Definition: Cpuid.h:45
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO
Definition: Cpuid.h:1306
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
VOID CreateExtendedProtectionRange(OUT MM_CPU_MEMORY_REGION **MemoryRegion, OUT UINTN *MemoryRegionCount)
EFI_PHYSICAL_ADDRESS GetSmmProfileData(IN OUT UINT64 *Size)
BOOLEAN EFIAPI SmmCpuFeaturesIsSmmRegisterSupported(IN UINTN CpuIndex, IN SMM_REG_NAME RegName)
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
EFI_SMM_CPU_PROTOCOL mSmmCpu
EFI_STATUS EFIAPI SmmReadSaveState(IN CONST EFI_SMM_CPU_PROTOCOL *This, IN UINTN Width, IN EFI_SMM_SAVE_STATE_REGISTER Register, IN UINTN CpuIndex, OUT VOID *Buffer)
#define WRITE_UNPROTECT_RO_PAGES(Wp, Cet)
@ SmmRegFeatureControl
EFI_STATUS EFIAPI InitSmmProfileCallBack(IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle)
Definition: SmmProfile.c:708
INTN EFIAPI ProtectionRangeCompare(IN CONST VOID *Buffer1, IN CONST VOID *Buffer2)
Definition: SmmProfile.c:401
VOID SmmProfilePFHandler(UINTN Rip, UINTN ErrorCode)
Definition: SmmProfile.c:1249
UINT64 GetSourceFromDestinationOnBts(UINTN CpuIndex, UINT64 DestinationIP)
Definition: SmmProfile.c:193
VOID GuardPagePFHandler(UINTN ErrorCode)
Definition: SmmProfile.c:1208
VOID SmmProfileStart(VOID)
Definition: SmmProfile.c:682
VOID InitSmmProfileInternal(VOID)
Definition: SmmProfile.c:742
BOOLEAN IsSmmProfilePFAddressAbove4GValid(IN EFI_PHYSICAL_ADDRESS Address, OUT BOOLEAN *Nx)
Definition: SmmProfile.c:328
VOID InitProtectedMemRange(VOID)
Definition: SmmProfile.c:420
UINTN GetCpuIndex(VOID)
Definition: SmmProfile.c:166
VOID SmmProfileRecordSmiNum(VOID)
Definition: SmmProfile.c:991
VOID ActivateSmmProfile(IN UINTN CpuIndex)
Definition: SmmProfile.c:1007
BOOLEAN IsInSmmRanges(IN EFI_PHYSICAL_ADDRESS Address)
Definition: SmmProfile.c:296
VOID SmmProfileUpdateMemoryAttributes(VOID)
Definition: SmmProfile.c:597
VOID ActivateLBR(VOID)
Definition: SmmProfile.c:941
VOID EnableBTS(VOID)
Definition: SmmProfile.c:148
VOID CheckFeatureSupported(IN UINTN CpuIndex)
Definition: SmmProfile.c:859
VOID ActivateBTS(IN UINTN CpuIndex)
Definition: SmmProfile.c:963
VOID RestorePageTableBelow4G(UINT64 *PageTable, UINT64 PFAddress, UINTN CpuIndex, UINTN ErrorCode)
Definition: SmmProfile.c:1078
VOID DisableBTS(VOID)
Definition: SmmProfile.c:130
VOID EFIAPI DebugExceptionHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_SYSTEM_CONTEXT SystemContext)
Definition: SmmProfile.c:247
BOOLEAN IsAddressSplit(IN EFI_PHYSICAL_ADDRESS Address)
Definition: SmmProfile.c:356
VOID InitSmmProfile(UINT32 Cr3)
Definition: SmmProfile.c:1036
VOID InitIdtr(VOID)
Definition: SmmProfile.c:1394
VOID ActivateSingleStepDB(VOID)
Definition: SmmProfile.c:921
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VOID EFIAPI PatchInstructionX86(OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, IN UINT64 PatchValue, IN UINTN ValueSize)
EFI_PHYSICAL_ADDRESS CpuStart
Definition: PiMultiPhase.h:127
Definition: Base.h:213
EFI_PHYSICAL_ADDRESS Base
struct MSR_IA32_DEBUGCTL_REGISTER::@645 Bits
struct MSR_IA32_MISC_ENABLE_REGISTER::@641 Bits