TianoCore EDK2 master
CpuPageTable.c
Go to the documentation of this file.
1
11#include <Base.h>
12#include <Uefi.h>
16#include <Library/PrintLib.h>
17#include <Protocol/SmmBase2.h>
19#include <Register/Intel/Msr.h>
20
21#include "CpuDxe.h"
22#include "CpuPageTable.h"
23
27#define IA32_PG_P BIT0
28#define IA32_PG_RW BIT1
29#define IA32_PG_U BIT2
30#define IA32_PG_WT BIT3
31#define IA32_PG_CD BIT4
32#define IA32_PG_A BIT5
33#define IA32_PG_D BIT6
34#define IA32_PG_PS BIT7
35#define IA32_PG_PAT_2M BIT12
36#define IA32_PG_PAT_4K IA32_PG_PS
37#define IA32_PG_PMNT BIT62
38#define IA32_PG_NX BIT63
39
40#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
41//
42// Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
43// X64 PAE PDPTE does not have such restriction
44//
45#define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P)
46
47#define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
48
49#define PAGING_4K_MASK 0xFFF
50#define PAGING_2M_MASK 0x1FFFFF
51#define PAGING_1G_MASK 0x3FFFFFFF
52
53#define PAGING_PAE_INDEX_MASK 0x1FF
54
55#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
56#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
57#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
58
59#define MAX_PF_ENTRY_COUNT 10
60#define MAX_DEBUG_MESSAGE_LENGTH 0x100
61#define IA32_PF_EC_ID BIT4
62
63typedef enum {
64 PageNone,
65 Page4K,
66 Page2M,
67 Page1G,
68} PAGE_ATTRIBUTE;
69
70typedef struct {
71 PAGE_ATTRIBUTE Attribute;
72 UINT64 Length;
73 UINT64 AddressMask;
75
76typedef enum {
77 PageActionAssign,
78 PageActionSet,
79 PageActionClear,
80} PAGE_ACTION;
81
82PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
83 { Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64 },
84 { Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64 },
85 { Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64 },
86};
87
88PAGE_TABLE_POOL *mPageTablePool = NULL;
89BOOLEAN mPageTablePoolLock = FALSE;
91EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL;
92
93//
94// Record the page fault exception count for one instruction execution.
95//
96UINTN *mPFEntryCount;
97UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
98
117BOOLEAN
119 VOID
120 )
121{
122 BOOLEAN InSmm;
123
124 InSmm = FALSE;
125 if (mSmmBase2 == NULL) {
126 gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&mSmmBase2);
127 }
128
129 if (mSmmBase2 != NULL) {
130 mSmmBase2->InSmm (mSmmBase2, &InSmm);
131 }
132
133 //
134 // mSmmBase2->InSmm() can only detect if the caller is running in SMRAM
135 // or from SMM driver. It cannot tell if the caller is running in SMM mode.
136 // Check page table base address to guarantee that because SMM mode willl
137 // load its own page table.
138 //
139 return (InSmm &&
140 mPagingContext.ContextData.X64.PageTableBase != (UINT64)AsmReadCr3 ());
141}
142
148VOID
151 )
152{
153 UINT32 RegEax;
156 IA32_CR4 Cr4;
157 IA32_CR0 Cr0;
158 UINT32 *Attributes;
159 UINTN *PageTableBase;
160
161 //
162 // Don't retrieve current paging context from processor if in SMM mode.
163 //
164 if (!IsInSmm ()) {
165 ZeroMem (&mPagingContext, sizeof (mPagingContext));
166 if (sizeof (UINTN) == sizeof (UINT64)) {
167 mPagingContext.MachineType = IMAGE_FILE_MACHINE_X64;
168 } else {
169 mPagingContext.MachineType = IMAGE_FILE_MACHINE_I386;
170 }
171
172 GetPagingDetails (&mPagingContext.ContextData, &PageTableBase, &Attributes);
173
174 Cr0.UintN = AsmReadCr0 ();
175 Cr4.UintN = AsmReadCr4 ();
176
177 if (Cr0.Bits.PG != 0) {
178 *PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
179 } else {
180 *PageTableBase = 0;
181 }
182
183 if (Cr0.Bits.WP != 0) {
184 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;
185 }
186
187 if (Cr4.Bits.PSE != 0) {
188 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;
189 }
190
191 if (Cr4.Bits.PAE != 0) {
192 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;
193 }
194
195 if (Cr4.Bits.LA57 != 0) {
196 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL;
197 }
198
200 if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
202
203 if (RegEdx.Bits.NX != 0) {
204 // XD supported
206 if (MsrEfer.Bits.NXE != 0) {
207 // XD activated
208 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;
209 }
210 }
211
212 if (RegEdx.Bits.Page1GB != 0) {
213 *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;
214 }
215 }
216 }
217
218 //
219 // This can avoid getting SMM paging context if in SMM mode. We cannot assume
220 // SMM mode shares the same paging context as DXE.
221 //
222 CopyMem (PagingContext, &mPagingContext, sizeof (mPagingContext));
223}
224
232UINTN
234 IN PAGE_ATTRIBUTE PageAttribute
235 )
236{
237 UINTN Index;
238
239 for (Index = 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttributeTable[0]); Index++) {
240 if (PageAttribute == mPageAttributeTable[Index].Attribute) {
241 return (UINTN)mPageAttributeTable[Index].Length;
242 }
243 }
244
245 return 0;
246}
247
255UINTN
257 IN PAGE_ATTRIBUTE PageAttribute
258 )
259{
260 UINTN Index;
261
262 for (Index = 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttributeTable[0]); Index++) {
263 if (PageAttribute == mPageAttributeTable[Index].Attribute) {
264 return (UINTN)mPageAttributeTable[Index].AddressMask;
265 }
266 }
267
268 return 0;
269}
270
280VOID *
282 IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext,
283 IN PHYSICAL_ADDRESS Address,
284 OUT PAGE_ATTRIBUTE *PageAttribute
285 )
286{
287 UINTN Index1;
288 UINTN Index2;
289 UINTN Index3;
290 UINTN Index4;
291 UINTN Index5;
292 UINT64 *L1PageTable;
293 UINT64 *L2PageTable;
294 UINT64 *L3PageTable;
295 UINT64 *L4PageTable;
296 UINT64 *L5PageTable;
297 UINT64 AddressEncMask;
298
299 ASSERT (PagingContext != NULL);
300
301 Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK;
302 Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;
303 Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;
304 Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;
305 Index1 = ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK;
306
307 // Make sure AddressEncMask is contained to smallest supported address field.
308 //
309 AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
310 if (AddressEncMask == 0) {
311 AddressEncMask = PcdGet64 (PcdTdxSharedBitMask) & PAGING_1G_ADDRESS_MASK_64;
312 }
313
314 if (PagingContext->MachineType == IMAGE_FILE_MACHINE_X64) {
315 if ((PagingContext->ContextData.X64.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL) != 0) {
316 L5PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;
317 if (L5PageTable[Index5] == 0) {
318 *PageAttribute = PageNone;
319 return NULL;
320 }
321
322 L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
323 } else {
324 L4PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;
325 }
326
327 if (L4PageTable[Index4] == 0) {
328 *PageAttribute = PageNone;
329 return NULL;
330 }
331
332 L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
333 } else {
334 ASSERT ((PagingContext->ContextData.Ia32.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE) != 0);
335 L3PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.Ia32.PageTableBase;
336 }
337
338 if (L3PageTable[Index3] == 0) {
339 *PageAttribute = PageNone;
340 return NULL;
341 }
342
343 if ((L3PageTable[Index3] & IA32_PG_PS) != 0) {
344 // 1G
345 *PageAttribute = Page1G;
346 return &L3PageTable[Index3];
347 }
348
349 L2PageTable = (UINT64 *)(UINTN)(L3PageTable[Index3] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
350 if (L2PageTable[Index2] == 0) {
351 *PageAttribute = PageNone;
352 return NULL;
353 }
354
355 if ((L2PageTable[Index2] & IA32_PG_PS) != 0) {
356 // 2M
357 *PageAttribute = Page2M;
358 return &L2PageTable[Index2];
359 }
360
361 // 4k
362 L1PageTable = (UINT64 *)(UINTN)(L2PageTable[Index2] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
363 if ((L1PageTable[Index1] == 0) && (Address != 0)) {
364 *PageAttribute = PageNone;
365 return NULL;
366 }
367
368 *PageAttribute = Page4K;
369 return &L1PageTable[Index1];
370}
371
379UINT64
381 IN UINT64 *PageEntry
382 )
383{
384 UINT64 Attributes;
385
386 Attributes = 0;
387 if ((*PageEntry & IA32_PG_P) == 0) {
388 Attributes |= EFI_MEMORY_RP;
389 }
390
391 if ((*PageEntry & IA32_PG_RW) == 0) {
392 Attributes |= EFI_MEMORY_RO;
393 }
394
395 if ((*PageEntry & IA32_PG_NX) != 0) {
396 Attributes |= EFI_MEMORY_XP;
397 }
398
399 return Attributes;
400}
401
411VOID
413 IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext,
414 IN UINT64 *PageEntry,
415 IN UINT64 Attributes,
416 IN PAGE_ACTION PageAction,
417 OUT BOOLEAN *IsModified
418 )
419{
420 UINT64 CurrentPageEntry;
421 UINT64 NewPageEntry;
422 UINT32 *PageAttributes;
423
424 CurrentPageEntry = *PageEntry;
425 NewPageEntry = CurrentPageEntry;
426 if ((Attributes & EFI_MEMORY_RP) != 0) {
427 switch (PageAction) {
428 case PageActionAssign:
429 case PageActionSet:
430 NewPageEntry &= ~(UINT64)IA32_PG_P;
431 break;
432 case PageActionClear:
433 NewPageEntry |= IA32_PG_P;
434 break;
435 }
436 } else {
437 switch (PageAction) {
438 case PageActionAssign:
439 NewPageEntry |= IA32_PG_P;
440 break;
441 case PageActionSet:
442 case PageActionClear:
443 break;
444 }
445 }
446
447 if ((Attributes & EFI_MEMORY_RO) != 0) {
448 switch (PageAction) {
449 case PageActionAssign:
450 case PageActionSet:
451 NewPageEntry &= ~(UINT64)IA32_PG_RW;
452 break;
453 case PageActionClear:
454 NewPageEntry |= IA32_PG_RW;
455 break;
456 }
457 } else {
458 switch (PageAction) {
459 case PageActionAssign:
460 NewPageEntry |= IA32_PG_RW;
461 break;
462 case PageActionSet:
463 case PageActionClear:
464 break;
465 }
466 }
467
468 GetPagingDetails (&PagingContext->ContextData, NULL, &PageAttributes);
469
470 if ((*PageAttributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED) != 0) {
471 if ((Attributes & EFI_MEMORY_XP) != 0) {
472 switch (PageAction) {
473 case PageActionAssign:
474 case PageActionSet:
475 NewPageEntry |= IA32_PG_NX;
476 break;
477 case PageActionClear:
478 NewPageEntry &= ~IA32_PG_NX;
479 break;
480 }
481 } else {
482 switch (PageAction) {
483 case PageActionAssign:
484 NewPageEntry &= ~IA32_PG_NX;
485 break;
486 case PageActionSet:
487 case PageActionClear:
488 break;
489 }
490 }
491 }
492
493 *PageEntry = NewPageEntry;
494 if (CurrentPageEntry != NewPageEntry) {
495 *IsModified = TRUE;
496 DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));
497 DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));
498 } else {
499 *IsModified = FALSE;
500 }
501}
502
513PAGE_ATTRIBUTE
515 IN PHYSICAL_ADDRESS BaseAddress,
516 IN UINT64 Length,
517 IN UINT64 *PageEntry,
518 IN PAGE_ATTRIBUTE PageAttribute
519 )
520{
521 UINT64 PageEntryLength;
522
523 PageEntryLength = PageAttributeToLength (PageAttribute);
524
525 if (((BaseAddress & (PageEntryLength - 1)) == 0) && (Length >= PageEntryLength)) {
526 return PageNone;
527 }
528
529 if (((BaseAddress & PAGING_2M_MASK) != 0) || (Length < SIZE_2MB)) {
530 return Page4K;
531 }
532
533 return Page2M;
534}
535
548RETURN_STATUS
550 IN UINT64 *PageEntry,
551 IN PAGE_ATTRIBUTE PageAttribute,
552 IN PAGE_ATTRIBUTE SplitAttribute,
553 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc
554 )
555{
556 UINT64 BaseAddress;
557 UINT64 *NewPageEntry;
558 UINTN Index;
559 UINT64 AddressEncMask;
560
561 ASSERT (PageAttribute == Page2M || PageAttribute == Page1G);
562
563 ASSERT (AllocatePagesFunc != NULL);
564
565 // Make sure AddressEncMask is contained to smallest supported address field.
566 //
567 AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
568
569 if (PageAttribute == Page2M) {
570 //
571 // Split 2M to 4K
572 //
573 ASSERT (SplitAttribute == Page4K);
574 if (SplitAttribute == Page4K) {
575 NewPageEntry = AllocatePagesFunc (1);
576 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));
577 if (NewPageEntry == NULL) {
579 }
580
581 BaseAddress = *PageEntry & ~AddressEncMask & PAGING_2M_ADDRESS_MASK_64;
582 for (Index = 0; Index < SIZE_4KB / sizeof (UINT64); Index++) {
583 NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | AddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS);
584 }
585
586 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
587 return RETURN_SUCCESS;
588 } else {
589 return RETURN_UNSUPPORTED;
590 }
591 } else if (PageAttribute == Page1G) {
592 //
593 // Split 1G to 2M
594 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
595 //
596 ASSERT (SplitAttribute == Page2M || SplitAttribute == Page4K);
597 if (((SplitAttribute == Page2M) || (SplitAttribute == Page4K))) {
598 NewPageEntry = AllocatePagesFunc (1);
599 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));
600 if (NewPageEntry == NULL) {
602 }
603
604 BaseAddress = *PageEntry & ~AddressEncMask & PAGING_1G_ADDRESS_MASK_64;
605 for (Index = 0; Index < SIZE_4KB / sizeof (UINT64); Index++) {
606 NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | AddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS);
607 }
608
609 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
610 return RETURN_SUCCESS;
611 } else {
612 return RETURN_UNSUPPORTED;
613 }
614 } else {
615 return RETURN_UNSUPPORTED;
616 }
617}
618
626BOOLEAN
628 VOID
629 )
630{
631 IA32_CR0 Cr0;
632
633 //
634 // To avoid unforseen consequences, don't touch paging settings in SMM mode
635 // in this driver.
636 //
637 if (!IsInSmm ()) {
638 Cr0.UintN = AsmReadCr0 ();
639 return (BOOLEAN)(Cr0.Bits.WP != 0);
640 }
641
642 return FALSE;
643}
644
648VOID
650 VOID
651 )
652{
653 IA32_CR0 Cr0;
654
655 //
656 // To avoid unforseen consequences, don't touch paging settings in SMM mode
657 // in this driver.
658 //
659 if (!IsInSmm ()) {
660 Cr0.UintN = AsmReadCr0 ();
661 Cr0.Bits.WP = 0;
662 AsmWriteCr0 (Cr0.UintN);
663 }
664}
665
669VOID
671 VOID
672 )
673{
674 IA32_CR0 Cr0;
675
676 //
677 // To avoid unforseen consequences, don't touch paging settings in SMM mode
678 // in this driver.
679 //
680 if (!IsInSmm ()) {
681 Cr0.UintN = AsmReadCr0 ();
682 Cr0.Bits.WP = 1;
683 AsmWriteCr0 (Cr0.UintN);
684 }
685}
686
716RETURN_STATUS
718 IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL,
719 IN PHYSICAL_ADDRESS BaseAddress,
720 IN UINT64 Length,
721 IN UINT64 Attributes,
722 IN PAGE_ACTION PageAction,
723 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL,
724 OUT BOOLEAN *IsSplitted OPTIONAL,
725 OUT BOOLEAN *IsModified OPTIONAL
726 )
727{
728 PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext;
729 UINT64 *PageEntry;
730 PAGE_ATTRIBUTE PageAttribute;
731 UINTN PageEntryLength;
732 PAGE_ATTRIBUTE SplitAttribute;
733 RETURN_STATUS Status;
734 BOOLEAN IsEntryModified;
735 BOOLEAN IsWpEnabled;
736
737 if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
738 DEBUG ((DEBUG_ERROR, "BaseAddress(0x%lx) is not aligned!\n", BaseAddress));
739 return EFI_UNSUPPORTED;
740 }
741
742 if ((Length & (SIZE_4KB - 1)) != 0) {
743 DEBUG ((DEBUG_ERROR, "Length(0x%lx) is not aligned!\n", Length));
744 return EFI_UNSUPPORTED;
745 }
746
747 if (Length == 0) {
748 DEBUG ((DEBUG_ERROR, "Length is 0!\n"));
750 }
751
752 if ((Attributes & ~EFI_MEMORY_ATTRIBUTE_MASK) != 0) {
753 DEBUG ((DEBUG_ERROR, "Attributes(0x%lx) has unsupported bit\n", Attributes));
754 return EFI_UNSUPPORTED;
755 }
756
757 if (PagingContext == NULL) {
758 GetCurrentPagingContext (&CurrentPagingContext);
759 } else {
760 CopyMem (&CurrentPagingContext, PagingContext, sizeof (CurrentPagingContext));
761 }
762
763 switch (CurrentPagingContext.MachineType) {
764 case IMAGE_FILE_MACHINE_I386:
765 if (CurrentPagingContext.ContextData.Ia32.PageTableBase == 0) {
766 if (Attributes == 0) {
767 return EFI_SUCCESS;
768 } else {
769 DEBUG ((DEBUG_ERROR, "PageTable is 0!\n"));
770 return EFI_UNSUPPORTED;
771 }
772 }
773
774 if ((CurrentPagingContext.ContextData.Ia32.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE) == 0) {
775 DEBUG ((DEBUG_ERROR, "Non-PAE Paging!\n"));
776 return EFI_UNSUPPORTED;
777 }
778
779 if ((BaseAddress + Length) > BASE_4GB) {
780 DEBUG ((DEBUG_ERROR, "Beyond 4GB memory in 32-bit mode!\n"));
781 return EFI_UNSUPPORTED;
782 }
783
784 break;
785 case IMAGE_FILE_MACHINE_X64:
786 ASSERT (CurrentPagingContext.ContextData.X64.PageTableBase != 0);
787 break;
788 default:
789 ASSERT (FALSE);
790 return EFI_UNSUPPORTED;
791 break;
792 }
793
794 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
795
796 if (IsSplitted != NULL) {
797 *IsSplitted = FALSE;
798 }
799
800 if (IsModified != NULL) {
801 *IsModified = FALSE;
802 }
803
804 if (AllocatePagesFunc == NULL) {
805 AllocatePagesFunc = AllocatePageTableMemory;
806 }
807
808 //
809 // Make sure that the page table is changeable.
810 //
811 IsWpEnabled = IsReadOnlyPageWriteProtected ();
812 if (IsWpEnabled) {
814 }
815
816 //
817 // Below logic is to check 2M/4K page to make sure we do not waste memory.
818 //
819 Status = EFI_SUCCESS;
820 while (Length != 0) {
821 PageEntry = GetPageTableEntry (&CurrentPagingContext, BaseAddress, &PageAttribute);
822 if (PageEntry == NULL) {
823 Status = RETURN_UNSUPPORTED;
824 goto Done;
825 }
826
827 PageEntryLength = PageAttributeToLength (PageAttribute);
828 SplitAttribute = NeedSplitPage (BaseAddress, Length, PageEntry, PageAttribute);
829 if (SplitAttribute == PageNone) {
830 ConvertPageEntryAttribute (&CurrentPagingContext, PageEntry, Attributes, PageAction, &IsEntryModified);
831 if (IsEntryModified) {
832 if (IsModified != NULL) {
833 *IsModified = TRUE;
834 }
835 }
836
837 //
838 // Convert success, move to next
839 //
840 BaseAddress += PageEntryLength;
841 Length -= PageEntryLength;
842 } else {
843 if (AllocatePagesFunc == NULL) {
844 Status = RETURN_UNSUPPORTED;
845 goto Done;
846 }
847
848 Status = SplitPage (PageEntry, PageAttribute, SplitAttribute, AllocatePagesFunc);
849 if (RETURN_ERROR (Status)) {
850 Status = RETURN_UNSUPPORTED;
851 goto Done;
852 }
853
854 if (IsSplitted != NULL) {
855 *IsSplitted = TRUE;
856 }
857
858 if (IsModified != NULL) {
859 *IsModified = TRUE;
860 }
861
862 //
863 // Just split current page
864 // Convert success in next around
865 //
866 }
867 }
868
869Done:
870 //
871 // Restore page table write protection, if any.
872 //
873 if (IsWpEnabled) {
875 }
876
877 return Status;
878}
879
908RETURN_STATUS
909EFIAPI
911 IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL,
912 IN PHYSICAL_ADDRESS BaseAddress,
913 IN UINT64 Length,
914 IN UINT64 Attributes,
915 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL
916 )
917{
918 RETURN_STATUS Status;
919 BOOLEAN IsModified;
920 BOOLEAN IsSplitted;
921
922 // DEBUG((DEBUG_INFO, "AssignMemoryPageAttributes: 0x%lx - 0x%lx (0x%lx)\n", BaseAddress, Length, Attributes));
923 Status = ConvertMemoryPageAttributes (PagingContext, BaseAddress, Length, Attributes, PageActionAssign, AllocatePagesFunc, &IsSplitted, &IsModified);
924 if (!EFI_ERROR (Status)) {
925 if ((PagingContext == NULL) && IsModified) {
926 //
927 // Flush TLB as last step.
928 //
929 // Note: Since APs will always init CR3 register in HLT loop mode or do
930 // TLB flush in MWAIT loop mode, there's no need to flush TLB for them
931 // here.
932 //
933 CpuFlushTlb ();
934 }
935 }
936
937 return Status;
938}
939
943BOOLEAN
945 VOID
946 )
947{
949
951 return (MsrEfer.Bits.NXE == 1);
952}
953
957VOID
959 VOID
960 )
961{
962 EFI_STATUS Status;
963 UINTN NumberOfDescriptors;
964 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
965 PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext;
966 PAGE_ATTRIBUTE PageAttribute;
967 UINT64 *PageEntry;
968 UINT64 PageLength;
969 UINT64 MemorySpaceLength;
970 UINT64 Length;
971 UINT64 BaseAddress;
972 UINT64 PageStartAddress;
973 UINT64 Attributes;
974 UINT64 Capabilities;
975 UINT64 NewAttributes;
976 UINTN Index;
977
978 //
979 // Assuming that memory space map returned is sorted already; otherwise sort
980 // them in the order of lowest address to highest address.
981 //
982 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
983 ASSERT_EFI_ERROR (Status);
984
985 GetCurrentPagingContext (&PagingContext);
986
987 Attributes = 0;
988 NewAttributes = 0;
989 BaseAddress = 0;
990 PageLength = 0;
991
993 Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP;
994 } else {
995 Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP;
996 }
997
998 for (Index = 0; Index < NumberOfDescriptors; Index++) {
999 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
1000 continue;
1001 }
1002
1003 //
1004 // Sync the actual paging related capabilities back to GCD service first.
1005 // As a side effect (good one), this can also help to avoid unnecessary
1006 // memory map entries due to the different capabilities of the same type
1007 // memory, such as multiple RT_CODE and RT_DATA entries in memory map,
1008 // which could cause boot failure of some old Linux distro (before v4.3).
1009 //
1010 Status = gDS->SetMemorySpaceCapabilities (
1011 MemorySpaceMap[Index].BaseAddress,
1012 MemorySpaceMap[Index].Length,
1013 MemorySpaceMap[Index].Capabilities | Capabilities
1014 );
1015 if (EFI_ERROR (Status)) {
1016 //
1017 // If we cannot update the capabilities, we cannot update its
1018 // attributes either. So just simply skip current block of memory.
1019 //
1020 DEBUG ((
1021 DEBUG_WARN,
1022 "Failed to update capability: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",
1023 (UINT64)Index,
1024 MemorySpaceMap[Index].BaseAddress,
1025 MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,
1026 MemorySpaceMap[Index].Capabilities,
1027 MemorySpaceMap[Index].Capabilities | Capabilities
1028 ));
1029 continue;
1030 }
1031
1032 if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) {
1033 //
1034 // Current memory space starts at a new page. Resetting PageLength will
1035 // trigger a retrieval of page attributes at new address.
1036 //
1037 PageLength = 0;
1038 } else {
1039 //
1040 // In case current memory space is not adjacent to last one
1041 //
1042 PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);
1043 }
1044
1045 //
1046 // Sync actual page attributes to GCD
1047 //
1048 BaseAddress = MemorySpaceMap[Index].BaseAddress;
1049 MemorySpaceLength = MemorySpaceMap[Index].Length;
1050 while (MemorySpaceLength > 0) {
1051 if (PageLength == 0) {
1052 PageEntry = GetPageTableEntry (&PagingContext, BaseAddress, &PageAttribute);
1053 if (PageEntry == NULL) {
1054 break;
1055 }
1056
1057 //
1058 // Note current memory space might start in the middle of a page
1059 //
1060 PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask (PageAttribute);
1061 PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress);
1062 Attributes = GetAttributesFromPageEntry (PageEntry);
1063 }
1064
1065 Length = MIN (PageLength, MemorySpaceLength);
1066 if (Attributes != (MemorySpaceMap[Index].Attributes &
1067 EFI_MEMORY_ATTRIBUTE_MASK))
1068 {
1069 NewAttributes = (MemorySpaceMap[Index].Attributes &
1070 ~EFI_MEMORY_ATTRIBUTE_MASK) | Attributes;
1071 Status = gDS->SetMemorySpaceAttributes (
1072 BaseAddress,
1073 Length,
1074 NewAttributes
1075 );
1076 ASSERT_EFI_ERROR (Status);
1077 DEBUG ((
1078 DEBUG_VERBOSE,
1079 "Updated memory space attribute: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",
1080 (UINT64)Index,
1081 BaseAddress,
1082 BaseAddress + Length - 1,
1083 MemorySpaceMap[Index].Attributes,
1084 NewAttributes
1085 ));
1086 }
1087
1088 PageLength -= Length;
1089 MemorySpaceLength -= Length;
1090 BaseAddress += Length;
1091 }
1092 }
1093
1094 FreePool (MemorySpaceMap);
1095}
1096
1114BOOLEAN
1116 IN UINTN PoolPages
1117 )
1118{
1119 VOID *Buffer;
1120 BOOLEAN IsModified;
1121
1122 //
1123 // Do not allow re-entrance.
1124 //
1125 if (mPageTablePoolLock) {
1126 return FALSE;
1127 }
1128
1129 mPageTablePoolLock = TRUE;
1130 IsModified = FALSE;
1131
1132 //
1133 // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for
1134 // header.
1135 //
1136 PoolPages += 1; // Add one page for header.
1137 PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) *
1138 PAGE_TABLE_POOL_UNIT_PAGES;
1139 Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
1140 if (Buffer == NULL) {
1141 DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n"));
1142 goto Done;
1143 }
1144
1145 DEBUG ((
1146 DEBUG_INFO,
1147 "Paging: added %lu pages to page table pool\r\n",
1148 (UINT64)PoolPages
1149 ));
1150
1151 //
1152 // Link all pools into a list for easier track later.
1153 //
1154 if (mPageTablePool == NULL) {
1155 mPageTablePool = Buffer;
1156 mPageTablePool->NextPool = mPageTablePool;
1157 } else {
1158 ((PAGE_TABLE_POOL *)Buffer)->NextPool = mPageTablePool->NextPool;
1159 mPageTablePool->NextPool = Buffer;
1160 mPageTablePool = Buffer;
1161 }
1162
1163 //
1164 // Reserve one page for pool header.
1165 //
1166 mPageTablePool->FreePages = PoolPages - 1;
1167 mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
1168
1169 //
1170 // Mark the whole pool pages as read-only.
1171 //
1173 NULL,
1174 (PHYSICAL_ADDRESS)(UINTN)Buffer,
1175 EFI_PAGES_TO_SIZE (PoolPages),
1176 EFI_MEMORY_RO,
1177 PageActionSet,
1179 NULL,
1180 &IsModified
1181 );
1182 ASSERT (IsModified == TRUE);
1183
1184Done:
1185 mPageTablePoolLock = FALSE;
1186 return IsModified;
1187}
1188
1206VOID *
1207EFIAPI
1209 IN UINTN Pages
1210 )
1211{
1212 VOID *Buffer;
1213
1214 if (Pages == 0) {
1215 return NULL;
1216 }
1217
1218 //
1219 // Renew the pool if necessary.
1220 //
1221 if ((mPageTablePool == NULL) ||
1222 (Pages > mPageTablePool->FreePages))
1223 {
1224 if (!InitializePageTablePool (Pages)) {
1225 return NULL;
1226 }
1227 }
1228
1229 Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
1230
1231 mPageTablePool->Offset += EFI_PAGES_TO_SIZE (Pages);
1232 mPageTablePool->FreePages -= Pages;
1233
1234 return Buffer;
1235}
1236
1246VOID
1247EFIAPI
1249 IN EFI_EXCEPTION_TYPE ExceptionType,
1250 IN EFI_SYSTEM_CONTEXT SystemContext
1251 )
1252{
1253 UINTN CpuIndex;
1254 UINTN PFEntry;
1255 BOOLEAN IsWpEnabled;
1256
1257 MpInitLibWhoAmI (&CpuIndex);
1258
1259 //
1260 // Clear last PF entries
1261 //
1262 IsWpEnabled = IsReadOnlyPageWriteProtected ();
1263 if (IsWpEnabled) {
1265 }
1266
1267 for (PFEntry = 0; PFEntry < mPFEntryCount[CpuIndex]; PFEntry++) {
1268 if (mLastPFEntryPointer[CpuIndex][PFEntry] != NULL) {
1269 *mLastPFEntryPointer[CpuIndex][PFEntry] &= ~(UINT64)IA32_PG_P;
1270 }
1271 }
1272
1273 if (IsWpEnabled) {
1275 }
1276
1277 //
1278 // Reset page fault exception count for next page fault.
1279 //
1280 mPFEntryCount[CpuIndex] = 0;
1281
1282 //
1283 // Flush TLB
1284 //
1285 CpuFlushTlb ();
1286
1287 //
1288 // Clear TF in EFLAGS
1289 //
1290 if (mPagingContext.MachineType == IMAGE_FILE_MACHINE_I386) {
1291 SystemContext.SystemContextIa32->Eflags &= (UINT32) ~BIT8;
1292 } else {
1293 SystemContext.SystemContextX64->Rflags &= (UINT64) ~BIT8;
1294 }
1295}
1296
1306VOID
1307EFIAPI
1309 IN EFI_EXCEPTION_TYPE ExceptionType,
1310 IN EFI_SYSTEM_CONTEXT SystemContext
1311 )
1312{
1313 EFI_STATUS Status;
1314 UINT64 PFAddress;
1315 PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext;
1316 PAGE_ATTRIBUTE PageAttribute;
1317 UINT64 Attributes;
1318 UINT64 *PageEntry;
1319 UINTN Index;
1320 UINTN CpuIndex;
1321 UINTN PageNumber;
1322 BOOLEAN NonStopMode;
1323
1324 PFAddress = AsmReadCr2 () & ~EFI_PAGE_MASK;
1325 if (PFAddress < BASE_4KB) {
1326 NonStopMode = NULL_DETECTION_NONSTOP_MODE ? TRUE : FALSE;
1327 } else {
1328 NonStopMode = HEAP_GUARD_NONSTOP_MODE ? TRUE : FALSE;
1329 }
1330
1331 if (NonStopMode) {
1332 MpInitLibWhoAmI (&CpuIndex);
1333 GetCurrentPagingContext (&PagingContext);
1334 //
1335 // Memory operation cross page boundary, like "rep mov" instruction, will
1336 // cause infinite loop between this and Debug Trap handler. We have to make
1337 // sure that current page and the page followed are both in PRESENT state.
1338 //
1339 PageNumber = 2;
1340 while (PageNumber > 0) {
1341 PageEntry = GetPageTableEntry (&PagingContext, PFAddress, &PageAttribute);
1342 ASSERT (PageEntry != NULL);
1343
1344 if (PageEntry != NULL) {
1345 Attributes = GetAttributesFromPageEntry (PageEntry);
1346 if ((Attributes & EFI_MEMORY_RP) != 0) {
1347 Attributes &= ~EFI_MEMORY_RP;
1349 &PagingContext,
1350 PFAddress,
1351 EFI_PAGE_SIZE,
1352 Attributes,
1353 NULL
1354 );
1355 if (!EFI_ERROR (Status)) {
1356 Index = mPFEntryCount[CpuIndex];
1357 //
1358 // Re-retrieve page entry because above calling might update page
1359 // table due to table split.
1360 //
1361 PageEntry = GetPageTableEntry (&PagingContext, PFAddress, &PageAttribute);
1362 mLastPFEntryPointer[CpuIndex][Index++] = PageEntry;
1363 mPFEntryCount[CpuIndex] = Index;
1364 }
1365 }
1366 }
1367
1368 PFAddress += EFI_PAGE_SIZE;
1369 --PageNumber;
1370 }
1371 }
1372
1373 //
1374 // Initialize the serial port before dumping.
1375 //
1377 //
1378 // Display ExceptionType, CPU information and Image information
1379 //
1380 DumpCpuContext (ExceptionType, SystemContext);
1381 if (NonStopMode) {
1382 //
1383 // Set TF in EFLAGS
1384 //
1385 if (mPagingContext.MachineType == IMAGE_FILE_MACHINE_I386) {
1386 SystemContext.SystemContextIa32->Eflags |= (UINT32)BIT8;
1387 } else {
1388 SystemContext.SystemContextX64->Rflags |= (UINT64)BIT8;
1389 }
1390 } else {
1391 CpuDeadLoop ();
1392 }
1393}
1394
1398VOID
1400 VOID
1401 )
1402{
1403 PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext;
1404 UINT32 *Attributes;
1405 UINTN *PageTableBase;
1406
1407 GetCurrentPagingContext (&CurrentPagingContext);
1408
1409 GetPagingDetails (&CurrentPagingContext.ContextData, &PageTableBase, &Attributes);
1410
1411 //
1412 // Reserve memory of page tables for future uses, if paging is enabled.
1413 //
1414 if ((*PageTableBase != 0) &&
1415 ((*Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE) != 0))
1416 {
1420 }
1421
1422 if (HEAP_GUARD_NONSTOP_MODE || NULL_DETECTION_NONSTOP_MODE) {
1423 mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mNumberOfProcessors);
1424 ASSERT (mPFEntryCount != NULL);
1425
1426 mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])
1427 AllocateZeroPool (sizeof (mLastPFEntryPointer[0]) * mNumberOfProcessors);
1428 ASSERT (mLastPFEntryPointer != NULL);
1429 }
1430
1431 DEBUG ((DEBUG_INFO, "CurrentPagingContext:\n"));
1432 DEBUG ((DEBUG_INFO, " MachineType - 0x%x\n", CurrentPagingContext.MachineType));
1433 DEBUG ((DEBUG_INFO, " PageTableBase - 0x%Lx\n", (UINT64)*PageTableBase));
1434 DEBUG ((DEBUG_INFO, " Attributes - 0x%x\n", *Attributes));
1435
1436 return;
1437}
UINT64 UINTN
RETURN_STATUS EFIAPI SerialPortInitialize(VOID)
Definition: SerialPortLib.c:25
#define NULL
Definition: Base.h:312
#define RETURN_ERROR(StatusCode)
Definition: Base.h:957
#define MIN(a, b)
Definition: Base.h:903
#define RETURN_UNSUPPORTED
Definition: Base.h:977
#define RETURN_OUT_OF_RESOURCES
Definition: Base.h:1010
#define RETURN_SUCCESS
Definition: Base.h:962
#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 RETURN_INVALID_PARAMETER
Definition: Base.h:972
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:23
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MSR_CORE_IA32_EFER
Definition: CoreMsr.h:996
VOID EFIAPI DumpCpuContext(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI CpuFlushTlb(VOID)
#define IA32_PG_P
Definition: CpuPageTable.c:27
VOID *EFIAPI AllocatePageTableMemory(IN UINTN Pages)
VOID GetCurrentPagingContext(IN OUT PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext)
Definition: CpuPageTable.c:149
PAGE_ATTRIBUTE NeedSplitPage(IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 *PageEntry, IN PAGE_ATTRIBUTE PageAttribute)
Definition: CpuPageTable.c:514
BOOLEAN IsInSmm(VOID)
Definition: CpuPageTable.c:118
VOID EnableReadOnlyPageWriteProtect(VOID)
Definition: CpuPageTable.c:670
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:717
UINT64 GetAttributesFromPageEntry(IN UINT64 *PageEntry)
Definition: CpuPageTable.c:380
VOID EFIAPI PageFaultExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
BOOLEAN IsExecuteDisableEnabled(VOID)
Definition: CpuPageTable.c:944
RETURN_STATUS SplitPage(IN UINT64 *PageEntry, IN PAGE_ATTRIBUTE PageAttribute, IN PAGE_ATTRIBUTE SplitAttribute, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc)
Definition: CpuPageTable.c:549
VOID EFIAPI DebugExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
UINTN PageAttributeToLength(IN PAGE_ATTRIBUTE PageAttribute)
Definition: CpuPageTable.c:233
BOOLEAN InitializePageTablePool(IN UINTN PoolPages)
VOID RefreshGcdMemoryAttributesFromPaging(VOID)
Definition: CpuPageTable.c:958
VOID InitializePageTableLib(VOID)
RETURN_STATUS EFIAPI AssignMemoryPageAttributes(IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL)
Definition: CpuPageTable.c:910
VOID DisableReadOnlyPageWriteProtect(VOID)
Definition: CpuPageTable.c:649
UINTN PageAttributeToMask(IN PAGE_ATTRIBUTE PageAttribute)
Definition: CpuPageTable.c:256
VOID ConvertPageEntryAttribute(IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext, IN UINT64 *PageEntry, IN UINT64 Attributes, IN PAGE_ACTION PageAction, OUT BOOLEAN *IsModified)
Definition: CpuPageTable.c:412
BOOLEAN IsReadOnlyPageWriteProtected(VOID)
Definition: CpuPageTable.c:627
VOID * GetPageTableEntry(IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext, IN PHYSICAL_ADDRESS Address, OUT PAGE_ATTRIBUTE *PageAttribute)
Definition: CpuPageTable.c:281
VOID GetPagingDetails(IN PAGE_TABLE_LIB_PAGING_CONTEXT_DATA *PagingContextData, OUT UINTN **PageTableBase OPTIONAL, OUT UINT32 **Attributes OPTIONAL)
VOID *(EFIAPI * PAGE_TABLE_LIB_ALLOCATE_PAGES)(IN UINTN Pages)
Definition: CpuPageTable.h:70
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:440
#define DEBUG(Expression)
Definition: DebugLib.h:417
#define ASSERT(Expression)
Definition: DebugLib.h:391
EFI_DXE_SERVICES * gDS
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 AsmReadCr0(VOID)
UINTN EFIAPI AsmWriteCr0(UINTN Cr0)
UINTN EFIAPI AsmReadCr2(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
#define MSR_IA32_EFER
#define CPUID_EXTENDED_FUNCTION
Definition: Cpuid.h:3740
#define CPUID_EXTENDED_CPU_SIG
Definition: Cpuid.h:3763
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
EFI_STATUS EFIAPI MpInitLibWhoAmI(OUT UINTN *ProcessorNumber)
Definition: MpLib.c:2354
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
BOOLEAN EFIAPI InSmm(VOID)
VOID *EFIAPI AllocateAlignedPages(IN UINTN Pages, IN UINTN Alignment)
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:210
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:28
#define EFI_SUCCESS
Definition: UefiBaseType.h:111
EFI_BOOT_SERVICES * gBS
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:125
struct CPUID_EXTENDED_CPU_SIG_EDX::@661 Bits
struct MSR_CORE_IA32_EFER_REGISTER::@704 Bits
struct MSR_IA32_EFER_REGISTER::@602 Bits