CacheLib.c 19 KB

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