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