TianoCore EDK2 master
Loading...
Searching...
No Matches
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 //
312 mTimerPeriod = DivU64x64Remainder (
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 MaxExtendedFunction;
509 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
510 UINT32 MaxFunction;
511 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtendedFeatureFlagsEcx;
513
514 AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL);
515
516 if (MaxExtendedFunction >= CPUID_VIR_PHY_ADDRESS_SIZE) {
517 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL);
518 } else {
519 VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
520 }
521
522 //
523 // CPUID enumeration of MAX_PA is unaffected by TME-MK activation and will continue
524 // to report the maximum physical address bits available for software to use,
525 // irrespective of the number of KeyID bits.
526 // So, we need to check if TME is enabled and adjust the PA size accordingly.
527 //
528 AsmCpuid (CPUID_SIGNATURE, &MaxFunction, NULL, NULL, NULL);
529 if (MaxFunction >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
530 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, NULL, &ExtendedFeatureFlagsEcx.Uint32, NULL);
531 if (ExtendedFeatureFlagsEcx.Bits.TME_EN == 1) {
533 if (TmeActivate.Bits.TmeEnable == 1) {
534 VirPhyAddressSize.Bits.PhysicalAddressBits -= TmeActivate.Bits.MkTmeKeyidBits;
535 }
536 }
537 }
538
539 mValidMtrrBitsMask = LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits) - 1;
540 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
541}
542
553UINT64
555 IN UINT8 MtrrAttributes
556 )
557{
558 switch (MtrrAttributes) {
559 case MTRR_CACHE_UNCACHEABLE:
560 return EFI_MEMORY_UC;
561 case MTRR_CACHE_WRITE_COMBINING:
562 return EFI_MEMORY_WC;
563 case MTRR_CACHE_WRITE_THROUGH:
564 return EFI_MEMORY_WT;
565 case MTRR_CACHE_WRITE_PROTECTED:
566 return EFI_MEMORY_WP;
567 case MTRR_CACHE_WRITE_BACK:
568 return EFI_MEMORY_WB;
569 default:
570 return 0;
571 }
572}
573
594 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
595 IN UINTN NumberOfDescriptors,
596 IN EFI_PHYSICAL_ADDRESS BaseAddress,
597 IN UINT64 Length,
598 OUT UINTN *StartIndex,
599 OUT UINTN *EndIndex
600 )
601{
602 UINTN Index;
603
604 *StartIndex = 0;
605 *EndIndex = 0;
606 for (Index = 0; Index < NumberOfDescriptors; Index++) {
607 if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&
608 (BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))
609 {
610 *StartIndex = Index;
611 }
612
613 if ((BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress) &&
614 (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))
615 {
616 *EndIndex = Index;
617 return EFI_SUCCESS;
618 }
619 }
620
621 return EFI_NOT_FOUND;
622}
623
642 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
643 IN UINTN NumberOfDescriptors,
644 IN EFI_PHYSICAL_ADDRESS BaseAddress,
645 IN UINT64 Length,
646 IN UINT64 Attributes
647 )
648{
649 EFI_STATUS Status;
650 UINTN Index;
651 UINTN StartIndex;
652 UINTN EndIndex;
653 EFI_PHYSICAL_ADDRESS RegionStart;
654 UINT64 RegionLength;
655
656 //
657 // Get all memory descriptors covered by the memory range
658 //
659 Status = SearchGcdMemorySpaces (
660 MemorySpaceMap,
661 NumberOfDescriptors,
662 BaseAddress,
663 Length,
664 &StartIndex,
665 &EndIndex
666 );
667 if (EFI_ERROR (Status)) {
668 return Status;
669 }
670
671 //
672 // Go through all related descriptors and set attributes accordingly
673 //
674 for (Index = StartIndex; Index <= EndIndex; Index++) {
675 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
676 continue;
677 }
678
679 //
680 // Calculate the start and end address of the overlapping range
681 //
682 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
683 RegionStart = BaseAddress;
684 } else {
685 RegionStart = MemorySpaceMap[Index].BaseAddress;
686 }
687
688 if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
689 RegionLength = BaseAddress + Length - RegionStart;
690 } else {
691 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
692 }
693
694 //
695 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
696 //
697 gDS->SetMemorySpaceAttributes (
698 RegionStart,
699 RegionLength,
700 (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
701 );
702 }
703
704 return EFI_SUCCESS;
705}
706
713VOID
715 VOID
716 )
717{
718 EFI_STATUS Status;
719 UINTN Index;
720 UINTN SubIndex;
721 UINT64 RegValue;
722 EFI_PHYSICAL_ADDRESS BaseAddress;
723 UINT64 Length;
724 UINT64 Attributes;
725 UINT64 CurrentAttributes;
726 UINT8 MtrrType;
727 UINTN NumberOfDescriptors;
728 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
729 UINT64 DefaultAttributes;
730 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
731 MTRR_FIXED_SETTINGS MtrrFixedSettings;
732 UINT32 FirmwareVariableMtrrCount;
733 UINT8 DefaultMemoryType;
734
735 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
736 ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
737
738 MemorySpaceMap = NULL;
739
740 //
741 // Initialize the valid bits mask and valid address mask for MTRRs
742 //
744
745 //
746 // Get the memory attribute of variable MTRRs
747 //
749 mValidMtrrBitsMask,
750 mValidMtrrAddressMask,
751 VariableMtrr
752 );
753
754 //
755 // Get the memory space map from GCD
756 //
757 Status = gDS->GetMemorySpaceMap (
758 &NumberOfDescriptors,
759 &MemorySpaceMap
760 );
761 ASSERT_EFI_ERROR (Status);
762
763 DefaultMemoryType = (UINT8)MtrrGetDefaultMemoryType ();
764 DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);
765
766 //
767 // Set default attributes to all spaces.
768 //
769 for (Index = 0; Index < NumberOfDescriptors; Index++) {
770 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
771 continue;
772 }
773
774 gDS->SetMemorySpaceAttributes (
775 MemorySpaceMap[Index].BaseAddress,
776 MemorySpaceMap[Index].Length,
777 (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) |
778 (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
779 );
780 }
781
782 //
783 // Go for variable MTRRs with WB attribute
784 //
785 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
786 if (VariableMtrr[Index].Valid &&
787 (VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK))
788 {
790 MemorySpaceMap,
791 NumberOfDescriptors,
792 VariableMtrr[Index].BaseAddress,
793 VariableMtrr[Index].Length,
794 EFI_MEMORY_WB
795 );
796 }
797 }
798
799 //
800 // Go for variable MTRRs with the attribute except for WB and UC attributes
801 //
802 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
803 if (VariableMtrr[Index].Valid &&
804 (VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) &&
805 (VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE))
806 {
807 Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8)VariableMtrr[Index].Type);
809 MemorySpaceMap,
810 NumberOfDescriptors,
811 VariableMtrr[Index].BaseAddress,
812 VariableMtrr[Index].Length,
813 Attributes
814 );
815 }
816 }
817
818 //
819 // Go for variable MTRRs with UC attribute
820 //
821 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
822 if (VariableMtrr[Index].Valid &&
823 (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE))
824 {
826 MemorySpaceMap,
827 NumberOfDescriptors,
828 VariableMtrr[Index].BaseAddress,
829 VariableMtrr[Index].Length,
830 EFI_MEMORY_UC
831 );
832 }
833 }
834
835 //
836 // Go for fixed MTRRs
837 //
838 Attributes = 0;
839 BaseAddress = 0;
840 Length = 0;
841 MtrrGetFixedMtrr (&MtrrFixedSettings);
842 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
843 RegValue = MtrrFixedSettings.Mtrr[Index];
844 //
845 // Check for continuous fixed MTRR sections
846 //
847 for (SubIndex = 0; SubIndex < 8; SubIndex++) {
848 MtrrType = (UINT8)RShiftU64 (RegValue, SubIndex * 8);
849 CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
850 if (Length == 0) {
851 //
852 // A new MTRR attribute begins
853 //
854 Attributes = CurrentAttributes;
855 } else {
856 //
857 // If fixed MTRR attribute changed, then set memory attribute for previous attribute
858 //
859 if (CurrentAttributes != Attributes) {
861 MemorySpaceMap,
862 NumberOfDescriptors,
863 BaseAddress,
864 Length,
865 Attributes
866 );
867 BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
868 Length = 0;
869 Attributes = CurrentAttributes;
870 }
871 }
872
873 Length += mFixedMtrrTable[Index].Length;
874 }
875 }
876
877 //
878 // Handle the last fixed MTRR region
879 //
881 MemorySpaceMap,
882 NumberOfDescriptors,
883 BaseAddress,
884 Length,
885 Attributes
886 );
887
888 //
889 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
890 //
891 if (MemorySpaceMap != NULL) {
892 FreePool (MemorySpaceMap);
893 }
894}
895
899BOOLEAN
901 VOID
902 )
903{
904 IA32_CR0 Cr0;
905 IA32_CR4 Cr4;
906
907 Cr0.UintN = AsmReadCr0 ();
908 Cr4.UintN = AsmReadCr4 ();
909
910 return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));
911}
912
920VOID
922 VOID
923 )
924{
925 mIsFlushingGCD = TRUE;
926
927 if (IsMtrrSupported ()) {
929 }
930
933 }
934
935 mIsFlushingGCD = FALSE;
936}
937
942VOID
944 VOID
945 )
946{
947 EFI_STATUS Status;
948 EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
949 EFI_VECTOR_HANDOFF_INFO *VectorInfo;
950 IA32_IDT_GATE_DESCRIPTOR *IdtTable;
951 IA32_DESCRIPTOR IdtDescriptor;
952 UINTN IdtEntryCount;
953
954 VectorInfo = NULL;
955 Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);
956 if ((Status == EFI_SUCCESS) && (VectorInfoList != NULL)) {
957 VectorInfo = VectorInfoList;
958 }
959
960 AsmReadIdtr (&IdtDescriptor);
961 IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
962 if (IdtEntryCount < CPU_INTERRUPT_NUM) {
963 //
964 // Increase Interrupt Descriptor Table and Copy the old IDT table in
965 //
966 IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);
967 ASSERT (IdtTable != NULL);
968 CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount);
969
970 //
971 // Load Interrupt Descriptor Table
972 //
973 IdtDescriptor.Base = (UINTN)IdtTable;
974 IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
975 AsmWriteIdtr (&IdtDescriptor);
976 }
977
978 Status = InitializeCpuExceptionHandlers (VectorInfo);
979 ASSERT_EFI_ERROR (Status);
980}
981
990VOID
991EFIAPI
993 IN EFI_EVENT Event,
994 IN VOID *Context
995 )
996{
997 CpuSleep ();
998}
999
1041 IN UINT64 Base,
1042 IN UINT64 Length,
1043 IN UINT64 Capabilities,
1045 )
1046{
1047 UINT64 IntersectionBase;
1048 UINT64 IntersectionEnd;
1049 EFI_STATUS Status;
1050
1051 if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
1052 ((Descriptor->Capabilities & Capabilities) == Capabilities))
1053 {
1054 return EFI_SUCCESS;
1055 }
1056
1057 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
1058 IntersectionEnd = MIN (
1059 Base + Length,
1060 Descriptor->BaseAddress + Descriptor->Length
1061 );
1062 if (IntersectionBase >= IntersectionEnd) {
1063 //
1064 // The descriptor and the aperture don't overlap.
1065 //
1066 return EFI_SUCCESS;
1067 }
1068
1069 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
1070 Status = gDS->AddMemorySpace (
1072 IntersectionBase,
1073 IntersectionEnd - IntersectionBase,
1074 Capabilities
1075 );
1076
1077 DEBUG ((
1078 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
1079 "%a: %a: add [%Lx, %Lx): %r\n",
1080 gEfiCallerBaseName,
1081 __func__,
1082 IntersectionBase,
1083 IntersectionEnd,
1084 Status
1085 ));
1086 return Status;
1087 }
1088
1089 DEBUG ((
1090 DEBUG_ERROR,
1091 "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
1092 "with aperture [%Lx, %Lx) cap %Lx\n",
1093 gEfiCallerBaseName,
1094 __func__,
1095 Descriptor->BaseAddress,
1096 Descriptor->BaseAddress + Descriptor->Length,
1097 (UINT32)Descriptor->GcdMemoryType,
1098 Descriptor->Capabilities,
1099 Base,
1100 Base + Length,
1101 Capabilities
1102 ));
1103 return EFI_INVALID_PARAMETER;
1104}
1105
1119 IN UINT64 Base,
1120 IN UINT64 Length,
1121 IN UINT64 Capabilities
1122 )
1123{
1124 EFI_STATUS Status;
1125 UINTN Index;
1126 UINTN NumberOfDescriptors;
1127 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
1128
1129 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
1130 if (EFI_ERROR (Status)) {
1131 DEBUG ((
1132 DEBUG_ERROR,
1133 "%a: %a: GetMemorySpaceMap(): %r\n",
1134 gEfiCallerBaseName,
1135 __func__,
1136 Status
1137 ));
1138 return Status;
1139 }
1140
1141 for (Index = 0; Index < NumberOfDescriptors; Index++) {
1142 Status = IntersectMemoryDescriptor (
1143 Base,
1144 Length,
1145 Capabilities,
1146 &MemorySpaceMap[Index]
1147 );
1148 if (EFI_ERROR (Status)) {
1149 goto FreeMemorySpaceMap;
1150 }
1151 }
1152
1154 //
1155 // Make sure there are adjacent descriptors covering [Base, Base + Length).
1156 // It is possible that they have not been merged; merging can be prevented
1157 // by allocation and different capabilities.
1158 //
1159 UINT64 CheckBase;
1160 EFI_STATUS CheckStatus;
1162
1163 for (CheckBase = Base;
1164 CheckBase < Base + Length;
1165 CheckBase = Descriptor.BaseAddress + Descriptor.Length)
1166 {
1167 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);
1168 ASSERT_EFI_ERROR (CheckStatus);
1169 ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);
1170 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);
1171 }
1172
1173 DEBUG_CODE_END ();
1174
1175FreeMemorySpaceMap:
1176 FreePool (MemorySpaceMap);
1177
1178 return Status;
1179}
1180
1187VOID
1189 IN EFI_HANDLE ImageHandle
1190 )
1191{
1192 EFI_STATUS Status;
1193 EFI_PHYSICAL_ADDRESS BaseAddress;
1194
1196 Status = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);
1197 ASSERT_EFI_ERROR (Status);
1198
1199 //
1200 // Try to allocate APIC memory mapped space, does not check return
1201 // status because it may be allocated by other driver, or DXE Core if
1202 // this range is built into Memory Allocation HOB.
1203 //
1204 Status = gDS->AllocateMemorySpace (
1207 0,
1208 SIZE_4KB,
1209 &BaseAddress,
1210 ImageHandle,
1211 NULL
1212 );
1213 if (EFI_ERROR (Status)) {
1214 DEBUG ((
1215 DEBUG_INFO,
1216 "%a: %a: AllocateMemorySpace() Status - %r\n",
1217 gEfiCallerBaseName,
1218 __func__,
1219 Status
1220 ));
1221 }
1222}
1223
1236EFIAPI
1238 IN EFI_HANDLE ImageHandle,
1239 IN EFI_SYSTEM_TABLE *SystemTable
1240 )
1241{
1242 EFI_STATUS Status;
1243 EFI_EVENT IdleLoopEvent;
1244
1246
1247 InitializeFloatingPointUnits ();
1248
1249 //
1250 // Make sure interrupts are disabled
1251 //
1253
1254 //
1255 // Init GDT for DXE
1256 //
1258
1259 //
1260 // Setup IDT pointer, IDT and interrupt entry points
1261 //
1263
1264 //
1265 // Install CPU Architectural Protocol
1266 //
1267 Status = gBS->InstallMultipleProtocolInterfaces (
1268 &mCpuHandle,
1269 &gEfiCpuArchProtocolGuid,
1270 &gCpu,
1271 NULL
1272 );
1273 ASSERT_EFI_ERROR (Status);
1274
1275 //
1276 // Refresh GCD memory space map according to MTRR value.
1277 //
1279
1280 //
1281 // Add and allocate local APIC memory mapped space
1282 //
1283 AddLocalApicMemorySpace (ImageHandle);
1284
1285 //
1286 // Setup a callback for idle events
1287 //
1288 Status = gBS->CreateEventEx (
1289 EVT_NOTIFY_SIGNAL,
1290 TPL_NOTIFY,
1292 NULL,
1293 &gIdleLoopEventGuid,
1294 &IdleLoopEvent
1295 );
1296 ASSERT_EFI_ERROR (Status);
1297
1299
1300 return Status;
1301}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
EFI_STATUS EFIAPI CpuGetInterruptState(IN EFI_CPU_ARCH_PROTOCOL *This, OUT BOOLEAN *State)
Definition: CpuDxe.c:126
VOID EFIAPI IdleLoopEventCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: CpuDxe.c:198
EFI_STATUS EFIAPI CpuRegisterInterruptHandler(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
Definition: CpuDxe.c:167
EFI_STATUS EFIAPI CpuGetTimerValue(IN EFI_CPU_ARCH_PROTOCOL *This, IN UINT32 TimerIndex, OUT UINT64 *TimerValue, OUT UINT64 *TimerPeriod OPTIONAL)
Definition: CpuDxe.c:178
EFI_STATUS EFIAPI CpuDisableInterrupt(IN EFI_CPU_ARCH_PROTOCOL *This)
Definition: CpuDxe.c:102
EFI_STATUS EFIAPI CpuInit(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_CPU_INIT_TYPE InitType)
Definition: CpuDxe.c:157
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:47
EFI_STATUS EFIAPI CpuEnableInterrupt(IN EFI_CPU_ARCH_PROTOCOL *This)
Definition: CpuDxe.c:82
EFI_STATUS EFIAPI CpuSetMemoryAttributes(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: CpuMmuCommon.c:185
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define MIN(a, b)
Definition: Base.h:1007
#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:992
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
UINT32 EFIAPI AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuIdEx.c:43
VOID EFIAPI CpuSleep(VOID)
VOID InitializeMpSupport(VOID)
Definition: CpuMp.c:747
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
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:445
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:537
#define DEBUG(Expression)
Definition: DebugLib.h:422
#define DEBUG_CODE_END()
Definition: DebugLib.h:548
EFI_DXE_SERVICES * gDS
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID EFIAPI AsmInvd(VOID)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
VOID EFIAPI AsmWbinvd(VOID)
UINTN EFIAPI AsmReadCr0(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
UINTN EFIAPI GetLocalApicBaseAddress(VOID)
Definition: BaseXApicLib.c:66
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_TME_ACTIVATE
#define MSR_IA32_MTRR_FIX4K_D8000
#define MSR_IA32_MTRR_FIX4K_C0000
#define MSR_IA32_MTRR_FIX4K_F0000
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
Definition: Cpuid.h:1301
#define CPUID_SIGNATURE
Definition: Cpuid.h:45
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:952
MTRR_SETTINGS *EFIAPI MtrrSetAllMtrrs(IN MTRR_SETTINGS *MtrrSetting)
Definition: MtrrLib.c:2805
UINT32 EFIAPI GetFirmwareVariableMtrrCount(VOID)
Definition: MtrrLib.c:211
BOOLEAN EFIAPI IsMtrrSupported(VOID)
Definition: MtrrLib.c:2846
RETURN_STATUS EFIAPI MtrrSetMemoryAttribute(IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN MTRR_MEMORY_CACHE_TYPE Attribute)
Definition: MtrrLib.c:2696
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:2765
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
@ EfiGcdAllocateAddress
Definition: PiDxeCis.h:110
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
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:641
BOOLEAN IsPagingAndPageAddressExtensionsEnabled(VOID)
Definition: CpuDxe.c:900
VOID InitInterruptDescriptorTable(VOID)
Definition: CpuDxe.c:943
UINT64 GetMemorySpaceAttributeFromMtrrType(IN UINT8 MtrrAttributes)
Definition: CpuDxe.c:554
EFI_STATUS EFIAPI InitializeCpu(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: CpuDxe.c:1237
VOID AddLocalApicMemorySpace(IN EFI_HANDLE ImageHandle)
Definition: CpuDxe.c:1188
VOID RefreshMemoryAttributesFromMtrr(VOID)
Definition: CpuDxe.c:714
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:593
VOID InitializeMtrrMask(VOID)
Definition: CpuDxe.c:504
VOID RefreshGcdMemoryAttributes(VOID)
Definition: CpuDxe.c:921
EFI_STATUS AddMemoryMappedIoSpace(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities)
Definition: CpuDxe.c:1118
EFI_STATUS IntersectMemoryDescriptor(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities, IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor)
Definition: CpuDxe.c:1040
VOID RefreshGcdMemoryAttributesFromPaging(VOID)
Definition: CpuPageTable.c:960
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:155
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:133
struct CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX::@646 Bits
struct CPUID_VIR_PHY_ADDRESS_SIZE_EAX::@690 Bits
struct MSR_IA32_TME_ACTIVATE_REGISTER::@617 Bits