示例#1
0
EFIAPI
MtrrSetAllMtrrs (
  IN MTRR_SETTINGS                *MtrrSetting
  )
{
  MTRR_CONTEXT  MtrrContext;

  if (!IsMtrrSupported ()) {
    return MtrrSetting;
  }

  PreMtrrChange (&MtrrContext);

  //
  // Set fixed MTRRs
  //
  MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);

  //
  // Set variable MTRRs
  //
  MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);

  //
  // Set MTRR_DEF_TYPE value
  //
  AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);

  PostMtrrChangeEnableCache (&MtrrContext);

  return MtrrSetting;
}
示例#2
0
EFIAPI
MtrrSetAllMtrrs (
  IN MTRR_SETTINGS                *MtrrSetting
  )
{
  UINTN  Cr4;

  if (!IsMtrrSupported ()) {
    return MtrrSetting;
  }

  Cr4 = PreMtrrChange ();

  //
  // Set fixed MTRRs
  //
  MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);

  //
  // Set variable MTRRs
  //
  MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);

  //
  // Set MTRR_DEF_TYPE value
  //
  AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);

  PostMtrrChange (Cr4);

  return MtrrSetting;
}
示例#3
0
EFIAPI
MtrrGetAllMtrrs (
  OUT MTRR_SETTINGS                *MtrrSetting
  )
{
  if (!IsMtrrSupported ()) {
    return MtrrSetting;
  }

  //
  // Get fixed MTRRs
  //
  MtrrGetFixedMtrr (&MtrrSetting->Fixed);

  //
  // Get variable MTRRs
  //
  MtrrGetVariableMtrr (&MtrrSetting->Variables);

  //
  // Get MTRR_DEF_TYPE value
  //
  MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);

  return MtrrSetting;
}
示例#4
0
/**
  Returns the variable MTRR count for the CPU.

  @return Variable MTRR count

**/
UINT32
GetVariableMtrrCount (
  VOID
  )
{
  if (!IsMtrrSupported ()) {
    return 0;
  }

  return (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);
}
示例#5
0
/**
  Returns the default MTRR cache type for the system.

  @return  The default MTRR cache type.

**/
MTRR_MEMORY_CACHE_TYPE
EFIAPI
MtrrGetDefaultMemoryType (
  VOID
  )
{
  if (!IsMtrrSupported ()) {
    return CacheUncacheable;
  }

  return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);
}
示例#6
0
/**
  Get the attribute of variable MTRRs.

  This function shadows the content of variable MTRRs into an
  internal array: VariableMtrr.

  @param  MtrrValidBitsMask     The mask for the valid bit of the MTRR
  @param  MtrrValidAddressMask  The valid address mask for MTRR
  @param  VariableMtrr          The array to shadow variable MTRRs content

  @return                       The return value of this paramter indicates the
                                number of MTRRs which has been used.

**/
UINT32
EFIAPI
MtrrGetMemoryAttributeInVariableMtrr (
  IN  UINT64                    MtrrValidBitsMask,
  IN  UINT64                    MtrrValidAddressMask,
  OUT VARIABLE_MTRR             *VariableMtrr
  )
{
  UINTN   Index;
  UINT32  MsrNum;
  UINT32  UsedMtrr;
  UINT32  FirmwareVariableMtrrCount;
  UINT32  VariableMtrrEnd;

  if (!IsMtrrSupported ()) {
    return 0;
  }

  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;

  ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);
  UsedMtrr = 0;

  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;
       (
         (MsrNum < VariableMtrrEnd) &&
         (Index < FirmwareVariableMtrrCount)
       );
       MsrNum += 2
      ) {
    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {
      VariableMtrr[Index].Msr          = MsrNum;
      VariableMtrr[Index].BaseAddress  = (AsmReadMsr64 (MsrNum) &
                                          MtrrValidAddressMask);
      VariableMtrr[Index].Length       = ((~(AsmReadMsr64 (MsrNum + 1) &
                                             MtrrValidAddressMask)
                                          ) &
                                          MtrrValidBitsMask
                                         ) + 1;
      VariableMtrr[Index].Type         = (AsmReadMsr64 (MsrNum) & 0x0ff);
      VariableMtrr[Index].Valid        = TRUE;
      VariableMtrr[Index].Used         = TRUE;
      UsedMtrr = UsedMtrr  + 1;
      Index++;
    }
  }
  return UsedMtrr;
}
示例#7
0
EFIAPI
MtrrSetVariableMtrr (
  IN MTRR_VARIABLE_SETTINGS         *VariableSettings
  )
{
  MTRR_CONTEXT  MtrrContext;

  if (!IsMtrrSupported ()) {
    return VariableSettings;
  }

  PreMtrrChange (&MtrrContext);
  MtrrSetVariableMtrrWorker (VariableSettings);
  PostMtrrChange (&MtrrContext);
  return  VariableSettings;
}
示例#8
0
EFIAPI
MtrrSetVariableMtrr (
  IN MTRR_VARIABLE_SETTINGS         *VariableSettings
  )
{
  UINTN  Cr4;

  if (!IsMtrrSupported ()) {
    return VariableSettings;
  }

  Cr4 = PreMtrrChange ();
  MtrrSetVariableMtrrWorker (VariableSettings);
  PostMtrrChange (Cr4);
  return  VariableSettings;
}
示例#9
0
EFIAPI
MtrrSetFixedMtrr (
  IN MTRR_FIXED_SETTINGS          *FixedSettings
  )
{
  MTRR_CONTEXT  MtrrContext;

  if (!IsMtrrSupported ()) {
    return FixedSettings;
  }

  PreMtrrChange (&MtrrContext);
  MtrrSetFixedMtrrWorker (FixedSettings);
  PostMtrrChange (&MtrrContext);

  return FixedSettings;
}
示例#10
0
/**
  Returns the variable MTRR count for the CPU.

  @return Variable MTRR count

**/
UINT32
EFIAPI
GetVariableMtrrCount (
  VOID
  )
{
  UINT32  VariableMtrrCount;

  if (!IsMtrrSupported ()) {
    return 0;
  }

  VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);
  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);

  return VariableMtrrCount;
}
示例#11
0
EFIAPI
MtrrSetFixedMtrr (
  IN MTRR_FIXED_SETTINGS          *FixedSettings
  )
{
  UINTN  Cr4;

  if (!IsMtrrSupported ()) {
    return FixedSettings;
  }

  Cr4 = PreMtrrChange ();
  MtrrSetFixedMtrrWorker (FixedSettings);
  PostMtrrChange (Cr4);

  return FixedSettings;
}
示例#12
0
EFIAPI
MtrrGetFixedMtrr (
  OUT MTRR_FIXED_SETTINGS         *FixedSettings
  )
{
  UINT32  Index;

  if (!IsMtrrSupported ()) {
    return FixedSettings;
  }

  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
      FixedSettings->Mtrr[Index] =
        AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
  };

  return FixedSettings;
}
示例#13
0
EFIAPI
MtrrGetVariableMtrr (
  OUT MTRR_VARIABLE_SETTINGS         *VariableSettings
  )
{
  UINT32  Index;
  UINT32  VariableMtrrCount;

  if (!IsMtrrSupported ()) {
    return VariableSettings;
  }

  VariableMtrrCount = GetVariableMtrrCount ();
  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);

  for (Index = 0; Index < VariableMtrrCount; Index++) {
    VariableSettings->Mtrr[Index].Base =
      AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));
    VariableSettings->Mtrr[Index].Mask =
      AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);
  }

  return  VariableSettings;
}
示例#14
0
/**
  This function will get the memory cache type of the specific address.

  This function is mainly for debug purpose.

  @param  Address   The specific address

  @return Memory cache type of the sepcific address

**/
MTRR_MEMORY_CACHE_TYPE
EFIAPI
MtrrGetMemoryAttribute (
  IN PHYSICAL_ADDRESS   Address
  )
{
  UINT64                  TempQword;
  UINTN                   Index;
  UINTN                   SubIndex;
  UINT64                  MtrrType;
  UINT64                  TempMtrrType;
  MTRR_MEMORY_CACHE_TYPE  CacheType;
  VARIABLE_MTRR           VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
  UINT64                  MtrrValidBitsMask;
  UINT64                  MtrrValidAddressMask;
  UINTN                   VariableMtrrCount;

  if (!IsMtrrSupported ()) {
    return CacheUncacheable;
  }

  //
  // Check if MTRR is enabled, if not, return UC as attribute
  //
  TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
  MtrrType = MTRR_CACHE_INVALID_TYPE;

  if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
    return CacheUncacheable;
  }

  //
  // If address is less than 1M, then try to go through the fixed MTRR
  //
  if (Address < BASE_1MB) {
    if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {
      //
      // Go through the fixed MTRR
      //
      for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
         if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&
             Address  < (
                          mMtrrLibFixedMtrrTable[Index].BaseAddress +
                          (mMtrrLibFixedMtrrTable[Index].Length * 8)
                        )
            ) {
           SubIndex =
             ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /
               mMtrrLibFixedMtrrTable[Index].Length;
           TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
           MtrrType =  RShiftU64 (TempQword, SubIndex * 8) & 0xFF;
           return GetMemoryCacheTypeFromMtrrType (MtrrType);
         }
      }
    }
  }
  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
  MtrrGetMemoryAttributeInVariableMtrr(
    MtrrValidBitsMask,
    MtrrValidAddressMask,
    VariableMtrr
    );

  //
  // Go through the variable MTRR
  //
  VariableMtrrCount = GetVariableMtrrCount ();
  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);

  for (Index = 0; Index < VariableMtrrCount; Index++) {
    if (VariableMtrr[Index].Valid) {
      if (Address >= VariableMtrr[Index].BaseAddress &&
          Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {
        TempMtrrType = VariableMtrr[Index].Type;
        MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);
      }
    }
  }
  CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);

  return CacheType;
}
示例#15
0
/**
  This function attempts to set the attributes for a memory range.

  @param  BaseAddress            The physical address that is the start
                                 address of a memory region.
  @param  Length                 The size in bytes of the memory region.
  @param  Attributes             The bit mask of attributes to set for the
                                 memory region.

  @retval RETURN_SUCCESS            The attributes were set for the memory
                                    region.
  @retval RETURN_INVALID_PARAMETER  Length is zero.
  @retval RETURN_UNSUPPORTED        The processor does not support one or
                                    more bytes of the memory resource range
                                    specified by BaseAddress and Length.
  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support
                                    for the memory resource range specified
                                    by BaseAddress and Length.
  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource
                                    range specified by BaseAddress and Length
                                    cannot be modified.
  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to
                                    modify the attributes of the memory
                                    resource range.

**/
RETURN_STATUS
EFIAPI
MtrrSetMemoryAttribute (
  IN PHYSICAL_ADDRESS        BaseAddress,
  IN UINT64                  Length,
  IN MTRR_MEMORY_CACHE_TYPE  Attribute
  )
{
  UINT64                    TempQword;
  RETURN_STATUS             Status;
  UINT64                    MemoryType;
  UINT64                    Remainder;
  BOOLEAN                   OverLap;
  BOOLEAN                   Positive;
  UINT32                    MsrNum;
  UINTN                     MtrrNumber;
  VARIABLE_MTRR             VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
  UINT32                    UsedMtrr;
  UINT64                    MtrrValidBitsMask;
  UINT64                    MtrrValidAddressMask;
  UINTN                     Cr4;
  BOOLEAN                   OverwriteExistingMtrr;
  UINT32                    FirmwareVariableMtrrCount;
  UINT32                    VariableMtrrEnd;

  if (!IsMtrrSupported ()) {
    return RETURN_UNSUPPORTED;
  }

  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;

  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);

  TempQword = 0;
  MemoryType = (UINT64)Attribute;
  OverwriteExistingMtrr = FALSE;

  //
  // Check for an invalid parameter
  //
  if (Length == 0) {
    return RETURN_INVALID_PARAMETER;
  }

  if (
       (BaseAddress &~MtrrValidAddressMask) != 0 ||
       (Length &~MtrrValidAddressMask) != 0
     ) {
    return RETURN_UNSUPPORTED;
  }

  //
  // Check if Fixed MTRR
  //
  Status = RETURN_SUCCESS;
  while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
    Cr4 = PreMtrrChange ();
    Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
    PostMtrrChange (Cr4);
    if (RETURN_ERROR (Status)) {
      return Status;
    }
  }

  if (Length == 0) {
    //
    // A Length of 0 can only make sense for fixed MTTR ranges.
    // Since we just handled the fixed MTRRs, we can skip the
    // variable MTRR section.
    //
    goto Done;
  }

  //
  // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
  // we can set the bade to 0 to save variable MTRRs.
  //
  if (BaseAddress == BASE_1MB) {
    BaseAddress = 0;
    Length += SIZE_1MB;
  }

  //
  // Check memory base address alignment
  //
  DivU64x64Remainder (BaseAddress, Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);
  if (Remainder != 0) {
    DivU64x64Remainder (BaseAddress, Power2MaxMemory (Length), &Remainder);
    if (Remainder != 0) {
      Status = RETURN_UNSUPPORTED;
      goto Done;
    }
  }

  //
  // Check for overlap
  //
  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
  OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
  if (OverLap) {
    Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }

    if (Length == 0) {
      //
      // Combined successfully
      //
      Status = RETURN_SUCCESS;
      goto Done;
    }
  }

  //
  // Program Variable MTRRs
  //
  // Avoid hardcode here and read data dynamically
  //
  if (UsedMtrr >= FirmwareVariableMtrrCount) {
    Status = RETURN_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // The memory type is the same with the type specified by
  // MTRR_LIB_IA32_MTRR_DEF_TYPE.
  //
  if ((!OverwriteExistingMtrr) && (Attribute == GetMtrrDefaultMemoryType ())) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);
    goto Done;
  }

  TempQword = Length;


  if (TempQword == Power2MaxMemory (TempQword)) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);

    //
    // Find first unused MTRR
    //
    for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
         MsrNum < VariableMtrrEnd;
         MsrNum += 2
        ) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );
  } else {

    Positive = GetDirection (TempQword, &MtrrNumber);

    if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
      Status = RETURN_OUT_OF_RESOURCES;
      goto Done;
    }

    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);

    //
    // Find first unused MTRR
    //
    for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
         MsrNum < VariableMtrrEnd;
         MsrNum += 2
        ) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    if (!Positive) {
      Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Length,
        MemoryType,
        MtrrValidAddressMask
        );
      BaseAddress += Length;
      TempQword   = Length - TempQword;
      MemoryType  = MTRR_CACHE_UNCACHEABLE;
    }

    do {
      //
      // Find unused MTRR
      //
      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
        if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
          break;
        }
      }

      Length = Power2MaxMemory (TempQword);
      if (!Positive) {
        BaseAddress -= Length;
      }

      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Length,
        MemoryType,
        MtrrValidAddressMask
        );

      if (Positive) {
        BaseAddress += Length;
      }
      TempQword -= Length;

    } while (TempQword > 0);
  }

