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