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