Done:
  return Status;

}
示例#16
0
/**
  This function attempts to set the attributes for a memory range.

  @param  BaseAddress            The physical address that is the start
                                 address of a memory region.
  @param  Length                 The size in bytes of the memory region.
  @param  Attributes             The bit mask of attributes to set for the
                                 memory region.

  @retval RETURN_SUCCESS            The attributes were set for the memory
                                    region.
  @retval RETURN_INVALID_PARAMETER  Length is zero.
  @retval RETURN_UNSUPPORTED        The processor does not support one or
                                    more bytes of the memory resource range
                                    specified by BaseAddress and Length.
  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support
                                    for the memory resource range specified
                                    by BaseAddress and Length.
  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource
                                    range specified by BaseAddress and Length
                                    cannot be modified.
  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to
                                    modify the attributes of the memory
                                    resource range.

**/
RETURN_STATUS
EFIAPI
MtrrSetMemoryAttribute (
  IN PHYSICAL_ADDRESS        BaseAddress,
  IN UINT64                  Length,
  IN MTRR_MEMORY_CACHE_TYPE  Attribute
  )
{
  UINT64                    TempQword;
  RETURN_STATUS             Status;
  UINT64                    MemoryType;
  UINT64                    Alignment;
  BOOLEAN                   OverLap;
  BOOLEAN                   Positive;
  UINT32                    MsrNum;
  UINTN                     MtrrNumber;
  VARIABLE_MTRR             VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
  UINT32                    UsedMtrr;
  UINT64                    MtrrValidBitsMask;
  UINT64                    MtrrValidAddressMask;
  BOOLEAN                   OverwriteExistingMtrr;
  UINT32                    FirmwareVariableMtrrCount;
  UINT32                    VariableMtrrEnd;
  MTRR_CONTEXT              MtrrContext;

  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));

  if (!IsMtrrSupported ()) {
    Status = RETURN_UNSUPPORTED;
    goto Done;
  }

  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;

  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);

  TempQword = 0;
  MemoryType = (UINT64)Attribute;
  OverwriteExistingMtrr = FALSE;

  //
  // Check for an invalid parameter
  //
  if (Length == 0) {
    Status = RETURN_INVALID_PARAMETER;
    goto Done;
  }

  if (
       (BaseAddress & ~MtrrValidAddressMask) != 0 ||
       (Length & ~MtrrValidAddressMask) != 0
     ) {
    Status = RETURN_UNSUPPORTED;
    goto Done;
  }

  //
  // Check if Fixed MTRR
  //
  Status = RETURN_SUCCESS;
  while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
    PreMtrrChange (&MtrrContext);
    Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
    PostMtrrChange (&MtrrContext);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }
  }

  if (Length == 0) {
    //
    // A Length of 0 can only make sense for fixed MTTR ranges.
    // Since we just handled the fixed MTRRs, we can skip the
    // variable MTRR section.
    //
    goto Done;
  }

  //
  // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
  // we can set the base to 0 to save variable MTRRs.
  //
  if (BaseAddress == BASE_1MB) {
    BaseAddress = 0;
    Length += SIZE_1MB;
  }

  //
  // Check for overlap
  //
  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
  OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
  if (OverLap) {
    Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }

    if (Length == 0) {
      //
      // Combined successfully, invalidate the now-unused MTRRs
      //
      InvalidateMtrr(VariableMtrr);
      Status = RETURN_SUCCESS;
      goto Done;
    }
  }

  //
  // The memory type is the same with the type specified by
  // MTRR_LIB_IA32_MTRR_DEF_TYPE.
  //
  if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);
    goto Done;
  }

  Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);

  if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
    Status = RETURN_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // Invalidate the now-unused MTRRs
  //
  InvalidateMtrr(VariableMtrr);

  //
  // Find first unused MTRR
  //
  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
       MsrNum < VariableMtrrEnd;
       MsrNum += 2
      ) {
    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
      break;
    }
  }

  if (BaseAddress != 0) {
    do {
      //
      // Calculate the alignment of the base address.
      //
      Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));

      if (Alignment > Length) {
        break;
      }

      //
      // Find unused MTRR
      //
      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
        if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
          break;
        }
      }

      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Alignment,
        MemoryType,
        MtrrValidAddressMask
        );
      BaseAddress += Alignment;
      Length -= Alignment;
    } while (TRUE);

    if (Length == 0) {
      goto Done;
    }
  }

  TempQword = Length;

  if (!Positive) {
    Length = Power2MaxMemory (LShiftU64 (TempQword, 1));

    //
    // Find unused MTRR
    //
    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );
    BaseAddress += Length;
    TempQword   = Length - TempQword;
    MemoryType  = MTRR_CACHE_UNCACHEABLE;
  }

  do {
    //
    // Find unused MTRR
    //
    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    Length = Power2MaxMemory (TempQword);
    if (!Positive) {
      BaseAddress -= Length;
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );

    if (Positive) {
      BaseAddress += Length;
    }
    TempQword -= Length;

  } while (TempQword > 0);

