AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Legacy / Proc / hobTransfer.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Hob Transfer functions.
6  *
7  * Contains code that copy Heap to temp memory or main memory.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 56322 $   @e \$Date: 2011-07-11 16:51:42 -0600 (Mon, 11 Jul 2011) $
13  *
14  */
15 /*
16  ******************************************************************************
17  *
18  * Copyright (C) 2012 Advanced Micro Devices, Inc.
19  * All rights reserved.
20  *
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.
31  *
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.
42  *
43  ******************************************************************************
44  */
45
46 /*----------------------------------------------------------------------------------------
47  *                             M O D U L E S    U S E D
48  *----------------------------------------------------------------------------------------
49  */
50
51 #include "AGESA.h"
52 #include "amdlib.h"
53 #include "Ids.h"
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"
61 #include "Filecode.h"
62 CODE_GROUP (G1_PEICC)
63 RDATA_GROUP (G2_PEI)
64
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  *----------------------------------------------------------------------------------------
69  */
70
71 /*----------------------------------------------------------------------------------------
72  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
73  *----------------------------------------------------------------------------------------
74  */
75
76
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  *----------------------------------------------------------------------------------------
80  */
81
82 /*----------------------------------------------------------------------------------------
83  *                          P U B L I C     F U N C T I O N S
84  *----------------------------------------------------------------------------------------
85  */
86
87 /*----------------------------------------------------------------------------------------
88  *                          E X P O R T E D    F U N C T I O N S
89  *----------------------------------------------------------------------------------------
90  */
91 extern BUILD_OPT_CFG UserOptions;
92
93 /* -----------------------------------------------------------------------------*/
94 /**
95  *
96  *  CopyHeapToTempRamAtPost
97  *
98  *     This function copies BSP heap content to RAM
99  *
100  *    @param[in,out]   StdHeader   - Pointer to AMD_CONFIG_PARAMS struct.
101  *
102  *    @retval          AGESA_STATUS
103  *
104  */
105 AGESA_STATUS
106 CopyHeapToTempRamAtPost (
107   IN OUT   AMD_CONFIG_PARAMS *StdHeader
108   )
109 {
110   UINT8 *BaseAddressInCache;
111   UINT8 *BaseAddressInTempMem;
112   UINT8 *Source;
113   UINT8 *Destination;
114   UINT8  AlignTo16ByteInCache;
115   UINT8  AlignTo16ByteInTempMem;
116   UINT8  Ignored;
117   UINT32 SizeOfNodeData;
118   UINT32 TotalSize;
119   UINT32 HeapRamFixMtrr;
120   UINT32 HeapRamVariableMtrr;
121   UINT32 HeapInCacheOffset;
122   UINT64 MsrData;
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;
133
134   AmdHeapRamAddress = (UINTN) UserOptions.CfgHeapDramAddress;
135   //
136   //If the user define address above 1M, Mem Init has already set
137   //whole available memory as WB cacheable.
138   //
139   if (AmdHeapRamAddress < 0x100000) {
140     // Region below 1MB
141     // Fixed MTTR region
142     // turn on modification bit
143     LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
144     MsrData |= 0x80000;
145     LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
146
147     if (AmdHeapRamAddress >= 0xC0000) {
148       //
149       // 0xC0000 ~ 0xFFFFF
150       //
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) {
156       //
157       // 0x80000~0xBFFFF
158       //
159       HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX16k_80000 + ((AmdHeapRamAddress >> 17) & 0x1));
160       MsrData = AMD_MTRR_FIX16K_UC_DRAM;
161       LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader);
162     } else {
163       //
164       // 0x0 ~ 0x7FFFF
165       //
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);
170     }
171
172     // Turn on MTTR enable bit and turn off modification bit
173     LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
174     MsrData |= 0x40000;
175     MsrData &= 0xFFFFFFFFFFF7FFFF;
176     LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
177   } else {
178     // Region above 1MB
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);
183
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)) {
191         break;
192       }
193     }
194     if (HeapRamVariableMtrr < AMD_MTRR_VARIABLE_BASE0) {
195       // All variable MTRR is used.
196       ASSERT (FALSE);
197     }
198
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);
206   }
207   // Copying Heap content
208   if (IsBsp (StdHeader, &IgnoredStatus)) {
209     TotalSize = sizeof (HEAP_MANAGER);
210     SizeOfNodeData = 0;
211     AlignTo16ByteInTempMem = 0;
212     BaseAddressInCache = (UINT8 *) StdHeader->HeapBasePtr;
213     HeapManagerInCache = (HEAP_MANAGER *) BaseAddressInCache;
214     HeapInCacheOffset = HeapManagerInCache->FirstActiveBufferOffset;
215     HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
216
217     BaseAddressInTempMem = (UINT8 *) UserOptions.CfgHeapDramAddress;
218     HeapManagerInTempMem = (HEAP_MANAGER *) BaseAddressInTempMem;
219     HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
220
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);
238       }
239       HeapInCacheOffset = HeapInCache->OffsetOfNextNode;
240       HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
241     }
242     // initialize heap manager
243     if (TotalSize == sizeof (HEAP_MANAGER)) {
244       // heap is empty
245       HeapManagerInTempMem->UsedSize = sizeof (HEAP_MANAGER);
246       HeapManagerInTempMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
247       HeapManagerInTempMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
248     } else {
249       // heap is NOT empty
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);
256     }
257     // heap signature
258     HeapManagerInCache->Signature = 0x00000000;
259     HeapManagerInTempMem->Signature = HEAP_SIGNATURE_VALID;
260     // Free space node
261     HeapInTempMem->BufferSize = (UINT32) (AMD_HEAP_SIZE_PER_CORE - TotalSize);
262     HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
263   }
264   return AGESA_SUCCESS;
265 }
266
267
268 /* -----------------------------------------------------------------------------*/
269 /**
270  *
271  *  CopyHeapToMainRamAtPost
272  *
273  *    This function copies Temp Ram heap content to Main Ram
274  *
275  *    @param[in,out]   StdHeader   - Pointer to AMD_CONFIG_PARAMS struct.
276  *
277  *    @retval          AGESA_STATUS
278  *
279  */
280 AGESA_STATUS
281 CopyHeapToMainRamAtPost (
282   IN OUT   AMD_CONFIG_PARAMS *StdHeader
283   )
284 {
285   UINT8 *BaseAddressInTempMem;
286   UINT8 *BaseAddressInMainMem;
287   UINT8 *Source;
288   UINT8 *Destination;
289   UINT8  AlignTo16ByteInTempMem;
290   UINT8  AlignTo16ByteInMainMem;
291   UINT8  Ignored;
292   UINT32 SizeOfNodeData;
293   UINT32 TotalSize;
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;
306
307   if (IsBsp (StdHeader, &IgnoredStatus)) {
308     TotalSize = sizeof (HEAP_MANAGER);
309     SizeOfNodeData = 0;
310     AlignTo16ByteInMainMem = 0;
311     BaseAddressInTempMem = (UINT8 *) StdHeader->HeapBasePtr;
312     HeapManagerInTempMem = (HEAP_MANAGER *) StdHeader->HeapBasePtr;
313     HeapInTempMemOffset = HeapManagerInTempMem->FirstActiveBufferOffset;
314     HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
315
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) {
320       return AGESA_ERROR;
321     }
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);
343       }
344       HeapInTempMemOffset = HeapInTempMem->OffsetOfNextNode;
345       HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
346     }
347     // initialize heap manager
348     if (TotalSize == sizeof (HEAP_MANAGER)) {
349       // heap is empty
350       HeapManagerInMainMem->UsedSize = sizeof (HEAP_MANAGER);
351       HeapManagerInMainMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
352       HeapManagerInMainMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
353     } else {
354       // heap is NOT empty
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);
361     }
362     // heap signature
363     HeapManagerInTempMem->Signature = 0x00000000;
364     HeapManagerInMainMem->Signature = HEAP_SIGNATURE_VALID;
365     // Free space node
366     HeapInMainMem->BufferSize = AMD_HEAP_SIZE_PER_CORE - TotalSize;
367     HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
368   }
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))) {
381         break;
382       }
383     }
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);
390     }
391   }
392   return AGESA_SUCCESS;
393 }