Update the copyright notice format
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
CommitLineData
a47463f2 1/** @file\r
2 CPU DXE Module.\r
3\r
01a1c0fc
HT
4 Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
26UINT8 mDefaultMemoryType = MTRR_CACHE_WRITE_BACK;\r
27UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
28UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
29\r
30FIXED_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
89EFI_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
112UINT32 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
126VOID\r
127EFIAPI\r
128CommonExceptionHandler (\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
353EFI_STATUS\r
354EFIAPI\r
355CpuFlushCpuDataCache (\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
383EFI_STATUS\r
384EFIAPI\r
385CpuEnableInterrupt (\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
405EFI_STATUS\r
406EFIAPI\r
407CpuDisableInterrupt (\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
428EFI_STATUS\r
429EFIAPI\r
430CpuGetInterruptState (\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
456EFI_STATUS\r
457EFIAPI\r
458CpuInit (\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
487EFI_STATUS\r
488EFIAPI\r
489CpuRegisterInterruptHandler (\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
535EFI_STATUS\r
536EFIAPI\r
537CpuGetTimerValue (\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
581EFI_STATUS\r
582EFIAPI\r
583CpuSetMemoryAttributes (\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
655VOID\r
656InitializeMtrrMask (\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
688UINT64\r
689GetMemorySpaceAttributeFromMtrrType (\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
727EFI_STATUS\r
728SearchGcdMemorySpaces (\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
771EFI_STATUS\r
772SetGcdMemorySpaceAttributes (\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
842VOID\r
843RefreshGcdMemoryAttributes (\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
1012STATIC\r
1013VOID\r
1014InitInterruptDescriptorTable (\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
1081EFI_STATUS\r
1082EFIAPI\r
1083InitializeCpu (\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