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