]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuDxe/CpuDxe.c
1. Separated DxeSmmCpuExceptionHandlerLib.inf into 2 instance DxeCpuExceptionHandlerL...
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
1 /** @file
2 CPU DXE Module.
3
4 Copyright (c) 2008 - 2013, 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
9
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.
12
13 **/
14
15 #include "CpuDxe.h"
16
17 //
18 // Global Variables
19 //
20 BOOLEAN InterruptState = FALSE;
21 EFI_HANDLE mCpuHandle = NULL;
22 BOOLEAN mIsFlushingGCD;
23 UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
24 UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
25
26 FIXED_MTRR mFixedMtrrTable[] = {
27 {
28 MTRR_LIB_IA32_MTRR_FIX64K_00000,
29 0,
30 0x10000
31 },
32 {
33 MTRR_LIB_IA32_MTRR_FIX16K_80000,
34 0x80000,
35 0x4000
36 },
37 {
38 MTRR_LIB_IA32_MTRR_FIX16K_A0000,
39 0xA0000,
40 0x4000
41 },
42 {
43 MTRR_LIB_IA32_MTRR_FIX4K_C0000,
44 0xC0000,
45 0x1000
46 },
47 {
48 MTRR_LIB_IA32_MTRR_FIX4K_C8000,
49 0xC8000,
50 0x1000
51 },
52 {
53 MTRR_LIB_IA32_MTRR_FIX4K_D0000,
54 0xD0000,
55 0x1000
56 },
57 {
58 MTRR_LIB_IA32_MTRR_FIX4K_D8000,
59 0xD8000,
60 0x1000
61 },
62 {
63 MTRR_LIB_IA32_MTRR_FIX4K_E0000,
64 0xE0000,
65 0x1000
66 },
67 {
68 MTRR_LIB_IA32_MTRR_FIX4K_E8000,
69 0xE8000,
70 0x1000
71 },
72 {
73 MTRR_LIB_IA32_MTRR_FIX4K_F0000,
74 0xF0000,
75 0x1000
76 },
77 {
78 MTRR_LIB_IA32_MTRR_FIX4K_F8000,
79 0xF8000,
80 0x1000
81 },
82 };
83
84
85 EFI_CPU_ARCH_PROTOCOL gCpu = {
86 CpuFlushCpuDataCache,
87 CpuEnableInterrupt,
88 CpuDisableInterrupt,
89 CpuGetInterruptState,
90 CpuInit,
91 CpuRegisterInterruptHandler,
92 CpuGetTimerValue,
93 CpuSetMemoryAttributes,
94 1, // NumberOfTimers
95 4 // DmaBufferAlignment
96 };
97
98 //
99 // CPU Arch Protocol Functions
100 //
101
102 /**
103 Flush CPU data cache. If the instruction cache is fully coherent
104 with all DMA operations then function can just return EFI_SUCCESS.
105
106 @param This Protocol instance structure
107 @param Start Physical address to start flushing from.
108 @param Length Number of bytes to flush. Round up to chipset
109 granularity.
110 @param FlushType Specifies the type of flush operation to perform.
111
112 @retval EFI_SUCCESS If cache was flushed
113 @retval EFI_UNSUPPORTED If flush type is not supported.
114 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
115
116 **/
117 EFI_STATUS
118 EFIAPI
119 CpuFlushCpuDataCache (
120 IN EFI_CPU_ARCH_PROTOCOL *This,
121 IN EFI_PHYSICAL_ADDRESS Start,
122 IN UINT64 Length,
123 IN EFI_CPU_FLUSH_TYPE FlushType
124 )
125 {
126 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
127 AsmWbinvd ();
128 return EFI_SUCCESS;
129 } else if (FlushType == EfiCpuFlushTypeInvalidate) {
130 AsmInvd ();
131 return EFI_SUCCESS;
132 } else {
133 return EFI_UNSUPPORTED;
134 }
135 }
136
137
138 /**
139 Enables CPU interrupts.
140
141 @param This Protocol instance structure
142
143 @retval EFI_SUCCESS If interrupts were enabled in the CPU
144 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
145
146 **/
147 EFI_STATUS
148 EFIAPI
149 CpuEnableInterrupt (
150 IN EFI_CPU_ARCH_PROTOCOL *This
151 )
152 {
153 EnableInterrupts ();
154
155 InterruptState = TRUE;
156 return EFI_SUCCESS;
157 }
158
159
160 /**
161 Disables CPU interrupts.
162
163 @param This Protocol instance structure
164
165 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
166 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
167
168 **/
169 EFI_STATUS
170 EFIAPI
171 CpuDisableInterrupt (
172 IN EFI_CPU_ARCH_PROTOCOL *This
173 )
174 {
175 DisableInterrupts ();
176
177 InterruptState = FALSE;
178 return EFI_SUCCESS;
179 }
180
181
182 /**
183 Return the state of interrupts.
184
185 @param This Protocol instance structure
186 @param State Pointer to the CPU's current interrupt state
187
188 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
189 @retval EFI_INVALID_PARAMETER State is NULL.
190
191 **/
192 EFI_STATUS
193 EFIAPI
194 CpuGetInterruptState (
195 IN EFI_CPU_ARCH_PROTOCOL *This,
196 OUT BOOLEAN *State
197 )
198 {
199 if (State == NULL) {
200 return EFI_INVALID_PARAMETER;
201 }
202
203 *State = InterruptState;
204 return EFI_SUCCESS;
205 }
206
207
208 /**
209 Generates an INIT to the CPU.
210
211 @param This Protocol instance structure
212 @param InitType Type of CPU INIT to perform
213
214 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
215 seen.
216 @retval EFI_DEVICE_ERROR If CPU INIT failed.
217 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 CpuInit (
223 IN EFI_CPU_ARCH_PROTOCOL *This,
224 IN EFI_CPU_INIT_TYPE InitType
225 )
226 {
227 return EFI_UNSUPPORTED;
228 }
229
230
231 /**
232 Registers a function to be called from the CPU interrupt handler.
233
234 @param This Protocol instance structure
235 @param InterruptType Defines which interrupt to hook. IA-32
236 valid range is 0x00 through 0xFF
237 @param InterruptHandler A pointer to a function of type
238 EFI_CPU_INTERRUPT_HANDLER that is called
239 when a processor interrupt occurs. A null
240 pointer is an error condition.
241
242 @retval EFI_SUCCESS If handler installed or uninstalled.
243 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
244 for InterruptType was previously installed.
245 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
246 InterruptType was not previously installed.
247 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
248 is not supported.
249
250 **/
251 EFI_STATUS
252 EFIAPI
253 CpuRegisterInterruptHandler (
254 IN EFI_CPU_ARCH_PROTOCOL *This,
255 IN EFI_EXCEPTION_TYPE InterruptType,
256 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
257 )
258 {
259 return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
260 }
261
262
263 /**
264 Returns a timer value from one of the CPU's internal timers. There is no
265 inherent time interval between ticks but is a function of the CPU frequency.
266
267 @param This - Protocol instance structure.
268 @param TimerIndex - Specifies which CPU timer is requested.
269 @param TimerValue - Pointer to the returned timer value.
270 @param TimerPeriod - A pointer to the amount of time that passes
271 in femtoseconds (10-15) for each increment
272 of TimerValue. If TimerValue does not
273 increment at a predictable rate, then 0 is
274 returned. The amount of time that has
275 passed between two calls to GetTimerValue()
276 can be calculated with the formula
277 (TimerValue2 - TimerValue1) * TimerPeriod.
278 This parameter is optional and may be NULL.
279
280 @retval EFI_SUCCESS - If the CPU timer count was returned.
281 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
282 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
283 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
284
285 **/
286 EFI_STATUS
287 EFIAPI
288 CpuGetTimerValue (
289 IN EFI_CPU_ARCH_PROTOCOL *This,
290 IN UINT32 TimerIndex,
291 OUT UINT64 *TimerValue,
292 OUT UINT64 *TimerPeriod OPTIONAL
293 )
294 {
295 if (TimerValue == NULL) {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 if (TimerIndex != 0) {
300 return EFI_INVALID_PARAMETER;
301 }
302
303 *TimerValue = AsmReadTsc ();
304
305 if (TimerPeriod != NULL) {
306 //
307 // BugBug: Hard coded. Don't know how to do this generically
308 //
309 *TimerPeriod = 1000000000;
310 }
311
312 return EFI_SUCCESS;
313 }
314
315
316 /**
317 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
318
319 This function modifies the attributes for the memory region specified by BaseAddress and
320 Length from their current attributes to the attributes specified by Attributes.
321
322 @param This The EFI_CPU_ARCH_PROTOCOL instance.
323 @param BaseAddress The physical address that is the start address of a memory region.
324 @param Length The size in bytes of the memory region.
325 @param Attributes The bit mask of attributes to set for the memory region.
326
327 @retval EFI_SUCCESS The attributes were set for the memory region.
328 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
329 BaseAddress and Length cannot be modified.
330 @retval EFI_INVALID_PARAMETER Length is zero.
331 Attributes specified an illegal combination of attributes that
332 cannot be set together.
333 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
334 the memory resource range.
335 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
336 resource range specified by BaseAddress and Length.
337 The bit mask of attributes is not support for the memory resource
338 range specified by BaseAddress and Length.
339
340 **/
341 EFI_STATUS
342 EFIAPI
343 CpuSetMemoryAttributes (
344 IN EFI_CPU_ARCH_PROTOCOL *This,
345 IN EFI_PHYSICAL_ADDRESS BaseAddress,
346 IN UINT64 Length,
347 IN UINT64 Attributes
348 )
349 {
350 RETURN_STATUS Status;
351 MTRR_MEMORY_CACHE_TYPE CacheType;
352
353 if (!IsMtrrSupported ()) {
354 return EFI_UNSUPPORTED;
355 }
356
357 //
358 // If this function is called because GCD SetMemorySpaceAttributes () is called
359 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
360 // map with MTRR values. So there is no need to modify MTRRs, just return immediately
361 // to avoid unnecessary computing.
362 //
363 if (mIsFlushingGCD) {
364 DEBUG((EFI_D_INFO, " Flushing GCD\n"));
365 return EFI_SUCCESS;
366 }
367
368 switch (Attributes) {
369 case EFI_MEMORY_UC:
370 CacheType = CacheUncacheable;
371 break;
372
373 case EFI_MEMORY_WC:
374 CacheType = CacheWriteCombining;
375 break;
376
377 case EFI_MEMORY_WT:
378 CacheType = CacheWriteThrough;
379 break;
380
381 case EFI_MEMORY_WP:
382 CacheType = CacheWriteProtected;
383 break;
384
385 case EFI_MEMORY_WB:
386 CacheType = CacheWriteBack;
387 break;
388
389 case EFI_MEMORY_UCE:
390 case EFI_MEMORY_RP:
391 case EFI_MEMORY_XP:
392 case EFI_MEMORY_RUNTIME:
393 return EFI_UNSUPPORTED;
394
395 default:
396 return EFI_INVALID_PARAMETER;
397 }
398 //
399 // call MTRR libary function
400 //
401 Status = MtrrSetMemoryAttribute (
402 BaseAddress,
403 Length,
404 CacheType
405 );
406
407 return (EFI_STATUS) Status;
408 }
409
410 /**
411 Initializes the valid bits mask and valid address mask for MTRRs.
412
413 This function initializes the valid bits mask and valid address mask for MTRRs.
414
415 **/
416 VOID
417 InitializeMtrrMask (
418 VOID
419 )
420 {
421 UINT32 RegEax;
422 UINT8 PhysicalAddressBits;
423
424 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
425
426 if (RegEax >= 0x80000008) {
427 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
428
429 PhysicalAddressBits = (UINT8) RegEax;
430
431 mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
432 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
433 } else {
434 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
435 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
436 }
437 }
438
439 /**
440 Gets GCD Mem Space type from MTRR Type.
441
442 This function gets GCD Mem Space type from MTRR Type.
443
444 @param MtrrAttributes MTRR memory type
445
446 @return GCD Mem Space type
447
448 **/
449 UINT64
450 GetMemorySpaceAttributeFromMtrrType (
451 IN UINT8 MtrrAttributes
452 )
453 {
454 switch (MtrrAttributes) {
455 case MTRR_CACHE_UNCACHEABLE:
456 return EFI_MEMORY_UC;
457 case MTRR_CACHE_WRITE_COMBINING:
458 return EFI_MEMORY_WC;
459 case MTRR_CACHE_WRITE_THROUGH:
460 return EFI_MEMORY_WT;
461 case MTRR_CACHE_WRITE_PROTECTED:
462 return EFI_MEMORY_WP;
463 case MTRR_CACHE_WRITE_BACK:
464 return EFI_MEMORY_WB;
465 default:
466 return 0;
467 }
468 }
469
470 /**
471 Searches memory descriptors covered by given memory range.
472
473 This function searches into the Gcd Memory Space for descriptors
474 (from StartIndex to EndIndex) that contains the memory range
475 specified by BaseAddress and Length.
476
477 @param MemorySpaceMap Gcd Memory Space Map as array.
478 @param NumberOfDescriptors Number of descriptors in map.
479 @param BaseAddress BaseAddress for the requested range.
480 @param Length Length for the requested range.
481 @param StartIndex Start index into the Gcd Memory Space Map.
482 @param EndIndex End index into the Gcd Memory Space Map.
483
484 @retval EFI_SUCCESS Search successfully.
485 @retval EFI_NOT_FOUND The requested descriptors does not exist.
486
487 **/
488 EFI_STATUS
489 SearchGcdMemorySpaces (
490 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
491 IN UINTN NumberOfDescriptors,
492 IN EFI_PHYSICAL_ADDRESS BaseAddress,
493 IN UINT64 Length,
494 OUT UINTN *StartIndex,
495 OUT UINTN *EndIndex
496 )
497 {
498 UINTN Index;
499
500 *StartIndex = 0;
501 *EndIndex = 0;
502 for (Index = 0; Index < NumberOfDescriptors; Index++) {
503 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&
504 BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
505 *StartIndex = Index;
506 }
507 if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&
508 BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
509 *EndIndex = Index;
510 return EFI_SUCCESS;
511 }
512 }
513 return EFI_NOT_FOUND;
514 }
515
516 /**
517 Sets the attributes for a specified range in Gcd Memory Space Map.
518
519 This function sets the attributes for a specified range in
520 Gcd Memory Space Map.
521
522 @param MemorySpaceMap Gcd Memory Space Map as array
523 @param NumberOfDescriptors Number of descriptors in map
524 @param BaseAddress BaseAddress for the range
525 @param Length Length for the range
526 @param Attributes Attributes to set
527
528 @retval EFI_SUCCESS Memory attributes set successfully
529 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
530
531 **/
532 EFI_STATUS
533 SetGcdMemorySpaceAttributes (
534 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
535 IN UINTN NumberOfDescriptors,
536 IN EFI_PHYSICAL_ADDRESS BaseAddress,
537 IN UINT64 Length,
538 IN UINT64 Attributes
539 )
540 {
541 EFI_STATUS Status;
542 UINTN Index;
543 UINTN StartIndex;
544 UINTN EndIndex;
545 EFI_PHYSICAL_ADDRESS RegionStart;
546 UINT64 RegionLength;
547
548 //
549 // Get all memory descriptors covered by the memory range
550 //
551 Status = SearchGcdMemorySpaces (
552 MemorySpaceMap,
553 NumberOfDescriptors,
554 BaseAddress,
555 Length,
556 &StartIndex,
557 &EndIndex
558 );
559 if (EFI_ERROR (Status)) {
560 return Status;
561 }
562
563 //
564 // Go through all related descriptors and set attributes accordingly
565 //
566 for (Index = StartIndex; Index <= EndIndex; Index++) {
567 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
568 continue;
569 }
570 //
571 // Calculate the start and end address of the overlapping range
572 //
573 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
574 RegionStart = BaseAddress;
575 } else {
576 RegionStart = MemorySpaceMap[Index].BaseAddress;
577 }
578 if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
579 RegionLength = BaseAddress + Length - RegionStart;
580 } else {
581 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
582 }
583 //
584 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
585 //
586 gDS->SetMemorySpaceAttributes (
587 RegionStart,
588 RegionLength,
589 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
590 );
591 }
592
593 return EFI_SUCCESS;
594 }
595
596
597 /**
598 Refreshes the GCD Memory Space attributes according to MTRRs.
599
600 This function refreshes the GCD Memory Space attributes according to MTRRs.
601
602 **/
603 VOID
604 RefreshGcdMemoryAttributes (
605 VOID
606 )
607 {
608 EFI_STATUS Status;
609 UINTN Index;
610 UINTN SubIndex;
611 UINT64 RegValue;
612 EFI_PHYSICAL_ADDRESS BaseAddress;
613 UINT64 Length;
614 UINT64 Attributes;
615 UINT64 CurrentAttributes;
616 UINT8 MtrrType;
617 UINTN NumberOfDescriptors;
618 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
619 UINT64 DefaultAttributes;
620 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
621 MTRR_FIXED_SETTINGS MtrrFixedSettings;
622 UINT32 FirmwareVariableMtrrCount;
623 UINT8 DefaultMemoryType;
624
625 if (!IsMtrrSupported ()) {
626 return;
627 }
628
629 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
630 ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
631
632 mIsFlushingGCD = TRUE;
633 MemorySpaceMap = NULL;
634
635 //
636 // Initialize the valid bits mask and valid address mask for MTRRs
637 //
638 InitializeMtrrMask ();
639
640 //
641 // Get the memory attribute of variable MTRRs
642 //
643 MtrrGetMemoryAttributeInVariableMtrr (
644 mValidMtrrBitsMask,
645 mValidMtrrAddressMask,
646 VariableMtrr
647 );
648
649 //
650 // Get the memory space map from GCD
651 //
652 Status = gDS->GetMemorySpaceMap (
653 &NumberOfDescriptors,
654 &MemorySpaceMap
655 );
656 ASSERT_EFI_ERROR (Status);
657
658 DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();
659 DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);
660
661 //
662 // Set default attributes to all spaces.
663 //
664 for (Index = 0; Index < NumberOfDescriptors; Index++) {
665 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
666 continue;
667 }
668 gDS->SetMemorySpaceAttributes (
669 MemorySpaceMap[Index].BaseAddress,
670 MemorySpaceMap[Index].Length,
671 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
672 (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
673 );
674 }
675
676 //
677 // Go for variable MTRRs with WB attribute
678 //
679 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
680 if (VariableMtrr[Index].Valid &&
681 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {
682 SetGcdMemorySpaceAttributes (
683 MemorySpaceMap,
684 NumberOfDescriptors,
685 VariableMtrr[Index].BaseAddress,
686 VariableMtrr[Index].Length,
687 EFI_MEMORY_WB
688 );
689 }
690 }
691
692 //
693 // Go for variable MTRRs with the attribute except for WB and UC attributes
694 //
695 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
696 if (VariableMtrr[Index].Valid &&
697 VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&
698 VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {
699 Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);
700 SetGcdMemorySpaceAttributes (
701 MemorySpaceMap,
702 NumberOfDescriptors,
703 VariableMtrr[Index].BaseAddress,
704 VariableMtrr[Index].Length,
705 Attributes
706 );
707 }
708 }
709
710 //
711 // Go for variable MTRRs with UC attribute
712 //
713 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
714 if (VariableMtrr[Index].Valid &&
715 VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {
716 SetGcdMemorySpaceAttributes (
717 MemorySpaceMap,
718 NumberOfDescriptors,
719 VariableMtrr[Index].BaseAddress,
720 VariableMtrr[Index].Length,
721 EFI_MEMORY_UC
722 );
723 }
724 }
725
726 //
727 // Go for fixed MTRRs
728 //
729 Attributes = 0;
730 BaseAddress = 0;
731 Length = 0;
732 MtrrGetFixedMtrr (&MtrrFixedSettings);
733 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
734 RegValue = MtrrFixedSettings.Mtrr[Index];
735 //
736 // Check for continuous fixed MTRR sections
737 //
738 for (SubIndex = 0; SubIndex < 8; SubIndex++) {
739 MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
740 CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
741 if (Length == 0) {
742 //
743 // A new MTRR attribute begins
744 //
745 Attributes = CurrentAttributes;
746 } else {
747 //
748 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
749 //
750 if (CurrentAttributes != Attributes) {
751 SetGcdMemorySpaceAttributes (
752 MemorySpaceMap,
753 NumberOfDescriptors,
754 BaseAddress,
755 Length,
756 Attributes
757 );
758 BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
759 Length = 0;
760 Attributes = CurrentAttributes;
761 }
762 }
763 Length += mFixedMtrrTable[Index].Length;
764 }
765 }
766 //
767 // Handle the last fixed MTRR region
768 //
769 SetGcdMemorySpaceAttributes (
770 MemorySpaceMap,
771 NumberOfDescriptors,
772 BaseAddress,
773 Length,
774 Attributes
775 );
776
777 //
778 // Free memory space map allocated by GCD service GetMemorySpaceMap ()
779 //
780 if (MemorySpaceMap != NULL) {
781 FreePool (MemorySpaceMap);
782 }
783
784 mIsFlushingGCD = FALSE;
785 }
786
787 /**
788 Initialize Interrupt Descriptor Table for interrupt handling.
789
790 **/
791 VOID
792 InitInterruptDescriptorTable (
793 VOID
794 )
795 {
796 EFI_STATUS Status;
797 EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
798 EFI_VECTOR_HANDOFF_INFO *VectorInfo;
799
800 VectorInfo = NULL;
801 Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorInfoList);
802 if (Status == EFI_SUCCESS && VectorInfoList != NULL) {
803 VectorInfo = VectorInfoList;
804 }
805 Status = InitializeCpuInterruptHandlers (VectorInfo);
806 ASSERT_EFI_ERROR (Status);
807 }
808
809
810 /**
811 Callback function for idle events.
812
813 @param Event Event whose notification function is being invoked.
814 @param Context The pointer to the notification function's context,
815 which is implementation-dependent.
816
817 **/
818 VOID
819 EFIAPI
820 IdleLoopEventCallback (
821 IN EFI_EVENT Event,
822 IN VOID *Context
823 )
824 {
825 CpuSleep ();
826 }
827
828
829 /**
830 Initialize the state information for the CPU Architectural Protocol.
831
832 @param ImageHandle Image handle this driver.
833 @param SystemTable Pointer to the System Table.
834
835 @retval EFI_SUCCESS Thread can be successfully created
836 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
837 @retval EFI_DEVICE_ERROR Cannot create the thread
838
839 **/
840 EFI_STATUS
841 EFIAPI
842 InitializeCpu (
843 IN EFI_HANDLE ImageHandle,
844 IN EFI_SYSTEM_TABLE *SystemTable
845 )
846 {
847 EFI_STATUS Status;
848 EFI_EVENT IdleLoopEvent;
849
850 InitializeFloatingPointUnits ();
851
852 //
853 // Make sure interrupts are disabled
854 //
855 DisableInterrupts ();
856
857 //
858 // Init GDT for DXE
859 //
860 InitGlobalDescriptorTable ();
861
862 //
863 // Setup IDT pointer, IDT and interrupt entry points
864 //
865 InitInterruptDescriptorTable ();
866
867 //
868 // Enable the local APIC for Virtual Wire Mode.
869 //
870 ProgramVirtualWireMode ();
871
872 //
873 // Install CPU Architectural Protocol
874 //
875 Status = gBS->InstallMultipleProtocolInterfaces (
876 &mCpuHandle,
877 &gEfiCpuArchProtocolGuid, &gCpu,
878 NULL
879 );
880 ASSERT_EFI_ERROR (Status);
881
882 //
883 // Refresh GCD memory space map according to MTRR value.
884 //
885 RefreshGcdMemoryAttributes ();
886
887 //
888 // Setup a callback for idle events
889 //
890 Status = gBS->CreateEventEx (
891 EVT_NOTIFY_SIGNAL,
892 TPL_NOTIFY,
893 IdleLoopEventCallback,
894 NULL,
895 &gIdleLoopEventGuid,
896 &IdleLoopEvent
897 );
898 ASSERT_EFI_ERROR (Status);
899
900 return Status;
901 }
902