]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformInitPei/MemoryPeim.c
Vlv2TbltDevicePkg: Enhance get mtrr mask logic.
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformInitPei / MemoryPeim.c
1 /** @file
2
3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
4
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 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 Module Name:
15
16
17 MemoryPeim.c
18
19 Abstract:
20
21 Tiano PEIM to provide the platform support functionality.
22 This file implements the Platform Memory Range PPI
23
24 --*/
25
26 #include "PlatformEarlyInit.h"
27
28 //
29 // Need min. of 48MB PEI phase
30 //
31 #define PEI_MIN_MEMORY_SIZE (6 * 0x800000)
32 #define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)
33
34 //
35 // This is the memory needed for PEI to start up DXE.
36 //
37 // Over-estimating this size will lead to higher fragmentation
38 // of main memory. Under-estimation of this will cause catastrophic
39 // failure of PEI to load DXE. Generally, the failure may only be
40 // realized during capsule updates.
41 //
42 #define PRERESERVED_PEI_MEMORY ( \
43 EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \
44 )
45
46 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
47 { EfiACPIReclaimMemory, 0x40 }, // 0x40 pages = 256k for ASL
48 { EfiACPIMemoryNVS, 0x100 }, // 0x100 pages = 1 MB for S3, SMM, HII, etc
49 { EfiReservedMemoryType, 0x600 }, // 48k for BIOS Reserved
50 { EfiMemoryMappedIO, 0 },
51 { EfiMemoryMappedIOPortSpace, 0 },
52 { EfiPalCode, 0 },
53 { EfiRuntimeServicesCode, 0x200 },
54 { EfiRuntimeServicesData, 0x100 },
55 { EfiLoaderCode, 0x100 },
56 { EfiLoaderData, 0x100 },
57 { EfiBootServicesCode, 0x800 },
58 { EfiBootServicesData, 0x2500},
59 { EfiConventionalMemory, 0 },
60 { EfiUnusableMemory, 0 },
61 { EfiMaxMemoryType, 0 }
62 };
63
64 STATIC
65 EFI_STATUS
66 GetMemorySize (
67 IN CONST EFI_PEI_SERVICES **PeiServices,
68 OUT UINT64 *LowMemoryLength,
69 OUT UINT64 *HighMemoryLength
70 );
71
72
73 /**
74 Initializes the valid address mask for MTRRs.
75
76 This function initializes the valid bits mask and valid address mask for MTRRs.
77
78 **/
79 UINT64
80 InitializeAddressMtrrMask (
81 VOID
82 )
83 {
84 UINT32 RegEax;
85 UINT8 PhysicalAddressBits;
86 UINT64 ValidMtrrBitsMask;
87
88 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
89
90 if (RegEax >= 0x80000008) {
91 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
92
93 PhysicalAddressBits = (UINT8) RegEax;
94 } else {
95 PhysicalAddressBits = 36;
96 }
97
98 ValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
99 return (ValidMtrrBitsMask & 0xfffffffffffff000ULL);
100 }
101
102 EFI_STATUS
103 EFIAPI
104 SetPeiCacheMode (
105 IN CONST EFI_PEI_SERVICES **PeiServices
106 )
107 {
108 EFI_STATUS Status;
109 PEI_CACHE_PPI *CachePpi;
110
111 EFI_BOOT_MODE BootMode;
112 UINT64 MemoryLength;
113 UINT64 MemOverflow;
114 UINT64 MemoryLengthUc;
115 UINT64 MaxMemoryLength;
116 UINT64 LowMemoryLength;
117 UINT64 HighMemoryLength;
118 UINT8 Index;
119 MTRR_SETTINGS MtrrSetting;
120 UINT64 ValidMtrrAddressMask;
121
122 //
123 // Load Cache PPI
124 //
125 Status = (**PeiServices).LocatePpi (
126 PeiServices,
127 &gPeiCachePpiGuid, // GUID
128 0, // Instance
129 NULL, // EFI_PEI_PPI_DESCRIPTOR
130 (void **)&CachePpi // PPI
131 );
132 if (!EFI_ERROR(Status)) {
133 //
134 // Clear the CAR Settings (Default Cache Type => UC)
135 //
136 DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n"));
137 CachePpi->ResetCache(
138 (EFI_PEI_SERVICES**)PeiServices,
139 CachePpi
140 );
141 }
142
143
144 //
145 // Variable initialization
146 //
147 LowMemoryLength = 0;
148 HighMemoryLength = 0;
149 MemoryLengthUc = 0;
150
151 Status = (*PeiServices)->GetBootMode (
152 PeiServices,
153 &BootMode
154 );
155
156 ValidMtrrAddressMask = InitializeAddressMtrrMask ();
157
158 //
159 // Determine memory usage
160 //
161 GetMemorySize (
162 PeiServices,
163 &LowMemoryLength,
164 &HighMemoryLength
165 );
166
167 LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70);
168 LowMemoryLength &= 0xFFF00000ULL;
169
170 MaxMemoryLength = LowMemoryLength;
171
172 //
173 // Round up to nearest 256MB with high memory and 64MB w/o high memory
174 //
175 if (HighMemoryLength != 0 ) {
176 MemOverflow = (LowMemoryLength & 0x0fffffff);
177 if (MemOverflow != 0) {
178 MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);
179 }
180 } else {
181 MemOverflow = (LowMemoryLength & 0x03ffffff);
182 if (MemOverflow != 0) {
183 MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);
184 }
185 }
186
187 ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));
188 for (Index = 0; Index < 2; Index++) {
189 MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606;
190 }
191 for (Index = 2; Index < 11; Index++) {
192 MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505;
193 }
194
195 //
196 // Cache the flash area to improve the boot performance in PEI phase
197 //
198 Index = 0;
199 MtrrSetting.Variables.Mtrr[0].Base = (FixedPcdGet32 (PcdFlashAreaBaseAddress) | CacheWriteProtected);
200 MtrrSetting.Variables.Mtrr[0].Mask = ((~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
201 Index ++;
202
203 MemOverflow =0;
204 while (MaxMemoryLength > MemOverflow){
205 MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & ValidMtrrAddressMask) | CacheWriteBack;
206 MemoryLength = MaxMemoryLength - MemOverflow;
207 MemoryLength = GetPowerOfTwo64 (MemoryLength);
208 MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & ValidMtrrAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
209
210 MemOverflow += MemoryLength;
211 Index++;
212 }
213
214 MemoryLength = LowMemoryLength;
215
216 while (MaxMemoryLength != MemoryLength) {
217 MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
218
219 MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask) | CacheUncacheable;
220 MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc - 1)) & ValidMtrrAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
221 MaxMemoryLength -= MemoryLengthUc;
222 Index++;
223 }
224
225 MemOverflow =0x100000000;
226 while (HighMemoryLength > 0) {
227 MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & ValidMtrrAddressMask) | CacheWriteBack;
228 MemoryLength = HighMemoryLength;
229 MemoryLength = GetPowerOfTwo64 (MemoryLength);
230
231 if (MemoryLength > MemOverflow){
232 MemoryLength = MemOverflow;
233 }
234
235 MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & ValidMtrrAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
236
237 MemOverflow += MemoryLength;
238 HighMemoryLength -= MemoryLength;
239 Index++;
240 }
241
242
243 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
244 if (MtrrSetting.Variables.Mtrr[Index].Base == 0){
245 break;
246 }
247 DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask));
248 }
249
250 //
251 // set FE/E bits for IA32_MTRR_DEF_TYPE
252 //
253 MtrrSetting.MtrrDefType |= 3 <<10;
254
255 MtrrSetAllMtrrs(&MtrrSetting);
256 //
257 // Dump MTRR Setting
258 //
259 MtrrDebugPrintAllMtrrs ();
260
261 return EFI_SUCCESS;
262 }
263
264 EFI_STATUS
265 EFIAPI
266 SetDxeCacheMode (
267 IN CONST EFI_PEI_SERVICES **PeiServices
268 )
269 {
270 //
271 // This is not needed for now.
272 //
273 return EFI_SUCCESS;
274 }
275
276 STATIC
277 EFI_STATUS
278 GetMemorySize (
279 IN CONST EFI_PEI_SERVICES **PeiServices,
280 OUT UINT64 *LowMemoryLength,
281 OUT UINT64 *HighMemoryLength
282 )
283 {
284 EFI_STATUS Status;
285 EFI_PEI_HOB_POINTERS Hob;
286
287 *HighMemoryLength = 0;
288 *LowMemoryLength = 0x100000;
289
290 //
291 // Get the HOB list for processing
292 //
293 Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw);
294 if (EFI_ERROR(Status)) {
295 return Status;
296 }
297
298 //
299 // Collect memory ranges
300 //
301 while (!END_OF_HOB_LIST (Hob)) {
302 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
303 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
304 //
305 // Need memory above 1MB to be collected here
306 //
307 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 &&
308 Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) {
309 *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
310 } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) {
311 *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
312 }
313 }
314 }
315 Hob.Raw = GET_NEXT_HOB (Hob);
316 }
317
318 return EFI_SUCCESS;
319 }
320
321
322 /**
323 Publish Memory Type Information.
324
325 @param NULL
326
327 @retval EFI_SUCCESS Success.
328 @retval Others Errors have occurred.
329 **/
330
331 EFI_STATUS
332 EFIAPI
333 PublishMemoryTypeInfo (
334 void
335 )
336 {
337 EFI_STATUS Status;
338 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
339 UINTN DataSize;
340 EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];
341
342 Status = PeiServicesLocatePpi (
343 &gEfiPeiReadOnlyVariable2PpiGuid,
344 0,
345 NULL,
346 (void **)&Variable
347 );
348 if (EFI_ERROR(Status)) {
349 DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status));
350 DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
351 //
352 // Build the default GUID'd HOB for DXE
353 //
354 BuildGuidDataHob (
355 &gEfiMemoryTypeInformationGuid,
356 mDefaultMemoryTypeInformation,
357 sizeof (mDefaultMemoryTypeInformation)
358 );
359
360 return Status;
361 }
362
363
364 DataSize = sizeof (MemoryData);
365
366 //
367 // This variable is saved in BDS stage. Now read it back
368 //
369 Status = Variable->GetVariable (
370 Variable,
371 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
372 &gEfiMemoryTypeInformationGuid,
373 NULL,
374 &DataSize,
375 &MemoryData
376 );
377 if (EFI_ERROR (Status)) {
378 //
379 //build default
380 //
381 DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
382 BuildGuidDataHob (
383 &gEfiMemoryTypeInformationGuid,
384 mDefaultMemoryTypeInformation,
385 sizeof (mDefaultMemoryTypeInformation)
386 );
387
388 } else {
389 //
390 // Build the GUID'd HOB for DXE from variable
391 //
392 DEBUG((EFI_D_ERROR, "Build Hob from variable \n"));
393 BuildGuidDataHob (
394 &gEfiMemoryTypeInformationGuid,
395 MemoryData,
396 DataSize
397 );
398 }
399
400 return Status;
401 }
402