]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/CpuDxe.c
Refine BaseTscTimerLib.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
CommitLineData
a47463f2 1/** @file\r
2 CPU DXE Module.\r
3\r
f877f300 4 Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>\r
01a1c0fc 5 This program and the accompanying materials\r
a47463f2 6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "CpuDxe.h"\r
16\r
17//\r
18// Global Variables\r
19//\r
20IA32_IDT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };\r
21\r
22EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];\r
23BOOLEAN InterruptState = FALSE;\r
24EFI_HANDLE mCpuHandle = NULL;\r
25BOOLEAN mIsFlushingGCD;\r
a47463f2 26UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
27UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
28\r
29FIXED_MTRR mFixedMtrrTable[] = {\r
30 {\r
31 MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
32 0,\r
33 0x10000\r
34 },\r
35 {\r
36 MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
37 0x80000,\r
38 0x4000\r
39 },\r
40 {\r
41 MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
42 0xA0000,\r
43 0x4000\r
44 },\r
45 {\r
46 MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
47 0xC0000,\r
48 0x1000\r
49 },\r
50 {\r
51 MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
52 0xC8000,\r
53 0x1000\r
54 },\r
55 {\r
56 MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
57 0xD0000,\r
58 0x1000\r
59 },\r
60 {\r
61 MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
62 0xD8000,\r
63 0x1000\r
64 },\r
65 {\r
66 MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
67 0xE0000,\r
68 0x1000\r
69 },\r
70 {\r
71 MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
72 0xE8000,\r
73 0x1000\r
74 },\r
75 {\r
76 MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
77 0xF0000,\r
78 0x1000\r
79 },\r
80 {\r
81 MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
82 0xF8000,\r
83 0x1000\r
84 },\r
85};\r
86\r
87\r
88EFI_CPU_ARCH_PROTOCOL gCpu = {\r
89 CpuFlushCpuDataCache,\r
90 CpuEnableInterrupt,\r
91 CpuDisableInterrupt,\r
92 CpuGetInterruptState,\r
93 CpuInit,\r
94 CpuRegisterInterruptHandler,\r
95 CpuGetTimerValue,\r
96 CpuSetMemoryAttributes,\r
97 1, // NumberOfTimers\r
98 4 // DmaBufferAlignment\r
99};\r
100\r
101//\r
102// Error code flag indicating whether or not an error code will be\r
103// pushed on the stack if an exception occurs.\r
104//\r
105// 1 means an error code will be pushed, otherwise 0\r
106//\r
107// bit 0 - exception 0\r
108// bit 1 - exception 1\r
109// etc.\r
110//\r
111UINT32 mErrorCodeFlag = 0x00027d00;\r
112\r
557b970a 113//\r
114// Local function prototypes\r
115//\r
1e51d595
ED
116\r
117/**\r
118 Set Interrupt Descriptor Table Handler Address.\r
119\r
120 @param Index The Index of the interrupt descriptor table handle.\r
121 @param Handler Handler address.\r
122\r
123**/\r
557b970a 124VOID\r
125SetInterruptDescriptorTableHandlerAddress (\r
126 IN UINTN Index,\r
127 IN VOID *Handler OPTIONAL\r
128 );\r
129\r
a47463f2 130//\r
131// CPU Arch Protocol Functions\r
132//\r
133\r
134\r
135/**\r
136 Common exception handler.\r
137\r
138 @param InterruptType Exception type\r
139 @param SystemContext EFI_SYSTEM_CONTEXT\r
140\r
141**/\r
142VOID\r
143EFIAPI\r
144CommonExceptionHandler (\r
145 IN EFI_EXCEPTION_TYPE InterruptType,\r
146 IN EFI_SYSTEM_CONTEXT SystemContext\r
147 )\r
148{\r
149#if defined (MDE_CPU_IA32)\r
150 DEBUG ((\r
151 EFI_D_ERROR,\r
152 "!!!! IA32 Exception Type - %08x !!!!\n",\r
153 InterruptType\r
154 ));\r
430fbbe0 155 if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
a47463f2 156 DEBUG ((\r
157 EFI_D_ERROR,\r
158 "ExceptionData - %08x\n",\r
159 SystemContext.SystemContextIa32->ExceptionData\r
160 ));\r
161 }\r
162 DEBUG ((\r
163 EFI_D_ERROR,\r
164 "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",\r
165 SystemContext.SystemContextIa32->Cs,\r
166 SystemContext.SystemContextIa32->Eip,\r
167 SystemContext.SystemContextIa32->Eflags,\r
168 SystemContext.SystemContextIa32->Ss\r
169 ));\r
170 DEBUG ((\r
171 EFI_D_ERROR,\r
172 "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",\r
173 SystemContext.SystemContextIa32->Ds,\r
174 SystemContext.SystemContextIa32->Es,\r
175 SystemContext.SystemContextIa32->Fs,\r
176 SystemContext.SystemContextIa32->Gs\r
177 ));\r
178 DEBUG ((\r
179 EFI_D_ERROR,\r
180 "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",\r
181 SystemContext.SystemContextIa32->Eax,\r
182 SystemContext.SystemContextIa32->Ebx,\r
183 SystemContext.SystemContextIa32->Ecx,\r
184 SystemContext.SystemContextIa32->Edx\r
185 ));\r
186 DEBUG ((\r
187 EFI_D_ERROR,\r
188 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",\r
189 SystemContext.SystemContextIa32->Esp,\r
190 SystemContext.SystemContextIa32->Ebp,\r
191 SystemContext.SystemContextIa32->Esi,\r
192 SystemContext.SystemContextIa32->Edi\r
193 ));\r
194 DEBUG ((\r
195 EFI_D_ERROR,\r
196 "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",\r
197 SystemContext.SystemContextIa32->Gdtr[0],\r
198 SystemContext.SystemContextIa32->Gdtr[1],\r
199 SystemContext.SystemContextIa32->Idtr[0],\r
200 SystemContext.SystemContextIa32->Idtr[1]\r
201 ));\r
202 DEBUG ((\r
203 EFI_D_ERROR,\r
204 "LDT - %08x, TR - %08x\n",\r
205 SystemContext.SystemContextIa32->Ldtr,\r
206 SystemContext.SystemContextIa32->Tr\r
207 ));\r
208 DEBUG ((\r
209 EFI_D_ERROR,\r
210 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",\r
211 SystemContext.SystemContextIa32->Cr0,\r
212 SystemContext.SystemContextIa32->Cr2,\r
213 SystemContext.SystemContextIa32->Cr3,\r
214 SystemContext.SystemContextIa32->Cr4\r
215 ));\r
216 DEBUG ((\r
217 EFI_D_ERROR,\r
218 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",\r
219 SystemContext.SystemContextIa32->Dr0,\r
220 SystemContext.SystemContextIa32->Dr1,\r
221 SystemContext.SystemContextIa32->Dr2,\r
222 SystemContext.SystemContextIa32->Dr3\r
223 ));\r
224 DEBUG ((\r
225 EFI_D_ERROR,\r
226 "DR6 - %08x, DR7 - %08x\n",\r
227 SystemContext.SystemContextIa32->Dr6,\r
228 SystemContext.SystemContextIa32->Dr7\r
229 ));\r
230#elif defined (MDE_CPU_X64)\r
231 DEBUG ((\r
232 EFI_D_ERROR,\r
233 "!!!! X64 Exception Type - %016lx !!!!\n",\r
234 (UINT64)InterruptType\r
235 ));\r
430fbbe0 236 if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
a47463f2 237 DEBUG ((\r
238 EFI_D_ERROR,\r
239 "ExceptionData - %016lx\n",\r
240 SystemContext.SystemContextX64->ExceptionData\r
241 ));\r
242 }\r
243 DEBUG ((\r
244 EFI_D_ERROR,\r
245 "RIP - %016lx, RFL - %016lx\n",\r
246 SystemContext.SystemContextX64->Rip,\r
247 SystemContext.SystemContextX64->Rflags\r
248 ));\r
249 DEBUG ((\r
250 EFI_D_ERROR,\r
251 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
252 SystemContext.SystemContextX64->Rax,\r
253 SystemContext.SystemContextX64->Rcx,\r
254 SystemContext.SystemContextX64->Rdx\r
255 ));\r
256 DEBUG ((\r
257 EFI_D_ERROR,\r
258 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
259 SystemContext.SystemContextX64->Rbx,\r
260 SystemContext.SystemContextX64->Rsp,\r
261 SystemContext.SystemContextX64->Rbp\r
262 ));\r
263 DEBUG ((\r
264 EFI_D_ERROR,\r
265 "RSI - %016lx, RDI - %016lx\n",\r
266 SystemContext.SystemContextX64->Rsi,\r
267 SystemContext.SystemContextX64->Rdi\r
268 ));\r
269 DEBUG ((\r
270 EFI_D_ERROR,\r
271 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",\r
272 SystemContext.SystemContextX64->R8,\r
273 SystemContext.SystemContextX64->R9,\r
274 SystemContext.SystemContextX64->R10\r
275 ));\r
276 DEBUG ((\r
277 EFI_D_ERROR,\r
278 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
279 SystemContext.SystemContextX64->R11,\r
280 SystemContext.SystemContextX64->R12,\r
281 SystemContext.SystemContextX64->R13\r
282 ));\r
283 DEBUG ((\r
284 EFI_D_ERROR,\r
285 "R14 - %016lx, R15 - %016lx\n",\r
286 SystemContext.SystemContextX64->R14,\r
287 SystemContext.SystemContextX64->R15\r
288 ));\r
289 DEBUG ((\r
290 EFI_D_ERROR,\r
291 "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",\r
292 SystemContext.SystemContextX64->Cs,\r
293 SystemContext.SystemContextX64->Ds,\r
294 SystemContext.SystemContextX64->Es,\r
295 SystemContext.SystemContextX64->Fs,\r
296 SystemContext.SystemContextX64->Gs,\r
297 SystemContext.SystemContextX64->Ss\r
298 ));\r
299 DEBUG ((\r
300 EFI_D_ERROR,\r
301 "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",\r
302 SystemContext.SystemContextX64->Gdtr[0],\r
303 SystemContext.SystemContextX64->Gdtr[1],\r
304 SystemContext.SystemContextX64->Idtr[0],\r
305 SystemContext.SystemContextX64->Idtr[1]\r
306 ));\r
307 DEBUG ((\r
308 EFI_D_ERROR,\r
309 "LDT - %016lx, TR - %016lx\n",\r
310 SystemContext.SystemContextX64->Ldtr,\r
311 SystemContext.SystemContextX64->Tr\r
312 ));\r
313 DEBUG ((\r
314 EFI_D_ERROR,\r
315 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
316 SystemContext.SystemContextX64->Cr0,\r
317 SystemContext.SystemContextX64->Cr2,\r
318 SystemContext.SystemContextX64->Cr3\r
319 ));\r
320 DEBUG ((\r
321 EFI_D_ERROR,\r
322 "CR4 - %016lx, CR8 - %016lx\n",\r
323 SystemContext.SystemContextX64->Cr4,\r
324 SystemContext.SystemContextX64->Cr8\r
325 ));\r
326 DEBUG ((\r
327 EFI_D_ERROR,\r
328 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
329 SystemContext.SystemContextX64->Dr0,\r
330 SystemContext.SystemContextX64->Dr1,\r
331 SystemContext.SystemContextX64->Dr2\r
332 ));\r
333 DEBUG ((\r
334 EFI_D_ERROR,\r
335 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
336 SystemContext.SystemContextX64->Dr3,\r
337 SystemContext.SystemContextX64->Dr6,\r
338 SystemContext.SystemContextX64->Dr7\r
339 ));\r
340#else\r
341#error CPU type not supported for exception information dump!\r
342#endif\r
343\r
344 //\r
345 // Hang the system with CpuSleep so the processor will enter a lower power\r
346 // state.\r
347 //\r
348 while (TRUE) {\r
349 CpuSleep ();\r
350 };\r
351}\r
352\r
353\r
354/**\r
355 Flush CPU data cache. If the instruction cache is fully coherent\r
356 with all DMA operations then function can just return EFI_SUCCESS.\r
357\r
358 @param This Protocol instance structure\r
359 @param Start Physical address to start flushing from.\r
360 @param Length Number of bytes to flush. Round up to chipset\r
361 granularity.\r
362 @param FlushType Specifies the type of flush operation to perform.\r
363\r
364 @retval EFI_SUCCESS If cache was flushed\r
365 @retval EFI_UNSUPPORTED If flush type is not supported.\r
366 @retval EFI_DEVICE_ERROR If requested range could not be flushed.\r
367\r
368**/\r
369EFI_STATUS\r
370EFIAPI\r
371CpuFlushCpuDataCache (\r
372 IN EFI_CPU_ARCH_PROTOCOL *This,\r
373 IN EFI_PHYSICAL_ADDRESS Start,\r
374 IN UINT64 Length,\r
375 IN EFI_CPU_FLUSH_TYPE FlushType\r
376 )\r
377{\r
378 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
379 AsmWbinvd ();\r
380 return EFI_SUCCESS;\r
381 } else if (FlushType == EfiCpuFlushTypeInvalidate) {\r
382 AsmInvd ();\r
383 return EFI_SUCCESS;\r
384 } else {\r
385 return EFI_UNSUPPORTED;\r
386 }\r
387}\r
388\r
389\r
390/**\r
391 Enables CPU interrupts.\r
392\r
393 @param This Protocol instance structure\r
394\r
395 @retval EFI_SUCCESS If interrupts were enabled in the CPU\r
396 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.\r
397\r
398**/\r
399EFI_STATUS\r
400EFIAPI\r
401CpuEnableInterrupt (\r
402 IN EFI_CPU_ARCH_PROTOCOL *This\r
403 )\r
404{\r
405 EnableInterrupts ();\r
406\r
407 InterruptState = TRUE;\r
408 return EFI_SUCCESS;\r
409}\r
410\r
411\r
412/**\r
413 Disables CPU interrupts.\r
414\r
415 @param This Protocol instance structure\r
416\r
417 @retval EFI_SUCCESS If interrupts were disabled in the CPU.\r
418 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.\r
419\r
420**/\r
421EFI_STATUS\r
422EFIAPI\r
423CpuDisableInterrupt (\r
424 IN EFI_CPU_ARCH_PROTOCOL *This\r
425 )\r
426{\r
427 DisableInterrupts ();\r
428\r
429 InterruptState = FALSE;\r
430 return EFI_SUCCESS;\r
431}\r
432\r
433\r
434/**\r
435 Return the state of interrupts.\r
436\r
437 @param This Protocol instance structure\r
438 @param State Pointer to the CPU's current interrupt state\r
439\r
440 @retval EFI_SUCCESS If interrupts were disabled in the CPU.\r
441 @retval EFI_INVALID_PARAMETER State is NULL.\r
442\r
443**/\r
444EFI_STATUS\r
445EFIAPI\r
446CpuGetInterruptState (\r
447 IN EFI_CPU_ARCH_PROTOCOL *This,\r
448 OUT BOOLEAN *State\r
449 )\r
450{\r
451 if (State == NULL) {\r
452 return EFI_INVALID_PARAMETER;\r
453 }\r
454\r
455 *State = InterruptState;\r
456 return EFI_SUCCESS;\r
457}\r
458\r
459\r
460/**\r
461 Generates an INIT to the CPU.\r
462\r
463 @param This Protocol instance structure\r
464 @param InitType Type of CPU INIT to perform\r
465\r
466 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be\r
467 seen.\r
468 @retval EFI_DEVICE_ERROR If CPU INIT failed.\r
469 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.\r
470\r
471**/\r
472EFI_STATUS\r
473EFIAPI\r
474CpuInit (\r
475 IN EFI_CPU_ARCH_PROTOCOL *This,\r
476 IN EFI_CPU_INIT_TYPE InitType\r
477 )\r
478{\r
479 return EFI_UNSUPPORTED;\r
480}\r
481\r
482\r
483/**\r
484 Registers a function to be called from the CPU interrupt handler.\r
485\r
486 @param This Protocol instance structure\r
487 @param InterruptType Defines which interrupt to hook. IA-32\r
488 valid range is 0x00 through 0xFF\r
489 @param InterruptHandler A pointer to a function of type\r
490 EFI_CPU_INTERRUPT_HANDLER that is called\r
491 when a processor interrupt occurs. A null\r
492 pointer is an error condition.\r
493\r
494 @retval EFI_SUCCESS If handler installed or uninstalled.\r
495 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler\r
496 for InterruptType was previously installed.\r
497 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for\r
498 InterruptType was not previously installed.\r
499 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType\r
500 is not supported.\r
501\r
502**/\r
503EFI_STATUS\r
504EFIAPI\r
505CpuRegisterInterruptHandler (\r
506 IN EFI_CPU_ARCH_PROTOCOL *This,\r
507 IN EFI_EXCEPTION_TYPE InterruptType,\r
508 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
509 )\r
510{\r
511 if (InterruptType < 0 || InterruptType > 0xff) {\r
512 return EFI_UNSUPPORTED;\r
513 }\r
514\r
515 if (InterruptHandler == NULL && ExternalVectorTable[InterruptType] == NULL) {\r
516 return EFI_INVALID_PARAMETER;\r
517 }\r
518\r
519 if (InterruptHandler != NULL && ExternalVectorTable[InterruptType] != NULL) {\r
520 return EFI_ALREADY_STARTED;\r
521 }\r
522\r
c52acd89 523 SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType, NULL);\r
a47463f2 524 ExternalVectorTable[InterruptType] = InterruptHandler;\r
525 return EFI_SUCCESS;\r
526}\r
527\r
528\r
529/**\r
530 Returns a timer value from one of the CPU's internal timers. There is no\r
531 inherent time interval between ticks but is a function of the CPU frequency.\r
532\r
533 @param This - Protocol instance structure.\r
534 @param TimerIndex - Specifies which CPU timer is requested.\r
535 @param TimerValue - Pointer to the returned timer value.\r
536 @param TimerPeriod - A pointer to the amount of time that passes\r
537 in femtoseconds (10-15) for each increment\r
538 of TimerValue. If TimerValue does not\r
539 increment at a predictable rate, then 0 is\r
540 returned. The amount of time that has\r
541 passed between two calls to GetTimerValue()\r
542 can be calculated with the formula\r
543 (TimerValue2 - TimerValue1) * TimerPeriod.\r
544 This parameter is optional and may be NULL.\r
545\r
546 @retval EFI_SUCCESS - If the CPU timer count was returned.\r
547 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.\r
548 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.\r
549 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.\r
550\r
551**/\r
552EFI_STATUS\r
553EFIAPI\r
554CpuGetTimerValue (\r
555 IN EFI_CPU_ARCH_PROTOCOL *This,\r
556 IN UINT32 TimerIndex,\r
557 OUT UINT64 *TimerValue,\r
558 OUT UINT64 *TimerPeriod OPTIONAL\r
559 )\r
560{\r
561 if (TimerValue == NULL) {\r
562 return EFI_INVALID_PARAMETER;\r
563 }\r
564\r
565 if (TimerIndex != 0) {\r
566 return EFI_INVALID_PARAMETER;\r
567 }\r
568\r
569 *TimerValue = AsmReadTsc ();\r
570\r
571 if (TimerPeriod != NULL) {\r
572 //\r
573 // BugBug: Hard coded. Don't know how to do this generically\r
574 //\r
575 *TimerPeriod = 1000000000;\r
576 }\r
577\r
578 return EFI_SUCCESS;\r
579}\r
580\r
581\r
582/**\r
4ec21e8b 583 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.\r
584\r
585 This function modifies the attributes for the memory region specified by BaseAddress and\r
586 Length from their current attributes to the attributes specified by Attributes.\r
587\r
588 @param This The EFI_CPU_ARCH_PROTOCOL instance.\r
589 @param BaseAddress The physical address that is the start address of a memory region.\r
590 @param Length The size in bytes of the memory region.\r
591 @param Attributes The bit mask of attributes to set for the memory region.\r
592\r
593 @retval EFI_SUCCESS The attributes were set for the memory region.\r
594 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
595 BaseAddress and Length cannot be modified.\r
596 @retval EFI_INVALID_PARAMETER Length is zero.\r
597 Attributes specified an illegal combination of attributes that\r
598 cannot be set together.\r
599 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
600 the memory resource range.\r
601 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
602 resource range specified by BaseAddress and Length.\r
603 The bit mask of attributes is not support for the memory resource\r
604 range specified by BaseAddress and Length.\r
a47463f2 605\r
606**/\r
607EFI_STATUS\r
608EFIAPI\r
609CpuSetMemoryAttributes (\r
610 IN EFI_CPU_ARCH_PROTOCOL *This,\r
611 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
612 IN UINT64 Length,\r
613 IN UINT64 Attributes\r
614 )\r
615{\r
616 RETURN_STATUS Status;\r
617 MTRR_MEMORY_CACHE_TYPE CacheType;\r
618\r
947a573a 619 if (!IsMtrrSupported ()) {\r
620 return EFI_UNSUPPORTED;\r
621 }\r
622\r
a47463f2 623 //\r
624 // If this function is called because GCD SetMemorySpaceAttributes () is called\r
625 // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory\r
626 // map with MTRR values. So there is no need to modify MTRRs, just return immediately\r
627 // to avoid unnecessary computing.\r
628 //\r
629 if (mIsFlushingGCD) {\r
630 DEBUG((EFI_D_ERROR, " Flushing GCD\n"));\r
631 return EFI_SUCCESS;\r
632 }\r
633\r
634 switch (Attributes) {\r
635 case EFI_MEMORY_UC:\r
636 CacheType = CacheUncacheable;\r
637 break;\r
638\r
639 case EFI_MEMORY_WC:\r
640 CacheType = CacheWriteCombining;\r
641 break;\r
642\r
643 case EFI_MEMORY_WT:\r
644 CacheType = CacheWriteThrough;\r
645 break;\r
646\r
647 case EFI_MEMORY_WP:\r
648 CacheType = CacheWriteProtected;\r
649 break;\r
650\r
651 case EFI_MEMORY_WB:\r
652 CacheType = CacheWriteBack;\r
653 break;\r
654\r
4ec21e8b 655 case EFI_MEMORY_UCE:\r
656 case EFI_MEMORY_RP:\r
657 case EFI_MEMORY_XP:\r
658 case EFI_MEMORY_RUNTIME:\r
a47463f2 659 return EFI_UNSUPPORTED;\r
4ec21e8b 660\r
661 default:\r
662 return EFI_INVALID_PARAMETER;\r
a47463f2 663 }\r
664 //\r
665 // call MTRR libary function\r
666 //\r
f877f300 667 Status = MtrrSetMemoryAttribute (\r
a47463f2 668 BaseAddress,\r
669 Length,\r
670 CacheType\r
671 );\r
672\r
a47463f2 673 return (EFI_STATUS) Status;\r
674}\r
675\r
676/**\r
677 Initializes the valid bits mask and valid address mask for MTRRs.\r
678\r
679 This function initializes the valid bits mask and valid address mask for MTRRs.\r
680\r
681**/\r
682VOID\r
683InitializeMtrrMask (\r
684 VOID\r
685 )\r
686{\r
687 UINT32 RegEax;\r
688 UINT8 PhysicalAddressBits;\r
689\r
690 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
691\r
692 if (RegEax >= 0x80000008) {\r
693 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
694\r
695 PhysicalAddressBits = (UINT8) RegEax;\r
696\r
697 mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
698 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
699 } else {\r
700 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
701 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
702 }\r
703}\r
704\r
705/**\r
430fbbe0 706 Gets GCD Mem Space type from MTRR Type.\r
a47463f2 707\r
430fbbe0 708 This function gets GCD Mem Space type from MTRR Type.\r
a47463f2 709\r
430fbbe0 710 @param MtrrAttributes MTRR memory type\r
a47463f2 711\r
712 @return GCD Mem Space type\r
713\r
714**/\r
715UINT64\r
716GetMemorySpaceAttributeFromMtrrType (\r
91ec7824 717 IN MTRR_MEMORY_CACHE_TYPE MtrrAttributes\r
a47463f2 718 )\r
719{\r
720 switch (MtrrAttributes) {\r
721 case MTRR_CACHE_UNCACHEABLE:\r
722 return EFI_MEMORY_UC;\r
723 case MTRR_CACHE_WRITE_COMBINING:\r
724 return EFI_MEMORY_WC;\r
725 case MTRR_CACHE_WRITE_THROUGH:\r
726 return EFI_MEMORY_WT;\r
727 case MTRR_CACHE_WRITE_PROTECTED:\r
728 return EFI_MEMORY_WP;\r
729 case MTRR_CACHE_WRITE_BACK:\r
730 return EFI_MEMORY_WB;\r
731 default:\r
732 return 0;\r
733 }\r
734}\r
735\r
736/**\r
737 Searches memory descriptors covered by given memory range.\r
738\r
739 This function searches into the Gcd Memory Space for descriptors\r
740 (from StartIndex to EndIndex) that contains the memory range\r
741 specified by BaseAddress and Length.\r
742\r
743 @param MemorySpaceMap Gcd Memory Space Map as array.\r
744 @param NumberOfDescriptors Number of descriptors in map.\r
745 @param BaseAddress BaseAddress for the requested range.\r
746 @param Length Length for the requested range.\r
747 @param StartIndex Start index into the Gcd Memory Space Map.\r
748 @param EndIndex End index into the Gcd Memory Space Map.\r
749\r
750 @retval EFI_SUCCESS Search successfully.\r
751 @retval EFI_NOT_FOUND The requested descriptors does not exist.\r
752\r
753**/\r
754EFI_STATUS\r
755SearchGcdMemorySpaces (\r
756 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
757 IN UINTN NumberOfDescriptors,\r
758 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
759 IN UINT64 Length,\r
760 OUT UINTN *StartIndex,\r
761 OUT UINTN *EndIndex\r
762 )\r
763{\r
764 UINTN Index;\r
765\r
766 *StartIndex = 0;\r
767 *EndIndex = 0;\r
768 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
769 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
770 BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
771 *StartIndex = Index;\r
772 }\r
773 if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
774 BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
775 *EndIndex = Index;\r
776 return EFI_SUCCESS;\r
777 }\r
778 }\r
779 return EFI_NOT_FOUND;\r
780}\r
781\r
782/**\r
783 Sets the attributes for a specified range in Gcd Memory Space Map.\r
784\r
785 This function sets the attributes for a specified range in\r
786 Gcd Memory Space Map.\r
787\r
788 @param MemorySpaceMap Gcd Memory Space Map as array\r
789 @param NumberOfDescriptors Number of descriptors in map\r
790 @param BaseAddress BaseAddress for the range\r
791 @param Length Length for the range\r
792 @param Attributes Attributes to set\r
793\r
794 @retval EFI_SUCCESS Memory attributes set successfully\r
795 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space\r
796\r
797**/\r
798EFI_STATUS\r
799SetGcdMemorySpaceAttributes (\r
800 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
801 IN UINTN NumberOfDescriptors,\r
802 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
803 IN UINT64 Length,\r
804 IN UINT64 Attributes\r
805 )\r
806{\r
807 EFI_STATUS Status;\r
808 UINTN Index;\r
809 UINTN StartIndex;\r
810 UINTN EndIndex;\r
811 EFI_PHYSICAL_ADDRESS RegionStart;\r
812 UINT64 RegionLength;\r
813\r
814 //\r
815 // Get all memory descriptors covered by the memory range\r
816 //\r
817 Status = SearchGcdMemorySpaces (\r
818 MemorySpaceMap,\r
819 NumberOfDescriptors,\r
820 BaseAddress,\r
821 Length,\r
822 &StartIndex,\r
823 &EndIndex\r
824 );\r
825 if (EFI_ERROR (Status)) {\r
826 return Status;\r
827 }\r
828\r
829 //\r
830 // Go through all related descriptors and set attributes accordingly\r
831 //\r
832 for (Index = StartIndex; Index <= EndIndex; Index++) {\r
833 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
834 continue;\r
835 }\r
836 //\r
837 // Calculate the start and end address of the overlapping range\r
838 //\r
839 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
840 RegionStart = BaseAddress;\r
841 } else {\r
842 RegionStart = MemorySpaceMap[Index].BaseAddress;\r
843 }\r
844 if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
845 RegionLength = BaseAddress + Length - RegionStart;\r
846 } else {\r
847 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
848 }\r
849 //\r
850 // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
851 //\r
852 gDS->SetMemorySpaceAttributes (\r
853 RegionStart,\r
854 RegionLength,\r
855 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
856 );\r
857 }\r
858\r
859 return EFI_SUCCESS;\r
860}\r
861\r
862\r
863/**\r
864 Refreshes the GCD Memory Space attributes according to MTRRs.\r
865\r
866 This function refreshes the GCD Memory Space attributes according to MTRRs.\r
867\r
868**/\r
869VOID\r
870RefreshGcdMemoryAttributes (\r
871 VOID\r
872 )\r
873{\r
874 EFI_STATUS Status;\r
875 UINTN Index;\r
876 UINTN SubIndex;\r
877 UINT64 RegValue;\r
878 EFI_PHYSICAL_ADDRESS BaseAddress;\r
879 UINT64 Length;\r
880 UINT64 Attributes;\r
881 UINT64 CurrentAttributes;\r
91ec7824 882 MTRR_MEMORY_CACHE_TYPE MtrrType;\r
a47463f2 883 UINTN NumberOfDescriptors;\r
884 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
885 UINT64 DefaultAttributes;\r
6640eb36 886 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
a47463f2 887 MTRR_FIXED_SETTINGS MtrrFixedSettings;\r
3b9be416 888 UINT32 FirmwareVariableMtrrCount;\r
91ec7824 889 MTRR_MEMORY_CACHE_TYPE DefaultMemoryType;\r
3b9be416 890\r
947a573a 891 if (!IsMtrrSupported ()) {\r
892 return;\r
893 }\r
894\r
3b9be416 895 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
5bdfa4e5 896 ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
a47463f2 897\r
91ec7824 898 mIsFlushingGCD = TRUE;\r
a47463f2 899 MemorySpaceMap = NULL;\r
900\r
901 //\r
902 // Initialize the valid bits mask and valid address mask for MTRRs\r
903 //\r
904 InitializeMtrrMask ();\r
905\r
906 //\r
907 // Get the memory attribute of variable MTRRs\r
908 //\r
909 MtrrGetMemoryAttributeInVariableMtrr (\r
910 mValidMtrrBitsMask,\r
911 mValidMtrrAddressMask,\r
912 VariableMtrr\r
913 );\r
914\r
915 //\r
916 // Get the memory space map from GCD\r
917 //\r
918 Status = gDS->GetMemorySpaceMap (\r
919 &NumberOfDescriptors,\r
920 &MemorySpaceMap\r
921 );\r
922 ASSERT_EFI_ERROR (Status);\r
923\r
91ec7824 924 DefaultMemoryType = MtrrGetDefaultMemoryType ();\r
925 DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);\r
a47463f2 926\r
927 //\r
928 // Set default attributes to all spaces.\r
929 //\r
930 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
931 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
932 continue;\r
933 }\r
934 gDS->SetMemorySpaceAttributes (\r
935 MemorySpaceMap[Index].BaseAddress,\r
936 MemorySpaceMap[Index].Length,\r
937 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |\r
938 (MemorySpaceMap[Index].Capabilities & DefaultAttributes)\r
939 );\r
940 }\r
941\r
942 //\r
943 // Go for variable MTRRs with WB attribute\r
944 //\r
3b9be416 945 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
a47463f2 946 if (VariableMtrr[Index].Valid &&\r
947 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
948 SetGcdMemorySpaceAttributes (\r
949 MemorySpaceMap,\r
950 NumberOfDescriptors,\r
951 VariableMtrr[Index].BaseAddress,\r
952 VariableMtrr[Index].Length,\r
953 EFI_MEMORY_WB\r
954 );\r
955 }\r
956 }\r
91ec7824 957\r
a47463f2 958 //\r
91ec7824 959 // Go for variable MTRRs with the attribute except for WB and UC attributes\r
a47463f2 960 //\r
3b9be416 961 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
91ec7824 962 if (VariableMtrr[Index].Valid && \r
963 VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&\r
964 VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {\r
965 Attributes = GetMemorySpaceAttributeFromMtrrType ((MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type);\r
a47463f2 966 SetGcdMemorySpaceAttributes (\r
967 MemorySpaceMap,\r
968 NumberOfDescriptors,\r
969 VariableMtrr[Index].BaseAddress,\r
970 VariableMtrr[Index].Length,\r
971 Attributes\r
972 );\r
973 }\r
974 }\r
975\r
91ec7824 976 //\r
977 // Go for variable MTRRs with UC attribute\r
978 //\r
979 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
980 if (VariableMtrr[Index].Valid &&\r
981 VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {\r
982 SetGcdMemorySpaceAttributes (\r
983 MemorySpaceMap,\r
984 NumberOfDescriptors,\r
985 VariableMtrr[Index].BaseAddress,\r
986 VariableMtrr[Index].Length,\r
987 EFI_MEMORY_UC\r
988 );\r
989 }\r
990 }\r
991\r
a47463f2 992 //\r
993 // Go for fixed MTRRs\r
994 //\r
995 Attributes = 0;\r
996 BaseAddress = 0;\r
997 Length = 0;\r
998 MtrrGetFixedMtrr (&MtrrFixedSettings);\r
999 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
1000 RegValue = MtrrFixedSettings.Mtrr[Index];\r
1001 //\r
1002 // Check for continuous fixed MTRR sections\r
1003 //\r
1004 for (SubIndex = 0; SubIndex < 8; SubIndex++) {\r
91ec7824 1005 MtrrType = (MTRR_MEMORY_CACHE_TYPE) RShiftU64 (RegValue, SubIndex * 8);\r
a47463f2 1006 CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);\r
1007 if (Length == 0) {\r
1008 //\r
1009 // A new MTRR attribute begins\r
1010 //\r
1011 Attributes = CurrentAttributes;\r
1012 } else {\r
1013 //\r
1014 // If fixed MTRR attribute changed, then set memory attribute for previous atrribute\r
1015 //\r
1016 if (CurrentAttributes != Attributes) {\r
1017 SetGcdMemorySpaceAttributes (\r
1018 MemorySpaceMap,\r
1019 NumberOfDescriptors,\r
1020 BaseAddress,\r
1021 Length,\r
1022 Attributes\r
1023 );\r
1024 BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;\r
1025 Length = 0;\r
1026 Attributes = CurrentAttributes;\r
1027 }\r
1028 }\r
1029 Length += mFixedMtrrTable[Index].Length;\r
1030 }\r
1031 }\r
1032 //\r
1033 // Handle the last fixed MTRR region\r
1034 //\r
1035 SetGcdMemorySpaceAttributes (\r
1036 MemorySpaceMap,\r
1037 NumberOfDescriptors,\r
1038 BaseAddress,\r
1039 Length,\r
1040 Attributes\r
1041 );\r
1042\r
1043 //\r
1044 // Free memory space map allocated by GCD service GetMemorySpaceMap ()\r
1045 //\r
1046 if (MemorySpaceMap != NULL) {\r
1047 FreePool (MemorySpaceMap);\r
1048 }\r
1049\r
1050 mIsFlushingGCD = FALSE;\r
1051}\r
1052\r
1e51d595
ED
1053/**\r
1054 Set Interrupt Descriptor Table Handler Address.\r
1055\r
1056 @param Index The Index of the interrupt descriptor table handle.\r
1057 @param Handler Handler address.\r
a47463f2 1058\r
1e51d595 1059**/\r
557b970a 1060VOID\r
1061SetInterruptDescriptorTableHandlerAddress (\r
1062 IN UINTN Index,\r
1063 IN VOID *Handler OPTIONAL\r
1064 )\r
1065{\r
1066 UINTN UintnHandler;\r
1067\r
1068 if (Handler != NULL) {\r
1069 UintnHandler = (UINTN) Handler;\r
1070 } else {\r
1071 UintnHandler = ((UINTN) AsmIdtVector00) + (8 * Index);\r
1072 }\r
1073\r
1074 gIdtTable[Index].Bits.OffsetLow = (UINT16)UintnHandler;\r
1075 gIdtTable[Index].Bits.Reserved_0 = 0;\r
1076 gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
1077 gIdtTable[Index].Bits.OffsetHigh = (UINT16)(UintnHandler >> 16);\r
1078#if defined (MDE_CPU_X64)\r
1079 gIdtTable[Index].Bits.OffsetUpper = (UINT32)(UintnHandler >> 32);\r
1080 gIdtTable[Index].Bits.Reserved_1 = 0;\r
1081#endif\r
1082}\r
1083\r
1084\r
a47463f2 1085/**\r
1086 Initialize Interrupt Descriptor Table for interrupt handling.\r
1087\r
1088**/\r
a47463f2 1089VOID\r
1090InitInterruptDescriptorTable (\r
1091 VOID\r
1092 )\r
1093{\r
557b970a 1094 EFI_STATUS Status;\r
1095 IA32_DESCRIPTOR OldIdtPtr;\r
1096 IA32_IDT_GATE_DESCRIPTOR *OldIdt;\r
1097 UINTN OldIdtSize;\r
1098 VOID *IdtPtrAlignmentBuffer;\r
1099 IA32_DESCRIPTOR *IdtPtr;\r
1100 UINTN Index;\r
1101 UINT16 CurrentCs;\r
1102 VOID *IntHandler;\r
a47463f2 1103\r
1104 SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);\r
1105\r
1106 //\r
557b970a 1107 // Get original IDT address and size.\r
a47463f2 1108 //\r
557b970a 1109 AsmReadIdtr ((IA32_DESCRIPTOR *) &OldIdtPtr);\r
1110\r
1111 if ((OldIdtPtr.Base != 0) && ((OldIdtPtr.Limit & 7) == 7)) {\r
1112 OldIdt = (IA32_IDT_GATE_DESCRIPTOR*) OldIdtPtr.Base;\r
304a39b7 1113 OldIdtSize = (OldIdtPtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
557b970a 1114 } else {\r
1115 OldIdt = NULL;\r
1116 OldIdtSize = 0;\r
a47463f2 1117 }\r
1118\r
0564ae5e 1119 //\r
557b970a 1120 // Intialize IDT\r
0564ae5e 1121 //\r
557b970a 1122 CurrentCs = AsmReadCs();\r
1123 for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {\r
1124 //\r
1125 // If the old IDT had a handler for this interrupt, then\r
1126 // preserve it.\r
1127 //\r
1128 if (Index < OldIdtSize) {\r
1129 IntHandler = \r
1130 (VOID*) (\r
1131 OldIdt[Index].Bits.OffsetLow +\r
1132 (OldIdt[Index].Bits.OffsetHigh << 16)\r
1133#if defined (MDE_CPU_X64)\r
1134 + (((UINTN) OldIdt[Index].Bits.OffsetUpper) << 32)\r
1135#endif\r
1136 );\r
1137 } else {\r
1138 IntHandler = NULL;\r
1139 }\r
0564ae5e 1140\r
557b970a 1141 gIdtTable[Index].Bits.Selector = CurrentCs;\r
1142 gIdtTable[Index].Bits.Reserved_0 = 0;\r
1143 gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
1144 SetInterruptDescriptorTableHandlerAddress (Index, IntHandler);\r
0564ae5e 1145 }\r
557b970a 1146\r
a47463f2 1147 //\r
1148 // Load IDT Pointer\r
1149 //\r
1150 IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);\r
1151 IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);\r
1152 IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));\r
5b7e61a0 1153 IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1);\r
ea99e00d 1154\r
a47463f2 1155 AsmWriteIdtr (IdtPtr);\r
ea99e00d 1156\r
a47463f2 1157 FreePool (IdtPtrAlignmentBuffer);\r
1158\r
1159 //\r
1160 // Initialize Exception Handlers\r
1161 //\r
62ba7e17 1162 for (Index = OldIdtSize; Index < 32; Index++) {\r
a47463f2 1163 Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);\r
1164 ASSERT_EFI_ERROR (Status);\r
1165 }\r
1166\r
1167 //\r
1168 // Set the pointer to the array of C based exception handling routines.\r
1169 //\r
1170 InitializeExternalVectorTablePtr (ExternalVectorTable);\r
1171\r
1172}\r
1173\r
1174\r
32394027 1175/**\r
1176 Callback function for idle events.\r
1177 \r
1178 @param Event Event whose notification function is being invoked.\r
1179 @param Context The pointer to the notification function's context,\r
1180 which is implementation-dependent.\r
1181\r
1182**/\r
1183VOID\r
1184EFIAPI\r
1185IdleLoopEventCallback (\r
1186 IN EFI_EVENT Event,\r
1187 IN VOID *Context\r
1188 )\r
1189{\r
1190 CpuSleep ();\r
1191}\r
1192\r
1193\r
a47463f2 1194/**\r
1195 Initialize the state information for the CPU Architectural Protocol.\r
1196\r
1197 @param ImageHandle Image handle this driver.\r
1198 @param SystemTable Pointer to the System Table.\r
1199\r
1200 @retval EFI_SUCCESS Thread can be successfully created\r
1201 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
1202 @retval EFI_DEVICE_ERROR Cannot create the thread\r
1203\r
1204**/\r
1205EFI_STATUS\r
1206EFIAPI\r
1207InitializeCpu (\r
1208 IN EFI_HANDLE ImageHandle,\r
1209 IN EFI_SYSTEM_TABLE *SystemTable\r
1210 )\r
1211{\r
1212 EFI_STATUS Status;\r
32394027 1213 EFI_EVENT IdleLoopEvent;\r
a47463f2 1214\r
1215 //\r
1216 // Make sure interrupts are disabled\r
1217 //\r
1218 DisableInterrupts ();\r
1219\r
1220 //\r
1221 // Init GDT for DXE\r
1222 //\r
1223 InitGlobalDescriptorTable ();\r
1224\r
1225 //\r
1226 // Setup IDT pointer, IDT and interrupt entry points\r
1227 //\r
1228 InitInterruptDescriptorTable ();\r
1229\r
1230 //\r
1231 // Install CPU Architectural Protocol\r
1232 //\r
1233 Status = gBS->InstallMultipleProtocolInterfaces (\r
1234 &mCpuHandle,\r
1235 &gEfiCpuArchProtocolGuid, &gCpu,\r
1236 NULL\r
1237 );\r
1238 ASSERT_EFI_ERROR (Status);\r
1239\r
1240 //\r
1241 // Refresh GCD memory space map according to MTRR value.\r
1242 //\r
1243 RefreshGcdMemoryAttributes ();\r
1244\r
32394027 1245 //\r
1246 // Setup a callback for idle events\r
1247 //\r
1248 Status = gBS->CreateEventEx (\r
1249 EVT_NOTIFY_SIGNAL,\r
1250 TPL_NOTIFY,\r
1251 IdleLoopEventCallback,\r
1252 NULL,\r
1253 &gIdleLoopEventGuid,\r
1254 &IdleLoopEvent\r
1255 );\r
1256 ASSERT_EFI_ERROR (Status);\r
1257\r
a47463f2 1258 return Status;\r
1259}\r
1260\r