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