]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
Reviewed the code comments in the Include/Protocol directory for typos, grammar issue...
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
CommitLineData
e50466da 1/** @file\r
2 MTRR setting library\r
3\r
4 Copyright (c) 2008 - 2009, Intel Corporation\r
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 <Base.h>\r
16\r
17#include <Library/MtrrLib.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/CpuLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/DebugLib.h>\r
22\r
23//\r
24// This table defines the offset, base and length of the fixed MTRRs\r
25//\r
26STATIC\r
27FIXED_MTRR MtrrLibFixedMtrrTable[] = {\r
28 {\r
29 MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
30 0,\r
31 SIZE_64KB\r
32 },\r
33 {\r
34 MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
35 0x80000,\r
36 SIZE_16KB\r
37 },\r
38 {\r
39 MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
40 0xA0000,\r
41 SIZE_16KB\r
42 },\r
43 {\r
44 MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
45 0xC0000,\r
46 SIZE_4KB\r
47 },\r
48 {\r
49 MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
50 0xC8000,\r
51 SIZE_4KB\r
52 },\r
53 {\r
54 MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
55 0xD0000,\r
56 SIZE_4KB\r
57 },\r
58 {\r
59 MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
60 0xD8000,\r
61 SIZE_4KB\r
62 },\r
63 {\r
64 MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
65 0xE0000,\r
66 SIZE_4KB\r
67 },\r
68 {\r
69 MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
70 0xE8000,\r
71 SIZE_4KB\r
72 },\r
73 {\r
74 MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
75 0xF0000,\r
76 SIZE_4KB\r
77 },\r
78 {\r
79 MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
80 0xF8000,\r
81 SIZE_4KB\r
82 },\r
83};\r
84\r
85\r
86/**\r
87 Returns the default MTRR cache type for the system.\r
88\r
89 @return MTRR default type\r
90\r
91**/\r
92UINT64\r
93GetMtrrDefaultMemoryType (\r
94 VOID\r
95)\r
96{\r
97 return (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0xff);\r
98}\r
99\r
100\r
101/**\r
102 Preparation before programming MTRR.\r
103\r
104 This function will do some preparation for programming MTRRs:\r
105 disable cache, invalid cache and disable MTRR caching functionality\r
106\r
107 @return CR4 value before changing.\r
108\r
109**/\r
110UINTN\r
111PreMtrrChange (\r
112 VOID\r
113 )\r
114{\r
115 UINTN Value;\r
116\r
117 //\r
118 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)\r
119 //\r
120 Value = AsmReadCr0 ();\r
121 Value = (UINTN) BitFieldWrite64 (Value, 30, 30, 1);\r
122 Value = (UINTN) BitFieldWrite64 (Value, 29, 29, 0);\r
123 AsmWriteCr0 (Value);\r
124 //\r
125 // Flush cache\r
126 //\r
127 AsmWbinvd ();\r
128 //\r
129 // Clear PGE flag Bit 7\r
130 //\r
131 Value = AsmReadCr4 ();\r
132 AsmWriteCr4 ((UINTN) BitFieldWrite64 (Value, 7, 7, 0));\r
133 //\r
134 // Flush all TLBs\r
135 //\r
136 CpuFlushTlb ();\r
137 //\r
138 // Disable Mtrrs\r
139 //\r
140 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);\r
141\r
142 return Value;\r
143}\r
144\r
145\r
146/**\r
147 Cleaning up after programming MTRRs.\r
148\r
149 This function will do some clean up after programming MTRRs:\r
150 enable MTRR caching functionality, and enable cache\r
151\r
152 @param Cr4 CR4 value to restore\r
153\r
154**/\r
155VOID\r
156PostMtrrChange (\r
157 UINTN Cr4\r
158 )\r
159{\r
160 UINTN Value;\r
161\r
162 //\r
163 // Enable Cache MTRR\r
164 //\r
165 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);\r
166\r
167 //\r
168 // Flush all TLBs and cache the second time\r
169 //\r
170 AsmWbinvd ();\r
171 CpuFlushTlb ();\r
172\r
173 //\r
174 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)\r
175 //\r
176 Value = AsmReadCr0 ();\r
177 Value = (UINTN) BitFieldWrite64 (Value, 30, 30, 0);\r
178 Value = (UINTN) BitFieldWrite64 (Value, 29, 29, 0);\r
179 AsmWriteCr0 (Value);\r
180\r
181 AsmWriteCr4 (Cr4);\r
182\r
183 return ;\r
184}\r
185\r
186\r
187/**\r
188 Programs fixed MTRRs registers.\r
189\r
190 @param MemoryCacheType The memory type to set.\r
191 @param Base The base address of memory range.\r
192 @param Length The length of memory range.\r
193\r
194 @retval RETURN_SUCCESS The cache type was updated successfully\r
195 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid\r
196 for the fixed MTRRs.\r
197\r
198**/\r
199RETURN_STATUS\r
200ProgramFixedMtrr (\r
201 IN UINT64 MemoryCacheType,\r
202 IN OUT UINT64 *Base,\r
203 IN OUT UINT64 *Length\r
204 )\r
205{\r
206 UINT32 MsrNum;\r
207 UINT32 ByteShift;\r
208 UINT64 TempQword;\r
209 UINT64 OrMask;\r
210 UINT64 ClearMask;\r
211\r
212 TempQword = 0;\r
213 OrMask = 0;\r
214 ClearMask = 0;\r
215\r
216 for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
217 if ((*Base >= MtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
218 (*Base <\r
219 (\r
220 MtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
221 (8 * MtrrLibFixedMtrrTable[MsrNum].Length)\r
222 )\r
223 )\r
224 ) {\r
225 break;\r
226 }\r
227 }\r
228\r
229 if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {\r
230 return RETURN_UNSUPPORTED;\r
231 }\r
232\r
233 //\r
234 // We found the fixed MTRR to be programmed\r
235 //\r
236 for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
237 if (*Base ==\r
238 (\r
239 MtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
240 (ByteShift * MtrrLibFixedMtrrTable[MsrNum].Length)\r
241 )\r
242 ) {\r
243 break;\r
244 }\r
245 }\r
246\r
247 if (ByteShift == 8) {\r
248 return RETURN_UNSUPPORTED;\r
249 }\r
250\r
251 for (\r
252 ;\r
253 ((ByteShift < 8) && (*Length >= MtrrLibFixedMtrrTable[MsrNum].Length));\r
254 ByteShift++\r
255 ) {\r
256 OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));\r
257 ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));\r
258 *Length -= MtrrLibFixedMtrrTable[MsrNum].Length;\r
259 *Base += MtrrLibFixedMtrrTable[MsrNum].Length;\r
260 }\r
261\r
262 if (ByteShift < 8 && (*Length != 0)) {\r
263 return RETURN_UNSUPPORTED;\r
264 }\r
265\r
266 TempQword =\r
267 (AsmReadMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;\r
268 AsmWriteMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);\r
269 return RETURN_SUCCESS;\r
270}\r
271\r
272\r
273/**\r
274 Get the attribute of variable MTRRs.\r
275\r
276 This function shadows the content of variable MTRRs into an\r
277 internal array: VariableMtrr.\r
278\r
279 @param MtrrValidBitsMask The mask for the valid bit of the MTRR\r
280 @param MtrrValidAddressMask The valid address mask for MTRR\r
281 @param VariableMtrr The array to shadow variable MTRRs content\r
282\r
283 @return The return value of this paramter indicates the\r
284 number of MTRRs which has been used.\r
285\r
286**/\r
287UINT32\r
288EFIAPI\r
289MtrrGetMemoryAttributeInVariableMtrr (\r
290 IN UINT64 MtrrValidBitsMask,\r
291 IN UINT64 MtrrValidAddressMask,\r
292 OUT VARIABLE_MTRR *VariableMtrr\r
293 )\r
294{\r
295 UINTN Index;\r
296 UINT32 MsrNum;\r
297 UINT32 UsedMtrr;\r
298\r
299 ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
300 UsedMtrr = 0;\r
301\r
302 for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
303 (\r
304 (MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END) &&\r
305 (Index < FIRMWARE_VARIABLE_MTRR_NUMBER)\r
306 );\r
307 MsrNum += 2\r
308 ) {\r
309 if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
310 VariableMtrr[Index].Msr = MsrNum;\r
311 VariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) &\r
312 MtrrValidAddressMask);\r
313 VariableMtrr[Index].Length = ((~(AsmReadMsr64 (MsrNum + 1) &\r
314 MtrrValidAddressMask)\r
315 ) &\r
316 MtrrValidBitsMask\r
317 ) + 1;\r
318 VariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff);\r
319 VariableMtrr[Index].Valid = TRUE;\r
320 VariableMtrr[Index].Used = TRUE;\r
321 UsedMtrr = UsedMtrr + 1;\r
322 Index++;\r
323 }\r
324 }\r
325 return UsedMtrr;\r
326}\r
327\r
328\r
329/**\r
330 Checks overlap between given memory range and MTRRs.\r
331\r
332 @param Start The start address of memory range.\r
333 @param End The end address of memory range.\r
334 @param VariableMtrr The array to shadow variable MTRRs content\r
335\r
336 @retval TRUE Overlap exists.\r
337 @retval FALSE No overlap.\r
338\r
339**/\r
340BOOLEAN\r
341CheckMemoryAttributeOverlap (\r
342 IN PHYSICAL_ADDRESS Start,\r
343 IN PHYSICAL_ADDRESS End,\r
344 IN VARIABLE_MTRR *VariableMtrr\r
345 )\r
346{\r
347 UINT32 Index;\r
348\r
349 for (Index = 0; Index < 6; Index++) {\r
350 if (\r
351 VariableMtrr[Index].Valid &&\r
352 !(\r
353 (Start > (VariableMtrr[Index].BaseAddress +\r
354 VariableMtrr[Index].Length - 1)\r
355 ) ||\r
356 (End < VariableMtrr[Index].BaseAddress)\r
357 )\r
358 ) {\r
359 return TRUE;\r
360 }\r
361 }\r
362\r
363 return FALSE;\r
364}\r
365\r
366\r
367/**\r
368 Marks a variable MTRR as non-valid.\r
369\r
370 @param Index The index of the array VariableMtrr to be invalidated\r
371 @param VariableMtrr The array to shadow variable MTRRs content\r
372 @param UsedMtrr The number of MTRRs which has already been used\r
373\r
374**/\r
375VOID\r
376InvalidateShadowMtrr (\r
377 IN UINTN Index,\r
378 IN VARIABLE_MTRR *VariableMtrr,\r
379 OUT UINT32 *UsedMtrr\r
380 )\r
381{\r
382 VariableMtrr[Index].Valid = FALSE;\r
383 *UsedMtrr = *UsedMtrr - 1;\r
384}\r
385\r
386\r
387/**\r
388 Combine memory attributes.\r
389\r
390 If overlap exists between given memory range and MTRRs, try to combine them.\r
391\r
392 @param Attributes The memory type to set.\r
393 @param Base The base address of memory range.\r
394 @param Length The length of memory range.\r
395 @param VariableMtrr The array to shadow variable MTRRs content\r
396 @param UsedMtrr The number of MTRRs which has already been used\r
397 @param OverwriteExistingMtrr Returns whether an existing MTRR was used\r
398\r
399 @retval EFI_SUCCESS Memory region successfully combined.\r
400 @retval EFI_ACCESS_DENIED Memory region cannot be combined.\r
401\r
402**/\r
403RETURN_STATUS\r
404CombineMemoryAttribute (\r
405 IN UINT64 Attributes,\r
406 IN OUT UINT64 *Base,\r
407 IN OUT UINT64 *Length,\r
408 IN VARIABLE_MTRR *VariableMtrr,\r
409 IN OUT UINT32 *UsedMtrr,\r
410 OUT BOOLEAN *OverwriteExistingMtrr\r
411 )\r
412{\r
413 UINT32 Index;\r
414 UINT64 CombineStart;\r
415 UINT64 CombineEnd;\r
416 UINT64 MtrrEnd;\r
417 UINT64 EndAddress;\r
418\r
419 *OverwriteExistingMtrr = FALSE;\r
420 EndAddress = *Base +*Length - 1;\r
421\r
422 for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
423\r
424 MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;\r
425 if (\r
426 !VariableMtrr[Index].Valid ||\r
427 (\r
428 *Base > (MtrrEnd) ||\r
429 (EndAddress < VariableMtrr[Index].BaseAddress)\r
430 )\r
431 ) {\r
432 continue;\r
433 }\r
434\r
435 //\r
436 // Combine same attribute MTRR range\r
437 //\r
438 if (Attributes == VariableMtrr[Index].Type) {\r
439 //\r
440 // if the Mtrr range contain the request range, return RETURN_SUCCESS\r
441 //\r
442 if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {\r
443 *Length = 0;\r
444 return RETURN_SUCCESS;\r
445 }\r
446 //\r
447 // invalid this MTRR, and program the combine range\r
448 //\r
449 CombineStart =\r
450 (*Base) < VariableMtrr[Index].BaseAddress ?\r
451 (*Base) :\r
452 VariableMtrr[Index].BaseAddress;\r
453 CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;\r
454\r
455 //\r
456 // Record the MTRR usage status in VariableMtrr array.\r
457 //\r
458 InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
459 *Base = CombineStart;\r
460 *Length = CombineEnd - CombineStart + 1;\r
461 EndAddress = CombineEnd;\r
462 *OverwriteExistingMtrr = TRUE;\r
463 continue;\r
464 } else {\r
465 //\r
466 // The cache type is different, but the range is convered by one MTRR\r
467 //\r
468 if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {\r
469 InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
470 continue;\r
471 }\r
472\r
473 }\r
474\r
475 if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&\r
476 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||\r
477 (Attributes == MTRR_CACHE_WRITE_BACK &&\r
478 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||\r
479 (Attributes == MTRR_CACHE_UNCACHEABLE) ||\r
480 (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)\r
481 ) {\r
482 *OverwriteExistingMtrr = TRUE;\r
483 continue;\r
484 }\r
485 //\r
486 // Other type memory overlap is invalid\r
487 //\r
488 return RETURN_ACCESS_DENIED;\r
489 }\r
490\r
491 return RETURN_SUCCESS;\r
492}\r
493\r
494\r
495/**\r
496 Calculate the maximum value which is a power of 2, but less the MemoryLength.\r
497\r
498 @param MemoryLength The number to pass in.\r
499 @return The maximum value which is align to power of 2 and less the MemoryLength\r
500\r
501**/\r
502UINT64\r
503Power2MaxMemory (\r
504 IN UINT64 MemoryLength\r
505 )\r
506{\r
507 UINT64 Result;\r
508\r
509 if (RShiftU64 (MemoryLength, 32)) {\r
510 Result = LShiftU64 (\r
511 (UINT64) GetPowerOfTwo32 (\r
512 (UINT32) RShiftU64 (MemoryLength, 32)\r
513 ),\r
514 32\r
515 );\r
516 } else {\r
517 Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);\r
518 }\r
519\r
520 return Result;\r
521}\r
522\r
523\r
524/**\r
525 Check the direction to program variable MTRRs.\r
526\r
527 This function determines which direction of programming the variable\r
528 MTRRs will use fewer MTRRs.\r
529\r
530 @param Input Length of Memory to program MTRR\r
531 @param MtrrNumber Pointer to the number of necessary MTRRs\r
532\r
533 @retval TRUE Positive direction is better.\r
534 FALSE Negtive direction is better.\r
535\r
536**/\r
537BOOLEAN\r
538GetDirection (\r
539 IN UINT64 Input,\r
540 IN UINTN *MtrrNumber\r
541 )\r
542{\r
543 UINT64 TempQword;\r
544 UINT32 Positive;\r
545 UINT32 Subtractive;\r
546\r
547 TempQword = Input;\r
548 Positive = 0;\r
549 Subtractive = 0;\r
550\r
551 do {\r
552 TempQword -= Power2MaxMemory (TempQword);\r
553 Positive++;\r
554 } while (TempQword != 0);\r
555\r
556 TempQword = Power2MaxMemory (LShiftU64 (Input, 1)) - Input;\r
557 Subtractive++;\r
558 do {\r
559 TempQword -= Power2MaxMemory (TempQword);\r
560 Subtractive++;\r
561 } while (TempQword != 0);\r
562\r
563 if (Positive <= Subtractive) {\r
564 *MtrrNumber = Positive;\r
565 return TRUE;\r
566 } else {\r
567 *MtrrNumber = Subtractive;\r
568 return FALSE;\r
569 }\r
570}\r
571\r
572/**\r
573 Invalid variable MTRRs according to the value in the shadow array.\r
574\r
575 This function programs MTRRs according to the values specified\r
576 in the shadow array.\r
577\r
578 @param VariableMtrr The array to shadow variable MTRRs content\r
579\r
580**/\r
581STATIC\r
582VOID\r
583InvalidateMtrr (\r
584 IN VARIABLE_MTRR *VariableMtrr\r
585 )\r
586{\r
587 UINTN Index;\r
588 UINTN Cr4;\r
589\r
590 Cr4 = PreMtrrChange ();\r
591 Index = 0;\r
592 while (Index < MTRR_NUMBER_OF_VARIABLE_MTRR) {\r
593 if (VariableMtrr[Index].Valid == FALSE && VariableMtrr[Index].Used == TRUE ) {\r
594 AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
595 AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);\r
596 VariableMtrr[Index].Used = FALSE;\r
597 }\r
598 Index ++;\r
599 }\r
600 PostMtrrChange (Cr4);\r
601}\r
602\r
603\r
604/**\r
605 Programs variable MTRRs\r
606\r
607 This function programs variable MTRRs\r
608\r
609 @param MtrrNumber Index of MTRR to program.\r
610 @param BaseAddress Base address of memory region.\r
611 @param Length Length of memory region.\r
612 @param MemoryCacheType Memory type to set.\r
613 @param MtrrValidAddressMask The valid address mask for MTRR\r
614\r
615**/\r
616STATIC\r
617VOID\r
618ProgramVariableMtrr (\r
619 IN UINTN MtrrNumber,\r
620 IN PHYSICAL_ADDRESS BaseAddress,\r
621 IN UINT64 Length,\r
622 IN UINT64 MemoryCacheType,\r
623 IN UINT64 MtrrValidAddressMask\r
624 )\r
625{\r
626 UINT64 TempQword;\r
627 UINTN Cr4;\r
628\r
629 Cr4 = PreMtrrChange ();\r
630\r
631 //\r
632 // MTRR Physical Base\r
633 //\r
634 TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;\r
635 AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);\r
636\r
637 //\r
638 // MTRR Physical Mask\r
639 //\r
640 TempQword = ~(Length - 1);\r
641 AsmWriteMsr64 (\r
642 (UINT32) (MtrrNumber + 1),\r
643 (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED\r
644 );\r
645\r
646 PostMtrrChange (Cr4);\r
647}\r
648\r
649\r
650/**\r
651 Convert the Memory attibute value to MTRR_MEMORY_CACHE_TYPE.\r
652\r
653 @param MtrrType MTRR memory type\r
654\r
655 @return The enum item in MTRR_MEMORY_CACHE_TYPE\r
656\r
657**/\r
658STATIC\r
659MTRR_MEMORY_CACHE_TYPE\r
660GetMemoryCacheTypeFromMtrrType (\r
661 IN UINT64 MtrrType\r
662 )\r
663{\r
664 switch (MtrrType) {\r
665 case MTRR_CACHE_UNCACHEABLE:\r
666 return CacheUncacheable;\r
667 case MTRR_CACHE_WRITE_COMBINING:\r
668 return CacheWriteCombining;\r
669 case MTRR_CACHE_WRITE_THROUGH:\r
670 return CacheWriteThrough;\r
671 case MTRR_CACHE_WRITE_PROTECTED:\r
672 return CacheWriteProtected;\r
673 case MTRR_CACHE_WRITE_BACK:\r
674 return CacheWriteBack;\r
675 default:\r
676 //\r
677 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means\r
678 // no mtrr covers the range\r
679 //\r
680 return CacheUncacheable;\r
681 }\r
682}\r
683\r
684/**\r
685 Initializes the valid bits mask and valid address mask for MTRRs.\r
686\r
687 This function initializes the valid bits mask and valid address mask for MTRRs.\r
688\r
689 @param MtrrValidBitsMask The mask for the valid bit of the MTRR\r
690 @param MtrrValidAddressMask The valid address mask for the MTRR\r
691\r
692**/\r
693STATIC\r
694VOID\r
695MtrrLibInitializeMtrrMask (\r
696 OUT UINT64 *MtrrValidBitsMask,\r
697 OUT UINT64 *MtrrValidAddressMask\r
698 )\r
699{\r
700 UINT32 RegEax;\r
701 UINT8 PhysicalAddressBits;\r
702\r
703 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
704\r
705 if (RegEax >= 0x80000008) {\r
706 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
707\r
708 PhysicalAddressBits = (UINT8) RegEax;\r
709\r
710 *MtrrValidBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
711 *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;\r
712 } else {\r
713 *MtrrValidBitsMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
714 *MtrrValidAddressMask = 0xFFFFFFFF;\r
715 }\r
716}\r
717\r
718\r
719/**\r
720 Determing the real attribute of a memory range.\r
721\r
722 This function is to arbitrate the real attribute of the memory when\r
723 there are 2 MTRR covers the same memory range. For further details,\r
724 please refer the IA32 Software Developer's Manual, Volume 3,\r
725 Section 10.11.4.1.\r
726\r
727 @param MtrrType1 the first kind of Memory type\r
728 @param MtrrType2 the second kind of memory type\r
729\r
730**/\r
731UINT64\r
732MtrrPrecedence (\r
733 UINT64 MtrrType1,\r
734 UINT64 MtrrType2\r
735 )\r
736{\r
737 UINT64 MtrrType;\r
738\r
739 MtrrType = MTRR_CACHE_INVALID_TYPE;\r
740 switch (MtrrType1) {\r
741 case MTRR_CACHE_UNCACHEABLE:\r
742 MtrrType = MTRR_CACHE_UNCACHEABLE;\r
743 break;\r
744 case MTRR_CACHE_WRITE_COMBINING:\r
745 if (\r
746 MtrrType2==MTRR_CACHE_WRITE_COMBINING ||\r
747 MtrrType2==MTRR_CACHE_UNCACHEABLE\r
748 ) {\r
749 MtrrType = MtrrType2;\r
750 }\r
751 break;\r
752 case MTRR_CACHE_WRITE_THROUGH:\r
753 if (\r
754 MtrrType2==MTRR_CACHE_WRITE_THROUGH ||\r
755 MtrrType2==MTRR_CACHE_WRITE_BACK\r
756 ) {\r
757 MtrrType = MTRR_CACHE_WRITE_THROUGH;\r
758 } else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {\r
759 MtrrType = MTRR_CACHE_UNCACHEABLE;\r
760 }\r
761 break;\r
762 case MTRR_CACHE_WRITE_PROTECTED:\r
763 if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||\r
764 MtrrType2 == MTRR_CACHE_UNCACHEABLE) {\r
765 MtrrType = MtrrType2;\r
766 }\r
767 break;\r
768 case MTRR_CACHE_WRITE_BACK:\r
769 if (\r
770 MtrrType2== MTRR_CACHE_UNCACHEABLE ||\r
771 MtrrType2==MTRR_CACHE_WRITE_THROUGH ||\r
772 MtrrType2== MTRR_CACHE_WRITE_BACK\r
773 ) {\r
774 MtrrType = MtrrType2;\r
775 }\r
776 break;\r
777 case MTRR_CACHE_INVALID_TYPE:\r
778 MtrrType = MtrrType2;\r
779 break;\r
780 default:\r
781 break;\r
782 }\r
783\r
784 if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) {\r
785 MtrrType = MtrrType1;\r
786 }\r
787 return MtrrType;\r
788}\r
789\r
790\r
791/**\r
792 This function attempts to set the attributes for a memory range.\r
793\r
794 @param BaseAddress The physical address that is the start\r
795 address of a memory region.\r
796 @param Length The size in bytes of the memory region.\r
797 @param Attributes The bit mask of attributes to set for the\r
798 memory region.\r
799\r
800 @retval RETURN_SUCCESS The attributes were set for the memory\r
801 region.\r
802 @retval RETURN_INVALID_PARAMETER Length is zero.\r
803 @retval RETURN_UNSUPPORTED The processor does not support one or\r
804 more bytes of the memory resource range\r
805 specified by BaseAddress and Length.\r
806 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support\r
807 for the memory resource range specified\r
808 by BaseAddress and Length.\r
809 @retval RETURN_ACCESS_DENIED The attributes for the memory resource\r
810 range specified by BaseAddress and Length\r
811 cannot be modified.\r
812 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to\r
813 modify the attributes of the memory\r
814 resource range.\r
815\r
816**/\r
817RETURN_STATUS\r
818EFIAPI\r
819MtrrSetMemoryAttribute (\r
820 IN PHYSICAL_ADDRESS BaseAddress,\r
821 IN UINT64 Length,\r
822 IN MTRR_MEMORY_CACHE_TYPE Attribute\r
823 )\r
824{\r
825 UINT64 TempQword;\r
826 RETURN_STATUS Status;\r
827 UINT64 MemoryType;\r
828 UINT64 Remainder;\r
829 BOOLEAN OverLap;\r
830 BOOLEAN Positive;\r
831 UINT32 MsrNum;\r
832 UINTN MtrrNumber;\r
833 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
834 UINT32 UsedMtrr;\r
835 UINT64 MtrrValidBitsMask;\r
836 UINT64 MtrrValidAddressMask;\r
837 UINTN Cr4;\r
838 BOOLEAN OverwriteExistingMtrr;\r
839\r
840 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
841\r
842 TempQword = 0;\r
843 MemoryType = (UINT64)Attribute;\r
844 OverwriteExistingMtrr = FALSE;\r
845\r
846 //\r
847 // Check for an invalid parameter\r
848 //\r
849 if (Length == 0) {\r
850 return RETURN_INVALID_PARAMETER;\r
851 }\r
852\r
853 if (\r
854 (BaseAddress &~MtrrValidAddressMask) != 0 ||\r
855 (Length &~MtrrValidAddressMask) != 0\r
856 ) {\r
857 return RETURN_UNSUPPORTED;\r
858 }\r
859\r
860 //\r
861 // Check if Fixed MTRR\r
862 //\r
863 Status = RETURN_SUCCESS;\r
864 while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
865 Cr4 = PreMtrrChange ();\r
866 Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);\r
867 PostMtrrChange (Cr4);\r
868 if (RETURN_ERROR (Status)) {\r
869 return Status;\r
870 }\r
871 }\r
872\r
873 if (Length == 0) {\r
874 //\r
875 // A Length of 0 can only make sense for fixed MTTR ranges.\r
876 // Since we just handled the fixed MTRRs, we can skip the\r
877 // variable MTRR section.\r
878 //\r
879 goto Done;\r
880 }\r
881\r
882 //\r
883 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
884 // we can set the bade to 0 to save variable MTRRs.\r
885 //\r
886 if (BaseAddress == BASE_1MB) {\r
887 BaseAddress = 0;\r
888 Length += SIZE_1MB;\r
889 }\r
890\r
891 //\r
892 // Check memory base address alignment\r
893 //\r
894 DivU64x64Remainder (BaseAddress, Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);\r
895 if (Remainder != 0) {\r
896 DivU64x64Remainder (BaseAddress, Power2MaxMemory (Length), &Remainder);\r
897 if (Remainder != 0) {\r
898 Status = RETURN_UNSUPPORTED;\r
899 goto Done;\r
900 }\r
901 }\r
902\r
903 //\r
904 // Check for overlap\r
905 //\r
906 UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
907 OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);\r
908 if (OverLap) {\r
909 Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);\r
910 if (RETURN_ERROR (Status)) {\r
911 goto Done;\r
912 }\r
913\r
914 if (Length == 0) {\r
915 //\r
916 // Combined successfully\r
917 //\r
918 Status = RETURN_SUCCESS;\r
919 goto Done;\r
920 }\r
921 }\r
922\r
923 //\r
924 // Program Variable MTRRs\r
925 //\r
926 // Avoid hardcode here and read data dynamically\r
927 //\r
928 if (UsedMtrr >= FIRMWARE_VARIABLE_MTRR_NUMBER) {\r
929 Status = RETURN_OUT_OF_RESOURCES;\r
930 goto Done;\r
931 }\r
932\r
933 //\r
934 // The memory type is the same with the type specified by\r
935 // MTRR_LIB_IA32_MTRR_DEF_TYPE.\r
936 //\r
937 if ((!OverwriteExistingMtrr) && (Attribute == GetMtrrDefaultMemoryType ())) {\r
938 //\r
939 // Invalidate the now-unused MTRRs\r
940 //\r
941 InvalidateMtrr(VariableMtrr);\r
942 goto Done;\r
943 }\r
944\r
945 TempQword = Length;\r
946\r
947\r
948 if (TempQword == Power2MaxMemory (TempQword)) {\r
949 //\r
950 // Invalidate the now-unused MTRRs\r
951 //\r
952 InvalidateMtrr(VariableMtrr);\r
953\r
954 //\r
955 // Find first unused MTRR\r
956 //\r
957 for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
958 MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END;\r
959 MsrNum += 2\r
960 ) {\r
961 if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
962 break;\r
963 }\r
964 }\r
965\r
966 ProgramVariableMtrr (\r
967 MsrNum,\r
968 BaseAddress,\r
969 Length,\r
970 MemoryType,\r
971 MtrrValidAddressMask\r
972 );\r
973 } else {\r
974\r
975 Positive = GetDirection (TempQword, &MtrrNumber);\r
976\r
977 if ((UsedMtrr + MtrrNumber) > FIRMWARE_VARIABLE_MTRR_NUMBER) {\r
978 Status = RETURN_OUT_OF_RESOURCES;\r
979 goto Done;\r
980 }\r
981\r
982 //\r
983 // Invalidate the now-unused MTRRs\r
984 //\r
985 InvalidateMtrr(VariableMtrr);\r
986\r
987 //\r
988 // Find first unused MTRR\r
989 //\r
990 for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
991 MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END;\r
992 MsrNum += 2\r
993 ) {\r
994 if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
995 break;\r
996 }\r
997 }\r
998\r
999 if (!Positive) {\r
1000 Length = Power2MaxMemory (LShiftU64 (TempQword, 1));\r
1001 ProgramVariableMtrr (\r
1002 MsrNum,\r
1003 BaseAddress,\r
1004 Length,\r
1005 MemoryType,\r
1006 MtrrValidAddressMask\r
1007 );\r
1008 BaseAddress += Length;\r
1009 TempQword = Length - TempQword;\r
1010 MemoryType = MTRR_CACHE_UNCACHEABLE;\r
1011 }\r
1012\r
1013 do {\r
1014 //\r
1015 // Find unused MTRR\r
1016 //\r
1017 for (; MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END; MsrNum += 2) {\r
1018 if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
1019 break;\r
1020 }\r
1021 }\r
1022\r
1023 Length = Power2MaxMemory (TempQword);\r
1024 if (!Positive) {\r
1025 BaseAddress -= Length;\r
1026 }\r
1027\r
1028 ProgramVariableMtrr (\r
1029 MsrNum,\r
1030 BaseAddress,\r
1031 Length,\r
1032 MemoryType,\r
1033 MtrrValidAddressMask\r
1034 );\r
1035\r
1036 if (Positive) {\r
1037 BaseAddress += Length;\r
1038 }\r
1039 TempQword -= Length;\r
1040\r
1041 } while (TempQword > 0);\r
1042 }\r
1043\r
1044Done:\r
1045 return Status;\r
1046\r
1047}\r
1048\r
1049\r
1050/**\r
1051 This function will get the memory cache type of the specific address.\r
1052\r
1053 This function is mainly for debug purpose.\r
1054\r
1055 @param Address The specific address\r
1056\r
1057 @return Memory cache type of the sepcific address\r
1058\r
1059**/\r
1060MTRR_MEMORY_CACHE_TYPE\r
1061EFIAPI\r
1062MtrrGetMemoryAttribute (\r
1063 IN PHYSICAL_ADDRESS Address\r
1064 )\r
1065{\r
1066 UINT64 TempQword;\r
1067 UINTN Index;\r
1068 UINTN SubIndex;\r
1069 UINT64 MtrrType;\r
1070 UINT64 TempMtrrType;\r
1071 MTRR_MEMORY_CACHE_TYPE CacheType;\r
1072 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
1073 UINT64 MtrrValidBitsMask;\r
1074 UINT64 MtrrValidAddressMask;\r
1075\r
1076 //\r
1077 // Check if MTRR is enabled, if not, return UC as attribute\r
1078 //\r
1079 TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
1080 MtrrType = MTRR_CACHE_INVALID_TYPE;\r
1081\r
1082 if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
1083 return CacheUncacheable;\r
1084 }\r
1085\r
1086 //\r
1087 // If address is less than 1M, then try to go through the fixed MTRR\r
1088 //\r
1089 if (Address < BASE_1MB) {\r
1090 if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {\r
1091 //\r
1092 // Go through the fixed MTRR\r
1093 //\r
1094 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
1095 if (Address >= MtrrLibFixedMtrrTable[Index].BaseAddress &&\r
1096 Address < (\r
1097 MtrrLibFixedMtrrTable[Index].BaseAddress +\r
1098 (MtrrLibFixedMtrrTable[Index].Length * 8)\r
1099 )\r
1100 ) {\r
1101 SubIndex =\r
1102 ((UINTN)Address - MtrrLibFixedMtrrTable[Index].BaseAddress) /\r
1103 MtrrLibFixedMtrrTable[Index].Length;\r
1104 TempQword = AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr);\r
1105 MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
1106 return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
1107 }\r
1108 }\r
1109 }\r
1110 }\r
1111 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
1112 MtrrGetMemoryAttributeInVariableMtrr(\r
1113 MtrrValidBitsMask,\r
1114 MtrrValidAddressMask,\r
1115 VariableMtrr\r
1116 );\r
1117\r
1118 //\r
1119 // Go through the variable MTRR\r
1120 //\r
1121 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
1122 if (VariableMtrr[Index].Valid) {\r
1123 if (Address >= VariableMtrr[Index].BaseAddress &&\r
1124 Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
1125 TempMtrrType = VariableMtrr[Index].Type;\r
1126 MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);\r
1127 }\r
1128 }\r
1129 }\r
1130 CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);\r
1131\r
1132 return CacheType;\r
1133}\r
1134\r
1135\r
1136/**\r
1137 This function will get the raw value in variable MTRRs\r
1138\r
1139 @param VariableSettings A buffer to hold variable MTRRs content.\r
1140\r
1141 @return The VariableSettings input pointer\r
1142\r
1143**/\r
1144MTRR_VARIABLE_SETTINGS*\r
1145EFIAPI\r
1146MtrrGetVariableMtrr (\r
1147 OUT MTRR_VARIABLE_SETTINGS *VariableSettings\r
1148 )\r
1149{\r
1150 UINT32 Index;\r
1151\r
1152 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
1153 VariableSettings->Mtrr[Index].Base =\r
1154 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
1155 VariableSettings->Mtrr[Index].Mask =\r
1156 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);\r
1157 }\r
1158\r
1159 return VariableSettings;\r
1160}\r
1161\r
1162\r
1163/**\r
1164 Worker function setting variable MTRRs\r
1165\r
1166 @param VariableSettings A buffer to hold variable MTRRs content.\r
1167\r
1168**/\r
1169VOID\r
1170MtrrSetVariableMtrrWorker (\r
1171 IN MTRR_VARIABLE_SETTINGS *VariableSettings\r
1172 )\r
1173{\r
1174 UINT32 Index;\r
1175\r
1176 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
1177 AsmWriteMsr64 (\r
1178 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),\r
1179 VariableSettings->Mtrr[Index].Base\r
1180 );\r
1181 AsmWriteMsr64 (\r
1182 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,\r
1183 VariableSettings->Mtrr[Index].Mask\r
1184 );\r
1185 }\r
1186}\r
1187\r
1188\r
1189/**\r
1190 This function sets variable MTRRs\r
1191\r
1192 @param VariableSettings A buffer to hold variable MTRRs content.\r
1193\r
1194 @return The pointer of VariableSettings\r
1195\r
1196**/\r
1197MTRR_VARIABLE_SETTINGS*\r
1198EFIAPI\r
1199MtrrSetVariableMtrr (\r
1200 IN MTRR_VARIABLE_SETTINGS *VariableSettings\r
1201 )\r
1202{\r
1203 UINTN Cr4;\r
1204\r
1205 Cr4 = PreMtrrChange ();\r
1206 MtrrSetVariableMtrrWorker (VariableSettings);\r
1207 PostMtrrChange (Cr4);\r
1208 return VariableSettings;\r
1209}\r
1210\r
1211\r
1212/**\r
1213 This function gets the content in fixed MTRRs\r
1214\r
1215 @param FixedSettings A buffer to hold fixed Mtrrs content.\r
1216\r
1217 @retval The pointer of FixedSettings\r
1218\r
1219**/\r
1220MTRR_FIXED_SETTINGS*\r
1221EFIAPI\r
1222MtrrGetFixedMtrr (\r
1223 OUT MTRR_FIXED_SETTINGS *FixedSettings\r
1224 )\r
1225{\r
1226 UINT32 Index;\r
1227\r
1228 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
1229 FixedSettings->Mtrr[Index] =\r
1230 AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr);\r
1231 };\r
1232\r
1233 return FixedSettings;\r
1234}\r
1235\r
1236/**\r
1237 Worker function setting fixed MTRRs\r
1238\r
1239 @param FixedSettings A buffer to hold fixed Mtrrs content.\r
1240\r
1241**/\r
1242VOID\r
1243MtrrSetFixedMtrrWorker (\r
1244 IN MTRR_FIXED_SETTINGS *FixedSettings\r
1245 )\r
1246{\r
1247 UINT32 Index;\r
1248\r
1249 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
1250 AsmWriteMsr64 (\r
1251 MtrrLibFixedMtrrTable[Index].Msr,\r
1252 FixedSettings->Mtrr[Index]\r
1253 );\r
1254 }\r
1255}\r
1256\r
1257\r
1258/**\r
1259 This function sets fixed MTRRs\r
1260\r
1261 @param FixedSettings A buffer to hold fixed Mtrrs content.\r
1262\r
1263 @retval The pointer of FixedSettings\r
1264\r
1265**/\r
1266MTRR_FIXED_SETTINGS*\r
1267EFIAPI\r
1268MtrrSetFixedMtrr (\r
1269 IN MTRR_FIXED_SETTINGS *FixedSettings\r
1270 )\r
1271{\r
1272 UINTN Cr4;\r
1273\r
1274 Cr4 = PreMtrrChange ();\r
1275 MtrrSetFixedMtrrWorker (FixedSettings);\r
1276 PostMtrrChange (Cr4);\r
1277\r
1278 return FixedSettings;\r
1279}\r
1280\r
1281\r
1282/**\r
1283 This function gets the content in all MTRRs (variable and fixed)\r
1284\r
1285 @param MtrrSetting A buffer to hold all Mtrrs content.\r
1286\r
1287 @retval the pointer of MtrrSetting\r
1288\r
1289**/\r
1290MTRR_SETTINGS *\r
1291EFIAPI\r
1292MtrrGetAllMtrrs (\r
1293 OUT MTRR_SETTINGS *MtrrSetting\r
1294 )\r
1295{\r
1296 //\r
1297 // Get fixed MTRRs\r
1298 //\r
1299 MtrrGetFixedMtrr (&MtrrSetting->Fixed);\r
1300\r
1301 //\r
1302 // Get variable MTRRs\r
1303 //\r
1304 MtrrGetVariableMtrr (&MtrrSetting->Variables);\r
1305\r
1306 //\r
1307 // Get MTRR_DEF_TYPE value\r
1308 //\r
1309 MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
1310\r
1311 return MtrrSetting;\r
1312}\r
1313\r
1314\r
1315/**\r
1316 This function sets all MTRRs (variable and fixed)\r
1317\r
1318 @param MtrrSetting A buffer holding all MTRRs content.\r
1319\r
1320 @retval The pointer of MtrrSetting\r
1321\r
1322**/\r
1323MTRR_SETTINGS *\r
1324EFIAPI\r
1325MtrrSetAllMtrrs (\r
1326 IN MTRR_SETTINGS *MtrrSetting\r
1327 )\r
1328{\r
1329 UINTN Cr4;\r
1330\r
1331 Cr4 = PreMtrrChange ();\r
1332\r
1333 //\r
1334 // Set fixed MTRRs\r
1335 //\r
1336 MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);\r
1337\r
1338 //\r
1339 // Set variable MTRRs\r
1340 //\r
1341 MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);\r
1342\r
1343 //\r
1344 // Set MTRR_DEF_TYPE value\r
1345 //\r
1346 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);\r
1347\r
1348 PostMtrrChange (Cr4);\r
1349\r
1350 return MtrrSetting;\r
1351}\r
1352\r
1353\r
1354/**\r
1355 This function prints all MTRRs for debugging.\r
1356**/\r
1357VOID\r
1358MtrrDebugPrintAllMtrrs (\r
1359 )\r
1360{\r
1361 DEBUG_CODE (\r
1362 {\r
1363 MTRR_SETTINGS MtrrSettings;\r
1364 UINTN Index;\r
1365\r
1366 MtrrGetAllMtrrs (&MtrrSettings);\r
1367 DEBUG((EFI_D_ERROR, "DefaultType = %016lx\n", MtrrSettings.MtrrDefType));\r
1368 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
1369 DEBUG((\r
1370 EFI_D_ERROR, "Fixed[%02d] = %016lx\n",\r
1371 Index,\r
1372 MtrrSettings.Fixed.Mtrr[Index]\r
1373 ));\r
1374 }\r
1375 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
1376 DEBUG((\r
1377 EFI_D_ERROR, "Variable[%02d] = %016lx, %016lx\n",\r
1378 Index,\r
1379 MtrrSettings.Variables.Mtrr[Index].Base,\r
1380 MtrrSettings.Variables.Mtrr[Index].Mask\r
1381 ));\r
1382 }\r
1383 }\r
1384 );\r
1385}\r
1386\r