zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 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: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ |
| 13 | * |
| 14 | */ |
| 15 | /* |
| 16 | ****************************************************************************** |
| 17 | * |
Siyuan Wang | 641f00c | 2013-06-08 11:50:55 +0800 | [diff] [blame] | 18 | * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc. |
| 19 | * All rights reserved. |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 20 | * |
Siyuan Wang | 641f00c | 2013-06-08 11:50:55 +0800 | [diff] [blame] | 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. |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 31 | * |
Siyuan Wang | 641f00c | 2013-06-08 11:50:55 +0800 | [diff] [blame] | 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. |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 42 | ****************************************************************************** |
| 43 | */ |
| 44 | |
| 45 | /*---------------------------------------------------------------------------------------- |
| 46 | * M O D U L E S U S E D |
| 47 | *---------------------------------------------------------------------------------------- |
| 48 | */ |
| 49 | |
| 50 | #include "AGESA.h" |
| 51 | #include "amdlib.h" |
| 52 | #include "Ids.h" |
| 53 | #include "cpuRegisters.h" |
| 54 | #include "GeneralServices.h" |
| 55 | #include "cpuServices.h" |
| 56 | #include "cpuCacheInit.h" |
| 57 | #include "cpuFamilyTranslation.h" |
| 58 | #include "heapManager.h" |
| 59 | #include "cpuLateInit.h" |
| 60 | #include "Filecode.h" |
| 61 | CODE_GROUP (G1_PEICC) |
| 62 | RDATA_GROUP (G1_PEICC) |
| 63 | |
| 64 | #define FILECODE LEGACY_PROC_HOBTRANSFER_FILECODE |
| 65 | /*---------------------------------------------------------------------------------------- |
| 66 | * D E F I N I T I O N S A N D M A C R O S |
| 67 | *---------------------------------------------------------------------------------------- |
| 68 | */ |
| 69 | |
| 70 | /*---------------------------------------------------------------------------------------- |
| 71 | * T Y P E D E F S A N D S T R U C T U R E S |
| 72 | *---------------------------------------------------------------------------------------- |
| 73 | */ |
| 74 | |
| 75 | |
| 76 | /*---------------------------------------------------------------------------------------- |
| 77 | * 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 |
| 78 | *---------------------------------------------------------------------------------------- |
| 79 | */ |
| 80 | |
| 81 | /*---------------------------------------------------------------------------------------- |
| 82 | * P U B L I C F U N C T I O N S |
| 83 | *---------------------------------------------------------------------------------------- |
| 84 | */ |
| 85 | |
| 86 | /*---------------------------------------------------------------------------------------- |
| 87 | * E X P O R T E D F U N C T I O N S |
| 88 | *---------------------------------------------------------------------------------------- |
| 89 | */ |
| 90 | extern BUILD_OPT_CFG UserOptions; |
| 91 | |
| 92 | /* -----------------------------------------------------------------------------*/ |
| 93 | /** |
| 94 | * |
| 95 | * CopyHeapToTempRamAtPost |
| 96 | * |
| 97 | * This function copies BSP heap content to RAM |
| 98 | * |
| 99 | * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. |
| 100 | * |
| 101 | * @retval AGESA_STATUS |
| 102 | * |
| 103 | */ |
| 104 | AGESA_STATUS |
| 105 | CopyHeapToTempRamAtPost ( |
| 106 | IN OUT AMD_CONFIG_PARAMS *StdHeader |
| 107 | ) |
| 108 | { |
| 109 | UINT8 *BaseAddressInCache; |
| 110 | UINT8 *BaseAddressInTempMem; |
| 111 | UINT8 *Source; |
| 112 | UINT8 *Destination; |
| 113 | UINT8 AlignTo16ByteInCache; |
| 114 | UINT8 AlignTo16ByteInTempMem; |
| 115 | UINT8 Ignored; |
| 116 | UINT32 SizeOfNodeData; |
| 117 | UINT32 TotalSize; |
| 118 | UINT32 HeapRamFixMtrr; |
| 119 | UINT32 HeapRamVariableMtrr; |
| 120 | UINT32 HeapInCacheOffset; |
| 121 | UINT64 MsrData; |
| 122 | UINT64 VariableMtrrBase; |
| 123 | UINT64 VariableMtrrMask; |
| 124 | UINTN AmdHeapRamAddress; |
| 125 | AGESA_STATUS IgnoredStatus; |
| 126 | BUFFER_NODE *HeapInCache; |
| 127 | BUFFER_NODE *HeapInTempMem; |
| 128 | HEAP_MANAGER *HeapManagerInCache; |
| 129 | HEAP_MANAGER *HeapManagerInTempMem; |
| 130 | CACHE_INFO *CacheInfoPtr; |
| 131 | CPU_SPECIFIC_SERVICES *FamilySpecificServices; |
| 132 | |
| 133 | AmdHeapRamAddress = (UINTN) UserOptions.CfgHeapDramAddress; |
| 134 | // |
| 135 | //If the user define address above 1M, Mem Init has already set |
| 136 | //whole available memory as WB cacheable. |
| 137 | // |
| 138 | if (AmdHeapRamAddress < 0x100000) { |
| 139 | // Region below 1MB |
Paul Menzel | 2e0d944 | 2014-01-25 15:59:31 +0100 | [diff] [blame] | 140 | // Fixed MTRR region |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 141 | // turn on modification bit |
| 142 | LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader); |
| 143 | MsrData |= 0x80000; |
| 144 | LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader); |
| 145 | |
| 146 | if (AmdHeapRamAddress >= 0xC0000) { |
| 147 | // |
| 148 | // 0xC0000 ~ 0xFFFFF |
| 149 | // |
Stefan Reinauer | d91ddc8 | 2015-07-30 11:17:40 -0700 | [diff] [blame] | 150 | HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX4k_C0000 + ((((UINTN)AmdHeapRamAddress >> 16) & 0x3) * 2)); |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 151 | MsrData = AMD_MTRR_FIX4K_UC_DRAM; |
| 152 | LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader); |
| 153 | LibAmdMsrWrite ((HeapRamFixMtrr + 1), &MsrData, StdHeader); |
| 154 | } else if (AmdHeapRamAddress >= 0x80000) { |
| 155 | // |
| 156 | // 0x80000~0xBFFFF |
| 157 | // |
Stefan Reinauer | d91ddc8 | 2015-07-30 11:17:40 -0700 | [diff] [blame] | 158 | HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX16k_80000 + (((UINTN)AmdHeapRamAddress >> 17) & 0x1)); |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 159 | MsrData = AMD_MTRR_FIX16K_UC_DRAM; |
| 160 | LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader); |
| 161 | } else { |
| 162 | // |
| 163 | // 0x0 ~ 0x7FFFF |
| 164 | // |
| 165 | LibAmdMsrRead (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader); |
| 166 | MsrData = MsrData & (~(0xFF << (8 * ((AmdHeapRamAddress >> 16) & 0x7)))); |
Stefan Reinauer | d91ddc8 | 2015-07-30 11:17:40 -0700 | [diff] [blame] | 167 | MsrData = MsrData | (AMD_MTRR_FIX64K_UC_DRAM << (8 * (((UINTN)AmdHeapRamAddress >> 16) & 0x7))); |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 168 | LibAmdMsrWrite (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader); |
| 169 | } |
| 170 | |
Paul Menzel | 2e0d944 | 2014-01-25 15:59:31 +0100 | [diff] [blame] | 171 | // Turn on MTRR enable bit and turn off modification bit |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 172 | LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader); |
| 173 | MsrData |= 0x40000; |
| 174 | MsrData &= 0xFFFFFFFFFFF7FFFF; |
| 175 | LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader); |
| 176 | } else { |
| 177 | // Region above 1MB |
Paul Menzel | 2e0d944 | 2014-01-25 15:59:31 +0100 | [diff] [blame] | 178 | // Variable MTRR region |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 179 | // Get family specific cache Info |
| 180 | GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); |
| 181 | FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader); |
| 182 | |
| 183 | // Find an empty MTRRphysBase/MTRRphysMask |
| 184 | for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE; |
| 185 | HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0; |
| 186 | HeapRamVariableMtrr--) { |
| 187 | LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader); |
| 188 | LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader); |
| 189 | if ((VariableMtrrBase == 0) && (VariableMtrrMask == 0)) { |
| 190 | break; |
| 191 | } |
| 192 | } |
| 193 | if (HeapRamVariableMtrr < AMD_MTRR_VARIABLE_BASE0) { |
| 194 | // All variable MTRR is used. |
| 195 | ASSERT (FALSE); |
| 196 | } |
| 197 | |
| 198 | // Set variable MTRR base and mask |
| 199 | // If the address ranges of two or more MTRRs overlap |
| 200 | // and if at least one of the memory types is UC, the UC memory type is used. |
| 201 | VariableMtrrBase = (UINT64) (AmdHeapRamAddress & CacheInfoPtr->HeapBaseMask); |
| 202 | VariableMtrrMask = CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK; |
| 203 | LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader); |
| 204 | LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader); |
| 205 | } |
| 206 | // Copying Heap content |
| 207 | if (IsBsp (StdHeader, &IgnoredStatus)) { |
| 208 | TotalSize = sizeof (HEAP_MANAGER); |
| 209 | SizeOfNodeData = 0; |
| 210 | AlignTo16ByteInTempMem = 0; |
Stefan Reinauer | d91ddc8 | 2015-07-30 11:17:40 -0700 | [diff] [blame] | 211 | BaseAddressInCache = (UINT8 *) (UINTN)StdHeader->HeapBasePtr; |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 212 | HeapManagerInCache = (HEAP_MANAGER *) BaseAddressInCache; |
| 213 | HeapInCacheOffset = HeapManagerInCache->FirstActiveBufferOffset; |
| 214 | HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset); |
| 215 | |
| 216 | BaseAddressInTempMem = (UINT8 *) (UINTN) UserOptions.CfgHeapDramAddress; |
| 217 | HeapManagerInTempMem = (HEAP_MANAGER *) BaseAddressInTempMem; |
| 218 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize); |
| 219 | |
| 220 | // copy heap from cache to temp memory. |
| 221 | // only heap with persist great than HEAP_LOCAL_CACHE will be copied. |
| 222 | // Note: Only copy heap with persist greater than HEAP_LOCAL_CACHE. |
| 223 | while (HeapInCacheOffset != AMD_HEAP_INVALID_HEAP_OFFSET) { |
| 224 | if (HeapInCache->Persist > HEAP_LOCAL_CACHE) { |
| 225 | AlignTo16ByteInCache = HeapInCache->PadSize; |
| 226 | AlignTo16ByteInTempMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInTempMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF); |
| 227 | SizeOfNodeData = HeapInCache->BufferSize - AlignTo16ByteInCache; |
| 228 | TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInTempMem); |
| 229 | Source = (UINT8 *) HeapInCache + sizeof (BUFFER_NODE) + AlignTo16ByteInCache; |
| 230 | Destination = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem; |
| 231 | LibAmdMemCopy (HeapInTempMem, HeapInCache, sizeof (BUFFER_NODE), StdHeader); |
| 232 | LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader); |
| 233 | HeapInTempMem->OffsetOfNextNode = TotalSize; |
| 234 | HeapInTempMem->BufferSize = SizeOfNodeData + AlignTo16ByteInTempMem; |
| 235 | HeapInTempMem->PadSize = AlignTo16ByteInTempMem; |
| 236 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize); |
| 237 | } |
| 238 | HeapInCacheOffset = HeapInCache->OffsetOfNextNode; |
| 239 | HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset); |
| 240 | } |
| 241 | // initialize heap manager |
| 242 | if (TotalSize == sizeof (HEAP_MANAGER)) { |
| 243 | // heap is empty |
| 244 | HeapManagerInTempMem->UsedSize = sizeof (HEAP_MANAGER); |
| 245 | HeapManagerInTempMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 246 | HeapManagerInTempMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER); |
| 247 | } else { |
| 248 | // heap is NOT empty |
| 249 | HeapManagerInTempMem->UsedSize = TotalSize; |
| 250 | HeapManagerInTempMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER); |
| 251 | HeapManagerInTempMem->FirstFreeSpaceOffset = TotalSize; |
| 252 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize - SizeOfNodeData - AlignTo16ByteInTempMem - sizeof (BUFFER_NODE)); |
| 253 | HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 254 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize); |
| 255 | } |
| 256 | // heap signature |
| 257 | HeapManagerInCache->Signature = 0x00000000; |
| 258 | HeapManagerInTempMem->Signature = HEAP_SIGNATURE_VALID; |
| 259 | // Free space node |
| 260 | HeapInTempMem->BufferSize = (UINT32) (AMD_HEAP_SIZE_PER_CORE - TotalSize); |
| 261 | HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 262 | } |
| 263 | return AGESA_SUCCESS; |
| 264 | } |
| 265 | |
| 266 | |
| 267 | /* -----------------------------------------------------------------------------*/ |
| 268 | /** |
| 269 | * |
| 270 | * CopyHeapToMainRamAtPost |
| 271 | * |
| 272 | * This function copies Temp Ram heap content to Main Ram |
| 273 | * |
| 274 | * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. |
| 275 | * |
| 276 | * @retval AGESA_STATUS |
| 277 | * |
| 278 | */ |
| 279 | AGESA_STATUS |
| 280 | CopyHeapToMainRamAtPost ( |
| 281 | IN OUT AMD_CONFIG_PARAMS *StdHeader |
| 282 | ) |
| 283 | { |
| 284 | UINT8 *BaseAddressInTempMem; |
| 285 | UINT8 *BaseAddressInMainMem; |
| 286 | UINT8 *Source; |
| 287 | UINT8 *Destination; |
| 288 | UINT8 AlignTo16ByteInTempMem; |
| 289 | UINT8 AlignTo16ByteInMainMem; |
| 290 | UINT8 Ignored; |
| 291 | UINT32 SizeOfNodeData; |
| 292 | UINT32 TotalSize; |
| 293 | UINT32 HeapInTempMemOffset; |
| 294 | UINT32 HeapRamVariableMtrr; |
| 295 | UINT64 VariableMtrrBase; |
| 296 | UINT64 VariableMtrrMask; |
| 297 | AGESA_STATUS IgnoredStatus; |
| 298 | BUFFER_NODE *HeapInTempMem; |
| 299 | BUFFER_NODE *HeapInMainMem; |
| 300 | HEAP_MANAGER *HeapManagerInTempMem; |
| 301 | HEAP_MANAGER *HeapManagerInMainMem; |
| 302 | AGESA_BUFFER_PARAMS AgesaBuffer; |
| 303 | CACHE_INFO *CacheInfoPtr; |
| 304 | CPU_SPECIFIC_SERVICES *FamilySpecificServices; |
| 305 | |
| 306 | if (IsBsp (StdHeader, &IgnoredStatus)) { |
| 307 | TotalSize = sizeof (HEAP_MANAGER); |
| 308 | SizeOfNodeData = 0; |
| 309 | AlignTo16ByteInMainMem = 0; |
Stefan Reinauer | d91ddc8 | 2015-07-30 11:17:40 -0700 | [diff] [blame] | 310 | BaseAddressInTempMem = (UINT8 *)(UINTN) StdHeader->HeapBasePtr; |
| 311 | HeapManagerInTempMem = (HEAP_MANAGER *)(UINTN) StdHeader->HeapBasePtr; |
zbao | 7d94cf9 | 2012-07-02 14:19:14 +0800 | [diff] [blame] | 312 | HeapInTempMemOffset = HeapManagerInTempMem->FirstActiveBufferOffset; |
| 313 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset); |
| 314 | |
| 315 | AgesaBuffer.StdHeader = *StdHeader; |
| 316 | AgesaBuffer.BufferHandle = AMD_HEAP_IN_MAIN_MEMORY_HANDLE; |
| 317 | AgesaBuffer.BufferLength = AMD_HEAP_SIZE_PER_CORE; |
| 318 | if (AgesaAllocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) { |
| 319 | return AGESA_ERROR; |
| 320 | } |
| 321 | BaseAddressInMainMem = (UINT8 *) AgesaBuffer.BufferPointer; |
| 322 | HeapManagerInMainMem = (HEAP_MANAGER *) BaseAddressInMainMem; |
| 323 | HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize); |
| 324 | LibAmdMemFill (BaseAddressInMainMem, 0x00, AMD_HEAP_SIZE_PER_CORE, StdHeader); |
| 325 | // copy heap from temp memory to main memory. |
| 326 | // only heap with persist great than HEAP_TEMP_MEM will be copied. |
| 327 | // Note: Only copy heap buffers with persist greater than HEAP_TEMP_MEM. |
| 328 | while (HeapInTempMemOffset != AMD_HEAP_INVALID_HEAP_OFFSET) { |
| 329 | if (HeapInTempMem->Persist > HEAP_TEMP_MEM) { |
| 330 | AlignTo16ByteInTempMem = HeapInTempMem->PadSize; |
| 331 | AlignTo16ByteInMainMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInMainMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF); |
| 332 | SizeOfNodeData = HeapInTempMem->BufferSize - AlignTo16ByteInTempMem; |
| 333 | TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInMainMem); |
| 334 | Source = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem; |
| 335 | Destination = (UINT8 *) HeapInMainMem + sizeof (BUFFER_NODE) + AlignTo16ByteInMainMem; |
| 336 | LibAmdMemCopy (HeapInMainMem, HeapInTempMem, sizeof (BUFFER_NODE), StdHeader); |
| 337 | LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader); |
| 338 | HeapInMainMem->OffsetOfNextNode = TotalSize; |
| 339 | HeapInMainMem->BufferSize = SizeOfNodeData + AlignTo16ByteInMainMem; |
| 340 | HeapInMainMem->PadSize = AlignTo16ByteInMainMem; |
| 341 | HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize); |
| 342 | } |
| 343 | HeapInTempMemOffset = HeapInTempMem->OffsetOfNextNode; |
| 344 | HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset); |
| 345 | } |
| 346 | // initialize heap manager |
| 347 | if (TotalSize == sizeof (HEAP_MANAGER)) { |
| 348 | // heap is empty |
| 349 | HeapManagerInMainMem->UsedSize = sizeof (HEAP_MANAGER); |
| 350 | HeapManagerInMainMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 351 | HeapManagerInMainMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER); |
| 352 | } else { |
| 353 | // heap is NOT empty |
| 354 | HeapManagerInMainMem->UsedSize = TotalSize; |
| 355 | HeapManagerInMainMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER); |
| 356 | HeapManagerInMainMem->FirstFreeSpaceOffset = TotalSize; |
| 357 | HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize - SizeOfNodeData - AlignTo16ByteInMainMem - sizeof (BUFFER_NODE)); |
| 358 | HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 359 | HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize); |
| 360 | } |
| 361 | // heap signature |
| 362 | HeapManagerInTempMem->Signature = 0x00000000; |
| 363 | HeapManagerInMainMem->Signature = HEAP_SIGNATURE_VALID; |
| 364 | // Free space node |
| 365 | HeapInMainMem->BufferSize = AMD_HEAP_SIZE_PER_CORE - TotalSize; |
| 366 | HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; |
| 367 | } |
| 368 | // if address of heap in temp memory is above 1M, then we must used one variable MTRR. |
| 369 | if ( (UINTN) StdHeader->HeapBasePtr >= 0x100000) { |
| 370 | // Find out which variable MTRR was used in CopyHeapToTempRamAtPost. |
| 371 | GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); |
| 372 | FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader); |
| 373 | for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE; |
| 374 | HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0; |
| 375 | HeapRamVariableMtrr--) { |
| 376 | LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader); |
| 377 | LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader); |
| 378 | if ((VariableMtrrBase == (UINT64) (UINTN) (StdHeader->HeapBasePtr & CacheInfoPtr->HeapBaseMask)) && |
| 379 | (VariableMtrrMask == (UINT64) (CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK))) { |
| 380 | break; |
| 381 | } |
| 382 | } |
| 383 | if (HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0) { |
| 384 | // Clear variable MTRR which set in CopyHeapToTempRamAtPost. |
| 385 | VariableMtrrBase = 0; |
| 386 | VariableMtrrMask = 0; |
| 387 | LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader); |
| 388 | LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader); |
| 389 | } |
| 390 | } |
| 391 | return AGESA_SUCCESS; |
| 392 | } |