5 * AMD Hob Transfer functions.
7 * Contains code that copy Heap to temp memory or main memory.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 56322 $ @e \$Date: 2011-07-11 16:51:42 -0600 (Mon, 11 Jul 2011) $
16 ******************************************************************************
18 * Copyright (C) 2012 Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 ******************************************************************************
46 /*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
54 #include "cpuRegisters.h"
55 #include "GeneralServices.h"
56 #include "cpuServices.h"
57 #include "cpuCacheInit.h"
58 #include "cpuFamilyTranslation.h"
59 #include "heapManager.h"
60 #include "cpuLateInit.h"
65 #define FILECODE LEGACY_PROC_HOBTRANSFER_FILECODE
66 /*----------------------------------------------------------------------------------------
67 * D E F I N I T I O N S A N D M A C R O S
68 *----------------------------------------------------------------------------------------
71 /*----------------------------------------------------------------------------------------
72 * T Y P E D E F S A N D S T R U C T U R E S
73 *----------------------------------------------------------------------------------------
77 /*----------------------------------------------------------------------------------------
78 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
79 *----------------------------------------------------------------------------------------
82 /*----------------------------------------------------------------------------------------
83 * P U B L I C F U N C T I O N S
84 *----------------------------------------------------------------------------------------
87 /*----------------------------------------------------------------------------------------
88 * E X P O R T E D F U N C T I O N S
89 *----------------------------------------------------------------------------------------
91 extern BUILD_OPT_CFG UserOptions;
93 /* -----------------------------------------------------------------------------*/
96 * CopyHeapToTempRamAtPost
98 * This function copies BSP heap content to RAM
100 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
102 * @retval AGESA_STATUS
106 CopyHeapToTempRamAtPost (
107 IN OUT AMD_CONFIG_PARAMS *StdHeader
110 UINT8 *BaseAddressInCache;
111 UINT8 *BaseAddressInTempMem;
114 UINT8 AlignTo16ByteInCache;
115 UINT8 AlignTo16ByteInTempMem;
117 UINT32 SizeOfNodeData;
119 UINT32 HeapRamFixMtrr;
120 UINT32 HeapRamVariableMtrr;
121 UINT32 HeapInCacheOffset;
123 UINT64 VariableMtrrBase;
124 UINT64 VariableMtrrMask;
125 UINTN AmdHeapRamAddress;
126 AGESA_STATUS IgnoredStatus;
127 BUFFER_NODE *HeapInCache;
128 BUFFER_NODE *HeapInTempMem;
129 HEAP_MANAGER *HeapManagerInCache;
130 HEAP_MANAGER *HeapManagerInTempMem;
131 CACHE_INFO *CacheInfoPtr;
132 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
134 AmdHeapRamAddress = (UINTN) UserOptions.CfgHeapDramAddress;
136 //If the user define address above 1M, Mem Init has already set
137 //whole available memory as WB cacheable.
139 if (AmdHeapRamAddress < 0x100000) {
142 // turn on modification bit
143 LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
145 LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
147 if (AmdHeapRamAddress >= 0xC0000) {
151 HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX4k_C0000 + (((AmdHeapRamAddress >> 16) & 0x3) * 2));
152 MsrData = AMD_MTRR_FIX4K_UC_DRAM;
153 LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader);
154 LibAmdMsrWrite ((HeapRamFixMtrr + 1), &MsrData, StdHeader);
155 } else if (AmdHeapRamAddress >= 0x80000) {
159 HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX16k_80000 + ((AmdHeapRamAddress >> 17) & 0x1));
160 MsrData = AMD_MTRR_FIX16K_UC_DRAM;
161 LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader);
166 LibAmdMsrRead (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader);
167 MsrData = MsrData & (~(0xFF << (8 * ((AmdHeapRamAddress >> 16) & 0x7))));
168 MsrData = MsrData | (AMD_MTRR_FIX64K_UC_DRAM << (8 * ((AmdHeapRamAddress >> 16) & 0x7)));
169 LibAmdMsrWrite (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader);
172 // Turn on MTTR enable bit and turn off modification bit
173 LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
175 MsrData &= 0xFFFFFFFFFFF7FFFF;
176 LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
179 // Variable MTTR region
180 // Get family specific cache Info
181 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
182 FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader);
184 // Find an empty MTRRphysBase/MTRRphysMask
185 for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE;
186 HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0;
187 HeapRamVariableMtrr--) {
188 LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
189 LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
190 if ((VariableMtrrBase == 0) && (VariableMtrrMask == 0)) {
194 if (HeapRamVariableMtrr < AMD_MTRR_VARIABLE_BASE0) {
195 // All variable MTRR is used.
199 // Set variable MTRR base and mask
200 // If the address ranges of two or more MTRRs overlap
201 // and if at least one of the memory types is UC, the UC memory type is used.
202 VariableMtrrBase = (UINT64) (AmdHeapRamAddress & CacheInfoPtr->HeapBaseMask);
203 VariableMtrrMask = CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK;
204 LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
205 LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
207 // Copying Heap content
208 if (IsBsp (StdHeader, &IgnoredStatus)) {
209 TotalSize = sizeof (HEAP_MANAGER);
211 AlignTo16ByteInTempMem = 0;
212 BaseAddressInCache = (UINT8 *) StdHeader->HeapBasePtr;
213 HeapManagerInCache = (HEAP_MANAGER *) BaseAddressInCache;
214 HeapInCacheOffset = HeapManagerInCache->FirstActiveBufferOffset;
215 HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
217 BaseAddressInTempMem = (UINT8 *) UserOptions.CfgHeapDramAddress;
218 HeapManagerInTempMem = (HEAP_MANAGER *) BaseAddressInTempMem;
219 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
221 // copy heap from cache to temp memory.
222 // only heap with persist great than HEAP_LOCAL_CACHE will be copied.
223 // Note: Only copy heap with persist greater than HEAP_LOCAL_CACHE.
224 while (HeapInCacheOffset != AMD_HEAP_INVALID_HEAP_OFFSET) {
225 if (HeapInCache->Persist > HEAP_LOCAL_CACHE) {
226 AlignTo16ByteInCache = HeapInCache->PadSize;
227 AlignTo16ByteInTempMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInTempMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF);
228 SizeOfNodeData = HeapInCache->BufferSize - AlignTo16ByteInCache;
229 TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInTempMem);
230 Source = (UINT8 *) HeapInCache + sizeof (BUFFER_NODE) + AlignTo16ByteInCache;
231 Destination = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem;
232 LibAmdMemCopy (HeapInTempMem, HeapInCache, sizeof (BUFFER_NODE), StdHeader);
233 LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader);
234 HeapInTempMem->OffsetOfNextNode = TotalSize;
235 HeapInTempMem->BufferSize = SizeOfNodeData + AlignTo16ByteInTempMem;
236 HeapInTempMem->PadSize = AlignTo16ByteInTempMem;
237 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
239 HeapInCacheOffset = HeapInCache->OffsetOfNextNode;
240 HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
242 // initialize heap manager
243 if (TotalSize == sizeof (HEAP_MANAGER)) {
245 HeapManagerInTempMem->UsedSize = sizeof (HEAP_MANAGER);
246 HeapManagerInTempMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
247 HeapManagerInTempMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
250 HeapManagerInTempMem->UsedSize = TotalSize;
251 HeapManagerInTempMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER);
252 HeapManagerInTempMem->FirstFreeSpaceOffset = TotalSize;
253 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize - SizeOfNodeData - AlignTo16ByteInTempMem - sizeof (BUFFER_NODE));
254 HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
255 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
258 HeapManagerInCache->Signature = 0x00000000;
259 HeapManagerInTempMem->Signature = HEAP_SIGNATURE_VALID;
261 HeapInTempMem->BufferSize = (UINT32) (AMD_HEAP_SIZE_PER_CORE - TotalSize);
262 HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
264 return AGESA_SUCCESS;
268 /* -----------------------------------------------------------------------------*/
271 * CopyHeapToMainRamAtPost
273 * This function copies Temp Ram heap content to Main Ram
275 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
277 * @retval AGESA_STATUS
281 CopyHeapToMainRamAtPost (
282 IN OUT AMD_CONFIG_PARAMS *StdHeader
285 UINT8 *BaseAddressInTempMem;
286 UINT8 *BaseAddressInMainMem;
289 UINT8 AlignTo16ByteInTempMem;
290 UINT8 AlignTo16ByteInMainMem;
292 UINT32 SizeOfNodeData;
294 UINT32 HeapInTempMemOffset;
295 UINT32 HeapRamVariableMtrr;
296 UINT64 VariableMtrrBase;
297 UINT64 VariableMtrrMask;
298 AGESA_STATUS IgnoredStatus;
299 BUFFER_NODE *HeapInTempMem;
300 BUFFER_NODE *HeapInMainMem;
301 HEAP_MANAGER *HeapManagerInTempMem;
302 HEAP_MANAGER *HeapManagerInMainMem;
303 AGESA_BUFFER_PARAMS AgesaBuffer;
304 CACHE_INFO *CacheInfoPtr;
305 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
307 if (IsBsp (StdHeader, &IgnoredStatus)) {
308 TotalSize = sizeof (HEAP_MANAGER);
310 AlignTo16ByteInMainMem = 0;
311 BaseAddressInTempMem = (UINT8 *) StdHeader->HeapBasePtr;
312 HeapManagerInTempMem = (HEAP_MANAGER *) StdHeader->HeapBasePtr;
313 HeapInTempMemOffset = HeapManagerInTempMem->FirstActiveBufferOffset;
314 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
316 AgesaBuffer.StdHeader = *StdHeader;
317 AgesaBuffer.BufferHandle = AMD_HEAP_IN_MAIN_MEMORY_HANDLE;
318 AgesaBuffer.BufferLength = AMD_HEAP_SIZE_PER_CORE;
319 if (AgesaAllocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
322 BaseAddressInMainMem = (UINT8 *) AgesaBuffer.BufferPointer;
323 HeapManagerInMainMem = (HEAP_MANAGER *) BaseAddressInMainMem;
324 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
325 LibAmdMemFill (BaseAddressInMainMem, 0x00, AMD_HEAP_SIZE_PER_CORE, StdHeader);
326 // copy heap from temp memory to main memory.
327 // only heap with persist great than HEAP_TEMP_MEM will be copied.
328 // Note: Only copy heap buffers with persist greater than HEAP_TEMP_MEM.
329 while (HeapInTempMemOffset != AMD_HEAP_INVALID_HEAP_OFFSET) {
330 if (HeapInTempMem->Persist > HEAP_TEMP_MEM) {
331 AlignTo16ByteInTempMem = HeapInTempMem->PadSize;
332 AlignTo16ByteInMainMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInMainMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF);
333 SizeOfNodeData = HeapInTempMem->BufferSize - AlignTo16ByteInTempMem;
334 TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInMainMem);
335 Source = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem;
336 Destination = (UINT8 *) HeapInMainMem + sizeof (BUFFER_NODE) + AlignTo16ByteInMainMem;
337 LibAmdMemCopy (HeapInMainMem, HeapInTempMem, sizeof (BUFFER_NODE), StdHeader);
338 LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader);
339 HeapInMainMem->OffsetOfNextNode = TotalSize;
340 HeapInMainMem->BufferSize = SizeOfNodeData + AlignTo16ByteInMainMem;
341 HeapInMainMem->PadSize = AlignTo16ByteInMainMem;
342 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
344 HeapInTempMemOffset = HeapInTempMem->OffsetOfNextNode;
345 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
347 // initialize heap manager
348 if (TotalSize == sizeof (HEAP_MANAGER)) {
350 HeapManagerInMainMem->UsedSize = sizeof (HEAP_MANAGER);
351 HeapManagerInMainMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
352 HeapManagerInMainMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
355 HeapManagerInMainMem->UsedSize = TotalSize;
356 HeapManagerInMainMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER);
357 HeapManagerInMainMem->FirstFreeSpaceOffset = TotalSize;
358 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize - SizeOfNodeData - AlignTo16ByteInMainMem - sizeof (BUFFER_NODE));
359 HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
360 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
363 HeapManagerInTempMem->Signature = 0x00000000;
364 HeapManagerInMainMem->Signature = HEAP_SIGNATURE_VALID;
366 HeapInMainMem->BufferSize = AMD_HEAP_SIZE_PER_CORE - TotalSize;
367 HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
369 // if address of heap in temp memory is above 1M, then we must used one variable MTRR.
370 if (StdHeader->HeapBasePtr >= 0x100000) {
371 // Find out which variable MTRR was used in CopyHeapToTempRamAtPost.
372 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
373 FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader);
374 for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE;
375 HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0;
376 HeapRamVariableMtrr--) {
377 LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
378 LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
379 if ((VariableMtrrBase == (UINT64) (StdHeader->HeapBasePtr & CacheInfoPtr->HeapBaseMask)) &&
380 (VariableMtrrMask == (UINT64) (CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK))) {
384 if (HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0) {
385 // Clear variable MTRR which set in CopyHeapToTempRamAtPost.
386 VariableMtrrBase = 0;
387 VariableMtrrMask = 0;
388 LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
389 LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
392 return AGESA_SUCCESS;