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