Done:
  DEBUG((DEBUG_CACHE, "  Status = %r\n", Status));
  if (!RETURN_ERROR (Status)) {
    MtrrDebugPrintAllMtrrs ();
  }

  return Status;
}
示例#17
0
文件: Mtrr.c 项目: shijunjing/edk2
/**
  Display the memory type registers

  @param [in] SocketFD      The socket's file descriptor to add to the list.
  @param [in] pPort         The WSDT_PORT structure address
  @param [out] pbDone       Address to receive the request completion status

  @retval EFI_SUCCESS       The request was successfully processed

**/
EFI_STATUS
MemoryTypeRegistersPage (
  IN int SocketFD,
  IN WSDT_PORT * pPort,
  OUT BOOLEAN * pbDone
  )
{
  UINT64 Addr;
  BOOLEAN bValid;
  MSR_IA32_MTRRCAP_REGISTER Capabilities;
  UINTN Count;
  MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
  UINTN Index;
  UINT64 Mask;

  CONST UINT64 mFixedAddresses [( 8 * MTRR_NUMBER_OF_FIXED_MTRR ) + 1 ] = {
           0ULL,
     0x10000ULL,
     0x20000ULL,
     0x30000ULL,
     0x40000ULL,
     0x50000ULL,
     0x60000ULL,
     0x70000ULL,

     0x80000ULL,
     0x84000ULL,
     0x88000ULL,
     0x8c000ULL,
     0x90000ULL,
     0x94000ULL,
     0x98000ULL,
     0x9c000ULL,

     0xa0000ULL,
     0xa4000ULL,
     0xa8000ULL,
     0xac000ULL,
     0xb0000ULL,
     0xb4000ULL,
     0xb8000ULL,
     0xbc000ULL,

     0xc0000ULL,
     0xc1000ULL,
     0xc2000ULL,
     0xc3000ULL,
     0xc4000ULL,
     0xc5000ULL,
     0xc6000ULL,
     0xc7000ULL,

     0xc8000ULL,
     0xc9000ULL,
     0xca000ULL,
     0xcb000ULL,
     0xcc000ULL,
     0xcd000ULL,
     0xce000ULL,
     0xcf000ULL,

     0xd0000ULL,
     0xd1000ULL,
     0xd2000ULL,
     0xd3000ULL,
     0xd4000ULL,
     0xd5000ULL,
     0xd6000ULL,
     0xd7000ULL,

     0xd8000ULL,
     0xd9000ULL,
     0xda000ULL,
     0xdb000ULL,
     0xdc000ULL,
     0xdd000ULL,
     0xde000ULL,
     0xdf000ULL,

     0xe0000ULL,
     0xe1000ULL,
     0xe2000ULL,
     0xe3000ULL,
     0xe4000ULL,
     0xe5000ULL,
     0xe6000ULL,
     0xe7000ULL,

     0xe8000ULL,
     0xe9000ULL,
     0xea000ULL,
     0xeb000ULL,
     0xec000ULL,
     0xed000ULL,
     0xee000ULL,
     0xef000ULL,

     0xf0000ULL,
     0xf1000ULL,
     0xf2000ULL,
     0xf3000ULL,
     0xf4000ULL,
     0xf5000ULL,
     0xf6000ULL,
     0xf7000ULL,

     0xf8000ULL,
     0xf9000ULL,
     0xfa000ULL,
     0xfb000ULL,
     0xfc000ULL,
     0xfd000ULL,
     0xfe000ULL,
     0xff000ULL,

    0x100000ULL
  };
  MTRR_SETTINGS Mtrr;
  CONST UINT64 * pMemEnd;
  CONST UINT64 * pMemStart;
  UINT64 PreviousType;
  UINT64 ShiftCount;
  EFI_STATUS Status;
  UINT64 Type;
  INT64 Value;
  
  DBG_ENTER ( );
  
  //
  //  Send the Memory Type Registers page
  //
  for ( ; ; ) {
    //
    //  Send the page header
    //
    Status = HttpPageHeader ( SocketFD, pPort, L"Memory Type Range Registers" );
    if ( EFI_ERROR ( Status )) {
      break;
    }

    //
    //  Send the header
    //
    Status = HttpSendAnsiString ( SocketFD,
                                  pPort,
                                  "<h1>Memory Type Range Registers</h1>\r\n" );
    if ( EFI_ERROR ( Status )) {
      break;
    }

    //
    //  Determine if MTRRs are supported
    //
    if ( !IsMtrrSupported ( )) {
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    "<p>Memory Type Range Registers are not supported!\r\n" );
      if ( EFI_ERROR ( Status )) {
        break;
      }
    }
    else {
      //
      //  Get the capabilities
      //
      Capabilities.Uint64 = AsmReadMsr64 ( MSR_IA32_MTRRCAP );
      DefType.Uint64 =  AsmReadMsr64 ( MSR_IA32_MTRR_DEF_TYPE );

      //
      //  Display the capabilities
      //
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    "<p>Capabilities: " );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendHexValue ( SocketFD,
                                  pPort,
                                  Capabilities.Uint64 );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    "<br>\r\n" );
      if ( EFI_ERROR ( Status )) {
        break;
      }

      //
      //  Display the default type
      //
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    "Def Type: " );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendHexValue ( SocketFD,
                                  pPort,
                                  DefType.Uint64);
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ", MTRRs " );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ( 0 != DefType.Bits.E )
                                    ? "Enabled"
                                    : "Disabled" );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ", Fixed MTRRs " );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ( 0 != DefType.Bits.FE )
                                    ? "Enabled"
                                    : "Disabled" );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ", " );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Type = DefType.Uint64 & 0xff;
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    ( DIM ( mMemoryType ) > Type )
                                    ? mMemoryType [ Type ]
                                    : "Reserved" );
      if ( EFI_ERROR ( Status )) {
        break;
      }
      Status = HttpSendAnsiString ( SocketFD,
                                    pPort,
                                    "</p>\r\n" );
      if ( EFI_ERROR ( Status )) {
        break;
      }

      //
      //  Determine if MTRRs are enabled
      //
      if ( 0 == DefType.Bits.E ) {
        Status = HttpSendAnsiString ( SocketFD,
                                      pPort,
                                      "<p>All memory is uncached!</p>\r\n" );
        if ( EFI_ERROR ( Status )) {
          break;
        }
      }
      else {
        //
        //  Get the MTRRs
        //
        MtrrGetAllMtrrs ( &Mtrr );

        //
        //  Determine if the fixed MTRRs are supported
        //
        if (( 0 != Capabilities.Bits.FIX )
          && ( 0 != DefType.Bits.FE)) {

          //
          //  Beginning of table
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "<h2>Fixed MTRRs</h2>\r\n"
                                        "<table>\r\n"
                                        "  <tr><th>Index</th><th align=\"right\">Value</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  Display the fixed MTRRs
          //
          pMemStart = &mFixedAddresses[ 0 ];
          for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) {
            //
            //  Start the row
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "  <tr><td>" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            
            //
            //  Index
            //
            Status = HttpSendValue ( SocketFD,
                                     pPort,
                                     Count );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            
            //
            //  Value
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</td><td align=\"right\"><code>0x" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Status = HttpSendHexValue ( SocketFD,
                                        pPort,
                                        Mtrr.Fixed.Mtrr[ Count ]);
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  Start
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td><td align=\"right\"><code>0x" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Status = HttpSendHexValue ( SocketFD,
                                        pPort,
                                        *pMemStart );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            pMemStart += 8;

            //
            //  Value
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td><td align=\"right\"><code>0x" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Status = HttpSendHexValue ( SocketFD,
                                        pPort,
                                        *pMemStart - 1 );
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  End of row
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td></tr>\r\n" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
          }
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  End of table
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "</table>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  Beginning of table
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "<table>\r\n"
                                        "  <tr><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"left\">Type</th></tr>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  Decode the fixed MTRRs
          //
          PreviousType = Mtrr.Fixed.Mtrr[ 0 ] & 0xff;
          pMemStart = &mFixedAddresses[ 0 ];
          pMemEnd = pMemStart;
          for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) {
            //
            //  Get the memory types
            //
            Type = Mtrr.Fixed.Mtrr[ Count ];

            //
            //  Walk the memory range
            //
            for ( Index = 0; 8 > Index; Index++ ) {
              //
              //  Determine if this is the same memory type
              //
              if ( PreviousType != ( Type & 0xff )) {
                //
                //  Display the row
                //
                Status = MtrrDisplayFixedRow ( SocketFD,
                                               pPort,
                                               *pMemStart,
                                               *pMemEnd,
                                               PreviousType );
                if ( EFI_ERROR ( Status )) {
                  break;
                }

                //
                //  Start the next range of addresses
                //
                pMemStart = pMemEnd;
                PreviousType = Type & 0xff;
              }

              //
              //  Set the next memory range and type
              //
              Type >>= 8;
              pMemEnd += 1;
            }
            if ( EFI_ERROR ( Status )) {
              break;
            }
          }
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  Display the final row
          //
          Status = MtrrDisplayFixedRow ( SocketFD,
                                         pPort,
                                         *pMemStart,
                                         *pMemEnd,
                                         PreviousType );
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  End of table 
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "</table>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }
        }

        //
        //  Determine if the variable MTRRs are supported
        //
        if ( 0 < Capabilities.Bits.VCNT ) {
          //
          //  Beginning of table
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "<h2>Variable MTRRs</h2>\r\n"
                                        "<table>\r\n"
                                        "  <tr><th>Index</th><th align=\"right\">Base</th><th align=\"right\">Mask</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  Display the variable MTRRs
          //
          for ( Count = 0; Capabilities.Bits.VCNT > Count; Count++ ) {
            //
            //  Start the row
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "  <tr><td>" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            
            //
            //  Index
            //
            Status = HttpSendValue ( SocketFD,
                                     pPort,
                                     Count );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            
            //
            //  Base
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</td><td align=\"right\"><code>0x" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Status = HttpSendHexValue ( SocketFD,
                                        pPort,
                                        Mtrr.Variables.Mtrr[ Count ].Base );
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  Mask
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</td><td align=\"right\"><code>0x" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Status = HttpSendHexValue ( SocketFD,
                                        pPort,
                                        Mtrr.Variables.Mtrr[ Count ].Mask );
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  Determine if the entry is valid
            //
            bValid = ( Mtrr.Variables.Mtrr[ Count ].Mask & VARIABLE_MTRR_VALID ) ? TRUE : FALSE;

            //
            //  Start
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td><td align=\"right\"><code>" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            Addr = Mtrr.Variables.Mtrr[ Count ].Base & 0xfffffffffffff000ULL;
            if ( bValid ) {
              Status = HttpSendAnsiString ( SocketFD,
                                            pPort,
                                            "0x" );
              if ( EFI_ERROR ( Status )) {
                break;
              }
              Status = HttpSendHexValue ( SocketFD,
                                          pPort,
                                          Addr );
            }
            else {
              Status = HttpSendAnsiString ( SocketFD,
                                            pPort,
                                            "Invalid" );
            }
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  End
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td><td align=\"right\"><code>" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            if ( bValid ) {
              //
              //  Determine the end address
              //
              Mask = Mtrr.Variables.Mtrr[ Count ].Mask;
              Value = Mask;
              ShiftCount = 0;
              while ( 0 < Value ) {
                Value <<= 1;
                ShiftCount += 1;
              }
              Value = 1;
              Value <<= 64 - ShiftCount;
              Value -= 1;
              Value = ~Value;
              Value |= Mask;
              Value &= ~VARIABLE_MTRR_VALID;
              Value = ~Value;

              Status = HttpSendAnsiString ( SocketFD,
                                            pPort,
                                            "0x" );
              if ( EFI_ERROR ( Status )) {
                break;
              }
              Status = HttpSendHexValue ( SocketFD,
                                          pPort,
                                          Addr + Value );
            }
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  Type
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</code></td><td>" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
            if ( bValid ) {
              Type = Mtrr.Variables.Mtrr[ Count ].Base & 0xFF;
              Status = HttpSendAnsiString ( SocketFD,
                                            pPort,
                                            ( DIM ( mMemoryType ) > Type )
                                            ? mMemoryType [ Type ]
                                            : "Reserved" );
            }
            if ( EFI_ERROR ( Status )) {
              break;
            }

            //
            //  End of row
            //
            Status = HttpSendAnsiString ( SocketFD,
                                          pPort,
                                          "</td></tr>\r\n" );
            if ( EFI_ERROR ( Status )) {
              break;
            }
          }
          if ( EFI_ERROR ( Status )) {
            break;
          }

          //
          //  End of table 
          //
          Status = HttpSendAnsiString ( SocketFD,
                                        pPort,
                                        "</table>\r\n" );
          if ( EFI_ERROR ( Status )) {
            break;
          }
        }
      }
    }

    //
    //  Send the page trailer
    //
    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
    break;
  }