4 Copyright (c) 2008 - 2010, 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 UINT8 mDefaultMemoryType
= MTRR_CACHE_WRITE_BACK
;
27 UINT64 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
28 UINT64 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
30 FIXED_MTRR mFixedMtrrTable
[] = {
32 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
37 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
42 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
47 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
52 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
57 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
62 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
67 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
72 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
77 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
82 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
89 EFI_CPU_ARCH_PROTOCOL gCpu
= {
95 CpuRegisterInterruptHandler
,
97 CpuSetMemoryAttributes
,
99 4 // DmaBufferAlignment
103 // Error code flag indicating whether or not an error code will be
104 // pushed on the stack if an exception occurs.
106 // 1 means an error code will be pushed, otherwise 0
108 // bit 0 - exception 0
109 // bit 1 - exception 1
112 UINT32 mErrorCodeFlag
= 0x00027d00;
115 // Local function prototypes
118 SetInterruptDescriptorTableHandlerAddress (
120 IN VOID
*Handler OPTIONAL
124 // CPU Arch Protocol Functions
129 Common exception handler.
131 @param InterruptType Exception type
132 @param SystemContext EFI_SYSTEM_CONTEXT
137 CommonExceptionHandler (
138 IN EFI_EXCEPTION_TYPE InterruptType
,
139 IN EFI_SYSTEM_CONTEXT SystemContext
142 #if defined (MDE_CPU_IA32)
145 "!!!! IA32 Exception Type - %08x !!!!\n",
148 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
151 "ExceptionData - %08x\n",
152 SystemContext
.SystemContextIa32
->ExceptionData
157 "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",
158 SystemContext
.SystemContextIa32
->Cs
,
159 SystemContext
.SystemContextIa32
->Eip
,
160 SystemContext
.SystemContextIa32
->Eflags
,
161 SystemContext
.SystemContextIa32
->Ss
165 "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",
166 SystemContext
.SystemContextIa32
->Ds
,
167 SystemContext
.SystemContextIa32
->Es
,
168 SystemContext
.SystemContextIa32
->Fs
,
169 SystemContext
.SystemContextIa32
->Gs
173 "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",
174 SystemContext
.SystemContextIa32
->Eax
,
175 SystemContext
.SystemContextIa32
->Ebx
,
176 SystemContext
.SystemContextIa32
->Ecx
,
177 SystemContext
.SystemContextIa32
->Edx
181 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
182 SystemContext
.SystemContextIa32
->Esp
,
183 SystemContext
.SystemContextIa32
->Ebp
,
184 SystemContext
.SystemContextIa32
->Esi
,
185 SystemContext
.SystemContextIa32
->Edi
189 "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",
190 SystemContext
.SystemContextIa32
->Gdtr
[0],
191 SystemContext
.SystemContextIa32
->Gdtr
[1],
192 SystemContext
.SystemContextIa32
->Idtr
[0],
193 SystemContext
.SystemContextIa32
->Idtr
[1]
197 "LDT - %08x, TR - %08x\n",
198 SystemContext
.SystemContextIa32
->Ldtr
,
199 SystemContext
.SystemContextIa32
->Tr
203 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
204 SystemContext
.SystemContextIa32
->Cr0
,
205 SystemContext
.SystemContextIa32
->Cr2
,
206 SystemContext
.SystemContextIa32
->Cr3
,
207 SystemContext
.SystemContextIa32
->Cr4
211 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
212 SystemContext
.SystemContextIa32
->Dr0
,
213 SystemContext
.SystemContextIa32
->Dr1
,
214 SystemContext
.SystemContextIa32
->Dr2
,
215 SystemContext
.SystemContextIa32
->Dr3
219 "DR6 - %08x, DR7 - %08x\n",
220 SystemContext
.SystemContextIa32
->Dr6
,
221 SystemContext
.SystemContextIa32
->Dr7
223 #elif defined (MDE_CPU_X64)
226 "!!!! X64 Exception Type - %016lx !!!!\n",
227 (UINT64
)InterruptType
229 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
232 "ExceptionData - %016lx\n",
233 SystemContext
.SystemContextX64
->ExceptionData
238 "RIP - %016lx, RFL - %016lx\n",
239 SystemContext
.SystemContextX64
->Rip
,
240 SystemContext
.SystemContextX64
->Rflags
244 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
245 SystemContext
.SystemContextX64
->Rax
,
246 SystemContext
.SystemContextX64
->Rcx
,
247 SystemContext
.SystemContextX64
->Rdx
251 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
252 SystemContext
.SystemContextX64
->Rbx
,
253 SystemContext
.SystemContextX64
->Rsp
,
254 SystemContext
.SystemContextX64
->Rbp
258 "RSI - %016lx, RDI - %016lx\n",
259 SystemContext
.SystemContextX64
->Rsi
,
260 SystemContext
.SystemContextX64
->Rdi
264 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
265 SystemContext
.SystemContextX64
->R8
,
266 SystemContext
.SystemContextX64
->R9
,
267 SystemContext
.SystemContextX64
->R10
271 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
272 SystemContext
.SystemContextX64
->R11
,
273 SystemContext
.SystemContextX64
->R12
,
274 SystemContext
.SystemContextX64
->R13
278 "R14 - %016lx, R15 - %016lx\n",
279 SystemContext
.SystemContextX64
->R14
,
280 SystemContext
.SystemContextX64
->R15
284 "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",
285 SystemContext
.SystemContextX64
->Cs
,
286 SystemContext
.SystemContextX64
->Ds
,
287 SystemContext
.SystemContextX64
->Es
,
288 SystemContext
.SystemContextX64
->Fs
,
289 SystemContext
.SystemContextX64
->Gs
,
290 SystemContext
.SystemContextX64
->Ss
294 "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",
295 SystemContext
.SystemContextX64
->Gdtr
[0],
296 SystemContext
.SystemContextX64
->Gdtr
[1],
297 SystemContext
.SystemContextX64
->Idtr
[0],
298 SystemContext
.SystemContextX64
->Idtr
[1]
302 "LDT - %016lx, TR - %016lx\n",
303 SystemContext
.SystemContextX64
->Ldtr
,
304 SystemContext
.SystemContextX64
->Tr
308 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
309 SystemContext
.SystemContextX64
->Cr0
,
310 SystemContext
.SystemContextX64
->Cr2
,
311 SystemContext
.SystemContextX64
->Cr3
315 "CR4 - %016lx, CR8 - %016lx\n",
316 SystemContext
.SystemContextX64
->Cr4
,
317 SystemContext
.SystemContextX64
->Cr8
321 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
322 SystemContext
.SystemContextX64
->Dr0
,
323 SystemContext
.SystemContextX64
->Dr1
,
324 SystemContext
.SystemContextX64
->Dr2
328 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
329 SystemContext
.SystemContextX64
->Dr3
,
330 SystemContext
.SystemContextX64
->Dr6
,
331 SystemContext
.SystemContextX64
->Dr7
334 #error CPU type not supported for exception information dump!
338 // Hang the system with CpuSleep so the processor will enter a lower power
348 Flush CPU data cache. If the instruction cache is fully coherent
349 with all DMA operations then function can just return EFI_SUCCESS.
351 @param This Protocol instance structure
352 @param Start Physical address to start flushing from.
353 @param Length Number of bytes to flush. Round up to chipset
355 @param FlushType Specifies the type of flush operation to perform.
357 @retval EFI_SUCCESS If cache was flushed
358 @retval EFI_UNSUPPORTED If flush type is not supported.
359 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
364 CpuFlushCpuDataCache (
365 IN EFI_CPU_ARCH_PROTOCOL
*This
,
366 IN EFI_PHYSICAL_ADDRESS Start
,
368 IN EFI_CPU_FLUSH_TYPE FlushType
371 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
374 } else if (FlushType
== EfiCpuFlushTypeInvalidate
) {
378 return EFI_UNSUPPORTED
;
384 Enables CPU interrupts.
386 @param This Protocol instance structure
388 @retval EFI_SUCCESS If interrupts were enabled in the CPU
389 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
395 IN EFI_CPU_ARCH_PROTOCOL
*This
400 InterruptState
= TRUE
;
406 Disables CPU interrupts.
408 @param This Protocol instance structure
410 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
411 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
416 CpuDisableInterrupt (
417 IN EFI_CPU_ARCH_PROTOCOL
*This
420 DisableInterrupts ();
422 InterruptState
= FALSE
;
428 Return the state of interrupts.
430 @param This Protocol instance structure
431 @param State Pointer to the CPU's current interrupt state
433 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
434 @retval EFI_INVALID_PARAMETER State is NULL.
439 CpuGetInterruptState (
440 IN EFI_CPU_ARCH_PROTOCOL
*This
,
445 return EFI_INVALID_PARAMETER
;
448 *State
= InterruptState
;
454 Generates an INIT to the CPU.
456 @param This Protocol instance structure
457 @param InitType Type of CPU INIT to perform
459 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
461 @retval EFI_DEVICE_ERROR If CPU INIT failed.
462 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
468 IN EFI_CPU_ARCH_PROTOCOL
*This
,
469 IN EFI_CPU_INIT_TYPE InitType
472 return EFI_UNSUPPORTED
;
477 Registers a function to be called from the CPU interrupt handler.
479 @param This Protocol instance structure
480 @param InterruptType Defines which interrupt to hook. IA-32
481 valid range is 0x00 through 0xFF
482 @param InterruptHandler A pointer to a function of type
483 EFI_CPU_INTERRUPT_HANDLER that is called
484 when a processor interrupt occurs. A null
485 pointer is an error condition.
487 @retval EFI_SUCCESS If handler installed or uninstalled.
488 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
489 for InterruptType was previously installed.
490 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
491 InterruptType was not previously installed.
492 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
498 CpuRegisterInterruptHandler (
499 IN EFI_CPU_ARCH_PROTOCOL
*This
,
500 IN EFI_EXCEPTION_TYPE InterruptType
,
501 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
504 if (InterruptType
< 0 || InterruptType
> 0xff) {
505 return EFI_UNSUPPORTED
;
508 if (InterruptHandler
== NULL
&& ExternalVectorTable
[InterruptType
] == NULL
) {
509 return EFI_INVALID_PARAMETER
;
512 if (InterruptHandler
!= NULL
&& ExternalVectorTable
[InterruptType
] != NULL
) {
513 return EFI_ALREADY_STARTED
;
516 SetInterruptDescriptorTableHandlerAddress ((UINTN
)InterruptType
, NULL
);
517 ExternalVectorTable
[InterruptType
] = InterruptHandler
;
523 Returns a timer value from one of the CPU's internal timers. There is no
524 inherent time interval between ticks but is a function of the CPU frequency.
526 @param This - Protocol instance structure.
527 @param TimerIndex - Specifies which CPU timer is requested.
528 @param TimerValue - Pointer to the returned timer value.
529 @param TimerPeriod - A pointer to the amount of time that passes
530 in femtoseconds (10-15) for each increment
531 of TimerValue. If TimerValue does not
532 increment at a predictable rate, then 0 is
533 returned. The amount of time that has
534 passed between two calls to GetTimerValue()
535 can be calculated with the formula
536 (TimerValue2 - TimerValue1) * TimerPeriod.
537 This parameter is optional and may be NULL.
539 @retval EFI_SUCCESS - If the CPU timer count was returned.
540 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
541 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
542 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
548 IN EFI_CPU_ARCH_PROTOCOL
*This
,
549 IN UINT32 TimerIndex
,
550 OUT UINT64
*TimerValue
,
551 OUT UINT64
*TimerPeriod OPTIONAL
554 if (TimerValue
== NULL
) {
555 return EFI_INVALID_PARAMETER
;
558 if (TimerIndex
!= 0) {
559 return EFI_INVALID_PARAMETER
;
562 *TimerValue
= AsmReadTsc ();
564 if (TimerPeriod
!= NULL
) {
566 // BugBug: Hard coded. Don't know how to do this generically
568 *TimerPeriod
= 1000000000;
576 Set memory cacheability attributes for given range of memeory.
578 @param This Protocol instance structure
579 @param BaseAddress Specifies the start address of the
581 @param Length Specifies the length of the memory range
582 @param Attributes The memory cacheability for the memory range
584 @retval EFI_SUCCESS If the cacheability of that memory range is
586 @retval EFI_UNSUPPORTED If the desired operation cannot be done
587 @retval EFI_INVALID_PARAMETER The input parameter is not correct,
593 CpuSetMemoryAttributes (
594 IN EFI_CPU_ARCH_PROTOCOL
*This
,
595 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
600 RETURN_STATUS Status
;
601 MTRR_MEMORY_CACHE_TYPE CacheType
;
603 if (!IsMtrrSupported ()) {
604 return EFI_UNSUPPORTED
;
607 DEBUG((EFI_D_ERROR
, "CpuAp: SetMemorySpaceAttributes(BA=%08x, Len=%08x, Attr=%08x)\n", BaseAddress
, Length
, Attributes
));
610 // If this function is called because GCD SetMemorySpaceAttributes () is called
611 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
612 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
613 // to avoid unnecessary computing.
615 if (mIsFlushingGCD
) {
616 DEBUG((EFI_D_ERROR
, " Flushing GCD\n"));
620 switch (Attributes
) {
622 CacheType
= CacheUncacheable
;
626 CacheType
= CacheWriteCombining
;
630 CacheType
= CacheWriteThrough
;
634 CacheType
= CacheWriteProtected
;
638 CacheType
= CacheWriteBack
;
642 return EFI_UNSUPPORTED
;
645 // call MTRR libary function
647 DEBUG((EFI_D_ERROR
, " MtrrSetMemoryAttribute()\n"));
648 Status
= MtrrSetMemoryAttribute(
654 MtrrDebugPrintAllMtrrs ();
656 return (EFI_STATUS
) Status
;
660 Initializes the valid bits mask and valid address mask for MTRRs.
662 This function initializes the valid bits mask and valid address mask for MTRRs.
671 UINT8 PhysicalAddressBits
;
673 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
675 if (RegEax
>= 0x80000008) {
676 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
678 PhysicalAddressBits
= (UINT8
) RegEax
;
680 mValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
681 mValidMtrrAddressMask
= mValidMtrrBitsMask
& 0xfffffffffffff000ULL
;
683 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
684 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
689 Gets GCD Mem Space type from MTRR Type.
691 This function gets GCD Mem Space type from MTRR Type.
693 @param MtrrAttributes MTRR memory type
695 @return GCD Mem Space type
699 GetMemorySpaceAttributeFromMtrrType (
700 IN UINT8 MtrrAttributes
703 switch (MtrrAttributes
) {
704 case MTRR_CACHE_UNCACHEABLE
:
705 return EFI_MEMORY_UC
;
706 case MTRR_CACHE_WRITE_COMBINING
:
707 return EFI_MEMORY_WC
;
708 case MTRR_CACHE_WRITE_THROUGH
:
709 return EFI_MEMORY_WT
;
710 case MTRR_CACHE_WRITE_PROTECTED
:
711 return EFI_MEMORY_WP
;
712 case MTRR_CACHE_WRITE_BACK
:
713 return EFI_MEMORY_WB
;
720 Searches memory descriptors covered by given memory range.
722 This function searches into the Gcd Memory Space for descriptors
723 (from StartIndex to EndIndex) that contains the memory range
724 specified by BaseAddress and Length.
726 @param MemorySpaceMap Gcd Memory Space Map as array.
727 @param NumberOfDescriptors Number of descriptors in map.
728 @param BaseAddress BaseAddress for the requested range.
729 @param Length Length for the requested range.
730 @param StartIndex Start index into the Gcd Memory Space Map.
731 @param EndIndex End index into the Gcd Memory Space Map.
733 @retval EFI_SUCCESS Search successfully.
734 @retval EFI_NOT_FOUND The requested descriptors does not exist.
738 SearchGcdMemorySpaces (
739 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
740 IN UINTN NumberOfDescriptors
,
741 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
743 OUT UINTN
*StartIndex
,
751 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
752 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
&&
753 BaseAddress
< MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
756 if (BaseAddress
+ Length
- 1 >= MemorySpaceMap
[Index
].BaseAddress
&&
757 BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
762 return EFI_NOT_FOUND
;
766 Sets the attributes for a specified range in Gcd Memory Space Map.
768 This function sets the attributes for a specified range in
769 Gcd Memory Space Map.
771 @param MemorySpaceMap Gcd Memory Space Map as array
772 @param NumberOfDescriptors Number of descriptors in map
773 @param BaseAddress BaseAddress for the range
774 @param Length Length for the range
775 @param Attributes Attributes to set
777 @retval EFI_SUCCESS Memory attributes set successfully
778 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
782 SetGcdMemorySpaceAttributes (
783 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
784 IN UINTN NumberOfDescriptors
,
785 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
794 EFI_PHYSICAL_ADDRESS RegionStart
;
798 // Get all memory descriptors covered by the memory range
800 Status
= SearchGcdMemorySpaces (
808 if (EFI_ERROR (Status
)) {
813 // Go through all related descriptors and set attributes accordingly
815 for (Index
= StartIndex
; Index
<= EndIndex
; Index
++) {
816 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
820 // Calculate the start and end address of the overlapping range
822 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) {
823 RegionStart
= BaseAddress
;
825 RegionStart
= MemorySpaceMap
[Index
].BaseAddress
;
827 if (BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
828 RegionLength
= BaseAddress
+ Length
- RegionStart
;
830 RegionLength
= MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- RegionStart
;
833 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
835 gDS
->SetMemorySpaceAttributes (
838 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) | (MemorySpaceMap
[Index
].Capabilities
& Attributes
)
847 Refreshes the GCD Memory Space attributes according to MTRRs.
849 This function refreshes the GCD Memory Space attributes according to MTRRs.
853 RefreshGcdMemoryAttributes (
861 EFI_PHYSICAL_ADDRESS BaseAddress
;
864 UINT64 CurrentAttributes
;
866 UINTN NumberOfDescriptors
;
867 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
868 UINT64 DefaultAttributes
;
869 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
870 MTRR_FIXED_SETTINGS MtrrFixedSettings
;
871 UINT32 FirmwareVariableMtrrCount
;
873 if (!IsMtrrSupported ()) {
877 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCount ();
878 ASSERT (FirmwareVariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
880 // mIsFlushingGCD = TRUE;
881 mIsFlushingGCD
= FALSE
;
882 MemorySpaceMap
= NULL
;
885 // Initialize the valid bits mask and valid address mask for MTRRs
887 InitializeMtrrMask ();
890 // Get the memory attribute of variable MTRRs
892 MtrrGetMemoryAttributeInVariableMtrr (
894 mValidMtrrAddressMask
,
899 // Get the memory space map from GCD
901 Status
= gDS
->GetMemorySpaceMap (
902 &NumberOfDescriptors
,
905 ASSERT_EFI_ERROR (Status
);
907 DefaultAttributes
= GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType
);
910 // Set default attributes to all spaces.
912 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
913 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
916 gDS
->SetMemorySpaceAttributes (
917 MemorySpaceMap
[Index
].BaseAddress
,
918 MemorySpaceMap
[Index
].Length
,
919 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) |
920 (MemorySpaceMap
[Index
].Capabilities
& DefaultAttributes
)
925 // Go for variable MTRRs with WB attribute
927 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
928 if (VariableMtrr
[Index
].Valid
&&
929 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) {
930 SetGcdMemorySpaceAttributes (
933 VariableMtrr
[Index
].BaseAddress
,
934 VariableMtrr
[Index
].Length
,
940 // Go for variable MTRRs with Non-WB attribute
942 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
943 if (VariableMtrr
[Index
].Valid
&&
944 VariableMtrr
[Index
].Type
!= MTRR_CACHE_WRITE_BACK
) {
945 Attributes
= GetMemorySpaceAttributeFromMtrrType ((UINT8
) VariableMtrr
[Index
].Type
);
946 SetGcdMemorySpaceAttributes (
949 VariableMtrr
[Index
].BaseAddress
,
950 VariableMtrr
[Index
].Length
,
957 // Go for fixed MTRRs
962 MtrrGetFixedMtrr (&MtrrFixedSettings
);
963 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
964 RegValue
= MtrrFixedSettings
.Mtrr
[Index
];
966 // Check for continuous fixed MTRR sections
968 for (SubIndex
= 0; SubIndex
< 8; SubIndex
++) {
969 MtrrType
= (UINT8
) RShiftU64 (RegValue
, SubIndex
* 8);
970 CurrentAttributes
= GetMemorySpaceAttributeFromMtrrType (MtrrType
);
973 // A new MTRR attribute begins
975 Attributes
= CurrentAttributes
;
978 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
980 if (CurrentAttributes
!= Attributes
) {
981 SetGcdMemorySpaceAttributes (
988 BaseAddress
= mFixedMtrrTable
[Index
].BaseAddress
+ mFixedMtrrTable
[Index
].Length
* SubIndex
;
990 Attributes
= CurrentAttributes
;
993 Length
+= mFixedMtrrTable
[Index
].Length
;
997 // Handle the last fixed MTRR region
999 SetGcdMemorySpaceAttributes (
1001 NumberOfDescriptors
,
1008 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
1010 if (MemorySpaceMap
!= NULL
) {
1011 FreePool (MemorySpaceMap
);
1014 mIsFlushingGCD
= FALSE
;
1019 SetInterruptDescriptorTableHandlerAddress (
1021 IN VOID
*Handler OPTIONAL
1026 if (Handler
!= NULL
) {
1027 UintnHandler
= (UINTN
) Handler
;
1029 UintnHandler
= ((UINTN
) AsmIdtVector00
) + (8 * Index
);
1032 gIdtTable
[Index
].Bits
.OffsetLow
= (UINT16
)UintnHandler
;
1033 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1034 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1035 gIdtTable
[Index
].Bits
.OffsetHigh
= (UINT16
)(UintnHandler
>> 16);
1036 #if defined (MDE_CPU_X64)
1037 gIdtTable
[Index
].Bits
.OffsetUpper
= (UINT32
)(UintnHandler
>> 32);
1038 gIdtTable
[Index
].Bits
.Reserved_1
= 0;
1044 Initialize Interrupt Descriptor Table for interrupt handling.
1048 InitInterruptDescriptorTable (
1053 IA32_DESCRIPTOR OldIdtPtr
;
1054 IA32_IDT_GATE_DESCRIPTOR
*OldIdt
;
1056 VOID
*IdtPtrAlignmentBuffer
;
1057 IA32_DESCRIPTOR
*IdtPtr
;
1062 SetMem (ExternalVectorTable
, sizeof(ExternalVectorTable
), 0);
1065 // Get original IDT address and size.
1067 AsmReadIdtr ((IA32_DESCRIPTOR
*) &OldIdtPtr
);
1069 if ((OldIdtPtr
.Base
!= 0) && ((OldIdtPtr
.Limit
& 7) == 7)) {
1070 OldIdt
= (IA32_IDT_GATE_DESCRIPTOR
*) OldIdtPtr
.Base
;
1071 OldIdtSize
= (OldIdtPtr
.Limit
+ 1) / 8;
1080 CurrentCs
= AsmReadCs();
1081 for (Index
= 0; Index
< INTERRUPT_VECTOR_NUMBER
; Index
++) {
1083 // If the old IDT had a handler for this interrupt, then
1086 if (Index
< OldIdtSize
) {
1089 OldIdt
[Index
].Bits
.OffsetLow
+
1090 (OldIdt
[Index
].Bits
.OffsetHigh
<< 16)
1091 #if defined (MDE_CPU_X64)
1092 + (((UINTN
) OldIdt
[Index
].Bits
.OffsetUpper
) << 32)
1099 gIdtTable
[Index
].Bits
.Selector
= CurrentCs
;
1100 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1101 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1102 SetInterruptDescriptorTableHandlerAddress (Index
, IntHandler
);
1108 IdtPtrAlignmentBuffer
= AllocatePool (sizeof (*IdtPtr
) + 16);
1109 IdtPtr
= ALIGN_POINTER (IdtPtrAlignmentBuffer
, 16);
1110 IdtPtr
->Base
= (UINT32
)(((UINTN
)(VOID
*) gIdtTable
) & (BASE_4GB
-1));
1111 IdtPtr
->Limit
= (UINT16
) (sizeof (gIdtTable
) - 1);
1113 AsmWriteIdtr (IdtPtr
);
1115 FreePool (IdtPtrAlignmentBuffer
);
1118 // Initialize Exception Handlers
1120 for (Index
= 0; Index
< 32; Index
++) {
1121 Status
= CpuRegisterInterruptHandler (&gCpu
, Index
, CommonExceptionHandler
);
1122 ASSERT_EFI_ERROR (Status
);
1126 // Set the pointer to the array of C based exception handling routines.
1128 InitializeExternalVectorTablePtr (ExternalVectorTable
);
1134 Initialize the state information for the CPU Architectural Protocol.
1136 @param ImageHandle Image handle this driver.
1137 @param SystemTable Pointer to the System Table.
1139 @retval EFI_SUCCESS Thread can be successfully created
1140 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
1141 @retval EFI_DEVICE_ERROR Cannot create the thread
1147 IN EFI_HANDLE ImageHandle
,
1148 IN EFI_SYSTEM_TABLE
*SystemTable
1154 // Make sure interrupts are disabled
1156 DisableInterrupts ();
1161 InitGlobalDescriptorTable ();
1164 // Setup IDT pointer, IDT and interrupt entry points
1166 InitInterruptDescriptorTable ();
1169 // Install CPU Architectural Protocol
1171 Status
= gBS
->InstallMultipleProtocolInterfaces (
1173 &gEfiCpuArchProtocolGuid
, &gCpu
,
1176 ASSERT_EFI_ERROR (Status
);
1179 // Refresh GCD memory space map according to MTRR value.
1181 RefreshGcdMemoryAttributes ();