4 Copyright (c) 2008 - 2011, 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.
20 IA32_IDT_GATE_DESCRIPTOR gIdtTable
[INTERRUPT_VECTOR_NUMBER
] = { 0 };
22 EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable
[0x100];
23 BOOLEAN InterruptState
= FALSE
;
24 EFI_HANDLE mCpuHandle
= NULL
;
25 BOOLEAN mIsFlushingGCD
;
26 UINT64 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
27 UINT64 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
28 IA32_IDT_GATE_DESCRIPTOR
*mOrigIdtEntry
= NULL
;
29 UINT16 mOrigIdtEntryCount
= 0;
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 // Error code flag indicating whether or not an error code will be
105 // pushed on the stack if an exception occurs.
107 // 1 means an error code will be pushed, otherwise 0
109 // bit 0 - exception 0
110 // bit 1 - exception 1
113 UINT32 mErrorCodeFlag
= 0x00027d00;
116 // Local function prototypes
120 Set Interrupt Descriptor Table Handler Address.
122 @param Index The Index of the interrupt descriptor table handle.
123 @param Handler Handler address.
127 SetInterruptDescriptorTableHandlerAddress (
129 IN VOID
*Handler OPTIONAL
133 // CPU Arch Protocol Functions
138 Common exception handler.
140 @param InterruptType Exception type
141 @param SystemContext EFI_SYSTEM_CONTEXT
146 CommonExceptionHandler (
147 IN EFI_EXCEPTION_TYPE InterruptType
,
148 IN EFI_SYSTEM_CONTEXT SystemContext
151 #if defined (MDE_CPU_IA32)
154 "!!!! IA32 Exception Type - %08x !!!!\n",
157 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
160 "ExceptionData - %08x\n",
161 SystemContext
.SystemContextIa32
->ExceptionData
166 "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",
167 SystemContext
.SystemContextIa32
->Cs
,
168 SystemContext
.SystemContextIa32
->Eip
,
169 SystemContext
.SystemContextIa32
->Eflags
,
170 SystemContext
.SystemContextIa32
->Ss
174 "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",
175 SystemContext
.SystemContextIa32
->Ds
,
176 SystemContext
.SystemContextIa32
->Es
,
177 SystemContext
.SystemContextIa32
->Fs
,
178 SystemContext
.SystemContextIa32
->Gs
182 "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",
183 SystemContext
.SystemContextIa32
->Eax
,
184 SystemContext
.SystemContextIa32
->Ebx
,
185 SystemContext
.SystemContextIa32
->Ecx
,
186 SystemContext
.SystemContextIa32
->Edx
190 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
191 SystemContext
.SystemContextIa32
->Esp
,
192 SystemContext
.SystemContextIa32
->Ebp
,
193 SystemContext
.SystemContextIa32
->Esi
,
194 SystemContext
.SystemContextIa32
->Edi
198 "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",
199 SystemContext
.SystemContextIa32
->Gdtr
[0],
200 SystemContext
.SystemContextIa32
->Gdtr
[1],
201 SystemContext
.SystemContextIa32
->Idtr
[0],
202 SystemContext
.SystemContextIa32
->Idtr
[1]
206 "LDT - %08x, TR - %08x\n",
207 SystemContext
.SystemContextIa32
->Ldtr
,
208 SystemContext
.SystemContextIa32
->Tr
212 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
213 SystemContext
.SystemContextIa32
->Cr0
,
214 SystemContext
.SystemContextIa32
->Cr2
,
215 SystemContext
.SystemContextIa32
->Cr3
,
216 SystemContext
.SystemContextIa32
->Cr4
220 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
221 SystemContext
.SystemContextIa32
->Dr0
,
222 SystemContext
.SystemContextIa32
->Dr1
,
223 SystemContext
.SystemContextIa32
->Dr2
,
224 SystemContext
.SystemContextIa32
->Dr3
228 "DR6 - %08x, DR7 - %08x\n",
229 SystemContext
.SystemContextIa32
->Dr6
,
230 SystemContext
.SystemContextIa32
->Dr7
232 #elif defined (MDE_CPU_X64)
235 "!!!! X64 Exception Type - %016lx !!!!\n",
236 (UINT64
)InterruptType
238 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
241 "ExceptionData - %016lx\n",
242 SystemContext
.SystemContextX64
->ExceptionData
247 "RIP - %016lx, RFL - %016lx\n",
248 SystemContext
.SystemContextX64
->Rip
,
249 SystemContext
.SystemContextX64
->Rflags
253 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
254 SystemContext
.SystemContextX64
->Rax
,
255 SystemContext
.SystemContextX64
->Rcx
,
256 SystemContext
.SystemContextX64
->Rdx
260 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
261 SystemContext
.SystemContextX64
->Rbx
,
262 SystemContext
.SystemContextX64
->Rsp
,
263 SystemContext
.SystemContextX64
->Rbp
267 "RSI - %016lx, RDI - %016lx\n",
268 SystemContext
.SystemContextX64
->Rsi
,
269 SystemContext
.SystemContextX64
->Rdi
273 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
274 SystemContext
.SystemContextX64
->R8
,
275 SystemContext
.SystemContextX64
->R9
,
276 SystemContext
.SystemContextX64
->R10
280 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
281 SystemContext
.SystemContextX64
->R11
,
282 SystemContext
.SystemContextX64
->R12
,
283 SystemContext
.SystemContextX64
->R13
287 "R14 - %016lx, R15 - %016lx\n",
288 SystemContext
.SystemContextX64
->R14
,
289 SystemContext
.SystemContextX64
->R15
293 "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",
294 SystemContext
.SystemContextX64
->Cs
,
295 SystemContext
.SystemContextX64
->Ds
,
296 SystemContext
.SystemContextX64
->Es
,
297 SystemContext
.SystemContextX64
->Fs
,
298 SystemContext
.SystemContextX64
->Gs
,
299 SystemContext
.SystemContextX64
->Ss
303 "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",
304 SystemContext
.SystemContextX64
->Gdtr
[0],
305 SystemContext
.SystemContextX64
->Gdtr
[1],
306 SystemContext
.SystemContextX64
->Idtr
[0],
307 SystemContext
.SystemContextX64
->Idtr
[1]
311 "LDT - %016lx, TR - %016lx\n",
312 SystemContext
.SystemContextX64
->Ldtr
,
313 SystemContext
.SystemContextX64
->Tr
317 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
318 SystemContext
.SystemContextX64
->Cr0
,
319 SystemContext
.SystemContextX64
->Cr2
,
320 SystemContext
.SystemContextX64
->Cr3
324 "CR4 - %016lx, CR8 - %016lx\n",
325 SystemContext
.SystemContextX64
->Cr4
,
326 SystemContext
.SystemContextX64
->Cr8
330 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
331 SystemContext
.SystemContextX64
->Dr0
,
332 SystemContext
.SystemContextX64
->Dr1
,
333 SystemContext
.SystemContextX64
->Dr2
337 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
338 SystemContext
.SystemContextX64
->Dr3
,
339 SystemContext
.SystemContextX64
->Dr6
,
340 SystemContext
.SystemContextX64
->Dr7
343 #error CPU type not supported for exception information dump!
347 // Hang the system with CpuSleep so the processor will enter a lower power
357 Flush CPU data cache. If the instruction cache is fully coherent
358 with all DMA operations then function can just return EFI_SUCCESS.
360 @param This Protocol instance structure
361 @param Start Physical address to start flushing from.
362 @param Length Number of bytes to flush. Round up to chipset
364 @param FlushType Specifies the type of flush operation to perform.
366 @retval EFI_SUCCESS If cache was flushed
367 @retval EFI_UNSUPPORTED If flush type is not supported.
368 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
373 CpuFlushCpuDataCache (
374 IN EFI_CPU_ARCH_PROTOCOL
*This
,
375 IN EFI_PHYSICAL_ADDRESS Start
,
377 IN EFI_CPU_FLUSH_TYPE FlushType
380 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
383 } else if (FlushType
== EfiCpuFlushTypeInvalidate
) {
387 return EFI_UNSUPPORTED
;
393 Enables CPU interrupts.
395 @param This Protocol instance structure
397 @retval EFI_SUCCESS If interrupts were enabled in the CPU
398 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
404 IN EFI_CPU_ARCH_PROTOCOL
*This
409 InterruptState
= TRUE
;
415 Disables CPU interrupts.
417 @param This Protocol instance structure
419 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
420 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
425 CpuDisableInterrupt (
426 IN EFI_CPU_ARCH_PROTOCOL
*This
429 DisableInterrupts ();
431 InterruptState
= FALSE
;
437 Return the state of interrupts.
439 @param This Protocol instance structure
440 @param State Pointer to the CPU's current interrupt state
442 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
443 @retval EFI_INVALID_PARAMETER State is NULL.
448 CpuGetInterruptState (
449 IN EFI_CPU_ARCH_PROTOCOL
*This
,
454 return EFI_INVALID_PARAMETER
;
457 *State
= InterruptState
;
463 Generates an INIT to the CPU.
465 @param This Protocol instance structure
466 @param InitType Type of CPU INIT to perform
468 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
470 @retval EFI_DEVICE_ERROR If CPU INIT failed.
471 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
477 IN EFI_CPU_ARCH_PROTOCOL
*This
,
478 IN EFI_CPU_INIT_TYPE InitType
481 return EFI_UNSUPPORTED
;
486 Registers a function to be called from the CPU interrupt handler.
488 @param This Protocol instance structure
489 @param InterruptType Defines which interrupt to hook. IA-32
490 valid range is 0x00 through 0xFF
491 @param InterruptHandler A pointer to a function of type
492 EFI_CPU_INTERRUPT_HANDLER that is called
493 when a processor interrupt occurs. A null
494 pointer is an error condition.
496 @retval EFI_SUCCESS If handler installed or uninstalled.
497 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
498 for InterruptType was previously installed.
499 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
500 InterruptType was not previously installed.
501 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
507 CpuRegisterInterruptHandler (
508 IN EFI_CPU_ARCH_PROTOCOL
*This
,
509 IN EFI_EXCEPTION_TYPE InterruptType
,
510 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
513 if (InterruptType
< 0 || InterruptType
> 0xff) {
514 return EFI_UNSUPPORTED
;
517 if (InterruptHandler
== NULL
&& ExternalVectorTable
[InterruptType
] == NULL
) {
518 return EFI_INVALID_PARAMETER
;
521 if (InterruptHandler
!= NULL
&& ExternalVectorTable
[InterruptType
] != NULL
) {
522 return EFI_ALREADY_STARTED
;
525 if (InterruptHandler
!= NULL
) {
526 SetInterruptDescriptorTableHandlerAddress ((UINTN
)InterruptType
, NULL
);
529 // Restore the original IDT handler address if InterruptHandler is NULL.
531 RestoreInterruptDescriptorTableHandlerAddress ((UINTN
)InterruptType
);
534 ExternalVectorTable
[InterruptType
] = InterruptHandler
;
540 Returns a timer value from one of the CPU's internal timers. There is no
541 inherent time interval between ticks but is a function of the CPU frequency.
543 @param This - Protocol instance structure.
544 @param TimerIndex - Specifies which CPU timer is requested.
545 @param TimerValue - Pointer to the returned timer value.
546 @param TimerPeriod - A pointer to the amount of time that passes
547 in femtoseconds (10-15) for each increment
548 of TimerValue. If TimerValue does not
549 increment at a predictable rate, then 0 is
550 returned. The amount of time that has
551 passed between two calls to GetTimerValue()
552 can be calculated with the formula
553 (TimerValue2 - TimerValue1) * TimerPeriod.
554 This parameter is optional and may be NULL.
556 @retval EFI_SUCCESS - If the CPU timer count was returned.
557 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
558 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
559 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
565 IN EFI_CPU_ARCH_PROTOCOL
*This
,
566 IN UINT32 TimerIndex
,
567 OUT UINT64
*TimerValue
,
568 OUT UINT64
*TimerPeriod OPTIONAL
571 if (TimerValue
== NULL
) {
572 return EFI_INVALID_PARAMETER
;
575 if (TimerIndex
!= 0) {
576 return EFI_INVALID_PARAMETER
;
579 *TimerValue
= AsmReadTsc ();
581 if (TimerPeriod
!= NULL
) {
583 // BugBug: Hard coded. Don't know how to do this generically
585 *TimerPeriod
= 1000000000;
593 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
595 This function modifies the attributes for the memory region specified by BaseAddress and
596 Length from their current attributes to the attributes specified by Attributes.
598 @param This The EFI_CPU_ARCH_PROTOCOL instance.
599 @param BaseAddress The physical address that is the start address of a memory region.
600 @param Length The size in bytes of the memory region.
601 @param Attributes The bit mask of attributes to set for the memory region.
603 @retval EFI_SUCCESS The attributes were set for the memory region.
604 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
605 BaseAddress and Length cannot be modified.
606 @retval EFI_INVALID_PARAMETER Length is zero.
607 Attributes specified an illegal combination of attributes that
608 cannot be set together.
609 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
610 the memory resource range.
611 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
612 resource range specified by BaseAddress and Length.
613 The bit mask of attributes is not support for the memory resource
614 range specified by BaseAddress and Length.
619 CpuSetMemoryAttributes (
620 IN EFI_CPU_ARCH_PROTOCOL
*This
,
621 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
626 RETURN_STATUS Status
;
627 MTRR_MEMORY_CACHE_TYPE CacheType
;
629 if (!IsMtrrSupported ()) {
630 return EFI_UNSUPPORTED
;
634 // If this function is called because GCD SetMemorySpaceAttributes () is called
635 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
636 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
637 // to avoid unnecessary computing.
639 if (mIsFlushingGCD
) {
640 DEBUG((EFI_D_ERROR
, " Flushing GCD\n"));
644 switch (Attributes
) {
646 CacheType
= CacheUncacheable
;
650 CacheType
= CacheWriteCombining
;
654 CacheType
= CacheWriteThrough
;
658 CacheType
= CacheWriteProtected
;
662 CacheType
= CacheWriteBack
;
668 case EFI_MEMORY_RUNTIME
:
669 return EFI_UNSUPPORTED
;
672 return EFI_INVALID_PARAMETER
;
675 // call MTRR libary function
677 Status
= MtrrSetMemoryAttribute (
683 return (EFI_STATUS
) Status
;
687 Initializes the valid bits mask and valid address mask for MTRRs.
689 This function initializes the valid bits mask and valid address mask for MTRRs.
698 UINT8 PhysicalAddressBits
;
700 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
702 if (RegEax
>= 0x80000008) {
703 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
705 PhysicalAddressBits
= (UINT8
) RegEax
;
707 mValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
708 mValidMtrrAddressMask
= mValidMtrrBitsMask
& 0xfffffffffffff000ULL
;
710 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
711 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
716 Gets GCD Mem Space type from MTRR Type.
718 This function gets GCD Mem Space type from MTRR Type.
720 @param MtrrAttributes MTRR memory type
722 @return GCD Mem Space type
726 GetMemorySpaceAttributeFromMtrrType (
727 IN UINT8 MtrrAttributes
730 switch (MtrrAttributes
) {
731 case MTRR_CACHE_UNCACHEABLE
:
732 return EFI_MEMORY_UC
;
733 case MTRR_CACHE_WRITE_COMBINING
:
734 return EFI_MEMORY_WC
;
735 case MTRR_CACHE_WRITE_THROUGH
:
736 return EFI_MEMORY_WT
;
737 case MTRR_CACHE_WRITE_PROTECTED
:
738 return EFI_MEMORY_WP
;
739 case MTRR_CACHE_WRITE_BACK
:
740 return EFI_MEMORY_WB
;
747 Searches memory descriptors covered by given memory range.
749 This function searches into the Gcd Memory Space for descriptors
750 (from StartIndex to EndIndex) that contains the memory range
751 specified by BaseAddress and Length.
753 @param MemorySpaceMap Gcd Memory Space Map as array.
754 @param NumberOfDescriptors Number of descriptors in map.
755 @param BaseAddress BaseAddress for the requested range.
756 @param Length Length for the requested range.
757 @param StartIndex Start index into the Gcd Memory Space Map.
758 @param EndIndex End index into the Gcd Memory Space Map.
760 @retval EFI_SUCCESS Search successfully.
761 @retval EFI_NOT_FOUND The requested descriptors does not exist.
765 SearchGcdMemorySpaces (
766 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
767 IN UINTN NumberOfDescriptors
,
768 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
770 OUT UINTN
*StartIndex
,
778 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
779 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
&&
780 BaseAddress
< MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
783 if (BaseAddress
+ Length
- 1 >= MemorySpaceMap
[Index
].BaseAddress
&&
784 BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
789 return EFI_NOT_FOUND
;
793 Sets the attributes for a specified range in Gcd Memory Space Map.
795 This function sets the attributes for a specified range in
796 Gcd Memory Space Map.
798 @param MemorySpaceMap Gcd Memory Space Map as array
799 @param NumberOfDescriptors Number of descriptors in map
800 @param BaseAddress BaseAddress for the range
801 @param Length Length for the range
802 @param Attributes Attributes to set
804 @retval EFI_SUCCESS Memory attributes set successfully
805 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
809 SetGcdMemorySpaceAttributes (
810 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
811 IN UINTN NumberOfDescriptors
,
812 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
821 EFI_PHYSICAL_ADDRESS RegionStart
;
825 // Get all memory descriptors covered by the memory range
827 Status
= SearchGcdMemorySpaces (
835 if (EFI_ERROR (Status
)) {
840 // Go through all related descriptors and set attributes accordingly
842 for (Index
= StartIndex
; Index
<= EndIndex
; Index
++) {
843 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
847 // Calculate the start and end address of the overlapping range
849 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) {
850 RegionStart
= BaseAddress
;
852 RegionStart
= MemorySpaceMap
[Index
].BaseAddress
;
854 if (BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
855 RegionLength
= BaseAddress
+ Length
- RegionStart
;
857 RegionLength
= MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- RegionStart
;
860 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
862 gDS
->SetMemorySpaceAttributes (
865 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) | (MemorySpaceMap
[Index
].Capabilities
& Attributes
)
874 Refreshes the GCD Memory Space attributes according to MTRRs.
876 This function refreshes the GCD Memory Space attributes according to MTRRs.
880 RefreshGcdMemoryAttributes (
888 EFI_PHYSICAL_ADDRESS BaseAddress
;
891 UINT64 CurrentAttributes
;
893 UINTN NumberOfDescriptors
;
894 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
895 UINT64 DefaultAttributes
;
896 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
897 MTRR_FIXED_SETTINGS MtrrFixedSettings
;
898 UINT32 FirmwareVariableMtrrCount
;
899 UINT8 DefaultMemoryType
;
901 if (!IsMtrrSupported ()) {
905 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCount ();
906 ASSERT (FirmwareVariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
908 mIsFlushingGCD
= TRUE
;
909 MemorySpaceMap
= NULL
;
912 // Initialize the valid bits mask and valid address mask for MTRRs
914 InitializeMtrrMask ();
917 // Get the memory attribute of variable MTRRs
919 MtrrGetMemoryAttributeInVariableMtrr (
921 mValidMtrrAddressMask
,
926 // Get the memory space map from GCD
928 Status
= gDS
->GetMemorySpaceMap (
929 &NumberOfDescriptors
,
932 ASSERT_EFI_ERROR (Status
);
934 DefaultMemoryType
= (UINT8
) MtrrGetDefaultMemoryType ();
935 DefaultAttributes
= GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType
);
938 // Set default attributes to all spaces.
940 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
941 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
944 gDS
->SetMemorySpaceAttributes (
945 MemorySpaceMap
[Index
].BaseAddress
,
946 MemorySpaceMap
[Index
].Length
,
947 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) |
948 (MemorySpaceMap
[Index
].Capabilities
& DefaultAttributes
)
953 // Go for variable MTRRs with WB attribute
955 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
956 if (VariableMtrr
[Index
].Valid
&&
957 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) {
958 SetGcdMemorySpaceAttributes (
961 VariableMtrr
[Index
].BaseAddress
,
962 VariableMtrr
[Index
].Length
,
969 // Go for variable MTRRs with the attribute except for WB and UC attributes
971 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
972 if (VariableMtrr
[Index
].Valid
&&
973 VariableMtrr
[Index
].Type
!= MTRR_CACHE_WRITE_BACK
&&
974 VariableMtrr
[Index
].Type
!= MTRR_CACHE_UNCACHEABLE
) {
975 Attributes
= GetMemorySpaceAttributeFromMtrrType ((UINT8
) VariableMtrr
[Index
].Type
);
976 SetGcdMemorySpaceAttributes (
979 VariableMtrr
[Index
].BaseAddress
,
980 VariableMtrr
[Index
].Length
,
987 // Go for variable MTRRs with UC attribute
989 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
990 if (VariableMtrr
[Index
].Valid
&&
991 VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
) {
992 SetGcdMemorySpaceAttributes (
995 VariableMtrr
[Index
].BaseAddress
,
996 VariableMtrr
[Index
].Length
,
1003 // Go for fixed MTRRs
1008 MtrrGetFixedMtrr (&MtrrFixedSettings
);
1009 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1010 RegValue
= MtrrFixedSettings
.Mtrr
[Index
];
1012 // Check for continuous fixed MTRR sections
1014 for (SubIndex
= 0; SubIndex
< 8; SubIndex
++) {
1015 MtrrType
= (UINT8
) RShiftU64 (RegValue
, SubIndex
* 8);
1016 CurrentAttributes
= GetMemorySpaceAttributeFromMtrrType (MtrrType
);
1019 // A new MTRR attribute begins
1021 Attributes
= CurrentAttributes
;
1024 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
1026 if (CurrentAttributes
!= Attributes
) {
1027 SetGcdMemorySpaceAttributes (
1029 NumberOfDescriptors
,
1034 BaseAddress
= mFixedMtrrTable
[Index
].BaseAddress
+ mFixedMtrrTable
[Index
].Length
* SubIndex
;
1036 Attributes
= CurrentAttributes
;
1039 Length
+= mFixedMtrrTable
[Index
].Length
;
1043 // Handle the last fixed MTRR region
1045 SetGcdMemorySpaceAttributes (
1047 NumberOfDescriptors
,
1054 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
1056 if (MemorySpaceMap
!= NULL
) {
1057 FreePool (MemorySpaceMap
);
1060 mIsFlushingGCD
= FALSE
;
1064 Set Interrupt Descriptor Table Handler Address.
1066 @param Index The Index of the interrupt descriptor table handle.
1067 @param Handler Handler address.
1071 SetInterruptDescriptorTableHandlerAddress (
1073 IN VOID
*Handler OPTIONAL
1078 if (Handler
!= NULL
) {
1079 UintnHandler
= (UINTN
) Handler
;
1081 UintnHandler
= ((UINTN
) AsmIdtVector00
) + (8 * Index
);
1084 gIdtTable
[Index
].Bits
.OffsetLow
= (UINT16
)UintnHandler
;
1085 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1086 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1087 gIdtTable
[Index
].Bits
.OffsetHigh
= (UINT16
)(UintnHandler
>> 16);
1088 #if defined (MDE_CPU_X64)
1089 gIdtTable
[Index
].Bits
.OffsetUpper
= (UINT32
)(UintnHandler
>> 32);
1090 gIdtTable
[Index
].Bits
.Reserved_1
= 0;
1095 Restore original Interrupt Descriptor Table Handler Address.
1097 @param Index The Index of the interrupt descriptor table handle.
1101 RestoreInterruptDescriptorTableHandlerAddress (
1105 if (Index
< mOrigIdtEntryCount
) {
1106 gIdtTable
[Index
].Bits
.OffsetLow
= mOrigIdtEntry
[Index
].Bits
.OffsetLow
;
1107 gIdtTable
[Index
].Bits
.OffsetHigh
= mOrigIdtEntry
[Index
].Bits
.OffsetHigh
;
1108 #if defined (MDE_CPU_X64)
1109 gIdtTable
[Index
].Bits
.OffsetUpper
= mOrigIdtEntry
[Index
].Bits
.OffsetUpper
;
1115 Initialize Interrupt Descriptor Table for interrupt handling.
1119 InitInterruptDescriptorTable (
1124 IA32_DESCRIPTOR OldIdtPtr
;
1125 IA32_IDT_GATE_DESCRIPTOR
*OldIdt
;
1127 VOID
*IdtPtrAlignmentBuffer
;
1128 IA32_DESCRIPTOR
*IdtPtr
;
1133 SetMem (ExternalVectorTable
, sizeof(ExternalVectorTable
), 0);
1136 // Get original IDT address and size.
1138 AsmReadIdtr ((IA32_DESCRIPTOR
*) &OldIdtPtr
);
1140 if ((OldIdtPtr
.Base
!= 0) && ((OldIdtPtr
.Limit
& 7) == 7)) {
1141 OldIdt
= (IA32_IDT_GATE_DESCRIPTOR
*) OldIdtPtr
.Base
;
1142 OldIdtSize
= (OldIdtPtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
);
1144 // Save original IDT entry and IDT entry count.
1146 mOrigIdtEntry
= AllocateCopyPool (OldIdtPtr
.Limit
+ 1, (VOID
*) OldIdtPtr
.Base
);
1147 ASSERT (mOrigIdtEntry
!= NULL
);
1148 mOrigIdtEntryCount
= (UINT16
) OldIdtSize
;
1157 CurrentCs
= AsmReadCs();
1158 for (Index
= 0; Index
< INTERRUPT_VECTOR_NUMBER
; Index
++) {
1160 // If the old IDT had a handler for this interrupt, then
1163 if (Index
< OldIdtSize
) {
1166 OldIdt
[Index
].Bits
.OffsetLow
+
1167 (OldIdt
[Index
].Bits
.OffsetHigh
<< 16)
1168 #if defined (MDE_CPU_X64)
1169 + (((UINTN
) OldIdt
[Index
].Bits
.OffsetUpper
) << 32)
1176 gIdtTable
[Index
].Bits
.Selector
= CurrentCs
;
1177 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1178 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1179 SetInterruptDescriptorTableHandlerAddress (Index
, IntHandler
);
1185 IdtPtrAlignmentBuffer
= AllocatePool (sizeof (*IdtPtr
) + 16);
1186 IdtPtr
= ALIGN_POINTER (IdtPtrAlignmentBuffer
, 16);
1187 IdtPtr
->Base
= (UINT32
)(((UINTN
)(VOID
*) gIdtTable
) & (BASE_4GB
-1));
1188 IdtPtr
->Limit
= (UINT16
) (sizeof (gIdtTable
) - 1);
1190 AsmWriteIdtr (IdtPtr
);
1192 FreePool (IdtPtrAlignmentBuffer
);
1195 // Initialize Exception Handlers
1197 for (Index
= OldIdtSize
; Index
< 32; Index
++) {
1198 Status
= CpuRegisterInterruptHandler (&gCpu
, Index
, CommonExceptionHandler
);
1199 ASSERT_EFI_ERROR (Status
);
1203 // Set the pointer to the array of C based exception handling routines.
1205 InitializeExternalVectorTablePtr (ExternalVectorTable
);
1211 Callback function for idle events.
1213 @param Event Event whose notification function is being invoked.
1214 @param Context The pointer to the notification function's context,
1215 which is implementation-dependent.
1220 IdleLoopEventCallback (
1230 Initialize the state information for the CPU Architectural Protocol.
1232 @param ImageHandle Image handle this driver.
1233 @param SystemTable Pointer to the System Table.
1235 @retval EFI_SUCCESS Thread can be successfully created
1236 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
1237 @retval EFI_DEVICE_ERROR Cannot create the thread
1243 IN EFI_HANDLE ImageHandle
,
1244 IN EFI_SYSTEM_TABLE
*SystemTable
1248 EFI_EVENT IdleLoopEvent
;
1251 // Make sure interrupts are disabled
1253 DisableInterrupts ();
1258 InitGlobalDescriptorTable ();
1261 // Setup IDT pointer, IDT and interrupt entry points
1263 InitInterruptDescriptorTable ();
1266 // Install CPU Architectural Protocol
1268 Status
= gBS
->InstallMultipleProtocolInterfaces (
1270 &gEfiCpuArchProtocolGuid
, &gCpu
,
1273 ASSERT_EFI_ERROR (Status
);
1276 // Refresh GCD memory space map according to MTRR value.
1278 RefreshGcdMemoryAttributes ();
1281 // Setup a callback for idle events
1283 Status
= gBS
->CreateEventEx (
1286 IdleLoopEventCallback
,
1288 &gIdleLoopEventGuid
,
1291 ASSERT_EFI_ERROR (Status
);