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