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
;
29 FIXED_MTRR mFixedMtrrTable
[] = {
31 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
36 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
41 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
46 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
51 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
56 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
61 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
66 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
71 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
76 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
81 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
88 EFI_CPU_ARCH_PROTOCOL gCpu
= {
94 CpuRegisterInterruptHandler
,
96 CpuSetMemoryAttributes
,
98 4 // DmaBufferAlignment
102 // Error code flag indicating whether or not an error code will be
103 // pushed on the stack if an exception occurs.
105 // 1 means an error code will be pushed, otherwise 0
107 // bit 0 - exception 0
108 // bit 1 - exception 1
111 UINT32 mErrorCodeFlag
= 0x00027d00;
114 // Local function prototypes
118 Set Interrupt Descriptor Table Handler Address.
120 @param Index The Index of the interrupt descriptor table handle.
121 @param Handler Handler address.
125 SetInterruptDescriptorTableHandlerAddress (
127 IN VOID
*Handler OPTIONAL
131 // CPU Arch Protocol Functions
136 Common exception handler.
138 @param InterruptType Exception type
139 @param SystemContext EFI_SYSTEM_CONTEXT
144 CommonExceptionHandler (
145 IN EFI_EXCEPTION_TYPE InterruptType
,
146 IN EFI_SYSTEM_CONTEXT SystemContext
149 #if defined (MDE_CPU_IA32)
152 "!!!! IA32 Exception Type - %08x !!!!\n",
155 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
158 "ExceptionData - %08x\n",
159 SystemContext
.SystemContextIa32
->ExceptionData
164 "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",
165 SystemContext
.SystemContextIa32
->Cs
,
166 SystemContext
.SystemContextIa32
->Eip
,
167 SystemContext
.SystemContextIa32
->Eflags
,
168 SystemContext
.SystemContextIa32
->Ss
172 "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",
173 SystemContext
.SystemContextIa32
->Ds
,
174 SystemContext
.SystemContextIa32
->Es
,
175 SystemContext
.SystemContextIa32
->Fs
,
176 SystemContext
.SystemContextIa32
->Gs
180 "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",
181 SystemContext
.SystemContextIa32
->Eax
,
182 SystemContext
.SystemContextIa32
->Ebx
,
183 SystemContext
.SystemContextIa32
->Ecx
,
184 SystemContext
.SystemContextIa32
->Edx
188 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
189 SystemContext
.SystemContextIa32
->Esp
,
190 SystemContext
.SystemContextIa32
->Ebp
,
191 SystemContext
.SystemContextIa32
->Esi
,
192 SystemContext
.SystemContextIa32
->Edi
196 "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",
197 SystemContext
.SystemContextIa32
->Gdtr
[0],
198 SystemContext
.SystemContextIa32
->Gdtr
[1],
199 SystemContext
.SystemContextIa32
->Idtr
[0],
200 SystemContext
.SystemContextIa32
->Idtr
[1]
204 "LDT - %08x, TR - %08x\n",
205 SystemContext
.SystemContextIa32
->Ldtr
,
206 SystemContext
.SystemContextIa32
->Tr
210 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
211 SystemContext
.SystemContextIa32
->Cr0
,
212 SystemContext
.SystemContextIa32
->Cr2
,
213 SystemContext
.SystemContextIa32
->Cr3
,
214 SystemContext
.SystemContextIa32
->Cr4
218 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
219 SystemContext
.SystemContextIa32
->Dr0
,
220 SystemContext
.SystemContextIa32
->Dr1
,
221 SystemContext
.SystemContextIa32
->Dr2
,
222 SystemContext
.SystemContextIa32
->Dr3
226 "DR6 - %08x, DR7 - %08x\n",
227 SystemContext
.SystemContextIa32
->Dr6
,
228 SystemContext
.SystemContextIa32
->Dr7
230 #elif defined (MDE_CPU_X64)
233 "!!!! X64 Exception Type - %016lx !!!!\n",
234 (UINT64
)InterruptType
236 if ((mErrorCodeFlag
& (1 << InterruptType
)) != 0) {
239 "ExceptionData - %016lx\n",
240 SystemContext
.SystemContextX64
->ExceptionData
245 "RIP - %016lx, RFL - %016lx\n",
246 SystemContext
.SystemContextX64
->Rip
,
247 SystemContext
.SystemContextX64
->Rflags
251 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
252 SystemContext
.SystemContextX64
->Rax
,
253 SystemContext
.SystemContextX64
->Rcx
,
254 SystemContext
.SystemContextX64
->Rdx
258 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
259 SystemContext
.SystemContextX64
->Rbx
,
260 SystemContext
.SystemContextX64
->Rsp
,
261 SystemContext
.SystemContextX64
->Rbp
265 "RSI - %016lx, RDI - %016lx\n",
266 SystemContext
.SystemContextX64
->Rsi
,
267 SystemContext
.SystemContextX64
->Rdi
271 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
272 SystemContext
.SystemContextX64
->R8
,
273 SystemContext
.SystemContextX64
->R9
,
274 SystemContext
.SystemContextX64
->R10
278 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
279 SystemContext
.SystemContextX64
->R11
,
280 SystemContext
.SystemContextX64
->R12
,
281 SystemContext
.SystemContextX64
->R13
285 "R14 - %016lx, R15 - %016lx\n",
286 SystemContext
.SystemContextX64
->R14
,
287 SystemContext
.SystemContextX64
->R15
291 "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",
292 SystemContext
.SystemContextX64
->Cs
,
293 SystemContext
.SystemContextX64
->Ds
,
294 SystemContext
.SystemContextX64
->Es
,
295 SystemContext
.SystemContextX64
->Fs
,
296 SystemContext
.SystemContextX64
->Gs
,
297 SystemContext
.SystemContextX64
->Ss
301 "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",
302 SystemContext
.SystemContextX64
->Gdtr
[0],
303 SystemContext
.SystemContextX64
->Gdtr
[1],
304 SystemContext
.SystemContextX64
->Idtr
[0],
305 SystemContext
.SystemContextX64
->Idtr
[1]
309 "LDT - %016lx, TR - %016lx\n",
310 SystemContext
.SystemContextX64
->Ldtr
,
311 SystemContext
.SystemContextX64
->Tr
315 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
316 SystemContext
.SystemContextX64
->Cr0
,
317 SystemContext
.SystemContextX64
->Cr2
,
318 SystemContext
.SystemContextX64
->Cr3
322 "CR4 - %016lx, CR8 - %016lx\n",
323 SystemContext
.SystemContextX64
->Cr4
,
324 SystemContext
.SystemContextX64
->Cr8
328 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
329 SystemContext
.SystemContextX64
->Dr0
,
330 SystemContext
.SystemContextX64
->Dr1
,
331 SystemContext
.SystemContextX64
->Dr2
335 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
336 SystemContext
.SystemContextX64
->Dr3
,
337 SystemContext
.SystemContextX64
->Dr6
,
338 SystemContext
.SystemContextX64
->Dr7
341 #error CPU type not supported for exception information dump!
345 // Hang the system with CpuSleep so the processor will enter a lower power
355 Flush CPU data cache. If the instruction cache is fully coherent
356 with all DMA operations then function can just return EFI_SUCCESS.
358 @param This Protocol instance structure
359 @param Start Physical address to start flushing from.
360 @param Length Number of bytes to flush. Round up to chipset
362 @param FlushType Specifies the type of flush operation to perform.
364 @retval EFI_SUCCESS If cache was flushed
365 @retval EFI_UNSUPPORTED If flush type is not supported.
366 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
371 CpuFlushCpuDataCache (
372 IN EFI_CPU_ARCH_PROTOCOL
*This
,
373 IN EFI_PHYSICAL_ADDRESS Start
,
375 IN EFI_CPU_FLUSH_TYPE FlushType
378 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
381 } else if (FlushType
== EfiCpuFlushTypeInvalidate
) {
385 return EFI_UNSUPPORTED
;
391 Enables CPU interrupts.
393 @param This Protocol instance structure
395 @retval EFI_SUCCESS If interrupts were enabled in the CPU
396 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
402 IN EFI_CPU_ARCH_PROTOCOL
*This
407 InterruptState
= TRUE
;
413 Disables CPU interrupts.
415 @param This Protocol instance structure
417 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
418 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
423 CpuDisableInterrupt (
424 IN EFI_CPU_ARCH_PROTOCOL
*This
427 DisableInterrupts ();
429 InterruptState
= FALSE
;
435 Return the state of interrupts.
437 @param This Protocol instance structure
438 @param State Pointer to the CPU's current interrupt state
440 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
441 @retval EFI_INVALID_PARAMETER State is NULL.
446 CpuGetInterruptState (
447 IN EFI_CPU_ARCH_PROTOCOL
*This
,
452 return EFI_INVALID_PARAMETER
;
455 *State
= InterruptState
;
461 Generates an INIT to the CPU.
463 @param This Protocol instance structure
464 @param InitType Type of CPU INIT to perform
466 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
468 @retval EFI_DEVICE_ERROR If CPU INIT failed.
469 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
475 IN EFI_CPU_ARCH_PROTOCOL
*This
,
476 IN EFI_CPU_INIT_TYPE InitType
479 return EFI_UNSUPPORTED
;
484 Registers a function to be called from the CPU interrupt handler.
486 @param This Protocol instance structure
487 @param InterruptType Defines which interrupt to hook. IA-32
488 valid range is 0x00 through 0xFF
489 @param InterruptHandler A pointer to a function of type
490 EFI_CPU_INTERRUPT_HANDLER that is called
491 when a processor interrupt occurs. A null
492 pointer is an error condition.
494 @retval EFI_SUCCESS If handler installed or uninstalled.
495 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
496 for InterruptType was previously installed.
497 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
498 InterruptType was not previously installed.
499 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
505 CpuRegisterInterruptHandler (
506 IN EFI_CPU_ARCH_PROTOCOL
*This
,
507 IN EFI_EXCEPTION_TYPE InterruptType
,
508 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
511 if (InterruptType
< 0 || InterruptType
> 0xff) {
512 return EFI_UNSUPPORTED
;
515 if (InterruptHandler
== NULL
&& ExternalVectorTable
[InterruptType
] == NULL
) {
516 return EFI_INVALID_PARAMETER
;
519 if (InterruptHandler
!= NULL
&& ExternalVectorTable
[InterruptType
] != NULL
) {
520 return EFI_ALREADY_STARTED
;
523 SetInterruptDescriptorTableHandlerAddress ((UINTN
)InterruptType
, NULL
);
524 ExternalVectorTable
[InterruptType
] = InterruptHandler
;
530 Returns a timer value from one of the CPU's internal timers. There is no
531 inherent time interval between ticks but is a function of the CPU frequency.
533 @param This - Protocol instance structure.
534 @param TimerIndex - Specifies which CPU timer is requested.
535 @param TimerValue - Pointer to the returned timer value.
536 @param TimerPeriod - A pointer to the amount of time that passes
537 in femtoseconds (10-15) for each increment
538 of TimerValue. If TimerValue does not
539 increment at a predictable rate, then 0 is
540 returned. The amount of time that has
541 passed between two calls to GetTimerValue()
542 can be calculated with the formula
543 (TimerValue2 - TimerValue1) * TimerPeriod.
544 This parameter is optional and may be NULL.
546 @retval EFI_SUCCESS - If the CPU timer count was returned.
547 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
548 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
549 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
555 IN EFI_CPU_ARCH_PROTOCOL
*This
,
556 IN UINT32 TimerIndex
,
557 OUT UINT64
*TimerValue
,
558 OUT UINT64
*TimerPeriod OPTIONAL
561 if (TimerValue
== NULL
) {
562 return EFI_INVALID_PARAMETER
;
565 if (TimerIndex
!= 0) {
566 return EFI_INVALID_PARAMETER
;
569 *TimerValue
= AsmReadTsc ();
571 if (TimerPeriod
!= NULL
) {
573 // BugBug: Hard coded. Don't know how to do this generically
575 *TimerPeriod
= 1000000000;
583 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
585 This function modifies the attributes for the memory region specified by BaseAddress and
586 Length from their current attributes to the attributes specified by Attributes.
588 @param This The EFI_CPU_ARCH_PROTOCOL instance.
589 @param BaseAddress The physical address that is the start address of a memory region.
590 @param Length The size in bytes of the memory region.
591 @param Attributes The bit mask of attributes to set for the memory region.
593 @retval EFI_SUCCESS The attributes were set for the memory region.
594 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
595 BaseAddress and Length cannot be modified.
596 @retval EFI_INVALID_PARAMETER Length is zero.
597 Attributes specified an illegal combination of attributes that
598 cannot be set together.
599 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
600 the memory resource range.
601 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
602 resource range specified by BaseAddress and Length.
603 The bit mask of attributes is not support for the memory resource
604 range specified by BaseAddress and Length.
609 CpuSetMemoryAttributes (
610 IN EFI_CPU_ARCH_PROTOCOL
*This
,
611 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
616 RETURN_STATUS Status
;
617 MTRR_MEMORY_CACHE_TYPE CacheType
;
619 if (!IsMtrrSupported ()) {
620 return EFI_UNSUPPORTED
;
624 // If this function is called because GCD SetMemorySpaceAttributes () is called
625 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
626 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
627 // to avoid unnecessary computing.
629 if (mIsFlushingGCD
) {
630 DEBUG((EFI_D_ERROR
, " Flushing GCD\n"));
634 switch (Attributes
) {
636 CacheType
= CacheUncacheable
;
640 CacheType
= CacheWriteCombining
;
644 CacheType
= CacheWriteThrough
;
648 CacheType
= CacheWriteProtected
;
652 CacheType
= CacheWriteBack
;
658 case EFI_MEMORY_RUNTIME
:
659 return EFI_UNSUPPORTED
;
662 return EFI_INVALID_PARAMETER
;
665 // call MTRR libary function
667 Status
= MtrrSetMemoryAttribute (
673 return (EFI_STATUS
) Status
;
677 Initializes the valid bits mask and valid address mask for MTRRs.
679 This function initializes the valid bits mask and valid address mask for MTRRs.
688 UINT8 PhysicalAddressBits
;
690 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
692 if (RegEax
>= 0x80000008) {
693 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
695 PhysicalAddressBits
= (UINT8
) RegEax
;
697 mValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
698 mValidMtrrAddressMask
= mValidMtrrBitsMask
& 0xfffffffffffff000ULL
;
700 mValidMtrrBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
701 mValidMtrrAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
706 Gets GCD Mem Space type from MTRR Type.
708 This function gets GCD Mem Space type from MTRR Type.
710 @param MtrrAttributes MTRR memory type
712 @return GCD Mem Space type
716 GetMemorySpaceAttributeFromMtrrType (
717 IN UINT8 MtrrAttributes
720 switch (MtrrAttributes
) {
721 case MTRR_CACHE_UNCACHEABLE
:
722 return EFI_MEMORY_UC
;
723 case MTRR_CACHE_WRITE_COMBINING
:
724 return EFI_MEMORY_WC
;
725 case MTRR_CACHE_WRITE_THROUGH
:
726 return EFI_MEMORY_WT
;
727 case MTRR_CACHE_WRITE_PROTECTED
:
728 return EFI_MEMORY_WP
;
729 case MTRR_CACHE_WRITE_BACK
:
730 return EFI_MEMORY_WB
;
737 Searches memory descriptors covered by given memory range.
739 This function searches into the Gcd Memory Space for descriptors
740 (from StartIndex to EndIndex) that contains the memory range
741 specified by BaseAddress and Length.
743 @param MemorySpaceMap Gcd Memory Space Map as array.
744 @param NumberOfDescriptors Number of descriptors in map.
745 @param BaseAddress BaseAddress for the requested range.
746 @param Length Length for the requested range.
747 @param StartIndex Start index into the Gcd Memory Space Map.
748 @param EndIndex End index into the Gcd Memory Space Map.
750 @retval EFI_SUCCESS Search successfully.
751 @retval EFI_NOT_FOUND The requested descriptors does not exist.
755 SearchGcdMemorySpaces (
756 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
757 IN UINTN NumberOfDescriptors
,
758 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
760 OUT UINTN
*StartIndex
,
768 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
769 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
&&
770 BaseAddress
< MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
773 if (BaseAddress
+ Length
- 1 >= MemorySpaceMap
[Index
].BaseAddress
&&
774 BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
779 return EFI_NOT_FOUND
;
783 Sets the attributes for a specified range in Gcd Memory Space Map.
785 This function sets the attributes for a specified range in
786 Gcd Memory Space Map.
788 @param MemorySpaceMap Gcd Memory Space Map as array
789 @param NumberOfDescriptors Number of descriptors in map
790 @param BaseAddress BaseAddress for the range
791 @param Length Length for the range
792 @param Attributes Attributes to set
794 @retval EFI_SUCCESS Memory attributes set successfully
795 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
799 SetGcdMemorySpaceAttributes (
800 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
801 IN UINTN NumberOfDescriptors
,
802 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
811 EFI_PHYSICAL_ADDRESS RegionStart
;
815 // Get all memory descriptors covered by the memory range
817 Status
= SearchGcdMemorySpaces (
825 if (EFI_ERROR (Status
)) {
830 // Go through all related descriptors and set attributes accordingly
832 for (Index
= StartIndex
; Index
<= EndIndex
; Index
++) {
833 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
837 // Calculate the start and end address of the overlapping range
839 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) {
840 RegionStart
= BaseAddress
;
842 RegionStart
= MemorySpaceMap
[Index
].BaseAddress
;
844 if (BaseAddress
+ Length
- 1 < MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) {
845 RegionLength
= BaseAddress
+ Length
- RegionStart
;
847 RegionLength
= MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- RegionStart
;
850 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
852 gDS
->SetMemorySpaceAttributes (
855 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) | (MemorySpaceMap
[Index
].Capabilities
& Attributes
)
864 Refreshes the GCD Memory Space attributes according to MTRRs.
866 This function refreshes the GCD Memory Space attributes according to MTRRs.
870 RefreshGcdMemoryAttributes (
878 EFI_PHYSICAL_ADDRESS BaseAddress
;
881 UINT64 CurrentAttributes
;
883 UINTN NumberOfDescriptors
;
884 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
885 UINT64 DefaultAttributes
;
886 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
887 MTRR_FIXED_SETTINGS MtrrFixedSettings
;
888 UINT32 FirmwareVariableMtrrCount
;
889 UINT8 DefaultMemoryType
;
891 if (!IsMtrrSupported ()) {
895 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCount ();
896 ASSERT (FirmwareVariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
898 mIsFlushingGCD
= TRUE
;
899 MemorySpaceMap
= NULL
;
902 // Initialize the valid bits mask and valid address mask for MTRRs
904 InitializeMtrrMask ();
907 // Get the memory attribute of variable MTRRs
909 MtrrGetMemoryAttributeInVariableMtrr (
911 mValidMtrrAddressMask
,
916 // Get the memory space map from GCD
918 Status
= gDS
->GetMemorySpaceMap (
919 &NumberOfDescriptors
,
922 ASSERT_EFI_ERROR (Status
);
924 DefaultMemoryType
= (UINT8
) MtrrGetDefaultMemoryType ();
925 DefaultAttributes
= GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType
);
928 // Set default attributes to all spaces.
930 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
931 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
934 gDS
->SetMemorySpaceAttributes (
935 MemorySpaceMap
[Index
].BaseAddress
,
936 MemorySpaceMap
[Index
].Length
,
937 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) |
938 (MemorySpaceMap
[Index
].Capabilities
& DefaultAttributes
)
943 // Go for variable MTRRs with WB attribute
945 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
946 if (VariableMtrr
[Index
].Valid
&&
947 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) {
948 SetGcdMemorySpaceAttributes (
951 VariableMtrr
[Index
].BaseAddress
,
952 VariableMtrr
[Index
].Length
,
959 // Go for variable MTRRs with the attribute except for WB and UC attributes
961 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
962 if (VariableMtrr
[Index
].Valid
&&
963 VariableMtrr
[Index
].Type
!= MTRR_CACHE_WRITE_BACK
&&
964 VariableMtrr
[Index
].Type
!= MTRR_CACHE_UNCACHEABLE
) {
965 Attributes
= GetMemorySpaceAttributeFromMtrrType ((UINT8
) VariableMtrr
[Index
].Type
);
966 SetGcdMemorySpaceAttributes (
969 VariableMtrr
[Index
].BaseAddress
,
970 VariableMtrr
[Index
].Length
,
977 // Go for variable MTRRs with UC attribute
979 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
980 if (VariableMtrr
[Index
].Valid
&&
981 VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
) {
982 SetGcdMemorySpaceAttributes (
985 VariableMtrr
[Index
].BaseAddress
,
986 VariableMtrr
[Index
].Length
,
993 // Go for fixed MTRRs
998 MtrrGetFixedMtrr (&MtrrFixedSettings
);
999 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1000 RegValue
= MtrrFixedSettings
.Mtrr
[Index
];
1002 // Check for continuous fixed MTRR sections
1004 for (SubIndex
= 0; SubIndex
< 8; SubIndex
++) {
1005 MtrrType
= (UINT8
) RShiftU64 (RegValue
, SubIndex
* 8);
1006 CurrentAttributes
= GetMemorySpaceAttributeFromMtrrType (MtrrType
);
1009 // A new MTRR attribute begins
1011 Attributes
= CurrentAttributes
;
1014 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
1016 if (CurrentAttributes
!= Attributes
) {
1017 SetGcdMemorySpaceAttributes (
1019 NumberOfDescriptors
,
1024 BaseAddress
= mFixedMtrrTable
[Index
].BaseAddress
+ mFixedMtrrTable
[Index
].Length
* SubIndex
;
1026 Attributes
= CurrentAttributes
;
1029 Length
+= mFixedMtrrTable
[Index
].Length
;
1033 // Handle the last fixed MTRR region
1035 SetGcdMemorySpaceAttributes (
1037 NumberOfDescriptors
,
1044 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
1046 if (MemorySpaceMap
!= NULL
) {
1047 FreePool (MemorySpaceMap
);
1050 mIsFlushingGCD
= FALSE
;
1054 Set Interrupt Descriptor Table Handler Address.
1056 @param Index The Index of the interrupt descriptor table handle.
1057 @param Handler Handler address.
1061 SetInterruptDescriptorTableHandlerAddress (
1063 IN VOID
*Handler OPTIONAL
1068 if (Handler
!= NULL
) {
1069 UintnHandler
= (UINTN
) Handler
;
1071 UintnHandler
= ((UINTN
) AsmIdtVector00
) + (8 * Index
);
1074 gIdtTable
[Index
].Bits
.OffsetLow
= (UINT16
)UintnHandler
;
1075 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1076 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1077 gIdtTable
[Index
].Bits
.OffsetHigh
= (UINT16
)(UintnHandler
>> 16);
1078 #if defined (MDE_CPU_X64)
1079 gIdtTable
[Index
].Bits
.OffsetUpper
= (UINT32
)(UintnHandler
>> 32);
1080 gIdtTable
[Index
].Bits
.Reserved_1
= 0;
1086 Initialize Interrupt Descriptor Table for interrupt handling.
1090 InitInterruptDescriptorTable (
1095 IA32_DESCRIPTOR OldIdtPtr
;
1096 IA32_IDT_GATE_DESCRIPTOR
*OldIdt
;
1098 VOID
*IdtPtrAlignmentBuffer
;
1099 IA32_DESCRIPTOR
*IdtPtr
;
1104 SetMem (ExternalVectorTable
, sizeof(ExternalVectorTable
), 0);
1107 // Get original IDT address and size.
1109 AsmReadIdtr ((IA32_DESCRIPTOR
*) &OldIdtPtr
);
1111 if ((OldIdtPtr
.Base
!= 0) && ((OldIdtPtr
.Limit
& 7) == 7)) {
1112 OldIdt
= (IA32_IDT_GATE_DESCRIPTOR
*) OldIdtPtr
.Base
;
1113 OldIdtSize
= (OldIdtPtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
);
1122 CurrentCs
= AsmReadCs();
1123 for (Index
= 0; Index
< INTERRUPT_VECTOR_NUMBER
; Index
++) {
1125 // If the old IDT had a handler for this interrupt, then
1128 if (Index
< OldIdtSize
) {
1131 OldIdt
[Index
].Bits
.OffsetLow
+
1132 (OldIdt
[Index
].Bits
.OffsetHigh
<< 16)
1133 #if defined (MDE_CPU_X64)
1134 + (((UINTN
) OldIdt
[Index
].Bits
.OffsetUpper
) << 32)
1141 gIdtTable
[Index
].Bits
.Selector
= CurrentCs
;
1142 gIdtTable
[Index
].Bits
.Reserved_0
= 0;
1143 gIdtTable
[Index
].Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
1144 SetInterruptDescriptorTableHandlerAddress (Index
, IntHandler
);
1150 IdtPtrAlignmentBuffer
= AllocatePool (sizeof (*IdtPtr
) + 16);
1151 IdtPtr
= ALIGN_POINTER (IdtPtrAlignmentBuffer
, 16);
1152 IdtPtr
->Base
= (UINT32
)(((UINTN
)(VOID
*) gIdtTable
) & (BASE_4GB
-1));
1153 IdtPtr
->Limit
= (UINT16
) (sizeof (gIdtTable
) - 1);
1155 AsmWriteIdtr (IdtPtr
);
1157 FreePool (IdtPtrAlignmentBuffer
);
1160 // Initialize Exception Handlers
1162 for (Index
= OldIdtSize
; Index
< 32; Index
++) {
1163 Status
= CpuRegisterInterruptHandler (&gCpu
, Index
, CommonExceptionHandler
);
1164 ASSERT_EFI_ERROR (Status
);
1168 // Set the pointer to the array of C based exception handling routines.
1170 InitializeExternalVectorTablePtr (ExternalVectorTable
);
1176 Callback function for idle events.
1178 @param Event Event whose notification function is being invoked.
1179 @param Context The pointer to the notification function's context,
1180 which is implementation-dependent.
1185 IdleLoopEventCallback (
1195 Initialize the state information for the CPU Architectural Protocol.
1197 @param ImageHandle Image handle this driver.
1198 @param SystemTable Pointer to the System Table.
1200 @retval EFI_SUCCESS Thread can be successfully created
1201 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
1202 @retval EFI_DEVICE_ERROR Cannot create the thread
1208 IN EFI_HANDLE ImageHandle
,
1209 IN EFI_SYSTEM_TABLE
*SystemTable
1213 EFI_EVENT IdleLoopEvent
;
1216 // Make sure interrupts are disabled
1218 DisableInterrupts ();
1223 InitGlobalDescriptorTable ();
1226 // Setup IDT pointer, IDT and interrupt entry points
1228 InitInterruptDescriptorTable ();
1231 // Install CPU Architectural Protocol
1233 Status
= gBS
->InstallMultipleProtocolInterfaces (
1235 &gEfiCpuArchProtocolGuid
, &gCpu
,
1238 ASSERT_EFI_ERROR (Status
);
1241 // Refresh GCD memory space map according to MTRR value.
1243 RefreshGcdMemoryAttributes ();
1246 // Setup a callback for idle events
1248 Status
= gBS
->CreateEventEx (
1251 IdleLoopEventCallback
,
1253 &gIdleLoopEventGuid
,
1256 ASSERT_EFI_ERROR (Status
);