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