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