]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
UefiCpuPkg/MtrrLib: Remove the loop of calculating Fixed-MTRR Mask
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
1 /** @file
2 MTRR setting library
3
4 Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Base.h>
16
17 #include <Library/MtrrLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/CpuLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22
23 #define OR_SEED 0x01010101
24 #define CLEAR_SEED 0xFFFFFFFF
25
26 //
27 // Context to save and restore when MTRRs are programmed
28 //
29 typedef struct {
30 UINTN Cr4;
31 BOOLEAN InterruptState;
32 } MTRR_CONTEXT;
33
34 //
35 // This table defines the offset, base and length of the fixed MTRRs
36 //
37 CONST FIXED_MTRR mMtrrLibFixedMtrrTable[] = {
38 {
39 MTRR_LIB_IA32_MTRR_FIX64K_00000,
40 0,
41 SIZE_64KB
42 },
43 {
44 MTRR_LIB_IA32_MTRR_FIX16K_80000,
45 0x80000,
46 SIZE_16KB
47 },
48 {
49 MTRR_LIB_IA32_MTRR_FIX16K_A0000,
50 0xA0000,
51 SIZE_16KB
52 },
53 {
54 MTRR_LIB_IA32_MTRR_FIX4K_C0000,
55 0xC0000,
56 SIZE_4KB
57 },
58 {
59 MTRR_LIB_IA32_MTRR_FIX4K_C8000,
60 0xC8000,
61 SIZE_4KB
62 },
63 {
64 MTRR_LIB_IA32_MTRR_FIX4K_D0000,
65 0xD0000,
66 SIZE_4KB
67 },
68 {
69 MTRR_LIB_IA32_MTRR_FIX4K_D8000,
70 0xD8000,
71 SIZE_4KB
72 },
73 {
74 MTRR_LIB_IA32_MTRR_FIX4K_E0000,
75 0xE0000,
76 SIZE_4KB
77 },
78 {
79 MTRR_LIB_IA32_MTRR_FIX4K_E8000,
80 0xE8000,
81 SIZE_4KB
82 },
83 {
84 MTRR_LIB_IA32_MTRR_FIX4K_F0000,
85 0xF0000,
86 SIZE_4KB
87 },
88 {
89 MTRR_LIB_IA32_MTRR_FIX4K_F8000,
90 0xF8000,
91 SIZE_4KB
92 }
93 };
94
95 //
96 // Lookup table used to print MTRRs
97 //
98 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = {
99 "UC", // CacheUncacheable
100 "WC", // CacheWriteCombining
101 "R*", // Invalid
102 "R*", // Invalid
103 "WT", // CacheWriteThrough
104 "WP", // CacheWriteProtected
105 "WB", // CacheWriteBack
106 "R*" // Invalid
107 };
108
109 /**
110 Worker function returns the variable MTRR count for the CPU.
111
112 @return Variable MTRR count
113
114 **/
115 UINT32
116 GetVariableMtrrCountWorker (
117 VOID
118 )
119 {
120 UINT32 VariableMtrrCount;
121
122 VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);
123 ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
124 return VariableMtrrCount;
125 }
126
127 /**
128 Returns the variable MTRR count for the CPU.
129
130 @return Variable MTRR count
131
132 **/
133 UINT32
134 EFIAPI
135 GetVariableMtrrCount (
136 VOID
137 )
138 {
139 if (!IsMtrrSupported ()) {
140 return 0;
141 }
142 return GetVariableMtrrCountWorker ();
143 }
144
145 /**
146 Worker function returns the firmware usable variable MTRR count for the CPU.
147
148 @return Firmware usable variable MTRR count
149
150 **/
151 UINT32
152 GetFirmwareVariableMtrrCountWorker (
153 VOID
154 )
155 {
156 UINT32 VariableMtrrCount;
157 UINT32 ReservedMtrrNumber;
158
159 VariableMtrrCount = GetVariableMtrrCountWorker ();
160 ReservedMtrrNumber = PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
161 if (VariableMtrrCount < ReservedMtrrNumber) {
162 return 0;
163 }
164
165 return VariableMtrrCount - ReservedMtrrNumber;
166 }
167
168 /**
169 Returns the firmware usable variable MTRR count for the CPU.
170
171 @return Firmware usable variable MTRR count
172
173 **/
174 UINT32
175 EFIAPI
176 GetFirmwareVariableMtrrCount (
177 VOID
178 )
179 {
180 if (!IsMtrrSupported ()) {
181 return 0;
182 }
183 return GetFirmwareVariableMtrrCountWorker ();
184 }
185
186 /**
187 Worker function returns the default MTRR cache type for the system.
188
189 If MtrrSetting is not NULL, returns the default MTRR cache type from input
190 MTRR settings buffer.
191 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
192
193 @param[in] MtrrSetting A buffer holding all MTRRs content.
194
195 @return The default MTRR cache type.
196
197 **/
198 MTRR_MEMORY_CACHE_TYPE
199 MtrrGetDefaultMemoryTypeWorker (
200 IN MTRR_SETTINGS *MtrrSetting
201 )
202 {
203 if (MtrrSetting == NULL) {
204 return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);
205 } else {
206 return (MTRR_MEMORY_CACHE_TYPE) (MtrrSetting->MtrrDefType & 0x7);
207 }
208 }
209
210
211 /**
212 Returns the default MTRR cache type for the system.
213
214 @return The default MTRR cache type.
215
216 **/
217 MTRR_MEMORY_CACHE_TYPE
218 EFIAPI
219 MtrrGetDefaultMemoryType (
220 VOID
221 )
222 {
223 if (!IsMtrrSupported ()) {
224 return CacheUncacheable;
225 }
226 return MtrrGetDefaultMemoryTypeWorker (NULL);
227 }
228
229 /**
230 Preparation before programming MTRR.
231
232 This function will do some preparation for programming MTRRs:
233 disable cache, invalid cache and disable MTRR caching functionality
234
235 @param[out] MtrrContext Pointer to context to save
236
237 **/
238 VOID
239 PreMtrrChange (
240 OUT MTRR_CONTEXT *MtrrContext
241 )
242 {
243 //
244 // Disable interrupts and save current interrupt state
245 //
246 MtrrContext->InterruptState = SaveAndDisableInterrupts();
247
248 //
249 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
250 //
251 AsmDisableCache ();
252
253 //
254 // Save original CR4 value and clear PGE flag (Bit 7)
255 //
256 MtrrContext->Cr4 = AsmReadCr4 ();
257 AsmWriteCr4 (MtrrContext->Cr4 & (~BIT7));
258
259 //
260 // Flush all TLBs
261 //
262 CpuFlushTlb ();
263
264 //
265 // Disable MTRRs
266 //
267 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);
268 }
269
270 /**
271 Cleaning up after programming MTRRs.
272
273 This function will do some clean up after programming MTRRs:
274 Flush all TLBs, re-enable caching, restore CR4.
275
276 @param[in] MtrrContext Pointer to context to restore
277
278 **/
279 VOID
280 PostMtrrChangeEnableCache (
281 IN MTRR_CONTEXT *MtrrContext
282 )
283 {
284 //
285 // Flush all TLBs
286 //
287 CpuFlushTlb ();
288
289 //
290 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
291 //
292 AsmEnableCache ();
293
294 //
295 // Restore original CR4 value
296 //
297 AsmWriteCr4 (MtrrContext->Cr4);
298
299 //
300 // Restore original interrupt state
301 //
302 SetInterruptState (MtrrContext->InterruptState);
303 }
304
305 /**
306 Cleaning up after programming MTRRs.
307
308 This function will do some clean up after programming MTRRs:
309 enable MTRR caching functionality, and enable cache
310
311 @param[in] MtrrContext Pointer to context to restore
312
313 **/
314 VOID
315 PostMtrrChange (
316 IN MTRR_CONTEXT *MtrrContext
317 )
318 {
319 //
320 // Enable Cache MTRR
321 //
322 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);
323
324 PostMtrrChangeEnableCache (MtrrContext);
325 }
326
327 /**
328 Worker function gets the content in fixed MTRRs
329
330 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
331
332 @retval The pointer of FixedSettings
333
334 **/
335 MTRR_FIXED_SETTINGS*
336 MtrrGetFixedMtrrWorker (
337 OUT MTRR_FIXED_SETTINGS *FixedSettings
338 )
339 {
340 UINT32 Index;
341
342 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
343 FixedSettings->Mtrr[Index] =
344 AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
345 }
346
347 return FixedSettings;
348 }
349
350
351 /**
352 This function gets the content in fixed MTRRs
353
354 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
355
356 @retval The pointer of FixedSettings
357
358 **/
359 MTRR_FIXED_SETTINGS*
360 EFIAPI
361 MtrrGetFixedMtrr (
362 OUT MTRR_FIXED_SETTINGS *FixedSettings
363 )
364 {
365 if (!IsMtrrSupported ()) {
366 return FixedSettings;
367 }
368
369 return MtrrGetFixedMtrrWorker (FixedSettings);
370 }
371
372
373 /**
374 Worker function will get the raw value in variable MTRRs
375
376 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
377 MTRR settings buffer.
378 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
379
380 @param[in] MtrrSetting A buffer holding all MTRRs content.
381 @param[in] VariableMtrrCount Number of variable MTRRs.
382 @param[out] VariableSettings A buffer to hold variable MTRRs content.
383
384 @return The VariableSettings input pointer
385
386 **/
387 MTRR_VARIABLE_SETTINGS*
388 MtrrGetVariableMtrrWorker (
389 IN MTRR_SETTINGS *MtrrSetting,
390 IN UINT32 VariableMtrrCount,
391 OUT MTRR_VARIABLE_SETTINGS *VariableSettings
392 )
393 {
394 UINT32 Index;
395
396 ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
397
398 for (Index = 0; Index < VariableMtrrCount; Index++) {
399 if (MtrrSetting == NULL) {
400 VariableSettings->Mtrr[Index].Base =
401 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));
402 VariableSettings->Mtrr[Index].Mask =
403 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);
404 } else {
405 VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;
406 VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;
407 }
408 }
409
410 return VariableSettings;
411 }
412
413 /**
414 This function will get the raw value in variable MTRRs
415
416 @param[out] VariableSettings A buffer to hold variable MTRRs content.
417
418 @return The VariableSettings input pointer
419
420 **/
421 MTRR_VARIABLE_SETTINGS*
422 EFIAPI
423 MtrrGetVariableMtrr (
424 OUT MTRR_VARIABLE_SETTINGS *VariableSettings
425 )
426 {
427 if (!IsMtrrSupported ()) {
428 return VariableSettings;
429 }
430
431 return MtrrGetVariableMtrrWorker (
432 NULL,
433 GetVariableMtrrCountWorker (),
434 VariableSettings
435 );
436 }
437
438 /**
439 Programs fixed MTRRs registers.
440
441 @param[in] MemoryCacheType The memory type to set.
442 @param[in, out] Base The base address of memory range.
443 @param[in, out] Length The length of memory range.
444 @param[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.
445 On return, the current index of the fixed MTRR MSR to program.
446 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
447 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
448
449 @retval RETURN_SUCCESS The cache type was updated successfully
450 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
451 for the fixed MTRRs.
452
453 **/
454 RETURN_STATUS
455 ProgramFixedMtrr (
456 IN UINT64 MemoryCacheType,
457 IN OUT UINT64 *Base,
458 IN OUT UINT64 *Length,
459 IN OUT UINT32 *LastMsrNum,
460 OUT UINT64 *ReturnClearMask,
461 OUT UINT64 *ReturnOrMask
462 )
463 {
464 UINT32 MsrNum;
465 UINT32 ByteShift;
466 UINT32 OrMask[2];
467 UINT32 ClearMask[2];
468 UINT64 SubLength;
469
470 *(UINT64 *)OrMask = 0;
471 *(UINT64 *)ClearMask = 0;
472
473 for (MsrNum = *LastMsrNum + 1; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {
474 if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&
475 (*Base <
476 (
477 mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +
478 (8 * mMtrrLibFixedMtrrTable[MsrNum].Length)
479 )
480 )
481 ) {
482 break;
483 }
484 }
485
486 if (MsrNum >= MTRR_NUMBER_OF_FIXED_MTRR) {
487 return RETURN_UNSUPPORTED;
488 }
489
490 //
491 // We found the fixed MTRR to be programmed
492 //
493 ByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)
494 / mMtrrLibFixedMtrrTable[MsrNum].Length;
495
496 if (ByteShift >= 8) {
497 return RETURN_UNSUPPORTED;
498 }
499
500 if (ByteShift < 4) {
501 OrMask[0] = OR_SEED * (UINT32)MemoryCacheType;
502 ClearMask[0] = CLEAR_SEED;
503 OrMask[1] = (OR_SEED * (UINT32)MemoryCacheType) >> ((4 - ByteShift) * 8);
504 ClearMask[1] = CLEAR_SEED >> ((4 - ByteShift) * 8);
505 } else {
506 OrMask[0] = (OR_SEED * (UINT32)MemoryCacheType) >> ((8 - ByteShift) * 8);
507 ClearMask[0] = CLEAR_SEED >> ((8 - ByteShift) * 8);
508 }
509
510 SubLength = mMtrrLibFixedMtrrTable[MsrNum].Length * (8 - ByteShift);
511 if (*Length < SubLength) {
512 return RETURN_UNSUPPORTED;
513 }
514
515 *Length -= SubLength;
516 *Base += SubLength;
517
518 *LastMsrNum = MsrNum;
519 *ReturnClearMask = *(UINT64 *)ClearMask;
520 *ReturnOrMask = *(UINT64 *)OrMask;
521
522 return RETURN_SUCCESS;
523 }
524
525
526 /**
527 Worker function gets the attribute of variable MTRRs.
528
529 This function shadows the content of variable MTRRs into an
530 internal array: VariableMtrr.
531
532 @param[in] VariableSettings The variable MTRR values to shadow
533 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
534 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
535 @param[in] MtrrValidAddressMask The valid address mask for MTRR
536 @param[out] VariableMtrr The array to shadow variable MTRRs content
537
538 @return The return value of this parameter indicates the
539 number of MTRRs which has been used.
540
541 **/
542 UINT32
543 MtrrGetMemoryAttributeInVariableMtrrWorker (
544 IN MTRR_VARIABLE_SETTINGS *VariableSettings,
545 IN UINTN FirmwareVariableMtrrCount,
546 IN UINT64 MtrrValidBitsMask,
547 IN UINT64 MtrrValidAddressMask,
548 OUT VARIABLE_MTRR *VariableMtrr
549 )
550 {
551 UINTN Index;
552 UINT32 UsedMtrr;
553
554 ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);
555 for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) {
556 if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {
557 VariableMtrr[Index].Msr = (UINT32)Index;
558 VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);
559 VariableMtrr[Index].Length = ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
560 VariableMtrr[Index].Type = (VariableSettings->Mtrr[Index].Base & 0x0ff);
561 VariableMtrr[Index].Valid = TRUE;
562 VariableMtrr[Index].Used = TRUE;
563 UsedMtrr++;
564 }
565 }
566 return UsedMtrr;
567 }
568
569
570 /**
571 Gets the attribute of variable MTRRs.
572
573 This function shadows the content of variable MTRRs into an
574 internal array: VariableMtrr.
575
576 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
577 @param[in] MtrrValidAddressMask The valid address mask for MTRR
578 @param[out] VariableMtrr The array to shadow variable MTRRs content
579
580 @return The return value of this paramter indicates the
581 number of MTRRs which has been used.
582
583 **/
584 UINT32
585 EFIAPI
586 MtrrGetMemoryAttributeInVariableMtrr (
587 IN UINT64 MtrrValidBitsMask,
588 IN UINT64 MtrrValidAddressMask,
589 OUT VARIABLE_MTRR *VariableMtrr
590 )
591 {
592 MTRR_VARIABLE_SETTINGS VariableSettings;
593
594 if (!IsMtrrSupported ()) {
595 return 0;
596 }
597
598 MtrrGetVariableMtrrWorker (
599 NULL,
600 GetVariableMtrrCountWorker (),
601 &VariableSettings
602 );
603
604 return MtrrGetMemoryAttributeInVariableMtrrWorker (
605 &VariableSettings,
606 GetFirmwareVariableMtrrCountWorker (),
607 MtrrValidBitsMask,
608 MtrrValidAddressMask,
609 VariableMtrr
610 );
611 }
612
613
614 /**
615 Checks overlap between given memory range and MTRRs.
616
617 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
618 to firmware.
619 @param[in] Start The start address of memory range.
620 @param[in] End The end address of memory range.
621 @param[in] VariableMtrr The array to shadow variable MTRRs content
622
623 @retval TRUE Overlap exists.
624 @retval FALSE No overlap.
625
626 **/
627 BOOLEAN
628 CheckMemoryAttributeOverlap (
629 IN UINTN FirmwareVariableMtrrCount,
630 IN PHYSICAL_ADDRESS Start,
631 IN PHYSICAL_ADDRESS End,
632 IN VARIABLE_MTRR *VariableMtrr
633 )
634 {
635 UINT32 Index;
636
637 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
638 if (
639 VariableMtrr[Index].Valid &&
640 !(
641 (Start > (VariableMtrr[Index].BaseAddress +
642 VariableMtrr[Index].Length - 1)
643 ) ||
644 (End < VariableMtrr[Index].BaseAddress)
645 )
646 ) {
647 return TRUE;
648 }
649 }
650
651 return FALSE;
652 }
653
654
655 /**
656 Marks a variable MTRR as non-valid.
657
658 @param[in] Index The index of the array VariableMtrr to be invalidated
659 @param[in] VariableMtrr The array to shadow variable MTRRs content
660 @param[out] UsedMtrr The number of MTRRs which has already been used
661
662 **/
663 VOID
664 InvalidateShadowMtrr (
665 IN UINTN Index,
666 IN VARIABLE_MTRR *VariableMtrr,
667 OUT UINT32 *UsedMtrr
668 )
669 {
670 VariableMtrr[Index].Valid = FALSE;
671 *UsedMtrr = *UsedMtrr - 1;
672 }
673
674
675 /**
676 Combines memory attributes.
677
678 If overlap exists between given memory range and MTRRs, try to combine them.
679
680 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
681 available to firmware.
682 @param[in] Attributes The memory type to set.
683 @param[in, out] Base The base address of memory range.
684 @param[in, out] Length The length of memory range.
685 @param[in] VariableMtrr The array to shadow variable MTRRs content
686 @param[in, out] UsedMtrr The number of MTRRs which has already been used
687 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
688
689 @retval EFI_SUCCESS Memory region successfully combined.
690 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
691
692 **/
693 RETURN_STATUS
694 CombineMemoryAttribute (
695 IN UINT32 FirmwareVariableMtrrCount,
696 IN UINT64 Attributes,
697 IN OUT UINT64 *Base,
698 IN OUT UINT64 *Length,
699 IN VARIABLE_MTRR *VariableMtrr,
700 IN OUT UINT32 *UsedMtrr,
701 OUT BOOLEAN *OverwriteExistingMtrr
702 )
703 {
704 UINT32 Index;
705 UINT64 CombineStart;
706 UINT64 CombineEnd;
707 UINT64 MtrrEnd;
708 UINT64 EndAddress;
709 BOOLEAN CoveredByExistingMtrr;
710
711 *OverwriteExistingMtrr = FALSE;
712 CoveredByExistingMtrr = FALSE;
713 EndAddress = *Base +*Length - 1;
714
715 for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
716
717 MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;
718 if (
719 !VariableMtrr[Index].Valid ||
720 (
721 *Base > (MtrrEnd) ||
722 (EndAddress < VariableMtrr[Index].BaseAddress)
723 )
724 ) {
725 continue;
726 }
727
728 //
729 // Combine same attribute MTRR range
730 //
731 if (Attributes == VariableMtrr[Index].Type) {
732 //
733 // if the MTRR range contain the request range, set a flag, then continue to
734 // invalidate any MTRR of the same request range with higher priority cache type.
735 //
736 if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {
737 CoveredByExistingMtrr = TRUE;
738 continue;
739 }
740 //
741 // invalid this MTRR, and program the combine range
742 //
743 CombineStart =
744 (*Base) < VariableMtrr[Index].BaseAddress ?
745 (*Base) :
746 VariableMtrr[Index].BaseAddress;
747 CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;
748
749 //
750 // Record the MTRR usage status in VariableMtrr array.
751 //
752 InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
753 *Base = CombineStart;
754 *Length = CombineEnd - CombineStart + 1;
755 EndAddress = CombineEnd;
756 *OverwriteExistingMtrr = TRUE;
757 continue;
758 } else {
759 //
760 // The cache type is different, but the range is convered by one MTRR
761 //
762 if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {
763 InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
764 continue;
765 }
766
767 }
768
769 if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&
770 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||
771 (Attributes == MTRR_CACHE_WRITE_BACK &&
772 VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||
773 (Attributes == MTRR_CACHE_UNCACHEABLE) ||
774 (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)
775 ) {
776 *OverwriteExistingMtrr = TRUE;
777 continue;
778 }
779 //
780 // Other type memory overlap is invalid
781 //
782 return RETURN_ACCESS_DENIED;
783 }
784
785 if (CoveredByExistingMtrr) {
786 *Length = 0;
787 }
788
789 return RETURN_SUCCESS;
790 }
791
792
793 /**
794 Calculates the maximum value which is a power of 2, but less the MemoryLength.
795
796 @param[in] MemoryLength The number to pass in.
797
798 @return The maximum value which is align to power of 2 and less the MemoryLength
799
800 **/
801 UINT64
802 Power2MaxMemory (
803 IN UINT64 MemoryLength
804 )
805 {
806 UINT64 Result;
807
808 if (RShiftU64 (MemoryLength, 32) != 0) {
809 Result = LShiftU64 (
810 (UINT64) GetPowerOfTwo32 (
811 (UINT32) RShiftU64 (MemoryLength, 32)
812 ),
813 32
814 );
815 } else {
816 Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);
817 }
818
819 return Result;
820 }
821
822
823 /**
824 Determines the MTRR numbers used to program a memory range.
825
826 This function first checks the alignment of the base address.
827 If the alignment of the base address <= Length, cover the memory range
828 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
829 Length -= alignment. Repeat the step until alignment > Length.
830
831 Then this function determines which direction of programming the variable
832 MTRRs for the remaining length will use fewer MTRRs.
833
834 @param[in] BaseAddress Length of Memory to program MTRR
835 @param[in] Length Length of Memory to program MTRR
836 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
837
838 @retval TRUE Positive direction is better.
839 FALSE Negative direction is better.
840
841 **/
842 BOOLEAN
843 GetMtrrNumberAndDirection (
844 IN UINT64 BaseAddress,
845 IN UINT64 Length,
846 IN UINTN *MtrrNumber
847 )
848 {
849 UINT64 TempQword;
850 UINT64 Alignment;
851 UINT32 Positive;
852 UINT32 Subtractive;
853
854 *MtrrNumber = 0;
855
856 if (BaseAddress != 0) {
857 do {
858 //
859 // Calculate the alignment of the base address.
860 //
861 Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
862
863 if (Alignment > Length) {
864 break;
865 }
866
867 (*MtrrNumber)++;
868 BaseAddress += Alignment;
869 Length -= Alignment;
870 } while (TRUE);
871
872 if (Length == 0) {
873 return TRUE;
874 }
875 }
876
877 TempQword = Length;
878 Positive = 0;
879 Subtractive = 0;
880
881 do {
882 TempQword -= Power2MaxMemory (TempQword);
883 Positive++;
884 } while (TempQword != 0);
885
886 TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;
887 Subtractive++;
888 do {
889 TempQword -= Power2MaxMemory (TempQword);
890 Subtractive++;
891 } while (TempQword != 0);
892
893 if (Positive <= Subtractive) {
894 *MtrrNumber += Positive;
895 return TRUE;
896 } else {
897 *MtrrNumber += Subtractive;
898 return FALSE;
899 }
900 }
901
902 /**
903 Invalid variable MTRRs according to the value in the shadow array.
904
905 This function programs MTRRs according to the values specified
906 in the shadow array.
907
908 @param[in, out] VariableSettings Variable MTRR settings
909 @param[in] VariableMtrrCount Number of variable MTRRs
910 @param[in, out] VariableMtrr Shadow of variable MTRR contents
911
912 **/
913 VOID
914 InvalidateMtrr (
915 IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings,
916 IN UINTN VariableMtrrCount,
917 IN OUT VARIABLE_MTRR *VariableMtrr
918 )
919 {
920 UINTN Index;
921
922 for (Index = 0; Index < VariableMtrrCount; Index++) {
923 if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {
924 VariableSettings->Mtrr[Index].Base = 0;
925 VariableSettings->Mtrr[Index].Mask = 0;
926 VariableMtrr[Index].Used = FALSE;
927 }
928 }
929 }
930
931
932 /**
933 Programs variable MTRRs
934
935 This function programs variable MTRRs
936
937 @param[in, out] VariableSettings Variable MTRR settings.
938 @param[in] MtrrNumber Index of MTRR to program.
939 @param[in] BaseAddress Base address of memory region.
940 @param[in] Length Length of memory region.
941 @param[in] MemoryCacheType Memory type to set.
942 @param[in] MtrrValidAddressMask The valid address mask for MTRR
943
944 **/
945 VOID
946 ProgramVariableMtrr (
947 IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings,
948 IN UINTN MtrrNumber,
949 IN PHYSICAL_ADDRESS BaseAddress,
950 IN UINT64 Length,
951 IN UINT64 MemoryCacheType,
952 IN UINT64 MtrrValidAddressMask
953 )
954 {
955 UINT64 TempQword;
956
957 //
958 // MTRR Physical Base
959 //
960 TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;
961 VariableSettings->Mtrr[MtrrNumber].Base = TempQword;
962
963 //
964 // MTRR Physical Mask
965 //
966 TempQword = ~(Length - 1);
967 VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
968 }
969
970
971 /**
972 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
973
974 If MtrrSetting is not NULL, gets the default memory attribute from input
975 MTRR settings buffer.
976 If MtrrSetting is NULL, gets the default memory attribute from MSR.
977
978 @param[in] MtrrSetting A buffer holding all MTRRs content.
979 @param[in] MtrrType MTRR memory type
980
981 @return The enum item in MTRR_MEMORY_CACHE_TYPE
982
983 **/
984 MTRR_MEMORY_CACHE_TYPE
985 GetMemoryCacheTypeFromMtrrType (
986 IN MTRR_SETTINGS *MtrrSetting,
987 IN UINT64 MtrrType
988 )
989 {
990 switch (MtrrType) {
991 case MTRR_CACHE_UNCACHEABLE:
992 return CacheUncacheable;
993 case MTRR_CACHE_WRITE_COMBINING:
994 return CacheWriteCombining;
995 case MTRR_CACHE_WRITE_THROUGH:
996 return CacheWriteThrough;
997 case MTRR_CACHE_WRITE_PROTECTED:
998 return CacheWriteProtected;
999 case MTRR_CACHE_WRITE_BACK:
1000 return CacheWriteBack;
1001 default:
1002 //
1003 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1004 // no MTRR covers the range
1005 //
1006 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting);
1007 }
1008 }
1009
1010 /**
1011 Initializes the valid bits mask and valid address mask for MTRRs.
1012
1013 This function initializes the valid bits mask and valid address mask for MTRRs.
1014
1015 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1016 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1017
1018 **/
1019 VOID
1020 MtrrLibInitializeMtrrMask (
1021 OUT UINT64 *MtrrValidBitsMask,
1022 OUT UINT64 *MtrrValidAddressMask
1023 )
1024 {
1025 UINT32 RegEax;
1026 UINT8 PhysicalAddressBits;
1027
1028 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
1029
1030 if (RegEax >= 0x80000008) {
1031 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
1032
1033 PhysicalAddressBits = (UINT8) RegEax;
1034
1035 *MtrrValidBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
1036 *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;
1037 } else {
1038 *MtrrValidBitsMask = MTRR_LIB_MSR_VALID_MASK;
1039 *MtrrValidAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
1040 }
1041 }
1042
1043
1044 /**
1045 Determines the real attribute of a memory range.
1046
1047 This function is to arbitrate the real attribute of the memory when
1048 there are 2 MTRRs covers the same memory range. For further details,
1049 please refer the IA32 Software Developer's Manual, Volume 3,
1050 Section 10.11.4.1.
1051
1052 @param[in] MtrrType1 The first kind of Memory type
1053 @param[in] MtrrType2 The second kind of memory type
1054
1055 **/
1056 UINT64
1057 MtrrPrecedence (
1058 IN UINT64 MtrrType1,
1059 IN UINT64 MtrrType2
1060 )
1061 {
1062 UINT64 MtrrType;
1063
1064 MtrrType = MTRR_CACHE_INVALID_TYPE;
1065 switch (MtrrType1) {
1066 case MTRR_CACHE_UNCACHEABLE:
1067 MtrrType = MTRR_CACHE_UNCACHEABLE;
1068 break;
1069 case MTRR_CACHE_WRITE_COMBINING:
1070 if (
1071 MtrrType2==MTRR_CACHE_WRITE_COMBINING ||
1072 MtrrType2==MTRR_CACHE_UNCACHEABLE
1073 ) {
1074 MtrrType = MtrrType2;
1075 }
1076 break;
1077 case MTRR_CACHE_WRITE_THROUGH:
1078 if (
1079 MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
1080 MtrrType2==MTRR_CACHE_WRITE_BACK
1081 ) {
1082 MtrrType = MTRR_CACHE_WRITE_THROUGH;
1083 } else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {
1084 MtrrType = MTRR_CACHE_UNCACHEABLE;
1085 }
1086 break;
1087 case MTRR_CACHE_WRITE_PROTECTED:
1088 if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||
1089 MtrrType2 == MTRR_CACHE_UNCACHEABLE) {
1090 MtrrType = MtrrType2;
1091 }
1092 break;
1093 case MTRR_CACHE_WRITE_BACK:
1094 if (
1095 MtrrType2== MTRR_CACHE_UNCACHEABLE ||
1096 MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
1097 MtrrType2== MTRR_CACHE_WRITE_BACK
1098 ) {
1099 MtrrType = MtrrType2;
1100 }
1101 break;
1102 case MTRR_CACHE_INVALID_TYPE:
1103 MtrrType = MtrrType2;
1104 break;
1105 default:
1106 break;
1107 }
1108
1109 if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) {
1110 MtrrType = MtrrType1;
1111 }
1112 return MtrrType;
1113 }
1114
1115 /**
1116 Worker function will get the memory cache type of the specific address.
1117
1118 If MtrrSetting is not NULL, gets the memory cache type from input
1119 MTRR settings buffer.
1120 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1121
1122 @param[in] MtrrSetting A buffer holding all MTRRs content.
1123 @param[in] Address The specific address
1124
1125 @return Memory cache type of the specific address
1126
1127 **/
1128 MTRR_MEMORY_CACHE_TYPE
1129 MtrrGetMemoryAttributeByAddressWorker (
1130 IN MTRR_SETTINGS *MtrrSetting,
1131 IN PHYSICAL_ADDRESS Address
1132 )
1133 {
1134 UINT64 TempQword;
1135 UINTN Index;
1136 UINTN SubIndex;
1137 UINT64 MtrrType;
1138 UINT64 TempMtrrType;
1139 MTRR_MEMORY_CACHE_TYPE CacheType;
1140 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
1141 UINT64 MtrrValidBitsMask;
1142 UINT64 MtrrValidAddressMask;
1143 UINTN VariableMtrrCount;
1144 MTRR_VARIABLE_SETTINGS VariableSettings;
1145
1146 //
1147 // Check if MTRR is enabled, if not, return UC as attribute
1148 //
1149 if (MtrrSetting == NULL) {
1150 TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
1151 } else {
1152 TempQword = MtrrSetting->MtrrDefType;
1153 }
1154 MtrrType = MTRR_CACHE_INVALID_TYPE;
1155
1156 if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
1157 return CacheUncacheable;
1158 }
1159
1160 //
1161 // If address is less than 1M, then try to go through the fixed MTRR
1162 //
1163 if (Address < BASE_1MB) {
1164 if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {
1165 //
1166 // Go through the fixed MTRR
1167 //
1168 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1169 if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&
1170 Address < (
1171 mMtrrLibFixedMtrrTable[Index].BaseAddress +
1172 (mMtrrLibFixedMtrrTable[Index].Length * 8)
1173 )
1174 ) {
1175 SubIndex =
1176 ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /
1177 mMtrrLibFixedMtrrTable[Index].Length;
1178 if (MtrrSetting == NULL) {
1179 TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
1180 } else {
1181 TempQword = MtrrSetting->Fixed.Mtrr[Index];
1182 }
1183 MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;
1184 return GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);
1185 }
1186 }
1187 }
1188 }
1189 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
1190
1191 MtrrGetVariableMtrrWorker (
1192 MtrrSetting,
1193 GetVariableMtrrCountWorker (),
1194 &VariableSettings
1195 );
1196
1197 MtrrGetMemoryAttributeInVariableMtrrWorker (
1198 &VariableSettings,
1199 GetFirmwareVariableMtrrCountWorker (),
1200 MtrrValidBitsMask,
1201 MtrrValidAddressMask,
1202 VariableMtrr
1203 );
1204
1205 //
1206 // Go through the variable MTRR
1207 //
1208 VariableMtrrCount = GetVariableMtrrCountWorker ();
1209 ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
1210
1211 for (Index = 0; Index < VariableMtrrCount; Index++) {
1212 if (VariableMtrr[Index].Valid) {
1213 if (Address >= VariableMtrr[Index].BaseAddress &&
1214 Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {
1215 TempMtrrType = VariableMtrr[Index].Type;
1216 MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);
1217 }
1218 }
1219 }
1220 CacheType = GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);
1221
1222 return CacheType;
1223 }
1224
1225
1226 /**
1227 This function will get the memory cache type of the specific address.
1228
1229 This function is mainly for debug purpose.
1230
1231 @param[in] Address The specific address
1232
1233 @return Memory cache type of the specific address
1234
1235 **/
1236 MTRR_MEMORY_CACHE_TYPE
1237 EFIAPI
1238 MtrrGetMemoryAttribute (
1239 IN PHYSICAL_ADDRESS Address
1240 )
1241 {
1242 if (!IsMtrrSupported ()) {
1243 return CacheUncacheable;
1244 }
1245
1246 return MtrrGetMemoryAttributeByAddressWorker (NULL, Address);
1247 }
1248
1249 /**
1250 Worker function prints all MTRRs for debugging.
1251
1252 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1253 settings buffer.
1254 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1255
1256 @param MtrrSetting A buffer holding all MTRRs content.
1257 **/
1258 VOID
1259 MtrrDebugPrintAllMtrrsWorker (
1260 IN MTRR_SETTINGS *MtrrSetting
1261 )
1262 {
1263 DEBUG_CODE (
1264 MTRR_SETTINGS LocalMtrrs;
1265 MTRR_SETTINGS *Mtrrs;
1266 UINTN Index;
1267 UINTN Index1;
1268 UINTN VariableMtrrCount;
1269 UINT64 Base;
1270 UINT64 Limit;
1271 UINT64 MtrrBase;
1272 UINT64 MtrrLimit;
1273 UINT64 RangeBase;
1274 UINT64 RangeLimit;
1275 UINT64 NoRangeBase;
1276 UINT64 NoRangeLimit;
1277 UINT32 RegEax;
1278 UINTN MemoryType;
1279 UINTN PreviousMemoryType;
1280 BOOLEAN Found;
1281
1282 if (!IsMtrrSupported ()) {
1283 return;
1284 }
1285
1286 DEBUG((DEBUG_CACHE, "MTRR Settings\n"));
1287 DEBUG((DEBUG_CACHE, "=============\n"));
1288
1289 if (MtrrSetting != NULL) {
1290 Mtrrs = MtrrSetting;
1291 } else {
1292 MtrrGetAllMtrrs (&LocalMtrrs);
1293 Mtrrs = &LocalMtrrs;
1294 }
1295
1296 DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));
1297 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1298 DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));
1299 }
1300
1301 VariableMtrrCount = GetVariableMtrrCount ();
1302 for (Index = 0; Index < VariableMtrrCount; Index++) {
1303 DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1304 Index,
1305 Mtrrs->Variables.Mtrr[Index].Base,
1306 Mtrrs->Variables.Mtrr[Index].Mask
1307 ));
1308 }
1309 DEBUG((DEBUG_CACHE, "\n"));
1310 DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));
1311 DEBUG((DEBUG_CACHE, "====================================\n"));
1312
1313 Base = 0;
1314 PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
1315 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1316 Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;
1317 for (Index1 = 0; Index1 < 8; Index1++) {
1318 MemoryType = (UINTN)(RShiftU64 (Mtrrs->Fixed.Mtrr[Index], Index1 * 8) & 0xff);
1319 if (MemoryType > CacheWriteBack) {
1320 MemoryType = MTRR_CACHE_INVALID_TYPE;
1321 }
1322 if (MemoryType != PreviousMemoryType) {
1323 if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
1324 DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
1325 }
1326 PreviousMemoryType = MemoryType;
1327 DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
1328 }
1329 Base += mMtrrLibFixedMtrrTable[Index].Length;
1330 }
1331 }
1332 DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
1333
1334 VariableMtrrCount = GetVariableMtrrCount ();
1335
1336 Limit = BIT36 - 1;
1337 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
1338 if (RegEax >= 0x80000008) {
1339 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
1340 Limit = LShiftU64 (1, RegEax & 0xff) - 1;
1341 }
1342 Base = BASE_1MB;
1343 PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
1344 do {
1345 MemoryType = MtrrGetMemoryAttributeByAddressWorker (Mtrrs, Base);
1346 if (MemoryType > CacheWriteBack) {
1347 MemoryType = MTRR_CACHE_INVALID_TYPE;
1348 }
1349
1350 if (MemoryType != PreviousMemoryType) {
1351 if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
1352 DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
1353 }
1354 PreviousMemoryType = MemoryType;
1355 DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
1356 }
1357
1358 RangeBase = BASE_1MB;
1359 NoRangeBase = BASE_1MB;
1360 RangeLimit = Limit;
1361 NoRangeLimit = Limit;
1362
1363 for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {
1364 if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
1365 //
1366 // If mask is not valid, then do not display range
1367 //
1368 continue;
1369 }
1370 MtrrBase = (Mtrrs->Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));
1371 MtrrLimit = MtrrBase + ((~(Mtrrs->Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);
1372
1373 if (Base >= MtrrBase && Base < MtrrLimit) {
1374 Found = TRUE;
1375 }
1376
1377 if (Base >= MtrrBase && MtrrBase > RangeBase) {
1378 RangeBase = MtrrBase;
1379 }
1380 if (Base > MtrrLimit && MtrrLimit > RangeBase) {
1381 RangeBase = MtrrLimit + 1;
1382 }
1383 if (Base < MtrrBase && MtrrBase < RangeLimit) {
1384 RangeLimit = MtrrBase - 1;
1385 }
1386 if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {
1387 RangeLimit = MtrrLimit;
1388 }
1389
1390 if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {
1391 NoRangeBase = MtrrLimit + 1;
1392 }
1393 if (Base < MtrrBase && NoRangeLimit > MtrrBase) {
1394 NoRangeLimit = MtrrBase - 1;
1395 }
1396 }
1397
1398 if (Found) {
1399 Base = RangeLimit + 1;
1400 } else {
1401 Base = NoRangeLimit + 1;
1402 }
1403 } while (Base < Limit);
1404 DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));
1405 );
1406 }
1407
1408
1409 /**
1410 This function prints all MTRRs for debugging.
1411 **/
1412 VOID
1413 EFIAPI
1414 MtrrDebugPrintAllMtrrs (
1415 VOID
1416 )
1417 {
1418 MtrrDebugPrintAllMtrrsWorker (NULL);
1419 }
1420
1421
1422 /**
1423 Worker function attempts to set the attributes for a memory range.
1424
1425 If MtrrSettings is not NULL, set the attributes into the input MTRR
1426 settings buffer.
1427 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1428
1429 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1430 @param[in] BaseAddress The physical address that is the start
1431 address of a memory region.
1432 @param[in] Length The size in bytes of the memory region.
1433 @param[in] Attribute The bit mask of attributes to set for the
1434 memory region.
1435
1436 @retval RETURN_SUCCESS The attributes were set for the memory
1437 region.
1438 @retval RETURN_INVALID_PARAMETER Length is zero.
1439 @retval RETURN_UNSUPPORTED The processor does not support one or
1440 more bytes of the memory resource range
1441 specified by BaseAddress and Length.
1442 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1443 for the memory resource range specified
1444 by BaseAddress and Length.
1445 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1446 range specified by BaseAddress and Length
1447 cannot be modified.
1448 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1449 modify the attributes of the memory
1450 resource range.
1451
1452 **/
1453 RETURN_STATUS
1454 MtrrSetMemoryAttributeWorker (
1455 IN OUT MTRR_SETTINGS *MtrrSetting,
1456 IN PHYSICAL_ADDRESS BaseAddress,
1457 IN UINT64 Length,
1458 IN MTRR_MEMORY_CACHE_TYPE Attribute
1459 )
1460 {
1461 UINT64 TempQword;
1462 RETURN_STATUS Status;
1463 UINT64 MemoryType;
1464 UINT64 Alignment;
1465 BOOLEAN OverLap;
1466 BOOLEAN Positive;
1467 UINT32 MsrNum;
1468 UINTN MtrrNumber;
1469 VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
1470 UINT32 UsedMtrr;
1471 UINT64 MtrrValidBitsMask;
1472 UINT64 MtrrValidAddressMask;
1473 BOOLEAN OverwriteExistingMtrr;
1474 UINT32 FirmwareVariableMtrrCount;
1475 MTRR_CONTEXT MtrrContext;
1476 BOOLEAN MtrrContextValid;
1477 BOOLEAN FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR];
1478 BOOLEAN FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR];
1479 MTRR_FIXED_SETTINGS WorkingFixedSettings;
1480 UINT32 VariableMtrrCount;
1481 MTRR_VARIABLE_SETTINGS OriginalVariableSettings;
1482 BOOLEAN ProgramVariableSettings;
1483 MTRR_VARIABLE_SETTINGS WorkingVariableSettings;
1484 UINT32 Index;
1485 UINT64 ClearMask;
1486 UINT64 OrMask;
1487 UINT64 NewValue;
1488 MTRR_VARIABLE_SETTINGS *VariableSettings;
1489
1490 MtrrContextValid = FALSE;
1491 VariableMtrrCount = 0;
1492 ZeroMem (&WorkingFixedSettings, sizeof (WorkingFixedSettings));
1493 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1494 FixedSettingsValid[Index] = FALSE;
1495 FixedSettingsModified[Index] = FALSE;
1496 }
1497 ProgramVariableSettings = FALSE;
1498
1499 if (!IsMtrrSupported ()) {
1500 Status = RETURN_UNSUPPORTED;
1501 goto Done;
1502 }
1503
1504 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
1505
1506 TempQword = 0;
1507 MemoryType = (UINT64)Attribute;
1508 OverwriteExistingMtrr = FALSE;
1509
1510 //
1511 // Check for an invalid parameter
1512 //
1513 if (Length == 0) {
1514 Status = RETURN_INVALID_PARAMETER;
1515 goto Done;
1516 }
1517
1518 if (
1519 (BaseAddress & ~MtrrValidAddressMask) != 0 ||
1520 (Length & ~MtrrValidAddressMask) != 0
1521 ) {
1522 Status = RETURN_UNSUPPORTED;
1523 goto Done;
1524 }
1525
1526 //
1527 // Check if Fixed MTRR
1528 //
1529 Status = RETURN_SUCCESS;
1530 if (BaseAddress < BASE_1MB) {
1531 MsrNum = (UINT32)-1;
1532 while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
1533 Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask);
1534 if (RETURN_ERROR (Status)) {
1535 goto Done;
1536 }
1537 if (MtrrSetting != NULL) {
1538 MtrrSetting->Fixed.Mtrr[MsrNum] = (MtrrSetting->Fixed.Mtrr[MsrNum] & ~ClearMask) | OrMask;
1539 MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED;
1540 } else {
1541 if (!FixedSettingsValid[MsrNum]) {
1542 WorkingFixedSettings.Mtrr[MsrNum] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr);
1543 FixedSettingsValid[MsrNum] = TRUE;
1544 }
1545 NewValue = (WorkingFixedSettings.Mtrr[MsrNum] & ~ClearMask) | OrMask;
1546 if (WorkingFixedSettings.Mtrr[MsrNum] != NewValue) {
1547 WorkingFixedSettings.Mtrr[MsrNum] = NewValue;
1548 FixedSettingsModified[MsrNum] = TRUE;
1549 }
1550 }
1551 }
1552
1553 if (Length == 0) {
1554 //
1555 // A Length of 0 can only make sense for fixed MTTR ranges.
1556 // Since we just handled the fixed MTRRs, we can skip the
1557 // variable MTRR section.
1558 //
1559 goto Done;
1560 }
1561 }
1562
1563 //
1564 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1565 // we can set the base to 0 to save variable MTRRs.
1566 //
1567 if (BaseAddress == BASE_1MB) {
1568 BaseAddress = 0;
1569 Length += SIZE_1MB;
1570 }
1571
1572 //
1573 // Read all variable MTRRs
1574 //
1575 VariableMtrrCount = GetVariableMtrrCountWorker ();
1576 FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();
1577 if (MtrrSetting != NULL) {
1578 VariableSettings = &MtrrSetting->Variables;
1579 } else {
1580 MtrrGetVariableMtrrWorker (NULL, VariableMtrrCount, &OriginalVariableSettings);
1581 CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));
1582 ProgramVariableSettings = TRUE;
1583 VariableSettings = &WorkingVariableSettings;
1584 }
1585
1586 //
1587 // Check for overlap
1588 //
1589 UsedMtrr = MtrrGetMemoryAttributeInVariableMtrrWorker (
1590 VariableSettings,
1591 FirmwareVariableMtrrCount,
1592 MtrrValidBitsMask,
1593 MtrrValidAddressMask,
1594 VariableMtrr
1595 );
1596 OverLap = CheckMemoryAttributeOverlap (
1597 FirmwareVariableMtrrCount,
1598 BaseAddress,
1599 BaseAddress + Length - 1,
1600 VariableMtrr
1601 );
1602 if (OverLap) {
1603 Status = CombineMemoryAttribute (
1604 FirmwareVariableMtrrCount,
1605 MemoryType,
1606 &BaseAddress,
1607 &Length,
1608 VariableMtrr,
1609 &UsedMtrr,
1610 &OverwriteExistingMtrr
1611 );
1612 if (RETURN_ERROR (Status)) {
1613 goto Done;
1614 }
1615
1616 if (Length == 0) {
1617 //
1618 // Combined successfully, invalidate the now-unused MTRRs
1619 //
1620 InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);
1621 Status = RETURN_SUCCESS;
1622 goto Done;
1623 }
1624 }
1625
1626 //
1627 // The memory type is the same with the type specified by
1628 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1629 //
1630 if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryTypeWorker (MtrrSetting))) {
1631 //
1632 // Invalidate the now-unused MTRRs
1633 //
1634 InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);
1635 goto Done;
1636 }
1637
1638 Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);
1639
1640 if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
1641 Status = RETURN_OUT_OF_RESOURCES;
1642 goto Done;
1643 }
1644
1645 //
1646 // Invalidate the now-unused MTRRs
1647 //
1648 InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);
1649
1650 //
1651 // Find first unused MTRR
1652 //
1653 for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) {
1654 if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
1655 break;
1656 }
1657 }
1658
1659 if (BaseAddress != 0) {
1660 do {
1661 //
1662 // Calculate the alignment of the base address.
1663 //
1664 Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
1665
1666 if (Alignment > Length) {
1667 break;
1668 }
1669
1670 //
1671 // Find unused MTRR
1672 //
1673 for (; MsrNum < VariableMtrrCount; MsrNum++) {
1674 if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
1675 break;
1676 }
1677 }
1678
1679 ProgramVariableMtrr (
1680 VariableSettings,
1681 MsrNum,
1682 BaseAddress,
1683 Alignment,
1684 MemoryType,
1685 MtrrValidAddressMask
1686 );
1687 BaseAddress += Alignment;
1688 Length -= Alignment;
1689 } while (TRUE);
1690
1691 if (Length == 0) {
1692 goto Done;
1693 }
1694 }
1695
1696 TempQword = Length;
1697
1698 if (!Positive) {
1699 Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
1700
1701 //
1702 // Find unused MTRR
1703 //
1704 for (; MsrNum < VariableMtrrCount; MsrNum++) {
1705 if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
1706 break;
1707 }
1708 }
1709
1710 ProgramVariableMtrr (
1711 VariableSettings,
1712 MsrNum,
1713 BaseAddress,
1714 Length,
1715 MemoryType,
1716 MtrrValidAddressMask
1717 );
1718 BaseAddress += Length;
1719 TempQword = Length - TempQword;
1720 MemoryType = MTRR_CACHE_UNCACHEABLE;
1721 }
1722
1723 do {
1724 //
1725 // Find unused MTRR
1726 //
1727 for (; MsrNum < VariableMtrrCount; MsrNum++) {
1728 if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
1729 break;
1730 }
1731 }
1732
1733 Length = Power2MaxMemory (TempQword);
1734 if (!Positive) {
1735 BaseAddress -= Length;
1736 }
1737
1738 ProgramVariableMtrr (
1739 VariableSettings,
1740 MsrNum,
1741 BaseAddress,
1742 Length,
1743 MemoryType,
1744 MtrrValidAddressMask
1745 );
1746
1747 if (Positive) {
1748 BaseAddress += Length;
1749 }
1750 TempQword -= Length;
1751
1752 } while (TempQword > 0);
1753
1754 Done:
1755
1756 //
1757 // Write fixed MTRRs that have been modified
1758 //
1759 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1760 if (FixedSettingsModified[Index]) {
1761 if (!MtrrContextValid) {
1762 PreMtrrChange (&MtrrContext);
1763 MtrrContextValid = TRUE;
1764 }
1765 AsmWriteMsr64 (
1766 mMtrrLibFixedMtrrTable[Index].Msr,
1767 WorkingFixedSettings.Mtrr[Index]
1768 );
1769 }
1770 }
1771
1772 //
1773 // Write variable MTRRs
1774 //
1775 if (ProgramVariableSettings) {
1776 for (Index = 0; Index < VariableMtrrCount; Index++) {
1777 if (WorkingVariableSettings.Mtrr[Index].Base != OriginalVariableSettings.Mtrr[Index].Base ||
1778 WorkingVariableSettings.Mtrr[Index].Mask != OriginalVariableSettings.Mtrr[Index].Mask ) {
1779 if (!MtrrContextValid) {
1780 PreMtrrChange (&MtrrContext);
1781 MtrrContextValid = TRUE;
1782 }
1783 AsmWriteMsr64 (
1784 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),
1785 WorkingVariableSettings.Mtrr[Index].Base
1786 );
1787 AsmWriteMsr64 (
1788 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,
1789 WorkingVariableSettings.Mtrr[Index].Mask
1790 );
1791 }
1792 }
1793 }
1794 if (MtrrContextValid) {
1795 PostMtrrChange (&MtrrContext);
1796 }
1797
1798 DEBUG((DEBUG_CACHE, " Status = %r\n", Status));
1799 if (!RETURN_ERROR (Status)) {
1800 if (MtrrSetting != NULL) {
1801 MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_MTRR_ENABLED;
1802 }
1803 MtrrDebugPrintAllMtrrsWorker (MtrrSetting);
1804 }
1805
1806 return Status;
1807 }
1808
1809 /**
1810 This function attempts to set the attributes for a memory range.
1811
1812 @param[in] BaseAddress The physical address that is the start
1813 address of a memory region.
1814 @param[in] Length The size in bytes of the memory region.
1815 @param[in] Attributes The bit mask of attributes to set for the
1816 memory region.
1817
1818 @retval RETURN_SUCCESS The attributes were set for the memory
1819 region.
1820 @retval RETURN_INVALID_PARAMETER Length is zero.
1821 @retval RETURN_UNSUPPORTED The processor does not support one or
1822 more bytes of the memory resource range
1823 specified by BaseAddress and Length.
1824 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1825 for the memory resource range specified
1826 by BaseAddress and Length.
1827 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1828 range specified by BaseAddress and Length
1829 cannot be modified.
1830 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1831 modify the attributes of the memory
1832 resource range.
1833
1834 **/
1835 RETURN_STATUS
1836 EFIAPI
1837 MtrrSetMemoryAttribute (
1838 IN PHYSICAL_ADDRESS BaseAddress,
1839 IN UINT64 Length,
1840 IN MTRR_MEMORY_CACHE_TYPE Attribute
1841 )
1842 {
1843 DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));
1844 return MtrrSetMemoryAttributeWorker (
1845 NULL,
1846 BaseAddress,
1847 Length,
1848 Attribute
1849 );
1850 }
1851
1852 /**
1853 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1854
1855 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1856 @param[in] BaseAddress The physical address that is the start address
1857 of a memory region.
1858 @param[in] Length The size in bytes of the memory region.
1859 @param[in] Attribute The bit mask of attributes to set for the
1860 memory region.
1861
1862 @retval RETURN_SUCCESS The attributes were set for the memory region.
1863 @retval RETURN_INVALID_PARAMETER Length is zero.
1864 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1865 memory resource range specified by BaseAddress and Length.
1866 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1867 range specified by BaseAddress and Length.
1868 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1869 BaseAddress and Length cannot be modified.
1870 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1871 the memory resource range.
1872
1873 **/
1874 RETURN_STATUS
1875 EFIAPI
1876 MtrrSetMemoryAttributeInMtrrSettings (
1877 IN OUT MTRR_SETTINGS *MtrrSetting,
1878 IN PHYSICAL_ADDRESS BaseAddress,
1879 IN UINT64 Length,
1880 IN MTRR_MEMORY_CACHE_TYPE Attribute
1881 )
1882 {
1883 DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting, mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));
1884 return MtrrSetMemoryAttributeWorker (
1885 MtrrSetting,
1886 BaseAddress,
1887 Length,
1888 Attribute
1889 );
1890 }
1891
1892 /**
1893 Worker function setting variable MTRRs
1894
1895 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1896
1897 **/
1898 VOID
1899 MtrrSetVariableMtrrWorker (
1900 IN MTRR_VARIABLE_SETTINGS *VariableSettings
1901 )
1902 {
1903 UINT32 Index;
1904 UINT32 VariableMtrrCount;
1905
1906 VariableMtrrCount = GetVariableMtrrCountWorker ();
1907 ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
1908
1909 for (Index = 0; Index < VariableMtrrCount; Index++) {
1910 AsmWriteMsr64 (
1911 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),
1912 VariableSettings->Mtrr[Index].Base
1913 );
1914 AsmWriteMsr64 (
1915 MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,
1916 VariableSettings->Mtrr[Index].Mask
1917 );
1918 }
1919 }
1920
1921
1922 /**
1923 This function sets variable MTRRs
1924
1925 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1926
1927 @return The pointer of VariableSettings
1928
1929 **/
1930 MTRR_VARIABLE_SETTINGS*
1931 EFIAPI
1932 MtrrSetVariableMtrr (
1933 IN MTRR_VARIABLE_SETTINGS *VariableSettings
1934 )
1935 {
1936 MTRR_CONTEXT MtrrContext;
1937
1938 if (!IsMtrrSupported ()) {
1939 return VariableSettings;
1940 }
1941
1942 PreMtrrChange (&MtrrContext);
1943 MtrrSetVariableMtrrWorker (VariableSettings);
1944 PostMtrrChange (&MtrrContext);
1945 MtrrDebugPrintAllMtrrs ();
1946
1947 return VariableSettings;
1948 }
1949
1950 /**
1951 Worker function setting fixed MTRRs
1952
1953 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1954
1955 **/
1956 VOID
1957 MtrrSetFixedMtrrWorker (
1958 IN MTRR_FIXED_SETTINGS *FixedSettings
1959 )
1960 {
1961 UINT32 Index;
1962
1963 for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
1964 AsmWriteMsr64 (
1965 mMtrrLibFixedMtrrTable[Index].Msr,
1966 FixedSettings->Mtrr[Index]
1967 );
1968 }
1969 }
1970
1971
1972 /**
1973 This function sets fixed MTRRs
1974
1975 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1976
1977 @retval The pointer of FixedSettings
1978
1979 **/
1980 MTRR_FIXED_SETTINGS*
1981 EFIAPI
1982 MtrrSetFixedMtrr (
1983 IN MTRR_FIXED_SETTINGS *FixedSettings
1984 )
1985 {
1986 MTRR_CONTEXT MtrrContext;
1987
1988 if (!IsMtrrSupported ()) {
1989 return FixedSettings;
1990 }
1991
1992 PreMtrrChange (&MtrrContext);
1993 MtrrSetFixedMtrrWorker (FixedSettings);
1994 PostMtrrChange (&MtrrContext);
1995 MtrrDebugPrintAllMtrrs ();
1996
1997 return FixedSettings;
1998 }
1999
2000
2001 /**
2002 This function gets the content in all MTRRs (variable and fixed)
2003
2004 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2005
2006 @retval the pointer of MtrrSetting
2007
2008 **/
2009 MTRR_SETTINGS *
2010 EFIAPI
2011 MtrrGetAllMtrrs (
2012 OUT MTRR_SETTINGS *MtrrSetting
2013 )
2014 {
2015 if (!IsMtrrSupported ()) {
2016 return MtrrSetting;
2017 }
2018
2019 //
2020 // Get fixed MTRRs
2021 //
2022 MtrrGetFixedMtrrWorker (&MtrrSetting->Fixed);
2023
2024 //
2025 // Get variable MTRRs
2026 //
2027 MtrrGetVariableMtrrWorker (
2028 NULL,
2029 GetVariableMtrrCountWorker (),
2030 &MtrrSetting->Variables
2031 );
2032
2033 //
2034 // Get MTRR_DEF_TYPE value
2035 //
2036 MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
2037
2038 return MtrrSetting;
2039 }
2040
2041
2042 /**
2043 This function sets all MTRRs (variable and fixed)
2044
2045 @param[in] MtrrSetting A buffer holding all MTRRs content.
2046
2047 @retval The pointer of MtrrSetting
2048
2049 **/
2050 MTRR_SETTINGS *
2051 EFIAPI
2052 MtrrSetAllMtrrs (
2053 IN MTRR_SETTINGS *MtrrSetting
2054 )
2055 {
2056 MTRR_CONTEXT MtrrContext;
2057
2058 if (!IsMtrrSupported ()) {
2059 return MtrrSetting;
2060 }
2061
2062 PreMtrrChange (&MtrrContext);
2063
2064 //
2065 // Set fixed MTRRs
2066 //
2067 MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);
2068
2069 //
2070 // Set variable MTRRs
2071 //
2072 MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);
2073
2074 //
2075 // Set MTRR_DEF_TYPE value
2076 //
2077 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);
2078
2079 PostMtrrChangeEnableCache (&MtrrContext);
2080
2081 MtrrDebugPrintAllMtrrs ();
2082
2083 return MtrrSetting;
2084 }
2085
2086
2087 /**
2088 Checks if MTRR is supported.
2089
2090 @retval TRUE MTRR is supported.
2091 @retval FALSE MTRR is not supported.
2092
2093 **/
2094 BOOLEAN
2095 EFIAPI
2096 IsMtrrSupported (
2097 VOID
2098 )
2099 {
2100 UINT32 RegEdx;
2101 UINT64 MtrrCap;
2102
2103 //
2104 // Check CPUID(1).EDX[12] for MTRR capability
2105 //
2106 AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
2107 if (BitFieldRead32 (RegEdx, 12, 12) == 0) {
2108 return FALSE;
2109 }
2110
2111 //
2112 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2113 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2114 // exist, return false.
2115 //
2116 MtrrCap = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP);
2117 if ((BitFieldRead64 (MtrrCap, 0, 7) == 0) || (BitFieldRead64 (MtrrCap, 8, 8) == 0)) {
2118 return FALSE;
2119 }
2120
2121 return TRUE;
2122 }