2 CPU DXE Module to produce CPU ARCH Protocol.
4 Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "CpuPageTable.h"
19 #define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)
20 #define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)
25 BOOLEAN InterruptState
= FALSE
;
26 EFI_HANDLE mCpuHandle
= NULL
;
27 BOOLEAN mIsFlushingGCD
;
28 UINT64 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
29 UINT64 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
31 FIXED_MTRR mFixedMtrrTable
[] = {
33 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
38 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
43 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
48 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
53 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
58 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
63 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
68 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
73 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
78 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
83 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
90 EFI_CPU_ARCH_PROTOCOL gCpu
= {
96 CpuRegisterInterruptHandler
,
98 CpuSetMemoryAttributes
,
100 4 // DmaBufferAlignment
104 // CPU Arch Protocol Functions
108 Flush CPU data cache. If the instruction cache is fully coherent
109 with all DMA operations then function can just return EFI_SUCCESS.
111 @param This Protocol instance structure
112 @param Start Physical address to start flushing from.
113 @param Length Number of bytes to flush. Round up to chipset
115 @param FlushType Specifies the type of flush operation to perform.
117 @retval EFI_SUCCESS If cache was flushed
118 @retval EFI_UNSUPPORTED If flush type is not supported.
119 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
124 CpuFlushCpuDataCache (
125 IN EFI_CPU_ARCH_PROTOCOL
*This
,
126 IN EFI_PHYSICAL_ADDRESS Start
,
128 IN EFI_CPU_FLUSH_TYPE FlushType
131 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
134 } else if (FlushType
== EfiCpuFlushTypeInvalidate
) {
138 return EFI_UNSUPPORTED
;
144 Enables CPU interrupts.
146 @param This Protocol instance structure
148 @retval EFI_SUCCESS If interrupts were enabled in the CPU
149 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
155 IN EFI_CPU_ARCH_PROTOCOL
*This
160 InterruptState
= TRUE
;
166 Disables CPU interrupts.
168 @param This Protocol instance structure
170 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
171 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
176 CpuDisableInterrupt (
177 IN EFI_CPU_ARCH_PROTOCOL
*This
180 DisableInterrupts ();
182 InterruptState
= FALSE
;
188 Return the state of interrupts.
190 @param This Protocol instance structure
191 @param State Pointer to the CPU's current interrupt state
193 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
194 @retval EFI_INVALID_PARAMETER State is NULL.
199 CpuGetInterruptState (
200 IN EFI_CPU_ARCH_PROTOCOL
*This
,
205 return EFI_INVALID_PARAMETER
;
208 *State
= InterruptState
;
214 Generates an INIT to the CPU.
216 @param This Protocol instance structure
217 @param InitType Type of CPU INIT to perform
219 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
221 @retval EFI_DEVICE_ERROR If CPU INIT failed.
222 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
228 IN EFI_CPU_ARCH_PROTOCOL
*This
,
229 IN EFI_CPU_INIT_TYPE InitType
232 return EFI_UNSUPPORTED
;
237 Registers a function to be called from the CPU interrupt handler.
239 @param This Protocol instance structure
240 @param InterruptType Defines which interrupt to hook. IA-32
241 valid range is 0x00 through 0xFF
242 @param InterruptHandler A pointer to a function of type
243 EFI_CPU_INTERRUPT_HANDLER that is called
244 when a processor interrupt occurs. A null
245 pointer is an error condition.
247 @retval EFI_SUCCESS If handler installed or uninstalled.
248 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
249 for InterruptType was previously installed.
250 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
251 InterruptType was not previously installed.
252 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
258 CpuRegisterInterruptHandler (
259 IN EFI_CPU_ARCH_PROTOCOL
*This
,
260 IN EFI_EXCEPTION_TYPE InterruptType
,
261 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
264 return RegisterCpuInterruptHandler (InterruptType
, InterruptHandler
);
269 Returns a timer value from one of the CPU's internal timers. There is no
270 inherent time interval between ticks but is a function of the CPU frequency.
272 @param This - Protocol instance structure.
273 @param TimerIndex - Specifies which CPU timer is requested.
274 @param TimerValue - Pointer to the returned timer value.
275 @param TimerPeriod - A pointer to the amount of time that passes
276 in femtoseconds (10-15) for each increment
277 of TimerValue. If TimerValue does not
278 increment at a predictable rate, then 0 is
279 returned. The amount of time that has
280 passed between two calls to GetTimerValue()
281 can be calculated with the formula
282 (TimerValue2 - TimerValue1) * TimerPeriod.
283 This parameter is optional and may be NULL.
285 @retval EFI_SUCCESS - If the CPU timer count was returned.
286 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
287 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
288 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
294 IN EFI_CPU_ARCH_PROTOCOL
*This
,
295 IN UINT32 TimerIndex
,
296 OUT UINT64
*TimerValue
,
297 OUT UINT64
*TimerPeriod OPTIONAL
300 if (TimerValue
== NULL
) {
301 return EFI_INVALID_PARAMETER
;
304 if (TimerIndex
!= 0) {
305 return EFI_INVALID_PARAMETER
;
308 *TimerValue
= AsmReadTsc ();
310 if (TimerPeriod
!= NULL
) {
312 // BugBug: Hard coded. Don't know how to do this generically
314 *TimerPeriod
= 1000000000;
321 A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to
322 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.
324 @param[in] Buffer Pointer to an MTRR_SETTINGS object, to be passed to
333 MtrrSetAllMtrrs (Buffer
);
337 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
339 This function modifies the attributes for the memory region specified by BaseAddress and
340 Length from their current attributes to the attributes specified by Attributes.
342 @param This The EFI_CPU_ARCH_PROTOCOL instance.
343 @param BaseAddress The physical address that is the start address of a memory region.
344 @param Length The size in bytes of the memory region.
345 @param Attributes The bit mask of attributes to set for the memory region.
347 @retval EFI_SUCCESS The attributes were set for the memory region.
348 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
349 BaseAddress and Length cannot be modified.
350 @retval EFI_INVALID_PARAMETER Length is zero.
351 Attributes specified an illegal combination of attributes that
352 cannot be set together.
353 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
354 the memory resource range.
355 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
356 resource range specified by BaseAddress and Length.
357 The bit mask of attributes is not support for the memory resource
358 range specified by BaseAddress and Length.
363 CpuSetMemoryAttributes (
364 IN EFI_CPU_ARCH_PROTOCOL
*This
,
365 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
370 RETURN_STATUS Status
;
371 MTRR_MEMORY_CACHE_TYPE CacheType
;
373 EFI_MP_SERVICES_PROTOCOL
*MpService
;
374 MTRR_SETTINGS MtrrSettings
;
375 UINT64 CacheAttributes
;
376 UINT64 MemoryAttributes
;
377 MTRR_MEMORY_CACHE_TYPE CurrentCacheType
;
380 // If this function is called because GCD SetMemorySpaceAttributes () is called
381 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
382 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
383 // to avoid unnecessary computing.
385 if (mIsFlushingGCD
) {
386 DEBUG((EFI_D_INFO
, " Flushing GCD\n"));
391 CacheAttributes
= Attributes
& CACHE_ATTRIBUTE_MASK
;
392 MemoryAttributes
= Attributes
& MEMORY_ATTRIBUTE_MASK
;
394 if (Attributes
!= (CacheAttributes
| MemoryAttributes
)) {
395 return EFI_INVALID_PARAMETER
;
398 if (CacheAttributes
!= 0) {
399 if (!IsMtrrSupported ()) {
400 return EFI_UNSUPPORTED
;
403 switch (CacheAttributes
) {
405 CacheType
= CacheUncacheable
;
409 CacheType
= CacheWriteCombining
;
413 CacheType
= CacheWriteThrough
;
417 CacheType
= CacheWriteProtected
;
421 CacheType
= CacheWriteBack
;
425 return EFI_INVALID_PARAMETER
;
427 CurrentCacheType
= MtrrGetMemoryAttribute(BaseAddress
);
428 if (CurrentCacheType
!= CacheType
) {
430 // call MTRR libary function
432 Status
= MtrrSetMemoryAttribute (
438 if (!RETURN_ERROR (Status
)) {
439 MpStatus
= gBS
->LocateProtocol (
440 &gEfiMpServiceProtocolGuid
,
445 // Synchronize the update with all APs
447 if (!EFI_ERROR (MpStatus
)) {
448 MtrrGetAllMtrrs (&MtrrSettings
);
449 MpStatus
= MpService
->StartupAllAPs (
451 SetMtrrsFromBuffer
, // Procedure
452 FALSE
, // SingleThread
454 0, // TimeoutInMicrosecsond
455 &MtrrSettings
, // ProcedureArgument
456 NULL
// FailedCpuList
458 ASSERT (MpStatus
== EFI_SUCCESS
|| MpStatus
== EFI_NOT_STARTED
);
461 if (EFI_ERROR(Status
)) {
468 // Set memory attribute by page table
470 return AssignMemoryPageAttributes (NULL
, BaseAddress
, Length
, MemoryAttributes
, AllocatePages
);
474 Initializes the valid bits mask and valid address mask for MTRRs.
476 This function initializes the valid bits mask and valid address mask for MTRRs.
485 UINT8 PhysicalAddressBits
;
487 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
489 if (RegEax
>= 0x80000008) {
490 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
492 PhysicalAddressBits
= (UINT8
) RegEax
;
494 mValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
495 mValidMtrrAddressMask
= mValidMtrrBitsMask
& 0xfffffffffffff000ULL
;
497 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
498 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
503 Gets GCD Mem Space type from MTRR Type.
505 This function gets GCD Mem Space type from MTRR Type.
507 @param MtrrAttributes MTRR memory type
509 @return GCD Mem Space type
513 GetMemorySpaceAttributeFromMtrrType (
514 IN UINT8 MtrrAttributes
517 switch (MtrrAttributes
) {
518 case MTRR_CACHE_UNCACHEABLE
:
519 return EFI_MEMORY_UC
;
520 case MTRR_CACHE_WRITE_COMBINING
:
521 return EFI_MEMORY_WC
;
522 case MTRR_CACHE_WRITE_THROUGH
:
523 return EFI_MEMORY_WT
;
524 case MTRR_CACHE_WRITE_PROTECTED
:
525 return EFI_MEMORY_WP
;
526 case MTRR_CACHE_WRITE_BACK
:
527 return EFI_MEMORY_WB
;
534 Searches memory descriptors covered by given memory range.
536 This function searches into the Gcd Memory Space for descriptors
537 (from StartIndex to EndIndex) that contains the memory range
538 specified by BaseAddress and Length.
540 @param MemorySpaceMap Gcd Memory Space Map as array.
541 @param NumberOfDescriptors Number of descriptors in map.
542 @param BaseAddress BaseAddress for the requested range.
543 @param Length Length for the requested range.
544 @param StartIndex Start index into the Gcd Memory Space Map.
545 @param EndIndex End index into the Gcd Memory Space Map.
547 @retval EFI_SUCCESS Search successfully.
548 @retval EFI_NOT_FOUND The requested descriptors does not exist.
552 SearchGcdMemorySpaces (
553 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
554 IN UINTN NumberOfDescriptors
,
555 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
557 OUT UINTN
*StartIndex
,
565 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
566 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
&&
567 BaseAddress
< MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
570 if (BaseAddress
+ Length
- 1 >= MemorySpaceMap
[Index
].BaseAddress
&&
571 BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
576 return EFI_NOT_FOUND
;
580 Sets the attributes for a specified range in Gcd Memory Space Map.
582 This function sets the attributes for a specified range in
583 Gcd Memory Space Map.
585 @param MemorySpaceMap Gcd Memory Space Map as array
586 @param NumberOfDescriptors Number of descriptors in map
587 @param BaseAddress BaseAddress for the range
588 @param Length Length for the range
589 @param Attributes Attributes to set
591 @retval EFI_SUCCESS Memory attributes set successfully
592 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
596 SetGcdMemorySpaceAttributes (
597 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
598 IN UINTN NumberOfDescriptors
,
599 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
608 EFI_PHYSICAL_ADDRESS RegionStart
;
612 // Get all memory descriptors covered by the memory range
614 Status
= SearchGcdMemorySpaces (
622 if (EFI_ERROR (Status
)) {
627 // Go through all related descriptors and set attributes accordingly
629 for (Index
= StartIndex
; Index
<= EndIndex
; Index
++) {
630 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
634 // Calculate the start and end address of the overlapping range
636 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) {
637 RegionStart
= BaseAddress
;
639 RegionStart
= MemorySpaceMap
[Index
].BaseAddress
;
641 if (BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
642 RegionLength
= BaseAddress
+ Length
- RegionStart
;
644 RegionLength
= MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- RegionStart
;
647 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
649 gDS
->SetMemorySpaceAttributes (
652 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) | (MemorySpaceMap
[Index
].Capabilities
& Attributes
)
661 Refreshes the GCD Memory Space attributes according to MTRRs.
663 This function refreshes the GCD Memory Space attributes according to MTRRs.
667 RefreshGcdMemoryAttributes (
675 EFI_PHYSICAL_ADDRESS BaseAddress
;
678 UINT64 CurrentAttributes
;
680 UINTN NumberOfDescriptors
;
681 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
682 UINT64 DefaultAttributes
;
683 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
684 MTRR_FIXED_SETTINGS MtrrFixedSettings
;
685 UINT32 FirmwareVariableMtrrCount
;
686 UINT8 DefaultMemoryType
;
688 if (!IsMtrrSupported ()) {
692 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCount ();
693 ASSERT (FirmwareVariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
695 mIsFlushingGCD
= TRUE
;
696 MemorySpaceMap
= NULL
;
699 // Initialize the valid bits mask and valid address mask for MTRRs
701 InitializeMtrrMask ();
704 // Get the memory attribute of variable MTRRs
706 MtrrGetMemoryAttributeInVariableMtrr (
708 mValidMtrrAddressMask
,
713 // Get the memory space map from GCD
715 Status
= gDS
->GetMemorySpaceMap (
716 &NumberOfDescriptors
,
719 ASSERT_EFI_ERROR (Status
);
721 DefaultMemoryType
= (UINT8
) MtrrGetDefaultMemoryType ();
722 DefaultAttributes
= GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType
);
725 // Set default attributes to all spaces.
727 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
728 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
731 gDS
->SetMemorySpaceAttributes (
732 MemorySpaceMap
[Index
].BaseAddress
,
733 MemorySpaceMap
[Index
].Length
,
734 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) |
735 (MemorySpaceMap
[Index
].Capabilities
& DefaultAttributes
)
740 // Go for variable MTRRs with WB attribute
742 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
743 if (VariableMtrr
[Index
].Valid
&&
744 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) {
745 SetGcdMemorySpaceAttributes (
748 VariableMtrr
[Index
].BaseAddress
,
749 VariableMtrr
[Index
].Length
,
756 // Go for variable MTRRs with the attribute except for WB and UC attributes
758 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
759 if (VariableMtrr
[Index
].Valid
&&
760 VariableMtrr
[Index
].Type
!= MTRR_CACHE_WRITE_BACK
&&
761 VariableMtrr
[Index
].Type
!= MTRR_CACHE_UNCACHEABLE
) {
762 Attributes
= GetMemorySpaceAttributeFromMtrrType ((UINT8
) VariableMtrr
[Index
].Type
);
763 SetGcdMemorySpaceAttributes (
766 VariableMtrr
[Index
].BaseAddress
,
767 VariableMtrr
[Index
].Length
,
774 // Go for variable MTRRs with UC attribute
776 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
777 if (VariableMtrr
[Index
].Valid
&&
778 VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
) {
779 SetGcdMemorySpaceAttributes (
782 VariableMtrr
[Index
].BaseAddress
,
783 VariableMtrr
[Index
].Length
,
790 // Go for fixed MTRRs
795 MtrrGetFixedMtrr (&MtrrFixedSettings
);
796 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
797 RegValue
= MtrrFixedSettings
.Mtrr
[Index
];
799 // Check for continuous fixed MTRR sections
801 for (SubIndex
= 0; SubIndex
< 8; SubIndex
++) {
802 MtrrType
= (UINT8
) RShiftU64 (RegValue
, SubIndex
* 8);
803 CurrentAttributes
= GetMemorySpaceAttributeFromMtrrType (MtrrType
);
806 // A new MTRR attribute begins
808 Attributes
= CurrentAttributes
;
811 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
813 if (CurrentAttributes
!= Attributes
) {
814 SetGcdMemorySpaceAttributes (
821 BaseAddress
= mFixedMtrrTable
[Index
].BaseAddress
+ mFixedMtrrTable
[Index
].Length
* SubIndex
;
823 Attributes
= CurrentAttributes
;
826 Length
+= mFixedMtrrTable
[Index
].Length
;
830 // Handle the last fixed MTRR region
832 SetGcdMemorySpaceAttributes (
841 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
843 if (MemorySpaceMap
!= NULL
) {
844 FreePool (MemorySpaceMap
);
847 mIsFlushingGCD
= FALSE
;
851 Initialize Interrupt Descriptor Table for interrupt handling.
855 InitInterruptDescriptorTable (
860 EFI_VECTOR_HANDOFF_INFO
*VectorInfoList
;
861 EFI_VECTOR_HANDOFF_INFO
*VectorInfo
;
864 Status
= EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid
, (VOID
**) &VectorInfoList
);
865 if (Status
== EFI_SUCCESS
&& VectorInfoList
!= NULL
) {
866 VectorInfo
= VectorInfoList
;
868 Status
= InitializeCpuInterruptHandlers (VectorInfo
);
869 ASSERT_EFI_ERROR (Status
);
874 Callback function for idle events.
876 @param Event Event whose notification function is being invoked.
877 @param Context The pointer to the notification function's context,
878 which is implementation-dependent.
883 IdleLoopEventCallback (
892 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
894 The memory space descriptor can come from the GCD memory space map, or it can
895 represent a gap between two neighboring memory space descriptors. In the
896 latter case, the GcdMemoryType field is expected to be
897 EfiGcdMemoryTypeNonExistent.
899 If the memory space descriptor already has type
900 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
901 required capabilities, then no action is taken -- it is by definition
902 compatible with the aperture.
904 Otherwise, the intersection of the memory space descriptor is calculated with
905 the aperture. If the intersection is the empty set (no overlap), no action is
906 taken; the memory space descriptor is compatible with the aperture.
908 Otherwise, the type of the descriptor is investigated again. If the type is
909 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
910 such a type), then an attempt is made to add the intersection as MMIO space
911 to the GCD memory space map, with the specified capabilities. This ensures
912 continuity for the aperture, and the descriptor is deemed compatible with the
915 Otherwise, the memory space descriptor is incompatible with the MMIO
918 @param[in] Base Base address of the aperture.
919 @param[in] Length Length of the aperture.
920 @param[in] Capabilities Capabilities required by the aperture.
921 @param[in] Descriptor The descriptor to ensure compatibility with the
924 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
925 space map may have been updated, for
926 continuity within the aperture.
927 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
928 @return Error codes from gDS->AddMemorySpace().
931 IntersectMemoryDescriptor (
934 IN UINT64 Capabilities
,
935 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
938 UINT64 IntersectionBase
;
939 UINT64 IntersectionEnd
;
942 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
&&
943 (Descriptor
->Capabilities
& Capabilities
) == Capabilities
) {
947 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
948 IntersectionEnd
= MIN (Base
+ Length
,
949 Descriptor
->BaseAddress
+ Descriptor
->Length
);
950 if (IntersectionBase
>= IntersectionEnd
) {
952 // The descriptor and the aperture don't overlap.
957 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
958 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo
,
959 IntersectionBase
, IntersectionEnd
- IntersectionBase
,
962 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
963 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
964 IntersectionBase
, IntersectionEnd
, Status
));
968 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
969 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName
, __FUNCTION__
,
970 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
971 (UINT32
)Descriptor
->GcdMemoryType
, Descriptor
->Capabilities
,
972 Base
, Base
+ Length
, Capabilities
));
973 return EFI_INVALID_PARAMETER
;
977 Add MMIO space to GCD.
978 The routine checks the GCD database and only adds those which are
979 not added in the specified range to GCD.
981 @param Base Base address of the MMIO space.
982 @param Length Length of the MMIO space.
983 @param Capabilities Capabilities of the MMIO space.
985 @retval EFI_SUCCES The MMIO space was added successfully.
988 AddMemoryMappedIoSpace (
991 IN UINT64 Capabilities
996 UINTN NumberOfDescriptors
;
997 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
999 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
1000 if (EFI_ERROR (Status
)) {
1001 DEBUG ((EFI_D_ERROR
, "%a: %a: GetMemorySpaceMap(): %r\n",
1002 gEfiCallerBaseName
, __FUNCTION__
, Status
));
1006 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
1007 Status
= IntersectMemoryDescriptor (Base
, Length
, Capabilities
,
1008 &MemorySpaceMap
[Index
]);
1009 if (EFI_ERROR (Status
)) {
1010 goto FreeMemorySpaceMap
;
1016 // Make sure there are adjacent descriptors covering [Base, Base + Length).
1017 // It is possible that they have not been merged; merging can be prevented
1018 // by allocation and different capabilities.
1021 EFI_STATUS CheckStatus
;
1022 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
1024 for (CheckBase
= Base
;
1025 CheckBase
< Base
+ Length
;
1026 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
1027 CheckStatus
= gDS
->GetMemorySpaceDescriptor (CheckBase
, &Descriptor
);
1028 ASSERT_EFI_ERROR (CheckStatus
);
1029 ASSERT (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
);
1030 ASSERT ((Descriptor
.Capabilities
& Capabilities
) == Capabilities
);
1035 FreePool (MemorySpaceMap
);
1041 Initialize the state information for the CPU Architectural Protocol.
1043 @param ImageHandle Image handle this driver.
1044 @param SystemTable Pointer to the System Table.
1046 @retval EFI_SUCCESS Thread can be successfully created
1047 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
1048 @retval EFI_DEVICE_ERROR Cannot create the thread
1054 IN EFI_HANDLE ImageHandle
,
1055 IN EFI_SYSTEM_TABLE
*SystemTable
1059 EFI_EVENT IdleLoopEvent
;
1061 InitializePageTableLib();
1063 InitializeFloatingPointUnits ();
1066 // Make sure interrupts are disabled
1068 DisableInterrupts ();
1073 InitGlobalDescriptorTable ();
1076 // Setup IDT pointer, IDT and interrupt entry points
1078 InitInterruptDescriptorTable ();
1081 // Enable the local APIC for Virtual Wire Mode.
1083 ProgramVirtualWireMode ();
1086 // Install CPU Architectural Protocol
1088 Status
= gBS
->InstallMultipleProtocolInterfaces (
1090 &gEfiCpuArchProtocolGuid
, &gCpu
,
1093 ASSERT_EFI_ERROR (Status
);
1096 // Refresh GCD memory space map according to MTRR value.
1098 RefreshGcdMemoryAttributes ();
1101 // Setup a callback for idle events
1103 Status
= gBS
->CreateEventEx (
1106 IdleLoopEventCallback
,
1108 &gIdleLoopEventGuid
,
1111 ASSERT_EFI_ERROR (Status
);
1113 InitializeMpSupport ();