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