11MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = {
12 CacheUncacheable, CacheWriteCombining, CacheWriteThrough, CacheWriteProtected, CacheWriteBack
15UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
26UINTN mNumberIndex = 0;
27extern UINTN mNumbers[];
28extern UINTN mNumberCount;
46 return mNumbers[mNumberIndex++ % (mNumberCount - 1)];
50CHAR8 mContentTemplate[] = {
52 " Pre-generated random number used by MtrrLib test.\n"
54 " Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\n"
55 " SPDX-License-Identifier: BSD-2-Clause-Patent\n"
57 "UINTN mNumberCount = %d;\n"
58 "UINTN mNumbers[] = {"
76 File = fopen (FilePath,
"w");
77 fprintf (File, mContentTemplate, Count);
78 for (Index = 0; Index < Count; Index++) {
79 if (Index % 10 == 0) {
80 fprintf (File,
"\n ");
83 fprintf (File,
" %d,", rand ());
86 fprintf (File,
"\n};\n");
127 OUT UINT32 *Eax OPTIONAL,
128 OUT UINT32 *Ebx OPTIONAL,
129 OUT UINT32 *Ecx OPTIONAL,
130 OUT UINT32 *Edx OPTIONAL
143 *Edx = mCpuidVersionInfoEdx.
Uint32;
150 *Ecx = mCpuidExtendedFeatureFlagsEcx.
Uint32;
155 case CPUID_EXTENDED_FUNCTION:
157 *Eax = CPUID_VIR_PHY_ADDRESS_SIZE;
162 case CPUID_VIR_PHY_ADDRESS_SIZE:
164 *Eax = mCpuidVirPhyAddressSizeEax.
Uint32;
207 OUT UINT32 *Eax OPTIONAL,
208 OUT UINT32 *Ebx OPTIONAL,
209 OUT UINT32 *Ecx OPTIONAL,
210 OUT UINT32 *Edx OPTIONAL
240 for (Index = 0; Index <
ARRAY_SIZE (mFixedMtrrsValue); Index++) {
241 if (MsrIndex == mFixedMtrrsIndex[Index]) {
243 return mFixedMtrrsValue[Index];
251 if (MsrIndex % 2 == 0) {
253 return mVariableMtrrsPhysBase[Index].
Uint64;
256 return mVariableMtrrsPhysMask[Index].
Uint64;
261 return mDefTypeMsr.
Uint64;
265 return mMtrrCapMsr.
Uint64;
269 return mTmeActivateMsr.
Uint64;
307 for (Index = 0; Index <
ARRAY_SIZE (mFixedMtrrsValue); Index++) {
308 if (MsrIndex == mFixedMtrrsIndex[Index]) {
310 mFixedMtrrsValue[Index] = Value;
319 if (MsrIndex % 2 == 0) {
321 mVariableMtrrsPhysBase[Index].
Uint64 = Value;
325 mVariableMtrrsPhysMask[Index].
Uint64 = Value;
335 mDefTypeMsr.
Uint64 = Value;
340 mMtrrCapMsr.
Uint64 = Value;
364 SetMem (mFixedMtrrsValue,
sizeof (mFixedMtrrsValue), SystemParameter->DefaultCacheType);
366 for (Index = 0; Index <
ARRAY_SIZE (mVariableMtrrsPhysBase); Index++) {
367 mVariableMtrrsPhysBase[Index].
Uint64 = 0;
368 mVariableMtrrsPhysMask[Index].
Uint64 = 0;
371 mDefTypeMsr.
Bits.
E = 1;
373 mDefTypeMsr.
Bits.
Type = SystemParameter->DefaultCacheType;
374 mDefTypeMsr.
Bits.Reserved1 = 0;
375 mDefTypeMsr.
Bits.Reserved2 = 0;
376 mDefTypeMsr.
Bits.Reserved3 = 0;
380 mMtrrCapMsr.
Bits.
VCNT = SystemParameter->VariableMtrrCount;
381 mMtrrCapMsr.
Bits.
FIX = SystemParameter->FixedMtrrSupported;
382 mMtrrCapMsr.
Bits.Reserved1 = 0;
383 mMtrrCapMsr.
Bits.Reserved2 = 0;
384 mMtrrCapMsr.
Bits.Reserved3 = 0;
386 mCpuidVersionInfoEdx.
Bits.
MTRR = SystemParameter->MtrrSupported;
398 if (SystemParameter->MkTmeKeyidBits != 0) {
399 mCpuidExtendedFeatureFlagsEcx.
Bits.
TME_EN = 1;
403 mCpuidExtendedFeatureFlagsEcx.
Bits.
TME_EN = 0;
408 return UNIT_TEST_PASSED;
438 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
439 IN UINT32 PhysicalAddressBits,
440 IN UINT32 VariableMtrrCount,
444 OUT UINT32 *MtrrCount
448 UINT64 MtrrValidBitsMask;
449 UINT64 MtrrValidAddressMask;
452 ASSERT (Mtrrs !=
NULL);
453 ASSERT (VariableMtrrCount <=
ARRAY_SIZE (Mtrrs->Variables.Mtrr));
455 MtrrValidBitsMask = (1ull << PhysicalAddressBits) - 1;
456 MtrrValidAddressMask = MtrrValidBitsMask & ~0xFFFull;
459 for (Index = 0; Index < VariableMtrrCount; Index++) {
461 RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs->Variables.Mtrr[Index].Base & MtrrValidAddressMask;
462 RawMemoryRanges[*MtrrCount].Type =
464 RawMemoryRanges[*MtrrCount].Length =
465 ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
486 return (UINT32)(((double)
Rand () / RAND_MAX) * (Limit - Start)) + Start;
502 return (UINT64)(((double)
Rand () / RAND_MAX) * (Limit - Start)) + Start;
515 IN UINT32 PhysicalAddressBits,
516 IN MTRR_MEMORY_CACHE_TYPE CacheType,
525 UINT64 RandomBoundary;
526 UINT64 MaxPhysicalAddress;
529 UINT64 PhysBasePhyMaskValidBitsMask;
531 MaxPhysicalAddress = 1ull << PhysicalAddressBits;
533 SizeShift =
Random32 (12, PhysicalAddressBits - 1);
534 RangeSize = 1ull << SizeShift;
536 BaseShift =
Random32 (SizeShift, PhysicalAddressBits - 1);
537 RandomBoundary =
Random64 (0, 1ull << (PhysicalAddressBits - BaseShift));
538 RangeBase = RandomBoundary << BaseShift;
539 }
while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1);
541 PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress - 1) & 0xfffffffffffff000ULL;
545 PhysBase.
Uint64 |= RangeBase & PhysBasePhyMaskValidBitsMask;
548 PhysMask.
Uint64 |= ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsMask;
550 if (MtrrPair !=
NULL) {
551 MtrrPair->Base = PhysBase.
Uint64;
552 MtrrPair->Mask = PhysMask.
Uint64;
555 if (MtrrMemoryRange !=
NULL) {
556 MtrrMemoryRange->BaseAddress = RangeBase;
557 MtrrMemoryRange->Length = RangeSize;
558 MtrrMemoryRange->Type = CacheType;
578 while (Count-- != 0) {
584 if ( ((Range->BaseAddress <= Ranges[Count].BaseAddress) && (Ranges[Count].BaseAddress < Range->BaseAddress + Range->Length))
585 || ((Ranges[Count].BaseAddress <= Range->BaseAddress) && (Range->BaseAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)))
607 IN UINT32 PhysicalAddressBits,
621 for (Index = 0; Index < UcCount; Index++) {
625 for (Index = UcCount; Index < UcCount + WtCount; Index++) {
629 for (Index = UcCount + WtCount; Index < UcCount + WtCount + WbCount; Index++) {
636 for (Index = UcCount + WtCount + WbCount; Index < UcCount + WtCount + WbCount + WpCount; Index++) {
638 while (
RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount)) {
646 for (Index = UcCount + WtCount + WbCount + WpCount; Index < UcCount + WtCount + WbCount + WpCount + WcCount; Index++) {
648 while (
RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) {
657MTRR_MEMORY_CACHE_TYPE
687 Delta = (*(UINT64 *)Left - *(UINT64 *)Right);
690 }
else if (Delta == 0) {
707 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
715 Range->Type = CacheInvalid;
716 for (Index = 0; Index < RangeCount; Index++) {
718 if (Ranges[Index].Type < Range->Type) {
719 Range->Type = Ranges[Index].Type;
724 if (Range->Type == CacheInvalid) {
725 Range->Type = DefaultType;
745 UINT64 CurrentElement;
747 CurrentElement = Array[Index];
748 while ((Index < Count) && (CurrentElement == Array[Index])) {
763 IN OUT UINT64 *Array,
772 while (Index < *Count) {
773 Array[NewCount] = Array[Index];
794 return (Address >= Range.BaseAddress) && (Address <= Range.BaseAddress + Range.Length - 1);
807 IN UINT32 RawMemoryRangeCount,
811 UINT64 OverlapBitFlag;
815 for (Index = 0; Index < RawMemoryRangeCount; Index++) {
817 OverlapBitFlag |= (1ull << Index);
821 return OverlapBitFlag;
841 if (Flag1 == Flag2) {
845 if ((Flag1 | Flag2) == Flag2) {
849 if ((Flag1 | Flag2) == Flag1) {
875 for (Index = 0; Index < RangeCount; Index++) {
894 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
895 IN UINT32 PhysicalAddressBits,
901 UINTN NewRangesCountAtMost;
903 UINTN NewRangesCountActual;
905 MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges;
909 UINTN OldRangesIndex;
911 NewRangesCountActual = 0;
912 NewRangesCountAtMost = *EffectiveMtrrMemoryRangesCount + 2;
914 OldRanges = *EffectiveMtrrMemoryRanges;
915 if (OldRanges[0].BaseAddress > 0) {
916 NewRanges[NewRangesCountActual].BaseAddress = 0;
917 NewRanges[NewRangesCountActual].Length = OldRanges[0].BaseAddress;
918 NewRanges[NewRangesCountActual].Type = DefaultType;
919 NewRangesCountActual++;
923 while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) {
924 CurrentRangeTypeInOldRanges = OldRanges[OldRangesIndex].Type;
925 CurrentRangeInNewRanges =
NULL;
926 if (NewRangesCountActual > 0) {
928 CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
931 if ((CurrentRangeInNewRanges !=
NULL) && (CurrentRangeInNewRanges->Type == CurrentRangeTypeInOldRanges)) {
932 CurrentRangeInNewRanges->Length += OldRanges[OldRangesIndex].Length;
934 NewRanges[NewRangesCountActual].BaseAddress = OldRanges[OldRangesIndex].BaseAddress;
935 NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
936 NewRanges[NewRangesCountActual].Type = CurrentRangeTypeInOldRanges;
937 while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && OldRanges[OldRangesIndex + 1].Type == CurrentRangeTypeInOldRanges) {
939 NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
942 NewRangesCountActual++;
948 MaxAddress = (1ull << PhysicalAddressBits) - 1;
949 OldLastRange = OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];
950 CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
951 if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) {
952 if (CurrentRangeInNewRanges->Type == DefaultType) {
953 CurrentRangeInNewRanges->Length = MaxAddress - CurrentRangeInNewRanges->BaseAddress + 1;
955 NewRanges[NewRangesCountActual].BaseAddress = OldLastRange.BaseAddress + OldLastRange.Length;
956 NewRanges[NewRangesCountActual].Length = MaxAddress - NewRanges[NewRangesCountActual].BaseAddress + 1;
957 NewRanges[NewRangesCountActual].Type = DefaultType;
958 NewRangesCountActual++;
962 free (*EffectiveMtrrMemoryRanges);
963 *EffectiveMtrrMemoryRanges = NewRanges;
964 *EffectiveMtrrMemoryRangesCount = NewRangesCountActual;
977 IN OUT UINT64 *Endpoints,
978 IN OUT UINT32 *EndPointCount,
980 IN UINT32 RawMemoryRangeCount
984 UINT32 RawRangeIndex;
986 ASSERT ((RawMemoryRangeCount << 1) == *EndPointCount);
988 for (Index = 0; Index < *EndPointCount; Index += 2) {
989 RawRangeIndex = Index >> 1;
990 Endpoints[Index] = RawMemoryRanges[RawRangeIndex].BaseAddress;
991 Endpoints[Index + 1] = RawMemoryRanges[RawRangeIndex].BaseAddress + RawMemoryRanges[RawRangeIndex].Length - 1;
1010 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
1011 IN UINT32 PhysicalAddressBits,
1013 IN UINT32 RawMemoryRangeCount,
1019 UINT32 AllEndPointsCount;
1020 UINT64 *AllEndPointsInclusive;
1021 UINT32 AllRangePiecesCountMax;
1023 UINTN AllRangePiecesCountActual;
1024 UINT64 OverlapBitFlag1;
1025 UINT64 OverlapBitFlag2;
1026 INT32 OverlapFlagRelation;
1028 if (RawMemoryRangeCount == 0) {
1029 MemoryRanges[0].BaseAddress = 0;
1030 MemoryRanges[0].Length = (1ull << PhysicalAddressBits);
1031 MemoryRanges[0].Type = DefaultType;
1032 *MemoryRangeCount = 1;
1036 AllEndPointsCount = RawMemoryRangeCount << 1;
1037 AllEndPointsInclusive = calloc (AllEndPointsCount,
sizeof (UINT64));
1038 AllRangePiecesCountMax = RawMemoryRangeCount * 3 + 1;
1040 CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemoryRanges, RawMemoryRangeCount);
1042 for (Index = 0, AllRangePiecesCountActual = 0; Index < AllEndPointsCount - 1; Index++) {
1043 OverlapBitFlag1 =
GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index]);
1044 OverlapBitFlag2 =
GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index + 1]);
1046 switch (OverlapFlagRelation) {
1048 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1049 AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1;
1050 AllRangePiecesCountActual++;
1053 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1054 AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1;
1055 AllRangePiecesCountActual++;
1058 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
1059 AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1;
1060 AllRangePiecesCountActual++;
1062 if (!
IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
1063 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1064 AllRangePieces[AllRangePiecesCountActual].Length = 1;
1065 AllRangePiecesCountActual++;
1070 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
1071 AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + 1) + 1;
1072 if (AllRangePieces[AllRangePiecesCountActual].Length == 0) {
1077 AllRangePiecesCountActual++;
1078 if (!
IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
1079 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1080 AllRangePieces[AllRangePiecesCountActual].Length = 1;
1081 AllRangePiecesCountActual++;
1090 for (Index = 0; Index < AllRangePiecesCountActual; Index++) {
1095 ASSERT (*MemoryRangeCount >= AllRangePiecesCountActual);
1096 memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual *
sizeof (
MTRR_MEMORY_RANGE));
1097 *MemoryRangeCount = AllRangePiecesCountActual;
1099 free (AllEndPointsInclusive);
1100 free (AllRangePieces);
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
#define ARRAY_SIZE(Array)
#define MSR_IA32_MTRR_PHYSBASE0
#define MSR_IA32_MTRR_DEF_TYPE
#define MSR_IA32_MTRR_PHYSMASK0
#define MSR_IA32_TME_ACTIVATE
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
#define CPUID_VERSION_INFO
UINT64 Random64(UINT64 Start, UINT64 Limit)
VOID CollectTestResult(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN UINT32 VariableMtrrCount, IN MTRR_SETTINGS *Mtrrs, OUT MTRR_MEMORY_RANGE *Ranges, IN OUT UINTN *RangeCount, OUT UINT32 *MtrrCount)
UINT32 GetNextDifferentElementInSortedArray(IN UINT32 Index, IN UINT64 *Array, IN UINT32 Count)
BOOLEAN IsEndpointInRanges(IN UINT64 Endpoint, IN MTRR_MEMORY_RANGE *Ranges, IN UINTN RangeCount)
UINT64 EFIAPI UnitTestMtrrLibAsmReadMsr64(IN UINT32 MsrIndex)
VOID RemoveDuplicatesInSortedArray(IN OUT UINT64 *Array, IN OUT UINT32 *Count)
VOID GenerateValidAndConfigurableMtrrPairs(IN UINT32 PhysicalAddressBits, IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 UcCount, IN UINT32 WtCount, IN UINT32 WbCount, IN UINT32 WpCount, IN UINT32 WcCount)
UINT64 GetOverlapBitFlag(IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount, IN UINT64 Address)
VOID CollectEndpoints(IN OUT UINT64 *Endpoints, IN OUT UINT32 *EndPointCount, IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount)
VOID GenerateRandomNumbers(CHAR8 *FilePath, UINTN Count)
UINT64 EFIAPI UnitTestMtrrLibAsmWriteMsr64(IN UINT32 MsrIndex, IN UINT64 Value)
UNIT_TEST_STATUS EFIAPI InitializeMtrrRegs(IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter)
UINT32 Random32(UINT32 Start, UINT32 Limit)
UINT32 CheckOverlapBitFlagsRelation(IN UINT64 Flag1, IN UINT64 Flag2)
MTRR_MEMORY_CACHE_TYPE GenerateRandomCacheType(VOID)
INT32 CompareFuncUint64(CONST VOID *Left, CONST VOID *Right)
BOOLEAN RangesOverlap(IN MTRR_MEMORY_RANGE *Range, IN MTRR_MEMORY_RANGE *Ranges, IN UINTN Count)
UINT32 EFIAPI UnitTestMtrrLibAsmCpuid(IN UINT32 Index, OUT UINT32 *Eax OPTIONAL, OUT UINT32 *Ebx OPTIONAL, OUT UINT32 *Ecx OPTIONAL, OUT UINT32 *Edx OPTIONAL)
UINT32 EFIAPI UnitTestMtrrLibAsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *Eax OPTIONAL, OUT UINT32 *Ebx OPTIONAL, OUT UINT32 *Ecx OPTIONAL, OUT UINT32 *Edx OPTIONAL)
UNIT_TEST_STATUS EFIAPI InitializeSystem(IN UNIT_TEST_CONTEXT Context)
BOOLEAN AddressInRange(IN UINT64 Address, IN MTRR_MEMORY_RANGE Range)
VOID CompactAndExtendEffectiveMtrrMemoryRanges(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges, IN OUT UINTN *EffectiveMtrrMemoryRangesCount)
VOID GetEffectiveMemoryRanges(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount, OUT MTRR_MEMORY_RANGE *MemoryRanges, OUT UINTN *MemoryRangeCount)
VOID GenerateRandomMtrrPair(IN UINT32 PhysicalAddressBits, IN MTRR_MEMORY_CACHE_TYPE CacheType, OUT MTRR_VARIABLE_SETTING *MtrrPair OPTIONAL, OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL)
VOID DetermineMemoryCacheType(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN OUT MTRR_MEMORY_RANGE *Range, IN MTRR_MEMORY_RANGE *Ranges, IN UINT32 RangeCount)
#define UT_ASSERT_TRUE(Expression)
#define UT_ASSERT_EQUAL(ValueA, ValueB)
UNIT_TEST_HOST_BASE_LIB gUnitTestHostBaseLib
struct CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX::@709 Bits
struct CPUID_VERSION_INFO_EDX::@696 Bits
struct CPUID_VIR_PHY_ADDRESS_SIZE_EAX::@753 Bits
UINT32 PhysicalAddressBits
struct MSR_IA32_MTRR_DEF_TYPE_REGISTER::@653 Bits
struct MSR_IA32_MTRR_PHYSBASE_REGISTER::@649 Bits
struct MSR_IA32_MTRR_PHYSMASK_REGISTER::@650 Bits
struct MSR_IA32_MTRRCAP_REGISTER::@631 Bits
struct MSR_IA32_TME_ACTIVATE_REGISTER::@680 Bits