]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/CpuDxe.c
UefiCpuPkg CpuCommFeaturesLib: Fix GP fault issue about ProcTrace
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
CommitLineData
a47463f2 1/** @file\r
7fadaacd 2 CPU DXE Module to produce CPU ARCH Protocol.\r
a47463f2 3\r
7367cc6c 4 Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a47463f2 6\r
7**/\r
8\r
9#include "CpuDxe.h"\r
6022e28c 10#include "CpuMp.h"\r
22292ed3
JY
11#include "CpuPageTable.h"\r
12\r
13#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)\r
14#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)\r
a47463f2 15\r
16//\r
17// Global Variables\r
18//\r
a47463f2 19BOOLEAN InterruptState = FALSE;\r
20EFI_HANDLE mCpuHandle = NULL;\r
21BOOLEAN mIsFlushingGCD;\r
147fd35c 22BOOLEAN mIsAllocatingPageTable = FALSE;\r
c894f83f
ED
23UINT64 mValidMtrrAddressMask;\r
24UINT64 mValidMtrrBitsMask;\r
7537f8c0 25UINT64 mTimerPeriod = 0;\r
a47463f2 26\r
27FIXED_MTRR mFixedMtrrTable[] = {\r
28 {\r
b1bd0d74 29 MSR_IA32_MTRR_FIX64K_00000,\r
a47463f2 30 0,\r
31 0x10000\r
32 },\r
33 {\r
b1bd0d74 34 MSR_IA32_MTRR_FIX16K_80000,\r
a47463f2 35 0x80000,\r
36 0x4000\r
37 },\r
38 {\r
b1bd0d74 39 MSR_IA32_MTRR_FIX16K_A0000,\r
a47463f2 40 0xA0000,\r
41 0x4000\r
42 },\r
43 {\r
b1bd0d74 44 MSR_IA32_MTRR_FIX4K_C0000,\r
a47463f2 45 0xC0000,\r
46 0x1000\r
47 },\r
48 {\r
b1bd0d74 49 MSR_IA32_MTRR_FIX4K_C8000,\r
a47463f2 50 0xC8000,\r
51 0x1000\r
52 },\r
53 {\r
b1bd0d74 54 MSR_IA32_MTRR_FIX4K_D0000,\r
a47463f2 55 0xD0000,\r
56 0x1000\r
57 },\r
58 {\r
b1bd0d74 59 MSR_IA32_MTRR_FIX4K_D8000,\r
a47463f2 60 0xD8000,\r
61 0x1000\r
62 },\r
63 {\r
b1bd0d74 64 MSR_IA32_MTRR_FIX4K_E0000,\r
a47463f2 65 0xE0000,\r
66 0x1000\r
67 },\r
68 {\r
b1bd0d74 69 MSR_IA32_MTRR_FIX4K_E8000,\r
a47463f2 70 0xE8000,\r
71 0x1000\r
72 },\r
73 {\r
b1bd0d74 74 MSR_IA32_MTRR_FIX4K_F0000,\r
a47463f2 75 0xF0000,\r
76 0x1000\r
77 },\r
78 {\r
b1bd0d74 79 MSR_IA32_MTRR_FIX4K_F8000,\r
a47463f2 80 0xF8000,\r
81 0x1000\r
82 },\r
83};\r
84\r
85\r
86EFI_CPU_ARCH_PROTOCOL gCpu = {\r
87 CpuFlushCpuDataCache,\r
88 CpuEnableInterrupt,\r
89 CpuDisableInterrupt,\r
90 CpuGetInterruptState,\r
91 CpuInit,\r
92 CpuRegisterInterruptHandler,\r
93 CpuGetTimerValue,\r
94 CpuSetMemoryAttributes,\r
95 1, // NumberOfTimers\r
96 4 // DmaBufferAlignment\r
97};\r
98\r
a47463f2 99//\r
100// CPU Arch Protocol Functions\r
101//\r
102\r
a47463f2 103/**\r
104 Flush CPU data cache. If the instruction cache is fully coherent\r
105 with all DMA operations then function can just return EFI_SUCCESS.\r
106\r
107 @param This Protocol instance structure\r
108 @param Start Physical address to start flushing from.\r
109 @param Length Number of bytes to flush. Round up to chipset\r
110 granularity.\r
111 @param FlushType Specifies the type of flush operation to perform.\r
112\r
113 @retval EFI_SUCCESS If cache was flushed\r
114 @retval EFI_UNSUPPORTED If flush type is not supported.\r
115 @retval EFI_DEVICE_ERROR If requested range could not be flushed.\r
116\r
117**/\r
118EFI_STATUS\r
119EFIAPI\r
120CpuFlushCpuDataCache (\r
121 IN EFI_CPU_ARCH_PROTOCOL *This,\r
122 IN EFI_PHYSICAL_ADDRESS Start,\r
123 IN UINT64 Length,\r
124 IN EFI_CPU_FLUSH_TYPE FlushType\r
125 )\r
126{\r
127 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
128 AsmWbinvd ();\r
129 return EFI_SUCCESS;\r
130 } else if (FlushType == EfiCpuFlushTypeInvalidate) {\r
131 AsmInvd ();\r
132 return EFI_SUCCESS;\r
133 } else {\r
134 return EFI_UNSUPPORTED;\r
135 }\r
136}\r
137\r
138\r
139/**\r
140 Enables CPU interrupts.\r
141\r
142 @param This Protocol instance structure\r
143\r
144 @retval EFI_SUCCESS If interrupts were enabled in the CPU\r
145 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.\r
146\r
147**/\r
148EFI_STATUS\r
149EFIAPI\r
150CpuEnableInterrupt (\r
151 IN EFI_CPU_ARCH_PROTOCOL *This\r
152 )\r
153{\r
154 EnableInterrupts ();\r
155\r
156 InterruptState = TRUE;\r
157 return EFI_SUCCESS;\r
158}\r
159\r
160\r
161/**\r
162 Disables CPU interrupts.\r
163\r
164 @param This Protocol instance structure\r
165\r
166 @retval EFI_SUCCESS If interrupts were disabled in the CPU.\r
167 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.\r
168\r
169**/\r
170EFI_STATUS\r
171EFIAPI\r
172CpuDisableInterrupt (\r
173 IN EFI_CPU_ARCH_PROTOCOL *This\r
174 )\r
175{\r
176 DisableInterrupts ();\r
177\r
178 InterruptState = FALSE;\r
179 return EFI_SUCCESS;\r
180}\r
181\r
182\r
183/**\r
184 Return the state of interrupts.\r
185\r
186 @param This Protocol instance structure\r
187 @param State Pointer to the CPU's current interrupt state\r
188\r
189 @retval EFI_SUCCESS If interrupts were disabled in the CPU.\r
190 @retval EFI_INVALID_PARAMETER State is NULL.\r
191\r
192**/\r
193EFI_STATUS\r
194EFIAPI\r
195CpuGetInterruptState (\r
196 IN EFI_CPU_ARCH_PROTOCOL *This,\r
197 OUT BOOLEAN *State\r
198 )\r
199{\r
200 if (State == NULL) {\r
201 return EFI_INVALID_PARAMETER;\r
202 }\r
203\r
204 *State = InterruptState;\r
205 return EFI_SUCCESS;\r
206}\r
207\r
208\r
209/**\r
210 Generates an INIT to the CPU.\r
211\r
212 @param This Protocol instance structure\r
213 @param InitType Type of CPU INIT to perform\r
214\r
215 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be\r
216 seen.\r
217 @retval EFI_DEVICE_ERROR If CPU INIT failed.\r
218 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.\r
219\r
220**/\r
221EFI_STATUS\r
222EFIAPI\r
223CpuInit (\r
224 IN EFI_CPU_ARCH_PROTOCOL *This,\r
225 IN EFI_CPU_INIT_TYPE InitType\r
226 )\r
227{\r
228 return EFI_UNSUPPORTED;\r
229}\r
230\r
231\r
232/**\r
233 Registers a function to be called from the CPU interrupt handler.\r
234\r
235 @param This Protocol instance structure\r
236 @param InterruptType Defines which interrupt to hook. IA-32\r
237 valid range is 0x00 through 0xFF\r
238 @param InterruptHandler A pointer to a function of type\r
239 EFI_CPU_INTERRUPT_HANDLER that is called\r
240 when a processor interrupt occurs. A null\r
241 pointer is an error condition.\r
242\r
243 @retval EFI_SUCCESS If handler installed or uninstalled.\r
244 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler\r
245 for InterruptType was previously installed.\r
246 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for\r
247 InterruptType was not previously installed.\r
248 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType\r
249 is not supported.\r
250\r
251**/\r
252EFI_STATUS\r
253EFIAPI\r
254CpuRegisterInterruptHandler (\r
255 IN EFI_CPU_ARCH_PROTOCOL *This,\r
256 IN EFI_EXCEPTION_TYPE InterruptType,\r
257 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
258 )\r
259{\r
e41aad15 260 return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);\r
a47463f2 261}\r
262\r
263\r
264/**\r
265 Returns a timer value from one of the CPU's internal timers. There is no\r
266 inherent time interval between ticks but is a function of the CPU frequency.\r
267\r
268 @param This - Protocol instance structure.\r
269 @param TimerIndex - Specifies which CPU timer is requested.\r
270 @param TimerValue - Pointer to the returned timer value.\r
271 @param TimerPeriod - A pointer to the amount of time that passes\r
272 in femtoseconds (10-15) for each increment\r
273 of TimerValue. If TimerValue does not\r
274 increment at a predictable rate, then 0 is\r
275 returned. The amount of time that has\r
276 passed between two calls to GetTimerValue()\r
277 can be calculated with the formula\r
278 (TimerValue2 - TimerValue1) * TimerPeriod.\r
279 This parameter is optional and may be NULL.\r
280\r
281 @retval EFI_SUCCESS - If the CPU timer count was returned.\r
282 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.\r
283 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.\r
284 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.\r
285\r
286**/\r
287EFI_STATUS\r
288EFIAPI\r
289CpuGetTimerValue (\r
290 IN EFI_CPU_ARCH_PROTOCOL *This,\r
291 IN UINT32 TimerIndex,\r
292 OUT UINT64 *TimerValue,\r
293 OUT UINT64 *TimerPeriod OPTIONAL\r
294 )\r
295{\r
7537f8c0
JF
296 UINT64 BeginValue;\r
297 UINT64 EndValue;\r
298\r
a47463f2 299 if (TimerValue == NULL) {\r
300 return EFI_INVALID_PARAMETER;\r
301 }\r
302\r
303 if (TimerIndex != 0) {\r
304 return EFI_INVALID_PARAMETER;\r
305 }\r
306\r
307 *TimerValue = AsmReadTsc ();\r
308\r
309 if (TimerPeriod != NULL) {\r
7537f8c0
JF
310 if (mTimerPeriod == 0) {\r
311 //\r
312 // Read time stamp counter before and after delay of 100 microseconds\r
313 //\r
314 BeginValue = AsmReadTsc ();\r
315 MicroSecondDelay (100);\r
316 EndValue = AsmReadTsc ();\r
a47463f2 317 //\r
7537f8c0 318 // Calculate the actual frequency\r
a47463f2 319 //\r
7537f8c0
JF
320 mTimerPeriod = DivU64x64Remainder (\r
321 MultU64x32 (\r
322 1000 * 1000 * 1000,\r
323 100\r
324 ),\r
325 EndValue - BeginValue,\r
326 NULL\r
327 );\r
328 }\r
329 *TimerPeriod = mTimerPeriod;\r
a47463f2 330 }\r
331\r
332 return EFI_SUCCESS;\r
333}\r
334\r
0b9f0dd6
JF
335/**\r
336 A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
337 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
338\r
339 @param[in] Buffer Pointer to an MTRR_SETTINGS object, to be passed to\r
340 MtrrSetAllMtrrs().\r
341**/\r
342VOID\r
343EFIAPI\r
344SetMtrrsFromBuffer (\r
345 IN VOID *Buffer\r
346 )\r
347{\r
348 MtrrSetAllMtrrs (Buffer);\r
349}\r
a47463f2 350\r
351/**\r
4ec21e8b 352 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.\r
353\r
354 This function modifies the attributes for the memory region specified by BaseAddress and\r
355 Length from their current attributes to the attributes specified by Attributes.\r
356\r
357 @param This The EFI_CPU_ARCH_PROTOCOL instance.\r
358 @param BaseAddress The physical address that is the start address of a memory region.\r
359 @param Length The size in bytes of the memory region.\r
360 @param Attributes The bit mask of attributes to set for the memory region.\r
361\r
362 @retval EFI_SUCCESS The attributes were set for the memory region.\r
363 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
364 BaseAddress and Length cannot be modified.\r
365 @retval EFI_INVALID_PARAMETER Length is zero.\r
366 Attributes specified an illegal combination of attributes that\r
367 cannot be set together.\r
368 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
369 the memory resource range.\r
370 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
371 resource range specified by BaseAddress and Length.\r
372 The bit mask of attributes is not support for the memory resource\r
373 range specified by BaseAddress and Length.\r
a47463f2 374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378CpuSetMemoryAttributes (\r
379 IN EFI_CPU_ARCH_PROTOCOL *This,\r
380 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
381 IN UINT64 Length,\r
382 IN UINT64 Attributes\r
383 )\r
384{\r
385 RETURN_STATUS Status;\r
386 MTRR_MEMORY_CACHE_TYPE CacheType;\r
94941c88
LE
387 EFI_STATUS MpStatus;\r
388 EFI_MP_SERVICES_PROTOCOL *MpService;\r
389 MTRR_SETTINGS MtrrSettings;\r
22292ed3
JY
390 UINT64 CacheAttributes;\r
391 UINT64 MemoryAttributes;\r
392 MTRR_MEMORY_CACHE_TYPE CurrentCacheType;\r
947a573a 393\r
a47463f2 394 //\r
395 // If this function is called because GCD SetMemorySpaceAttributes () is called\r
396 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory\r
397 // map with MTRR values. So there is no need to modify MTRRs, just return immediately\r
398 // to avoid unnecessary computing.\r
399 //\r
400 if (mIsFlushingGCD) {\r
7c7c8190 401 DEBUG((DEBUG_VERBOSE, " Flushing GCD\n"));\r
79aca636
SEHM
402 return EFI_SUCCESS;\r
403 }\r
a47463f2 404\r
147fd35c
JW
405 //\r
406 // During memory attributes updating, new pages may be allocated to setup\r
407 // smaller granularity of page table. Page allocation action might then cause\r
408 // another calling of CpuSetMemoryAttributes() recursively, due to memory\r
409 // protection policy configured (such as PcdDxeNxMemoryProtectionPolicy).\r
410 // Since this driver will always protect memory used as page table by itself,\r
411 // there's no need to apply protection policy requested from memory service.\r
412 // So it's safe to just return EFI_SUCCESS if this time of calling is caused\r
413 // by page table memory allocation.\r
414 //\r
415 if (mIsAllocatingPageTable) {\r
416 DEBUG((DEBUG_VERBOSE, " Allocating page table memory\n"));\r
417 return EFI_SUCCESS;\r
418 }\r
a47463f2 419\r
22292ed3
JY
420 CacheAttributes = Attributes & CACHE_ATTRIBUTE_MASK;\r
421 MemoryAttributes = Attributes & MEMORY_ATTRIBUTE_MASK;\r
a47463f2 422\r
22292ed3
JY
423 if (Attributes != (CacheAttributes | MemoryAttributes)) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
a47463f2 426\r
22292ed3
JY
427 if (CacheAttributes != 0) {\r
428 if (!IsMtrrSupported ()) {\r
429 return EFI_UNSUPPORTED;\r
430 }\r
a47463f2 431\r
22292ed3
JY
432 switch (CacheAttributes) {\r
433 case EFI_MEMORY_UC:\r
434 CacheType = CacheUncacheable;\r
435 break;\r
a47463f2 436\r
22292ed3
JY
437 case EFI_MEMORY_WC:\r
438 CacheType = CacheWriteCombining;\r
439 break;\r
4ec21e8b 440\r
22292ed3
JY
441 case EFI_MEMORY_WT:\r
442 CacheType = CacheWriteThrough;\r
443 break;\r
a47463f2 444\r
22292ed3
JY
445 case EFI_MEMORY_WP:\r
446 CacheType = CacheWriteProtected;\r
447 break;\r
448\r
449 case EFI_MEMORY_WB:\r
450 CacheType = CacheWriteBack;\r
451 break;\r
452\r
453 default:\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456 CurrentCacheType = MtrrGetMemoryAttribute(BaseAddress);\r
457 if (CurrentCacheType != CacheType) {\r
458 //\r
459 // call MTRR libary function\r
460 //\r
461 Status = MtrrSetMemoryAttribute (\r
462 BaseAddress,\r
463 Length,\r
464 CacheType\r
465 );\r
466\r
467 if (!RETURN_ERROR (Status)) {\r
468 MpStatus = gBS->LocateProtocol (\r
469 &gEfiMpServiceProtocolGuid,\r
470 NULL,\r
471 (VOID **)&MpService\r
472 );\r
473 //\r
474 // Synchronize the update with all APs\r
475 //\r
476 if (!EFI_ERROR (MpStatus)) {\r
477 MtrrGetAllMtrrs (&MtrrSettings);\r
478 MpStatus = MpService->StartupAllAPs (\r
479 MpService, // This\r
480 SetMtrrsFromBuffer, // Procedure\r
481 FALSE, // SingleThread\r
482 NULL, // WaitEvent\r
483 0, // TimeoutInMicrosecsond\r
484 &MtrrSettings, // ProcedureArgument\r
485 NULL // FailedCpuList\r
486 );\r
487 ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
488 }\r
489 }\r
490 if (EFI_ERROR(Status)) {\r
491 return Status;\r
492 }\r
94941c88
LE
493 }\r
494 }\r
22292ed3
JY
495\r
496 //\r
497 // Set memory attribute by page table\r
498 //\r
147fd35c 499 return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
a47463f2 500}\r
501\r
502/**\r
503 Initializes the valid bits mask and valid address mask for MTRRs.\r
504\r
505 This function initializes the valid bits mask and valid address mask for MTRRs.\r
506\r
507**/\r
508VOID\r
509InitializeMtrrMask (\r
510 VOID\r
511 )\r
512{\r
513 UINT32 RegEax;\r
514 UINT8 PhysicalAddressBits;\r
515\r
516 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
517\r
518 if (RegEax >= 0x80000008) {\r
519 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
520\r
521 PhysicalAddressBits = (UINT8) RegEax;\r
a47463f2 522 } else {\r
c894f83f 523 PhysicalAddressBits = 36;\r
a47463f2 524 }\r
c894f83f
ED
525\r
526 mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
527 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
a47463f2 528}\r
529\r
530/**\r
430fbbe0 531 Gets GCD Mem Space type from MTRR Type.\r
a47463f2 532\r
430fbbe0 533 This function gets GCD Mem Space type from MTRR Type.\r
a47463f2 534\r
430fbbe0 535 @param MtrrAttributes MTRR memory type\r
a47463f2 536\r
537 @return GCD Mem Space type\r
538\r
539**/\r
540UINT64\r
541GetMemorySpaceAttributeFromMtrrType (\r
2c4b1bdc 542 IN UINT8 MtrrAttributes\r
a47463f2 543 )\r
544{\r
545 switch (MtrrAttributes) {\r
546 case MTRR_CACHE_UNCACHEABLE:\r
547 return EFI_MEMORY_UC;\r
548 case MTRR_CACHE_WRITE_COMBINING:\r
549 return EFI_MEMORY_WC;\r
550 case MTRR_CACHE_WRITE_THROUGH:\r
551 return EFI_MEMORY_WT;\r
552 case MTRR_CACHE_WRITE_PROTECTED:\r
553 return EFI_MEMORY_WP;\r
554 case MTRR_CACHE_WRITE_BACK:\r
555 return EFI_MEMORY_WB;\r
556 default:\r
557 return 0;\r
558 }\r
559}\r
560\r
561/**\r
562 Searches memory descriptors covered by given memory range.\r
563\r
564 This function searches into the Gcd Memory Space for descriptors\r
565 (from StartIndex to EndIndex) that contains the memory range\r
566 specified by BaseAddress and Length.\r
567\r
568 @param MemorySpaceMap Gcd Memory Space Map as array.\r
569 @param NumberOfDescriptors Number of descriptors in map.\r
570 @param BaseAddress BaseAddress for the requested range.\r
571 @param Length Length for the requested range.\r
572 @param StartIndex Start index into the Gcd Memory Space Map.\r
573 @param EndIndex End index into the Gcd Memory Space Map.\r
574\r
575 @retval EFI_SUCCESS Search successfully.\r
576 @retval EFI_NOT_FOUND The requested descriptors does not exist.\r
577\r
578**/\r
579EFI_STATUS\r
580SearchGcdMemorySpaces (\r
581 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
582 IN UINTN NumberOfDescriptors,\r
583 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
584 IN UINT64 Length,\r
585 OUT UINTN *StartIndex,\r
586 OUT UINTN *EndIndex\r
587 )\r
588{\r
589 UINTN Index;\r
590\r
591 *StartIndex = 0;\r
592 *EndIndex = 0;\r
593 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
594 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
595 BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
596 *StartIndex = Index;\r
597 }\r
598 if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
599 BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
600 *EndIndex = Index;\r
601 return EFI_SUCCESS;\r
602 }\r
603 }\r
604 return EFI_NOT_FOUND;\r
605}\r
606\r
607/**\r
608 Sets the attributes for a specified range in Gcd Memory Space Map.\r
609\r
610 This function sets the attributes for a specified range in\r
611 Gcd Memory Space Map.\r
612\r
613 @param MemorySpaceMap Gcd Memory Space Map as array\r
614 @param NumberOfDescriptors Number of descriptors in map\r
615 @param BaseAddress BaseAddress for the range\r
616 @param Length Length for the range\r
617 @param Attributes Attributes to set\r
618\r
619 @retval EFI_SUCCESS Memory attributes set successfully\r
620 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space\r
621\r
622**/\r
623EFI_STATUS\r
624SetGcdMemorySpaceAttributes (\r
625 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
626 IN UINTN NumberOfDescriptors,\r
627 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
628 IN UINT64 Length,\r
629 IN UINT64 Attributes\r
630 )\r
631{\r
632 EFI_STATUS Status;\r
633 UINTN Index;\r
634 UINTN StartIndex;\r
635 UINTN EndIndex;\r
636 EFI_PHYSICAL_ADDRESS RegionStart;\r
637 UINT64 RegionLength;\r
638\r
639 //\r
640 // Get all memory descriptors covered by the memory range\r
641 //\r
642 Status = SearchGcdMemorySpaces (\r
643 MemorySpaceMap,\r
644 NumberOfDescriptors,\r
645 BaseAddress,\r
646 Length,\r
647 &StartIndex,\r
648 &EndIndex\r
649 );\r
650 if (EFI_ERROR (Status)) {\r
651 return Status;\r
652 }\r
653\r
654 //\r
655 // Go through all related descriptors and set attributes accordingly\r
656 //\r
657 for (Index = StartIndex; Index <= EndIndex; Index++) {\r
658 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
659 continue;\r
660 }\r
661 //\r
662 // Calculate the start and end address of the overlapping range\r
663 //\r
664 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
665 RegionStart = BaseAddress;\r
666 } else {\r
667 RegionStart = MemorySpaceMap[Index].BaseAddress;\r
668 }\r
669 if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
670 RegionLength = BaseAddress + Length - RegionStart;\r
671 } else {\r
672 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
673 }\r
674 //\r
675 // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
676 //\r
677 gDS->SetMemorySpaceAttributes (\r
678 RegionStart,\r
679 RegionLength,\r
680 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
681 );\r
682 }\r
683\r
684 return EFI_SUCCESS;\r
685}\r
686\r
687\r
688/**\r
689 Refreshes the GCD Memory Space attributes according to MTRRs.\r
690\r
691 This function refreshes the GCD Memory Space attributes according to MTRRs.\r
692\r
693**/\r
694VOID\r
c46bced2 695RefreshMemoryAttributesFromMtrr (\r
a47463f2 696 VOID\r
697 )\r
698{\r
699 EFI_STATUS Status;\r
700 UINTN Index;\r
701 UINTN SubIndex;\r
702 UINT64 RegValue;\r
703 EFI_PHYSICAL_ADDRESS BaseAddress;\r
704 UINT64 Length;\r
705 UINT64 Attributes;\r
706 UINT64 CurrentAttributes;\r
2c4b1bdc 707 UINT8 MtrrType;\r
a47463f2 708 UINTN NumberOfDescriptors;\r
709 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
710 UINT64 DefaultAttributes;\r
6640eb36 711 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
a47463f2 712 MTRR_FIXED_SETTINGS MtrrFixedSettings;\r
3b9be416 713 UINT32 FirmwareVariableMtrrCount;\r
2c4b1bdc 714 UINT8 DefaultMemoryType;\r
3b9be416
JY
715\r
716 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
5bdfa4e5 717 ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
a47463f2 718\r
a47463f2 719 MemorySpaceMap = NULL;\r
720\r
721 //\r
722 // Initialize the valid bits mask and valid address mask for MTRRs\r
723 //\r
724 InitializeMtrrMask ();\r
725\r
726 //\r
727 // Get the memory attribute of variable MTRRs\r
728 //\r
729 MtrrGetMemoryAttributeInVariableMtrr (\r
730 mValidMtrrBitsMask,\r
731 mValidMtrrAddressMask,\r
732 VariableMtrr\r
733 );\r
734\r
735 //\r
736 // Get the memory space map from GCD\r
737 //\r
738 Status = gDS->GetMemorySpaceMap (\r
739 &NumberOfDescriptors,\r
740 &MemorySpaceMap\r
741 );\r
742 ASSERT_EFI_ERROR (Status);\r
743\r
2c4b1bdc 744 DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();\r
91ec7824 745 DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);\r
a47463f2 746\r
747 //\r
748 // Set default attributes to all spaces.\r
749 //\r
750 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
751 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
752 continue;\r
753 }\r
754 gDS->SetMemorySpaceAttributes (\r
755 MemorySpaceMap[Index].BaseAddress,\r
756 MemorySpaceMap[Index].Length,\r
757 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |\r
758 (MemorySpaceMap[Index].Capabilities & DefaultAttributes)\r
759 );\r
760 }\r
761\r
762 //\r
763 // Go for variable MTRRs with WB attribute\r
764 //\r
3b9be416 765 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
a47463f2 766 if (VariableMtrr[Index].Valid &&\r
767 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
768 SetGcdMemorySpaceAttributes (\r
769 MemorySpaceMap,\r
770 NumberOfDescriptors,\r
771 VariableMtrr[Index].BaseAddress,\r
772 VariableMtrr[Index].Length,\r
773 EFI_MEMORY_WB\r
774 );\r
775 }\r
776 }\r
91ec7824 777\r
a47463f2 778 //\r
91ec7824 779 // Go for variable MTRRs with the attribute except for WB and UC attributes\r
a47463f2 780 //\r
3b9be416 781 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
d4605c23 782 if (VariableMtrr[Index].Valid &&\r
91ec7824 783 VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&\r
784 VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {\r
2c4b1bdc 785 Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);\r
a47463f2 786 SetGcdMemorySpaceAttributes (\r
787 MemorySpaceMap,\r
788 NumberOfDescriptors,\r
789 VariableMtrr[Index].BaseAddress,\r
790 VariableMtrr[Index].Length,\r
791 Attributes\r
792 );\r
793 }\r
794 }\r
795\r
91ec7824 796 //\r
797 // Go for variable MTRRs with UC attribute\r
798 //\r
799 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
800 if (VariableMtrr[Index].Valid &&\r
801 VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {\r
802 SetGcdMemorySpaceAttributes (\r
803 MemorySpaceMap,\r
804 NumberOfDescriptors,\r
805 VariableMtrr[Index].BaseAddress,\r
806 VariableMtrr[Index].Length,\r
807 EFI_MEMORY_UC\r
808 );\r
809 }\r
810 }\r
811\r
a47463f2 812 //\r
813 // Go for fixed MTRRs\r
814 //\r
815 Attributes = 0;\r
816 BaseAddress = 0;\r
817 Length = 0;\r
818 MtrrGetFixedMtrr (&MtrrFixedSettings);\r
819 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
820 RegValue = MtrrFixedSettings.Mtrr[Index];\r
821 //\r
822 // Check for continuous fixed MTRR sections\r
823 //\r
824 for (SubIndex = 0; SubIndex < 8; SubIndex++) {\r
2c4b1bdc 825 MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);\r
a47463f2 826 CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);\r
827 if (Length == 0) {\r
828 //\r
829 // A new MTRR attribute begins\r
830 //\r
831 Attributes = CurrentAttributes;\r
832 } else {\r
833 //\r
834 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute\r
835 //\r
836 if (CurrentAttributes != Attributes) {\r
837 SetGcdMemorySpaceAttributes (\r
838 MemorySpaceMap,\r
839 NumberOfDescriptors,\r
840 BaseAddress,\r
841 Length,\r
842 Attributes\r
843 );\r
844 BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;\r
845 Length = 0;\r
846 Attributes = CurrentAttributes;\r
847 }\r
848 }\r
849 Length += mFixedMtrrTable[Index].Length;\r
850 }\r
851 }\r
852 //\r
853 // Handle the last fixed MTRR region\r
854 //\r
855 SetGcdMemorySpaceAttributes (\r
856 MemorySpaceMap,\r
857 NumberOfDescriptors,\r
858 BaseAddress,\r
859 Length,\r
860 Attributes\r
861 );\r
862\r
863 //\r
864 // Free memory space map allocated by GCD service GetMemorySpaceMap ()\r
865 //\r
866 if (MemorySpaceMap != NULL) {\r
867 FreePool (MemorySpaceMap);\r
868 }\r
c46bced2 869}\r
a47463f2 870\r
c46bced2
JW
871/**\r
872 Check if paging is enabled or not.\r
873**/\r
874BOOLEAN\r
875IsPagingAndPageAddressExtensionsEnabled (\r
876 VOID\r
877 )\r
878{\r
879 IA32_CR0 Cr0;\r
880 IA32_CR4 Cr4;\r
881\r
882 Cr0.UintN = AsmReadCr0 ();\r
883 Cr4.UintN = AsmReadCr4 ();\r
884\r
885 return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));\r
886}\r
887\r
888/**\r
889 Refreshes the GCD Memory Space attributes according to MTRRs and Paging.\r
890\r
891 This function refreshes the GCD Memory Space attributes according to MTRRs\r
892 and page tables.\r
893\r
894**/\r
895VOID\r
896RefreshGcdMemoryAttributes (\r
897 VOID\r
898 )\r
899{\r
900 mIsFlushingGCD = TRUE;\r
901\r
902 if (IsMtrrSupported ()) {\r
903 RefreshMemoryAttributesFromMtrr ();\r
904 }\r
905\r
906 if (IsPagingAndPageAddressExtensionsEnabled ()) {\r
907 RefreshGcdMemoryAttributesFromPaging ();\r
908 }\r
c1cab54c 909\r
a47463f2 910 mIsFlushingGCD = FALSE;\r
911}\r
912\r
a47463f2 913/**\r
914 Initialize Interrupt Descriptor Table for interrupt handling.\r
915\r
916**/\r
a47463f2 917VOID\r
918InitInterruptDescriptorTable (\r
919 VOID\r
920 )\r
921{\r
e41aad15
JF
922 EFI_STATUS Status;\r
923 EFI_VECTOR_HANDOFF_INFO *VectorInfoList;\r
924 EFI_VECTOR_HANDOFF_INFO *VectorInfo;\r
925\r
926 VectorInfo = NULL;\r
927 Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorInfoList);\r
928 if (Status == EFI_SUCCESS && VectorInfoList != NULL) {\r
929 VectorInfo = VectorInfoList;\r
a47463f2 930 }\r
e41aad15
JF
931 Status = InitializeCpuInterruptHandlers (VectorInfo);\r
932 ASSERT_EFI_ERROR (Status);\r
a47463f2 933}\r
934\r
935\r
32394027 936/**\r
937 Callback function for idle events.\r
d4605c23 938\r
32394027 939 @param Event Event whose notification function is being invoked.\r
940 @param Context The pointer to the notification function's context,\r
941 which is implementation-dependent.\r
942\r
943**/\r
944VOID\r
945EFIAPI\r
946IdleLoopEventCallback (\r
947 IN EFI_EVENT Event,\r
948 IN VOID *Context\r
949 )\r
950{\r
951 CpuSleep ();\r
952}\r
953\r
410590f1
JF
954/**\r
955 Ensure the compatibility of a memory space descriptor with the MMIO aperture.\r
956\r
957 The memory space descriptor can come from the GCD memory space map, or it can\r
958 represent a gap between two neighboring memory space descriptors. In the\r
959 latter case, the GcdMemoryType field is expected to be\r
960 EfiGcdMemoryTypeNonExistent.\r
961\r
962 If the memory space descriptor already has type\r
963 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the\r
964 required capabilities, then no action is taken -- it is by definition\r
965 compatible with the aperture.\r
966\r
967 Otherwise, the intersection of the memory space descriptor is calculated with\r
968 the aperture. If the intersection is the empty set (no overlap), no action is\r
969 taken; the memory space descriptor is compatible with the aperture.\r
970\r
971 Otherwise, the type of the descriptor is investigated again. If the type is\r
972 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with\r
973 such a type), then an attempt is made to add the intersection as MMIO space\r
974 to the GCD memory space map, with the specified capabilities. This ensures\r
975 continuity for the aperture, and the descriptor is deemed compatible with the\r
976 aperture.\r
977\r
978 Otherwise, the memory space descriptor is incompatible with the MMIO\r
979 aperture.\r
980\r
981 @param[in] Base Base address of the aperture.\r
982 @param[in] Length Length of the aperture.\r
983 @param[in] Capabilities Capabilities required by the aperture.\r
984 @param[in] Descriptor The descriptor to ensure compatibility with the\r
985 aperture for.\r
986\r
987 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory\r
988 space map may have been updated, for\r
989 continuity within the aperture.\r
990 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.\r
991 @return Error codes from gDS->AddMemorySpace().\r
992**/\r
993EFI_STATUS\r
994IntersectMemoryDescriptor (\r
995 IN UINT64 Base,\r
996 IN UINT64 Length,\r
997 IN UINT64 Capabilities,\r
998 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
999 )\r
1000{\r
1001 UINT64 IntersectionBase;\r
1002 UINT64 IntersectionEnd;\r
1003 EFI_STATUS Status;\r
1004\r
1005 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo &&\r
1006 (Descriptor->Capabilities & Capabilities) == Capabilities) {\r
1007 return EFI_SUCCESS;\r
1008 }\r
1009\r
1010 IntersectionBase = MAX (Base, Descriptor->BaseAddress);\r
1011 IntersectionEnd = MIN (Base + Length,\r
1012 Descriptor->BaseAddress + Descriptor->Length);\r
1013 if (IntersectionBase >= IntersectionEnd) {\r
1014 //\r
1015 // The descriptor and the aperture don't overlap.\r
1016 //\r
1017 return EFI_SUCCESS;\r
1018 }\r
1019\r
1020 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
1021 Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo,\r
1022 IntersectionBase, IntersectionEnd - IntersectionBase,\r
1023 Capabilities);\r
1024\r
af9bce40 1025 DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
410590f1
JF
1026 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,\r
1027 IntersectionBase, IntersectionEnd, Status));\r
1028 return Status;\r
1029 }\r
1030\r
af9bce40 1031 DEBUG ((DEBUG_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
410590f1
JF
1032 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__,\r
1033 Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,\r
1034 (UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities,\r
1035 Base, Base + Length, Capabilities));\r
1036 return EFI_INVALID_PARAMETER;\r
1037}\r
1038\r
1039/**\r
1040 Add MMIO space to GCD.\r
1041 The routine checks the GCD database and only adds those which are\r
1042 not added in the specified range to GCD.\r
1043\r
1044 @param Base Base address of the MMIO space.\r
1045 @param Length Length of the MMIO space.\r
1046 @param Capabilities Capabilities of the MMIO space.\r
1047\r
1048 @retval EFI_SUCCES The MMIO space was added successfully.\r
1049**/\r
1050EFI_STATUS\r
1051AddMemoryMappedIoSpace (\r
1052 IN UINT64 Base,\r
1053 IN UINT64 Length,\r
1054 IN UINT64 Capabilities\r
1055 )\r
1056{\r
1057 EFI_STATUS Status;\r
1058 UINTN Index;\r
1059 UINTN NumberOfDescriptors;\r
1060 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
1061\r
1062 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
1063 if (EFI_ERROR (Status)) {\r
af9bce40 1064 DEBUG ((DEBUG_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",\r
410590f1
JF
1065 gEfiCallerBaseName, __FUNCTION__, Status));\r
1066 return Status;\r
1067 }\r
1068\r
1069 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
1070 Status = IntersectMemoryDescriptor (Base, Length, Capabilities,\r
1071 &MemorySpaceMap[Index]);\r
1072 if (EFI_ERROR (Status)) {\r
1073 goto FreeMemorySpaceMap;\r
1074 }\r
1075 }\r
1076\r
1077 DEBUG_CODE (\r
1078 //\r
1079 // Make sure there are adjacent descriptors covering [Base, Base + Length).\r
1080 // It is possible that they have not been merged; merging can be prevented\r
1081 // by allocation and different capabilities.\r
1082 //\r
1083 UINT64 CheckBase;\r
1084 EFI_STATUS CheckStatus;\r
1085 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
1086\r
1087 for (CheckBase = Base;\r
1088 CheckBase < Base + Length;\r
1089 CheckBase = Descriptor.BaseAddress + Descriptor.Length) {\r
1090 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);\r
1091 ASSERT_EFI_ERROR (CheckStatus);\r
1092 ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);\r
1093 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);\r
1094 }\r
1095 );\r
1096\r
1097FreeMemorySpaceMap:\r
1098 FreePool (MemorySpaceMap);\r
1099\r
1100 return Status;\r
1101}\r
32394027 1102\r
14f92ded 1103/**\r
7367cc6c 1104 Add and allocate CPU local APIC memory mapped space.\r
14f92ded
JF
1105\r
1106 @param[in]ImageHandle Image handle this driver.\r
1107\r
1108**/\r
1109VOID\r
1110AddLocalApicMemorySpace (\r
1111 IN EFI_HANDLE ImageHandle\r
1112 )\r
1113{\r
1114 EFI_STATUS Status;\r
1115 EFI_PHYSICAL_ADDRESS BaseAddress;\r
1116\r
1117 BaseAddress = (EFI_PHYSICAL_ADDRESS) GetLocalApicBaseAddress();\r
1118 Status = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);\r
1119 ASSERT_EFI_ERROR (Status);\r
1120\r
29c90f14 1121 //\r
7367cc6c 1122 // Try to allocate APIC memory mapped space, does not check return\r
29c90f14
JF
1123 // status because it may be allocated by other driver, or DXE Core if\r
1124 // this range is built into Memory Allocation HOB.\r
1125 //\r
14f92ded
JF
1126 Status = gDS->AllocateMemorySpace (\r
1127 EfiGcdAllocateAddress,\r
1128 EfiGcdMemoryTypeMemoryMappedIo,\r
1129 0,\r
1130 SIZE_4KB,\r
1131 &BaseAddress,\r
1132 ImageHandle,\r
1133 NULL\r
1134 );\r
29c90f14
JF
1135 if (EFI_ERROR (Status)) {\r
1136 DEBUG ((DEBUG_INFO, "%a: %a: AllocateMemorySpace() Status - %r\n",\r
1137 gEfiCallerBaseName, __FUNCTION__, Status));\r
1138 }\r
14f92ded
JF
1139}\r
1140\r
a47463f2 1141/**\r
1142 Initialize the state information for the CPU Architectural Protocol.\r
1143\r
1144 @param ImageHandle Image handle this driver.\r
1145 @param SystemTable Pointer to the System Table.\r
1146\r
1147 @retval EFI_SUCCESS Thread can be successfully created\r
1148 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
1149 @retval EFI_DEVICE_ERROR Cannot create the thread\r
1150\r
1151**/\r
1152EFI_STATUS\r
1153EFIAPI\r
1154InitializeCpu (\r
1155 IN EFI_HANDLE ImageHandle,\r
1156 IN EFI_SYSTEM_TABLE *SystemTable\r
1157 )\r
1158{\r
1159 EFI_STATUS Status;\r
32394027 1160 EFI_EVENT IdleLoopEvent;\r
7367cc6c 1161\r
22292ed3 1162 InitializePageTableLib();\r
a47463f2 1163\r
661cab5d 1164 InitializeFloatingPointUnits ();\r
1165\r
a47463f2 1166 //\r
1167 // Make sure interrupts are disabled\r
1168 //\r
1169 DisableInterrupts ();\r
1170\r
1171 //\r
1172 // Init GDT for DXE\r
1173 //\r
1174 InitGlobalDescriptorTable ();\r
1175\r
1176 //\r
1177 // Setup IDT pointer, IDT and interrupt entry points\r
1178 //\r
1179 InitInterruptDescriptorTable ();\r
1180\r
1181 //\r
1182 // Install CPU Architectural Protocol\r
1183 //\r
1184 Status = gBS->InstallMultipleProtocolInterfaces (\r
1185 &mCpuHandle,\r
1186 &gEfiCpuArchProtocolGuid, &gCpu,\r
1187 NULL\r
1188 );\r
1189 ASSERT_EFI_ERROR (Status);\r
1190\r
1191 //\r
1192 // Refresh GCD memory space map according to MTRR value.\r
1193 //\r
1194 RefreshGcdMemoryAttributes ();\r
1195\r
14f92ded
JF
1196 //\r
1197 // Add and allocate local APIC memory mapped space\r
1198 //\r
1199 AddLocalApicMemorySpace (ImageHandle);\r
1200\r
32394027 1201 //\r
1202 // Setup a callback for idle events\r
1203 //\r
1204 Status = gBS->CreateEventEx (\r
1205 EVT_NOTIFY_SIGNAL,\r
1206 TPL_NOTIFY,\r
1207 IdleLoopEventCallback,\r
1208 NULL,\r
1209 &gIdleLoopEventGuid,\r
1210 &IdleLoopEvent\r
1211 );\r
1212 ASSERT_EFI_ERROR (Status);\r
1213\r
6022e28c
JJ
1214 InitializeMpSupport ();\r
1215\r
a47463f2 1216 return Status;\r
1217}\r
1218\r