Home | History | Annotate | Download | only in BaseCacheLib
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      4   This program and the accompanying materials
      5   are licensed and made available under the terms and conditions of the BSD License
      6   which accompanies this distribution.  The full text of the license may be found at
      7   http://opensource.org/licenses/bsd-license.php.
      8 
      9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 **/
     13 
     14 #include <Uefi.h>
     15 #include <Library/BaseLib.h>
     16 #include <Library/CacheLib.h>
     17 #include <Library/CacheAsRamLib.h>
     18 #include "CacheLibInternal.h"
     19 
     20 /**
     21   Search the memory cache type for specific memory from MTRR.
     22 
     23   @param[in]  MemoryAddress         the address of target memory
     24   @param[in]  MemoryLength          the length of target memory
     25   @param[in]  ValidMtrrAddressMask  the MTRR address mask
     26   @param[out] UsedMsrNum            the used MSR number
     27   @param[out] UsedMemoryCacheType   the cache type for the target memory
     28 
     29   @retval EFI_SUCCESS    The memory is found in MTRR and cache type is returned
     30   @retval EFI_NOT_FOUND  The memory is not found in MTRR
     31 
     32 **/
     33 EFI_STATUS
     34 SearchForExactMtrr (
     35   IN  EFI_PHYSICAL_ADDRESS      MemoryAddress,
     36   IN  UINT64                    MemoryLength,
     37   IN  UINT64                    ValidMtrrAddressMask,
     38   OUT UINT32                    *UsedMsrNum,
     39   OUT EFI_MEMORY_CACHE_TYPE     *MemoryCacheType
     40   );
     41 
     42 /**
     43   Check if CacheType match current default setting.
     44 
     45   @param[in] MemoryCacheType  input cache type to be checked.
     46 
     47   @retval TRUE MemoryCacheType is default MTRR setting.
     48   @retval FALSE MemoryCacheType is NOT default MTRR setting.
     49 **/
     50 BOOLEAN
     51 IsDefaultType (
     52   IN  EFI_MEMORY_CACHE_TYPE     MemoryCacheType
     53   );
     54 
     55 /**
     56   Return MTRR alignment requirement for base address and size.
     57 
     58   @param[in]  BaseAddress     Base address.
     59   @param[in]  Size            Size.
     60 
     61   @retval Zero      Alligned.
     62   @retval Non-Zero  Not alligned.
     63 
     64 **/
     65 UINT32
     66 CheckMtrrAlignment (
     67   IN  UINT64                    BaseAddress,
     68   IN  UINT64                    Size
     69   );
     70 
     71 typedef struct {
     72   UINT32    Msr;
     73   UINT32    BaseAddress;
     74   UINT32    Length;
     75 } EFI_FIXED_MTRR;
     76 
     77 EFI_FIXED_MTRR mFixedMtrrTable[] = {
     78   { EFI_MSR_IA32_MTRR_FIX64K_00000, 0,       0x10000},
     79   { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000},
     80   { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000},
     81   { EFI_MSR_IA32_MTRR_FIX4K_C0000,  0xC0000, 0x1000},
     82   { EFI_MSR_IA32_MTRR_FIX4K_C8000,  0xC8000, 0x1000},
     83   { EFI_MSR_IA32_MTRR_FIX4K_D0000,  0xD0000, 0x1000},
     84   { EFI_MSR_IA32_MTRR_FIX4K_D8000,  0xD8000, 0x1000},
     85   { EFI_MSR_IA32_MTRR_FIX4K_E0000,  0xE0000, 0x1000},
     86   { EFI_MSR_IA32_MTRR_FIX4K_E8000,  0xE8000, 0x1000},
     87   { EFI_MSR_IA32_MTRR_FIX4K_F0000,  0xF0000, 0x1000},
     88   { EFI_MSR_IA32_MTRR_FIX4K_F8000,  0xF8000, 0x1000}
     89 };
     90 
     91 /**
     92   Given the input, check if the number of MTRR is lesser.
     93   if positive or subtractive.
     94 
     95   @param[in]  Input   Length of Memory to program MTRR.
     96 
     97   @retval  Zero      do positive.
     98   @retval  Non-Zero  do subtractive.
     99 
    100 **/
    101 INT8
    102 CheckDirection (
    103   IN  UINT64                    Input
    104   )
    105 {
    106   return 0;
    107 }
    108 
    109 /**
    110   Disable cache and its mtrr.
    111 
    112   @param[out]  OldMtrr To return the Old MTRR value
    113 
    114 **/
    115 VOID
    116 EfiDisableCacheMtrr (
    117   OUT UINT64                   *OldMtrr
    118   )
    119 {
    120   UINT64  TempQword;
    121 
    122   //
    123   // Disable Cache MTRR
    124   //
    125   *OldMtrr = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
    126   TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;
    127   AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
    128   AsmDisableCache ();
    129 }
    130 
    131 /**
    132   Recover cache MTRR.
    133 
    134   @param[in] EnableMtrr Whether to enable the MTRR
    135   @param[in] OldMtrr    The saved old MTRR value to restore when not to enable the MTRR
    136 
    137 **/
    138 VOID
    139 EfiRecoverCacheMtrr (
    140   IN BOOLEAN                  EnableMtrr,
    141   IN UINT64                   OldMtrr
    142   )
    143 {
    144   UINT64  TempQword;
    145 
    146   //
    147   // Enable Cache MTRR
    148   //
    149   if (EnableMtrr) {
    150     TempQword = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
    151     TempQword |= (UINT64)(B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);
    152   } else {
    153     TempQword = OldMtrr;
    154   }
    155 
    156   AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
    157 
    158   AsmEnableCache ();
    159 }
    160 
    161 /**
    162   Programming MTRR according to Memory address, length, and type.
    163 
    164   @param[in] MtrrNumber           the variable MTRR index number
    165   @param[in] MemoryAddress        the address of target memory
    166   @param[in] MemoryLength         the length of target memory
    167   @param[in] MemoryCacheType      the cache type of target memory
    168   @param[in] ValidMtrrAddressMask the MTRR address mask
    169 
    170 **/
    171 VOID
    172 EfiProgramMtrr (
    173   IN  UINTN                     MtrrNumber,
    174   IN  EFI_PHYSICAL_ADDRESS      MemoryAddress,
    175   IN  UINT64                    MemoryLength,
    176   IN  EFI_MEMORY_CACHE_TYPE     MemoryCacheType,
    177   IN  UINT64                    ValidMtrrAddressMask
    178   )
    179 {
    180   UINT64                        TempQword;
    181   UINT64                        OldMtrr;
    182 
    183   if (MemoryLength == 0) {
    184     return;
    185   }
    186 
    187   EfiDisableCacheMtrr (&OldMtrr);
    188 
    189   //
    190   // MTRR Physical Base
    191   //
    192   TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;
    193   AsmWriteMsr64 (MtrrNumber, TempQword);
    194 
    195   //
    196   // MTRR Physical Mask
    197   //
    198   TempQword = ~(MemoryLength - 1);
    199   AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);
    200 
    201   EfiRecoverCacheMtrr (TRUE, OldMtrr);
    202 }
    203 
    204 /**
    205   Calculate the maximum value which is a power of 2, but less the MemoryLength.
    206 
    207   @param[in]  MemoryAddress       Memory address.
    208   @param[in]  MemoryLength        The number to pass in.
    209 
    210   @return The maximum value which is align to power of 2 and less the MemoryLength
    211 
    212 **/
    213 UINT64
    214 Power2MaxMemory (
    215   IN UINT64                 MemoryAddress,
    216   IN UINT64                 MemoryLength
    217   )
    218 {
    219   UINT64                    Result;
    220 
    221   if (MemoryLength == 0) {
    222     return EFI_INVALID_PARAMETER;
    223   }
    224 
    225   //
    226   // Compute inital power of 2 size to return
    227   //
    228   Result = GetPowerOfTwo64(MemoryLength);
    229 
    230   //
    231   // Special case base of 0 as all ranges are valid
    232   //
    233   if (MemoryAddress == 0) {
    234     return Result;
    235   }
    236 
    237   //
    238   // Loop till a value that can be mapped to this base address is found
    239   //
    240   while (CheckMtrrAlignment (MemoryAddress, Result) != 0) {
    241     //
    242     // Need to try the next smaller power of 2
    243     //
    244     Result = RShiftU64 (Result, 1);
    245   }
    246 
    247   return Result;
    248 }
    249 
    250 /**
    251   Return MTRR alignment requirement for base address and size.
    252 
    253   @param[in]  BaseAddress     Base address.
    254   @param[in]  Size            Size.
    255 
    256   @retval Zero      Alligned.
    257   @retval Non-Zero  Not alligned.
    258 
    259 **/
    260 UINT32
    261 CheckMtrrAlignment (
    262   IN  UINT64    BaseAddress,
    263   IN  UINT64    Size
    264   )
    265 {
    266   UINT32      ShiftedBase;
    267   UINT32      ShiftedSize;
    268 
    269   //
    270   // Shift base and size right 12 bits to allow for larger memory sizes.  The
    271   // MTRRs do not use the first 12 bits so this is safe for now.  Only supports
    272   // up to 52 bits of physical address space.
    273   //
    274   ShiftedBase = (UINT32) RShiftU64 (BaseAddress, 12);
    275   ShiftedSize = (UINT32) RShiftU64 (Size, 12);
    276 
    277   //
    278   // Return the results to the caller of the MOD
    279   //
    280   return ShiftedBase % ShiftedSize;
    281 }
    282 
    283 /**
    284   Programs fixed MTRRs registers.
    285 
    286   @param[in]  MemoryCacheType  The memory type to set.
    287   @param[in]  Base             The base address of memory range.
    288   @param[in]  Length           The length of memory range.
    289 
    290   @retval RETURN_SUCCESS      The cache type was updated successfully
    291   @retval RETURN_UNSUPPORTED  The requested range or cache type was invalid
    292                               for the fixed MTRRs.
    293 
    294 **/
    295 EFI_STATUS
    296 ProgramFixedMtrr (
    297   IN  EFI_MEMORY_CACHE_TYPE     MemoryCacheType,
    298   IN  UINT64                    *Base,
    299   IN  UINT64                    *Len
    300   )
    301 {
    302   UINT32                      MsrNum;
    303   UINT32                      ByteShift;
    304   UINT64                      TempQword;
    305   UINT64                      OrMask;
    306   UINT64                      ClearMask;
    307 
    308   TempQword = 0;
    309   OrMask =  0;
    310   ClearMask = 0;
    311 
    312   for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {
    313     if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
    314         (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))) {
    315       break;
    316     }
    317   }
    318   if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) {
    319     return EFI_DEVICE_ERROR;
    320   }
    321   //
    322   // We found the fixed MTRR to be programmed
    323   //
    324   for (ByteShift=0; ByteShift < 8; ByteShift++) {
    325     if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
    326       break;
    327     }
    328   }
    329   if (ByteShift == 8 ) {
    330     return EFI_DEVICE_ERROR;
    331   }
    332   for (; ((ByteShift<8) && (*Len >= mFixedMtrrTable[MsrNum].Length));ByteShift++) {
    333     OrMask |= LShiftU64((UINT64) MemoryCacheType, (UINT32) (ByteShift* 8));
    334     ClearMask |= LShiftU64((UINT64) 0xFF, (UINT32) (ByteShift * 8));
    335     *Len -= mFixedMtrrTable[MsrNum].Length;
    336     *Base += mFixedMtrrTable[MsrNum].Length;
    337   }
    338   TempQword = (AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask)) | OrMask;
    339   AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);
    340 
    341   return EFI_SUCCESS;
    342 }
    343 
    344 /**
    345   Check if there is a valid variable MTRR that overlaps the given range.
    346 
    347   @param[in]  Start  Base Address of the range to check.
    348   @param[in]  End    End address of the range to check.
    349 
    350   @retval TRUE   Mtrr overlap.
    351   @retval FALSE  Mtrr not overlap.
    352 **/
    353 BOOLEAN
    354 CheckMtrrOverlap (
    355   IN  EFI_PHYSICAL_ADDRESS      Start,
    356   IN  EFI_PHYSICAL_ADDRESS      End
    357   )
    358 {
    359   return FALSE;
    360 }
    361 
    362 /**
    363   Given the memory range and cache type, programs the MTRRs.
    364 
    365   @param[in] MemoryAddress           Base Address of Memory to program MTRR.
    366   @param[in] MemoryLength            Length of Memory to program MTRR.
    367   @param[in] MemoryCacheType         Cache Type.
    368 
    369   @retval EFI_SUCCESS            Mtrr are set successfully.
    370   @retval EFI_LOAD_ERROR         No empty MTRRs to use.
    371   @retval EFI_INVALID_PARAMETER  The input parameter is not valid.
    372   @retval others                 An error occurs when setting MTTR.
    373 
    374 **/
    375 EFI_STATUS
    376 EFIAPI
    377 SetCacheAttributes (
    378   IN  EFI_PHYSICAL_ADDRESS      MemoryAddress,
    379   IN  UINT64                    MemoryLength,
    380   IN  EFI_MEMORY_CACHE_TYPE     MemoryCacheType
    381   )
    382 {
    383   EFI_STATUS            Status;
    384   UINT32                MsrNum, MsrNumEnd;
    385   UINT64                TempQword;
    386   UINT32                LastVariableMtrrForBios;
    387   UINT64                OldMtrr;
    388   UINT32                UsedMsrNum;
    389   EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;
    390   UINT64                ValidMtrrAddressMask;
    391   UINT32                Cpuid_RegEax;
    392 
    393   AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL);
    394   if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
    395     AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL);
    396     ValidMtrrAddressMask = (LShiftU64((UINT64) 1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF);
    397   } else {
    398     ValidMtrrAddressMask = (LShiftU64((UINT64) 1, 36) - 1) & (~(UINT64)0x0FFF);
    399   }
    400 
    401   //
    402   // Check for invalid parameter
    403   //
    404   if ((MemoryAddress & ~ValidMtrrAddressMask) != 0 || (MemoryLength & ~ValidMtrrAddressMask) != 0) {
    405     return EFI_INVALID_PARAMETER;
    406   }
    407 
    408   if (MemoryLength == 0) {
    409     return EFI_INVALID_PARAMETER;
    410   }
    411 
    412   switch (MemoryCacheType) {
    413     case EFI_CACHE_UNCACHEABLE:
    414     case EFI_CACHE_WRITECOMBINING:
    415     case EFI_CACHE_WRITETHROUGH:
    416     case EFI_CACHE_WRITEPROTECTED:
    417     case EFI_CACHE_WRITEBACK:
    418       break;
    419 
    420     default:
    421       return EFI_INVALID_PARAMETER;
    422   }
    423 
    424   //
    425   // Check if Fixed MTRR
    426   //
    427   if ((MemoryAddress + MemoryLength) <= (1 << 20)) {
    428     Status = EFI_SUCCESS;
    429     EfiDisableCacheMtrr (&OldMtrr);
    430     while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) {
    431       Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength);
    432     }
    433     EfiRecoverCacheMtrr (TRUE, OldMtrr);
    434     return Status;
    435   }
    436 
    437   //
    438   // Search if the range attribute has been set before
    439   //
    440   Status = SearchForExactMtrr(
    441                               MemoryAddress,
    442                               MemoryLength,
    443                               ValidMtrrAddressMask,
    444                               &UsedMsrNum,
    445                               &UsedMemoryCacheType
    446                               );
    447 
    448   if (!EFI_ERROR(Status)) {
    449     //
    450     // Compare if it has the same type as current setting
    451     //
    452     if (UsedMemoryCacheType == MemoryCacheType) {
    453       return EFI_SUCCESS;
    454     } else {
    455       //
    456       // Different type
    457       //
    458 
    459       //
    460       // Check if the set type is the same as Default Type
    461       //
    462       if (IsDefaultType(MemoryCacheType)) {
    463         //
    464         // Clear the MTRR
    465         //
    466         AsmWriteMsr64(UsedMsrNum, 0);
    467         AsmWriteMsr64(UsedMsrNum + 1, 0);
    468 
    469         return EFI_SUCCESS;
    470       } else {
    471         //
    472         // Modify the MTRR type
    473         //
    474         EfiProgramMtrr(UsedMsrNum,
    475                        MemoryAddress,
    476                        MemoryLength,
    477                        MemoryCacheType,
    478                        ValidMtrrAddressMask
    479                        );
    480         return EFI_SUCCESS;
    481       }
    482     }
    483   }
    484 
    485 #if 0
    486   //
    487   // @bug - Need to create memory map so that when checking for overlap we
    488   //        can determine if an overlap exists based on all caching requests.
    489   //
    490   // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE
    491   //
    492   if (MemoryCacheType == (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE))  {
    493     if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) {
    494       return EFI_SUCCESS;
    495     }
    496   }
    497 #endif
    498 
    499   //
    500   // Find first unused MTRR
    501   //
    502   MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
    503   for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
    504     if ((AsmReadMsr64(MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) {
    505       break;
    506     }
    507   }
    508 
    509   //
    510   // Reserve 1 MTRR pair for OS.
    511   //
    512   LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2);
    513   if (MsrNum > LastVariableMtrrForBios) {
    514     return EFI_LOAD_ERROR;
    515   }
    516 
    517   //
    518   // Special case for 1 MB base address
    519   //
    520   if (MemoryAddress == BASE_1MB) {
    521     MemoryAddress = 0;
    522   }
    523 
    524   //
    525   // Program MTRRs
    526   //
    527   TempQword = MemoryLength;
    528 
    529   if (TempQword == Power2MaxMemory(MemoryAddress, TempQword)) {
    530     EfiProgramMtrr(MsrNum,
    531                    MemoryAddress,
    532                    MemoryLength,
    533                    MemoryCacheType,
    534                    ValidMtrrAddressMask
    535                    );
    536 
    537   } else {
    538     //
    539     // Fill in MTRRs with values.  Direction can not be checked for this method
    540     // as we are using WB as the default cache type and only setting areas to UC.
    541     //
    542     do {
    543       //
    544       // Do boundary check so we don't go past last MTRR register
    545       // for BIOS use.  Leave one MTRR pair for OS use.
    546       //
    547       if (MsrNum > LastVariableMtrrForBios) {
    548         return EFI_LOAD_ERROR;
    549       }
    550 
    551       //
    552       // Set next power of 2 region
    553       //
    554       MemoryLength = Power2MaxMemory(MemoryAddress, TempQword);
    555       EfiProgramMtrr(MsrNum,
    556                      MemoryAddress,
    557                      MemoryLength,
    558                      MemoryCacheType,
    559                      ValidMtrrAddressMask
    560                      );
    561       MemoryAddress += MemoryLength;
    562       TempQword -= MemoryLength;
    563       MsrNum += 2;
    564     } while (TempQword != 0);
    565   }
    566 
    567   return EFI_SUCCESS;
    568 }
    569 
    570 /**
    571  Reset all the MTRRs to a known state.
    572 
    573   @retval  EFI_SUCCESS All MTRRs have been reset successfully.
    574 
    575 **/
    576 EFI_STATUS
    577 EFIAPI
    578 ResetCacheAttributes (
    579   VOID
    580   )
    581 {
    582   UINT32                      MsrNum, MsrNumEnd;
    583   UINT16                      Index;
    584   UINT64                      OldMtrr;
    585   UINT64                      CacheType;
    586   BOOLEAN                     DisableCar;
    587   Index = 0;
    588   DisableCar = TRUE;
    589 
    590   //
    591   // Determine default cache type
    592   //
    593   CacheType = EFI_CACHE_UNCACHEABLE;
    594 
    595   //
    596   // Set default cache type
    597   //
    598   AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType);
    599 
    600   //
    601   // Disable CAR
    602   //
    603   DisableCacheAsRam (DisableCar);
    604 
    605   EfiDisableCacheMtrr (&OldMtrr);
    606 
    607   //
    608   // Reset Fixed MTRRs
    609   //
    610   for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {
    611     AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0);
    612   }
    613 
    614   //
    615   // Reset Variable MTRRs
    616   //
    617   MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
    618   for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) {
    619     AsmWriteMsr64 (MsrNum, 0);
    620   }
    621 
    622   //
    623   // Enable Fixed and Variable MTRRs
    624   //
    625   EfiRecoverCacheMtrr (TRUE, OldMtrr);
    626 
    627   return EFI_SUCCESS;
    628 }
    629 
    630 /**
    631   Search the memory cache type for specific memory from MTRR.
    632 
    633   @param[in]  MemoryAddress         the address of target memory
    634   @param[in]  MemoryLength          the length of target memory
    635   @param[in]  ValidMtrrAddressMask  the MTRR address mask
    636   @param[out] UsedMsrNum            the used MSR number
    637   @param[out] UsedMemoryCacheType   the cache type for the target memory
    638 
    639   @retval EFI_SUCCESS    The memory is found in MTRR and cache type is returned
    640   @retval EFI_NOT_FOUND  The memory is not found in MTRR
    641 
    642 **/
    643 EFI_STATUS
    644 SearchForExactMtrr (
    645   IN  EFI_PHYSICAL_ADDRESS      MemoryAddress,
    646   IN  UINT64                    MemoryLength,
    647   IN  UINT64                    ValidMtrrAddressMask,
    648   OUT UINT32                    *UsedMsrNum,
    649   OUT EFI_MEMORY_CACHE_TYPE     *UsedMemoryCacheType
    650   )
    651 {
    652   UINT32                      MsrNum, MsrNumEnd;
    653   UINT64                      TempQword;
    654 
    655   if (MemoryLength == 0) {
    656     return EFI_INVALID_PARAMETER;
    657   }
    658 
    659   MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
    660   for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
    661     TempQword = AsmReadMsr64(MsrNum+1);
    662     if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
    663       continue;
    664     }
    665 
    666     if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {
    667       continue;
    668     }
    669 
    670     TempQword = AsmReadMsr64 (MsrNum);
    671     if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {
    672       continue;
    673     }
    674 
    675     *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE);
    676     *UsedMsrNum = MsrNum;
    677 
    678     return EFI_SUCCESS;
    679   }
    680 
    681   return EFI_NOT_FOUND;
    682 }
    683 
    684 /**
    685   Check if CacheType match current default setting.
    686 
    687   @param[in] MemoryCacheType  input cache type to be checked.
    688 
    689   @retval TRUE MemoryCacheType is default MTRR setting.
    690   @retval TRUE MemoryCacheType is NOT default MTRR setting.
    691 **/
    692 BOOLEAN
    693 IsDefaultType (
    694   IN  EFI_MEMORY_CACHE_TYPE     MemoryCacheType
    695   )
    696 {
    697   if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) {
    698     return FALSE;
    699   }
    700 
    701   return TRUE;
    702 }
    703 
    704