TianoCore EDK2 master
CpuDxe.c
Go to the documentation of this file.
1
9#include "CpuDxe.h"
10#include "CpuMp.h"
11#include "CpuPageTable.h"
12
13#define CPU_INTERRUPT_NUM 256
14
15//
16// Global Variables
17//
18BOOLEAN InterruptState = FALSE;
19EFI_HANDLE mCpuHandle = NULL;
20BOOLEAN mIsFlushingGCD;
21BOOLEAN mIsAllocatingPageTable = FALSE;
22UINT64 mValidMtrrAddressMask;
23UINT64 mValidMtrrBitsMask;
24UINT64 mTimerPeriod = 0;
25
26FIXED_MTRR mFixedMtrrTable[] = {
27 {
29 0,
30 0x10000
31 },
32 {
34 0x80000,
35 0x4000
36 },
37 {
39 0xA0000,
40 0x4000
41 },
42 {
44 0xC0000,
45 0x1000
46 },
47 {
49 0xC8000,
50 0x1000
51 },
52 {
54 0xD0000,
55 0x1000
56 },
57 {
59 0xD8000,
60 0x1000
61 },
62 {
64 0xE0000,
65 0x1000
66 },
67 {
69 0xE8000,
70 0x1000
71 },
72 {
74 0xF0000,
75 0x1000
76 },
77 {
79 0xF8000,
80 0x1000
81 },
82};
83
89 CpuInit,
93 1, // NumberOfTimers
94 4 // DmaBufferAlignment
95};
96
97//
98// CPU Arch Protocol Functions
99//
100
117EFIAPI
121 IN UINT64 Length,
122 IN EFI_CPU_FLUSH_TYPE FlushType
123 )
124{
125 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
126 AsmWbinvd ();
127 return EFI_SUCCESS;
128 } else if (FlushType == EfiCpuFlushTypeInvalidate) {
129 AsmInvd ();
130 return EFI_SUCCESS;
131 } else {
132 return EFI_UNSUPPORTED;
133 }
134}
135
146EFIAPI
149 )
150{
152
153 InterruptState = TRUE;
154 return EFI_SUCCESS;
155}
156
167EFIAPI
170 )
171{
173
174 InterruptState = FALSE;
175 return EFI_SUCCESS;
176}
177
189EFIAPI
192 OUT BOOLEAN *State
193 )
194{
195 if (State == NULL) {
196 return EFI_INVALID_PARAMETER;
197 }
198
199 *State = InterruptState;
200 return EFI_SUCCESS;
201}
202
216EFIAPI
219 IN EFI_CPU_INIT_TYPE InitType
220 )
221{
222 return EFI_UNSUPPORTED;
223}
224
246EFIAPI
249 IN EFI_EXCEPTION_TYPE InterruptType,
250 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
251 )
252{
253 return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
254}
255
280EFIAPI
283 IN UINT32 TimerIndex,
284 OUT UINT64 *TimerValue,
285 OUT UINT64 *TimerPeriod OPTIONAL
286 )
287{
288 UINT64 BeginValue;
289 UINT64 EndValue;
290
291 if (TimerValue == NULL) {
292 return EFI_INVALID_PARAMETER;
293 }
294
295 if (TimerIndex != 0) {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 *TimerValue = AsmReadTsc ();
300
301 if (TimerPeriod != NULL) {
302 if (mTimerPeriod == 0) {
303 //
304 // Read time stamp counter before and after delay of 100 microseconds
305 //
306 BeginValue = AsmReadTsc ();
307 MicroSecondDelay (100);
308 EndValue = AsmReadTsc ();
309 //
310 // Calculate the actual frequency
311 //
313 MultU64x32 (
314 1000 * 1000 * 1000,
315 100
316 ),
317 EndValue - BeginValue,
318 NULL
319 );
320 }
321
322 *TimerPeriod = mTimerPeriod;
323 }
324
325 return EFI_SUCCESS;
326}
327
335VOID
336EFIAPI
338 IN VOID *Buffer
339 )
340{
341 MtrrSetAllMtrrs (Buffer);
342}
343
370EFIAPI
373 IN EFI_PHYSICAL_ADDRESS BaseAddress,
374 IN UINT64 Length,
375 IN UINT64 Attributes
376 )
377{
378 RETURN_STATUS Status;
379 MTRR_MEMORY_CACHE_TYPE CacheType;
380 EFI_STATUS MpStatus;
381 EFI_MP_SERVICES_PROTOCOL *MpService;
382 MTRR_SETTINGS MtrrSettings;
383 UINT64 CacheAttributes;
384 UINT64 MemoryAttributes;
385 MTRR_MEMORY_CACHE_TYPE CurrentCacheType;
386
387 //
388 // If this function is called because GCD SetMemorySpaceAttributes () is called
389 // by RefreshGcdMemoryAttributes (), then we are just synchronizing GCD memory
390 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
391 // to avoid unnecessary computing.
392 //
393 if (mIsFlushingGCD) {
394 DEBUG ((DEBUG_VERBOSE, " Flushing GCD\n"));
395 return EFI_SUCCESS;
396 }
397
398 //
399 // During memory attributes updating, new pages may be allocated to setup
400 // smaller granularity of page table. Page allocation action might then cause
401 // another calling of CpuSetMemoryAttributes() recursively, due to memory
402 // protection policy configured (such as PcdDxeNxMemoryProtectionPolicy).
403 // Since this driver will always protect memory used as page table by itself,
404 // there's no need to apply protection policy requested from memory service.
405 // So it's safe to just return EFI_SUCCESS if this time of calling is caused
406 // by page table memory allocation.
407 //
408 if (mIsAllocatingPageTable) {
409 DEBUG ((DEBUG_VERBOSE, " Allocating page table memory\n"));
410 return EFI_SUCCESS;
411 }
412
413 CacheAttributes = Attributes & EFI_CACHE_ATTRIBUTE_MASK;
414 MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;
415
416 if (Attributes != (CacheAttributes | MemoryAttributes)) {
417 return EFI_INVALID_PARAMETER;
418 }
419
420 if (CacheAttributes != 0) {
421 if (!IsMtrrSupported ()) {
422 return EFI_UNSUPPORTED;
423 }
424
425 switch (CacheAttributes) {
426 case EFI_MEMORY_UC:
427 CacheType = CacheUncacheable;
428 break;
429
430 case EFI_MEMORY_WC:
431 CacheType = CacheWriteCombining;
432 break;
433
434 case EFI_MEMORY_WT:
435 CacheType = CacheWriteThrough;
436 break;
437
438 case EFI_MEMORY_WP:
439 CacheType = CacheWriteProtected;
440 break;
441
442 case EFI_MEMORY_WB:
443 CacheType = CacheWriteBack;
444 break;
445
446 default:
447 return EFI_INVALID_PARAMETER;
448 }
449
450 CurrentCacheType = MtrrGetMemoryAttribute (BaseAddress);
451 if (CurrentCacheType != CacheType) {
452 //
453 // call MTRR library function
454 //
455 Status = MtrrSetMemoryAttribute (
456 BaseAddress,
457 Length,
458 CacheType
459 );
460
461 if (!RETURN_ERROR (Status)) {
462 MpStatus = gBS->LocateProtocol (
463 &gEfiMpServiceProtocolGuid,
464 NULL,
465 (VOID **)&MpService
466 );
467 //
468 // Synchronize the update with all APs
469 //
470 if (!EFI_ERROR (MpStatus)) {
471 MtrrGetAllMtrrs (&MtrrSettings);
472 MpStatus = MpService->StartupAllAPs (
473 MpService, // This
474 SetMtrrsFromBuffer, // Procedure
475 FALSE, // SingleThread
476 NULL, // WaitEvent
477 0, // TimeoutInMicrosecsond
478 &MtrrSettings, // ProcedureArgument
479 NULL // FailedCpuList
480 );
481 ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);
482 }
483 }
484
485 if (EFI_ERROR (Status)) {
486 return Status;
487 }
488 }
489 }
490
491 //
492 // Set memory attribute by page table
493 //
494 return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);
495}
496
503VOID
505 VOID
506 )
507{
508 UINT32 RegEax;
509 UINT8 PhysicalAddressBits;
510
511 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
512
513 if (RegEax >= 0x80000008) {
514 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
515
516 PhysicalAddressBits = (UINT8)RegEax;
517 } else {
518 PhysicalAddressBits = 36;
519 }
520
521 mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
522 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
523}
524
535UINT64
537 IN UINT8 MtrrAttributes
538 )
539{
540 switch (MtrrAttributes) {
541 case MTRR_CACHE_UNCACHEABLE:
542 return EFI_MEMORY_UC;
543 case MTRR_CACHE_WRITE_COMBINING:
544 return EFI_MEMORY_WC;
545 case MTRR_CACHE_WRITE_THROUGH:
546 return EFI_MEMORY_WT;
547 case MTRR_CACHE_WRITE_PROTECTED:
548 return EFI_MEMORY_WP;
549 case MTRR_CACHE_WRITE_BACK:
550 return EFI_MEMORY_WB;
551 default:
552 return 0;
553 }
554}
555
576 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
577 IN UINTN NumberOfDescriptors,
578 IN EFI_PHYSICAL_ADDRESS BaseAddress,
579 IN UINT64 Length,
580 OUT UINTN *StartIndex,
581 OUT UINTN *EndIndex
582 )
583{
584 UINTN Index;
585
586 *StartIndex = 0;
587 *EndIndex = 0;
588 for (Index = 0; Index < NumberOfDescriptors; Index++) {
589 if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&
590 (BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))
591 {
592 *StartIndex = Index;
593 }
594
595 if ((BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress) &&
596 (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))
597 {
598 *EndIndex = Index;
599 return EFI_SUCCESS;
600 }
601 }
602
603 return EFI_NOT_FOUND;
604}
605
624 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
625 IN UINTN NumberOfDescriptors,
626 IN EFI_PHYSICAL_ADDRESS BaseAddress,
627 IN UINT64 Length,
628 IN UINT64 Attributes
629 )
630{
631 EFI_STATUS Status;
632 UINTN Index;
633 UINTN StartIndex;
634 UINTN EndIndex;
635 EFI_PHYSICAL_ADDRESS RegionStart;
636 UINT64 RegionLength;
637
638 //
639 // Get all memory descriptors covered by the memory range
640 //
641 Status = SearchGcdMemorySpaces (
642 MemorySpaceMap,
643 NumberOfDescriptors,
644 BaseAddress,
645 Length,
646 &StartIndex,
647 &EndIndex
648 );
649 if (EFI_ERROR (Status)) {
650 return Status;
651 }
652
653 //
654 // Go through all related descriptors and set attributes accordingly
655 //
656 for (Index = StartIndex; Index <= EndIndex; Index++) {
657 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
658 continue;
659 }
660
661 //
662 // Calculate the start and end address of the overlapping range
663 //
664 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
665 RegionStart = BaseAddress;
666 } else {
667 RegionStart = MemorySpaceMap[Index].BaseAddress;
668 }
669
670 if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
671 RegionLength = BaseAddress + Length - RegionStart;
672 } else {
673 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
674 }
675
676 //
677 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
678 //
679 gDS->SetMemorySpaceAttributes (
680 RegionStart,
681 RegionLength,
682 (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
683 );
684 }
685
686 return EFI_SUCCESS;
687}
688
695VOID
697 VOID
698 )
699{
700 EFI_STATUS Status;
701 UINTN Index;
702 UINTN SubIndex;
703 UINT64 RegValue;
704 EFI_PHYSICAL_ADDRESS BaseAddress;
705 UINT64 Length;
706 UINT64 Attributes;
707 UINT64 CurrentAttributes;
708 UINT8 MtrrType;
709 UINTN NumberOfDescriptors;
710 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
711 UINT64 DefaultAttributes;
712 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
713 MTRR_FIXED_SETTINGS MtrrFixedSettings;
714 UINT32 FirmwareVariableMtrrCount;
715 UINT8 DefaultMemoryType;
716
717 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
718 ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
719
720 MemorySpaceMap = NULL;
721
722 //
723 // Initialize the valid bits mask and valid address mask for MTRRs
724 //
726
727 //
728 // Get the memory attribute of variable MTRRs
729 //
731 mValidMtrrBitsMask,
732 mValidMtrrAddressMask,
733 VariableMtrr
734 );
735
736 //
737 // Get the memory space map from GCD
738 //
739 Status = gDS->GetMemorySpaceMap (
740 &NumberOfDescriptors,
741 &MemorySpaceMap
742 );
743 ASSERT_EFI_ERROR (Status);
744
745 DefaultMemoryType = (UINT8)MtrrGetDefaultMemoryType ();
746 DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);
747
748 //
749 // Set default attributes to all spaces.
750 //
751 for (Index = 0; Index < NumberOfDescriptors; Index++) {
752 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
753 continue;
754 }
755
756 gDS->SetMemorySpaceAttributes (
757 MemorySpaceMap[Index].BaseAddress,
758 MemorySpaceMap[Index].Length,
759 (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) |
760 (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
761 );
762 }
763
764 //
765 // Go for variable MTRRs with WB attribute
766 //
767 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
768 if (VariableMtrr[Index].Valid &&
769 (VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK))
770 {
772 MemorySpaceMap,
773 NumberOfDescriptors,
774 VariableMtrr[Index].BaseAddress,
775 VariableMtrr[Index].Length,
776 EFI_MEMORY_WB
777 );
778 }
779 }
780
781 //
782 // Go for variable MTRRs with the attribute except for WB and UC attributes
783 //
784 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
785 if (VariableMtrr[Index].Valid &&
786 (VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) &&
787 (VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE))
788 {
789 Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8)VariableMtrr[Index].Type);
791 MemorySpaceMap,
792 NumberOfDescriptors,
793 VariableMtrr[Index].BaseAddress,
794 VariableMtrr[Index].Length,
795 Attributes
796 );
797 }
798 }
799
800 //
801 // Go for variable MTRRs with UC attribute
802 //
803 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
804 if (VariableMtrr[Index].Valid &&
805 (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE))
806 {
808 MemorySpaceMap,
809 NumberOfDescriptors,
810 VariableMtrr[Index].BaseAddress,
811 VariableMtrr[Index].Length,
812 EFI_MEMORY_UC
813 );
814 }
815 }
816
817 //
818 // Go for fixed MTRRs
819 //
820 Attributes = 0;
821 BaseAddress = 0;
822 Length = 0;
823 MtrrGetFixedMtrr (&MtrrFixedSettings);
824 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
825 RegValue = MtrrFixedSettings.Mtrr[Index];
826 //
827 // Check for continuous fixed MTRR sections
828 //
829 for (SubIndex = 0; SubIndex < 8; SubIndex++) {
830 MtrrType = (UINT8)RShiftU64 (RegValue, SubIndex * 8);
831 CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
832 if (Length == 0) {
833 //
834 // A new MTRR attribute begins
835 //
836 Attributes = CurrentAttributes;
837 } else {
838 //
839 // If fixed MTRR attribute changed, then set memory attribute for previous attribute
840 //
841 if (CurrentAttributes != Attributes) {
843 MemorySpaceMap,
844 NumberOfDescriptors,
845 BaseAddress,
846 Length,
847 Attributes
848 );
849 BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
850 Length = 0;
851 Attributes = CurrentAttributes;
852 }
853 }
854
855 Length += mFixedMtrrTable[Index].Length;
856 }
857 }
858
859 //
860 // Handle the last fixed MTRR region
861 //
863 MemorySpaceMap,
864 NumberOfDescriptors,
865 BaseAddress,
866 Length,
867 Attributes
868 );
869
870 //
871 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
872 //
873 if (MemorySpaceMap != NULL) {
874 FreePool (MemorySpaceMap);
875 }
876}
877
881BOOLEAN
883 VOID
884 )
885{
886 IA32_CR0 Cr0;
887 IA32_CR4 Cr4;
888
889 Cr0.UintN = AsmReadCr0 ();
890 Cr4.UintN = AsmReadCr4 ();
891
892 return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));
893}
894
902VOID
904 VOID
905 )
906{
907 mIsFlushingGCD = TRUE;
908
909 if (IsMtrrSupported ()) {
911 }
912
915 }
916
917 mIsFlushingGCD = FALSE;
918}
919
924VOID
926 VOID
927 )
928{
929 EFI_STATUS Status;
930 EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
931 EFI_VECTOR_HANDOFF_INFO *VectorInfo;
932 IA32_IDT_GATE_DESCRIPTOR *IdtTable;
933 IA32_DESCRIPTOR IdtDescriptor;
934 UINTN IdtEntryCount;
935
936 VectorInfo = NULL;
937 Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);
938 if ((Status == EFI_SUCCESS) && (VectorInfoList != NULL)) {
939 VectorInfo = VectorInfoList;
940 }
941
942 AsmReadIdtr (&IdtDescriptor);
943 IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
944 if (IdtEntryCount < CPU_INTERRUPT_NUM) {
945 //
946 // Increase Interrupt Descriptor Table and Copy the old IDT table in
947 //
948 IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);
949 ASSERT (IdtTable != NULL);
950 CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount);
951
952 //
953 // Load Interrupt Descriptor Table
954 //
955 IdtDescriptor.Base = (UINTN)IdtTable;
956 IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
957 AsmWriteIdtr (&IdtDescriptor);
958 }
959
960 Status = InitializeCpuExceptionHandlers (VectorInfo);
961 ASSERT_EFI_ERROR (Status);
962}
963
972VOID
973EFIAPI
975 IN EFI_EVENT Event,
976 IN VOID *Context
977 )
978{
979 CpuSleep ();
980}
981
1023 IN UINT64 Base,
1024 IN UINT64 Length,
1025 IN UINT64 Capabilities,
1027 )
1028{
1029 UINT64 IntersectionBase;
1030 UINT64 IntersectionEnd;
1031 EFI_STATUS Status;
1032
1033 if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
1034 ((Descriptor->Capabilities & Capabilities) == Capabilities))
1035 {
1036 return EFI_SUCCESS;
1037 }
1038
1039 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
1040 IntersectionEnd = MIN (
1041 Base + Length,
1042 Descriptor->BaseAddress + Descriptor->Length
1043 );
1044 if (IntersectionBase >= IntersectionEnd) {
1045 //
1046 // The descriptor and the aperture don't overlap.
1047 //
1048 return EFI_SUCCESS;
1049 }
1050
1051 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
1052 Status = gDS->AddMemorySpace (
1054 IntersectionBase,
1055 IntersectionEnd - IntersectionBase,
1056 Capabilities
1057 );
1058
1059 DEBUG ((
1060 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
1061 "%a: %a: add [%Lx, %Lx): %r\n",
1062 gEfiCallerBaseName,
1063 __FUNCTION__,
1064 IntersectionBase,
1065 IntersectionEnd,
1066 Status
1067 ));
1068 return Status;
1069 }
1070
1071 DEBUG ((
1072 DEBUG_ERROR,
1073 "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
1074 "with aperture [%Lx, %Lx) cap %Lx\n",
1075 gEfiCallerBaseName,
1076 __FUNCTION__,
1077 Descriptor->BaseAddress,
1078 Descriptor->BaseAddress + Descriptor->Length,
1079 (UINT32)Descriptor->GcdMemoryType,
1080 Descriptor->Capabilities,
1081 Base,
1082 Base + Length,
1083 Capabilities
1084 ));
1085 return EFI_INVALID_PARAMETER;
1086}
1087
1101 IN UINT64 Base,
1102 IN UINT64 Length,
1103 IN UINT64 Capabilities
1104 )
1105{
1106 EFI_STATUS Status;
1107 UINTN Index;
1108 UINTN NumberOfDescriptors;
1109 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
1110
1111 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
1112 if (EFI_ERROR (Status)) {
1113 DEBUG ((
1114 DEBUG_ERROR,
1115 "%a: %a: GetMemorySpaceMap(): %r\n",
1116 gEfiCallerBaseName,
1117 __FUNCTION__,
1118 Status
1119 ));
1120 return Status;
1121 }
1122
1123 for (Index = 0; Index < NumberOfDescriptors; Index++) {
1124 Status = IntersectMemoryDescriptor (
1125 Base,
1126 Length,
1127 Capabilities,
1128 &MemorySpaceMap[Index]
1129 );
1130 if (EFI_ERROR (Status)) {
1131 goto FreeMemorySpaceMap;
1132 }
1133 }
1134
1136 //
1137 // Make sure there are adjacent descriptors covering [Base, Base + Length).
1138 // It is possible that they have not been merged; merging can be prevented
1139 // by allocation and different capabilities.
1140 //
1141 UINT64 CheckBase;
1142 EFI_STATUS CheckStatus;
1144
1145 for (CheckBase = Base;
1146 CheckBase < Base + Length;
1147 CheckBase = Descriptor.BaseAddress + Descriptor.Length)
1148 {
1149 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);
1150 ASSERT_EFI_ERROR (CheckStatus);
1152 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);
1153 }
1154
1155 DEBUG_CODE_END ();
1156
1157FreeMemorySpaceMap:
1158 FreePool (MemorySpaceMap);
1159
1160 return Status;
1161}
1162
1169VOID
1171 IN EFI_HANDLE ImageHandle
1172 )
1173{
1174 EFI_STATUS Status;
1175 EFI_PHYSICAL_ADDRESS BaseAddress;
1176
1178 Status = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);
1179 ASSERT_EFI_ERROR (Status);
1180
1181 //
1182 // Try to allocate APIC memory mapped space, does not check return
1183 // status because it may be allocated by other driver, or DXE Core if
1184 // this range is built into Memory Allocation HOB.
1185 //
1186 Status = gDS->AllocateMemorySpace (
1189 0,
1190 SIZE_4KB,
1191 &BaseAddress,
1192 ImageHandle,
1193 NULL
1194 );
1195 if (EFI_ERROR (Status)) {
1196 DEBUG ((
1197 DEBUG_INFO,
1198 "%a: %a: AllocateMemorySpace() Status - %r\n",
1199 gEfiCallerBaseName,
1200 __FUNCTION__,
1201 Status
1202 ));
1203 }
1204}
1205
1218EFIAPI
1220 IN EFI_HANDLE ImageHandle,
1221 IN EFI_SYSTEM_TABLE *SystemTable
1222 )
1223{
1224 EFI_STATUS Status;
1225 EFI_EVENT IdleLoopEvent;
1226
1228
1230
1231 //
1232 // Make sure interrupts are disabled
1233 //
1235
1236 //
1237 // Init GDT for DXE
1238 //
1240
1241 //
1242 // Setup IDT pointer, IDT and interrupt entry points
1243 //
1245
1246 //
1247 // Install CPU Architectural Protocol
1248 //
1249 Status = gBS->InstallMultipleProtocolInterfaces (
1250 &mCpuHandle,
1251 &gEfiCpuArchProtocolGuid,
1252 &gCpu,
1253 NULL
1254 );
1255 ASSERT_EFI_ERROR (Status);
1256
1257 //
1258 // Refresh GCD memory space map according to MTRR value.
1259 //
1261
1262 //
1263 // Add and allocate local APIC memory mapped space
1264 //
1265 AddLocalApicMemorySpace (ImageHandle);
1266
1267 //
1268 // Setup a callback for idle events
1269 //
1270 Status = gBS->CreateEventEx (
1271 EVT_NOTIFY_SIGNAL,
1272 TPL_NOTIFY,
1274 NULL,
1275 &gIdleLoopEventGuid,
1276 &IdleLoopEvent
1277 );
1278 ASSERT_EFI_ERROR (Status);
1279
1281
1282 return Status;
1283}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
EFI_STATUS EFIAPI CpuGetInterruptState(IN EFI_CPU_ARCH_PROTOCOL *This, OUT BOOLEAN *State)
Definition: CpuDxe.c:124
VOID EFIAPI IdleLoopEventCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: CpuDxe.c:196
EFI_STATUS EFIAPI CpuRegisterInterruptHandler(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
Definition: CpuDxe.c:165
EFI_STATUS EFIAPI CpuGetTimerValue(IN EFI_CPU_ARCH_PROTOCOL *This, IN UINT32 TimerIndex, OUT UINT64 *TimerValue, OUT UINT64 *TimerPeriod OPTIONAL)
Definition: CpuDxe.c:176
EFI_STATUS EFIAPI CpuDisableInterrupt(IN EFI_CPU_ARCH_PROTOCOL *This)
Definition: CpuDxe.c:100
EFI_STATUS EFIAPI CpuInit(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_CPU_INIT_TYPE InitType)
Definition: CpuDxe.c:155
EFI_STATUS EFIAPI CpuFlushCpuDataCache(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 Length, IN EFI_CPU_FLUSH_TYPE FlushType)
Definition: CpuDxe.c:45
EFI_STATUS EFIAPI CpuEnableInterrupt(IN EFI_CPU_ARCH_PROTOCOL *This)
Definition: CpuDxe.c:80
#define NULL
Definition: Base.h:312
#define CONST
Definition: Base.h:259
#define RETURN_ERROR(StatusCode)
Definition: Base.h:957
#define MIN(a, b)
Definition: Base.h:903
#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 MAX(a, b)
Definition: Base.h:888
UINT64 EFIAPI AsmReadTsc(VOID)
Definition: GccInline.c:555
VOID EFIAPI EnableInterrupts(VOID)
Definition: CpuBreakpoint.c:67
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
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)
EFI_CPU_FLUSH_TYPE
Definition: Cpu.h:24
EFI_CPU_INIT_TYPE
Definition: Cpu.h:34
VOID(EFIAPI * EFI_CPU_INTERRUPT_HANDLER)(IN CONST EFI_EXCEPTION_TYPE InterruptType, IN CONST EFI_SYSTEM_CONTEXT SystemContext)
Definition: Cpu.h:52
EFI_STATUS EFIAPI InitializeCpuExceptionHandlers(IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL)
EFI_STATUS EFIAPI RegisterCpuInterruptHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
VOID EFIAPI CpuSleep(VOID)
VOID InitializeMpSupport(VOID)
Definition: CpuMp.c:817
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
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:440
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:532
#define DEBUG(Expression)
Definition: DebugLib.h:417
#define ASSERT(Expression)
Definition: DebugLib.h:391
#define DEBUG_CODE_END()
Definition: DebugLib.h:543
EFI_DXE_SERVICES * gDS
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINT64 mTimerPeriod
Definition: HpetTimer.c:177
VOID EFIAPI AsmInvd(VOID)
VOID EFIAPI AsmWbinvd(VOID)
UINTN EFIAPI AsmReadCr0(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
UINTN EFIAPI GetLocalApicBaseAddress(VOID)
Definition: BaseXApicLib.c:67
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
#define MSR_IA32_MTRR_FIX4K_E0000
#define MSR_IA32_MTRR_FIX4K_C8000
#define MSR_IA32_MTRR_FIX4K_E8000
#define MSR_IA32_MTRR_FIX4K_F8000
#define MSR_IA32_MTRR_FIX16K_80000
#define MSR_IA32_MTRR_FIX16K_A0000
#define MSR_IA32_MTRR_FIX4K_D0000
#define MSR_IA32_MTRR_FIX64K_00000
#define MSR_IA32_MTRR_FIX4K_D8000
#define MSR_IA32_MTRR_FIX4K_C0000
#define MSR_IA32_MTRR_FIX4K_F0000
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
UINT32 EFIAPI MtrrGetMemoryAttributeInVariableMtrr(IN UINT64 MtrrValidBitsMask, IN UINT64 MtrrValidAddressMask, OUT VARIABLE_MTRR *VariableMtrr)
Definition: MtrrLib.c:671
MTRR_MEMORY_CACHE_TYPE EFIAPI MtrrGetMemoryAttribute(IN PHYSICAL_ADDRESS Address)
Definition: MtrrLib.c:932
MTRR_SETTINGS *EFIAPI MtrrSetAllMtrrs(IN MTRR_SETTINGS *MtrrSetting)
Definition: MtrrLib.c:2800
UINT32 EFIAPI GetFirmwareVariableMtrrCount(VOID)
Definition: MtrrLib.c:211
BOOLEAN EFIAPI IsMtrrSupported(VOID)
Definition: MtrrLib.c:2841
RETURN_STATUS EFIAPI MtrrSetMemoryAttribute(IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN MTRR_MEMORY_CACHE_TYPE Attribute)
Definition: MtrrLib.c:2691
MTRR_FIXED_SETTINGS *EFIAPI MtrrGetFixedMtrr(OUT MTRR_FIXED_SETTINGS *FixedSettings)
Definition: MtrrLib.c:409
MTRR_MEMORY_CACHE_TYPE EFIAPI MtrrGetDefaultMemoryType(VOID)
Definition: MtrrLib.c:258
MTRR_SETTINGS *EFIAPI MtrrGetAllMtrrs(OUT MTRR_SETTINGS *MtrrSetting)
Definition: MtrrLib.c:2760
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
@ EfiGcdAllocateAddress
Definition: PiDxeCis.h:102
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:49
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:28
VOID * EFI_EVENT
Definition: UefiBaseType.h:36
VOID * EFI_HANDLE
Definition: UefiBaseType.h:32
#define EFI_SUCCESS
Definition: UefiBaseType.h:111
EFI_BOOT_SERVICES * gBS
VOID EFIAPI InitializeFloatingPointUnits(VOID)
EFI_STATUS EFIAPI CpuSetMemoryAttributes(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: CpuDxe.c:371
EFI_STATUS SetGcdMemorySpaceAttributes(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: CpuDxe.c:623
BOOLEAN IsPagingAndPageAddressExtensionsEnabled(VOID)
Definition: CpuDxe.c:882
VOID InitInterruptDescriptorTable(VOID)
Definition: CpuDxe.c:925
UINT64 GetMemorySpaceAttributeFromMtrrType(IN UINT8 MtrrAttributes)
Definition: CpuDxe.c:536
EFI_STATUS EFIAPI InitializeCpu(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: CpuDxe.c:1219
VOID AddLocalApicMemorySpace(IN EFI_HANDLE ImageHandle)
Definition: CpuDxe.c:1170
VOID RefreshMemoryAttributesFromMtrr(VOID)
Definition: CpuDxe.c:696
VOID EFIAPI SetMtrrsFromBuffer(IN VOID *Buffer)
Definition: CpuDxe.c:337
EFI_STATUS SearchGcdMemorySpaces(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, OUT UINTN *StartIndex, OUT UINTN *EndIndex)
Definition: CpuDxe.c:575
VOID InitializeMtrrMask(VOID)
Definition: CpuDxe.c:504
VOID RefreshGcdMemoryAttributes(VOID)
Definition: CpuDxe.c:903
EFI_STATUS AddMemoryMappedIoSpace(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities)
Definition: CpuDxe.c:1100
EFI_STATUS IntersectMemoryDescriptor(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities, IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor)
Definition: CpuDxe.c:1022
VOID RefreshGcdMemoryAttributesFromPaging(VOID)
Definition: CpuPageTable.c:958
VOID InitGlobalDescriptorTable(VOID)
Definition: CpuGdt.c:123
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)
EFI_GCD_MEMORY_TYPE GcdMemoryType
Definition: PiDxeCis.h:147
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:125