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