Siyuan Wang | affe85f | 2013-07-25 15:14:15 +0800 | [diff] [blame] | 1 | /* $NoKeywords:$ */ |
| 2 | /** |
| 3 | * @file |
| 4 | * |
| 5 | * mfParallelTraining.c |
| 6 | * |
| 7 | * This is the parallel training feature |
| 8 | * |
| 9 | * @xrefitem bom "File Content Label" "Release Content" |
| 10 | * @e project: AGESA |
| 11 | * @e sub-project: (Mem/Feat/PARTRN) |
| 12 | * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ |
| 13 | * |
| 14 | **/ |
| 15 | /***************************************************************************** |
| 16 | * |
| 17 | * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc. |
| 18 | * All rights reserved. |
| 19 | * |
| 20 | * Redistribution and use in source and binary forms, with or without |
| 21 | * modification, are permitted provided that the following conditions are met: |
| 22 | * * Redistributions of source code must retain the above copyright |
| 23 | * notice, this list of conditions and the following disclaimer. |
| 24 | * * Redistributions in binary form must reproduce the above copyright |
| 25 | * notice, this list of conditions and the following disclaimer in the |
| 26 | * documentation and/or other materials provided with the distribution. |
| 27 | * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| 28 | * its contributors may be used to endorse or promote products derived |
| 29 | * from this software without specific prior written permission. |
| 30 | * |
| 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 33 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 34 | * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| 35 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 36 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 37 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 38 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 40 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 41 | * *************************************************************************** |
| 42 | * |
| 43 | */ |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | #include "AGESA.h" |
| 49 | #include "amdlib.h" |
| 50 | #include "OptionMemory.h" |
| 51 | #include "mm.h" |
| 52 | #include "mn.h" |
| 53 | #include "Ids.h" |
| 54 | #include "cpuRegisters.h" |
| 55 | #include "cpuApicUtilities.h" |
| 56 | #include "mfParallelTraining.h" |
| 57 | #include "heapManager.h" |
| 58 | #include "GeneralServices.h" |
| 59 | #include "Filecode.h" |
| 60 | CODE_GROUP (G2_PEI) |
| 61 | RDATA_GROUP (G2_PEI) |
| 62 | |
| 63 | #define FILECODE PROC_MEM_FEAT_PARTRN_MFPARALLELTRAINING_FILECODE |
| 64 | |
| 65 | /*----------------------------------------------------------------------------- |
| 66 | * EXPORTED FUNCTIONS |
| 67 | * |
| 68 | *----------------------------------------------------------------------------- |
| 69 | */ |
| 70 | extern MEM_TECH_CONSTRUCTOR* memTechInstalled[]; |
| 71 | |
| 72 | /* -----------------------------------------------------------------------------*/ |
| 73 | /** |
| 74 | * |
| 75 | * |
| 76 | * This is the main function to perform parallel training on all nodes. |
| 77 | * This is the routine which will run on the remote AP. |
| 78 | * |
| 79 | * @param[in,out] *EnvPtr - Pointer to the Training Environment Data |
| 80 | * @param[in,out] *StdHeader - Pointer to the Standard Header of the AP |
| 81 | * |
| 82 | * @return TRUE - This feature is enabled. |
| 83 | * @return FALSE - This feature is not enabled. |
| 84 | */ |
| 85 | BOOLEAN |
| 86 | MemFParallelTraining ( |
| 87 | IN OUT REMOTE_TRAINING_ENV *EnvPtr, |
| 88 | IN OUT AMD_CONFIG_PARAMS *StdHeader |
| 89 | ) |
| 90 | { |
| 91 | MEM_PARAMETER_STRUCT ParameterList; |
| 92 | MEM_NB_BLOCK NB; |
| 93 | MEM_TECH_BLOCK TB; |
| 94 | ALLOCATE_HEAP_PARAMS AllocHeapParams; |
| 95 | MEM_DATA_STRUCT *MemPtr; |
| 96 | DIE_STRUCT *MCTPtr; |
| 97 | UINT8 p; |
| 98 | UINT8 i; |
| 99 | UINT8 Dct; |
| 100 | UINT8 Channel; |
| 101 | UINT8 *BufferPtr; |
| 102 | UINT8 DctCount; |
| 103 | UINT8 ChannelCount; |
| 104 | UINT8 RowCount; |
| 105 | UINT8 ColumnCount; |
| 106 | UINT16 SizeOfNewBuffer; |
| 107 | AP_DATA_TRANSFER ReturnData; |
| 108 | |
| 109 | // |
| 110 | // Initialize Parameters |
| 111 | // |
| 112 | ReturnData.DataPtr = NULL; |
| 113 | ReturnData.DataSizeInDwords = 0; |
| 114 | ReturnData.DataTransferFlags = 0; |
| 115 | |
| 116 | ASSERT (EnvPtr != NULL); |
| 117 | // |
| 118 | // Replace Standard header of a AP |
| 119 | // |
| 120 | LibAmdMemCopy (StdHeader, &(EnvPtr->StdHeader), sizeof (AMD_CONFIG_PARAMS), &(EnvPtr->StdHeader)); |
| 121 | |
| 122 | |
| 123 | // |
| 124 | // Allocate buffer for training data |
| 125 | // |
| 126 | BufferPtr = (UINT8 *) (&EnvPtr->DieStruct); |
| 127 | DctCount = EnvPtr->DieStruct.DctCount; |
| 128 | BufferPtr += sizeof (DIE_STRUCT); |
| 129 | ChannelCount = ((DCT_STRUCT *) BufferPtr)->ChannelCount; |
| 130 | BufferPtr += DctCount * sizeof (DCT_STRUCT); |
| 131 | RowCount = ((CH_DEF_STRUCT *) BufferPtr)->RowCount; |
| 132 | ColumnCount = ((CH_DEF_STRUCT *) BufferPtr)->ColumnCount; |
| 133 | |
| 134 | SizeOfNewBuffer = sizeof (DIE_STRUCT) + |
| 135 | DctCount * ( |
| 136 | sizeof (DCT_STRUCT) + ( |
| 137 | ChannelCount * ( |
| 138 | sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK) + ( |
| 139 | RowCount * ColumnCount * NUMBER_OF_DELAY_TABLES + |
| 140 | (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) + |
| 141 | (MAX_DIMMS_PER_CHANNEL * MAX_NUMBER_LANES) |
| 142 | ) |
| 143 | ) |
| 144 | ) |
| 145 | ); |
| 146 | AllocHeapParams.RequestedBufferSize = SizeOfNewBuffer; |
| 147 | AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_PAR_TRN_HANDLE, 0, 0, 0); |
| 148 | AllocHeapParams.Persist = HEAP_LOCAL_CACHE; |
| 149 | if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { |
| 150 | BufferPtr = AllocHeapParams.BufferPtr; |
| 151 | LibAmdMemCopy ( BufferPtr, |
| 152 | &(EnvPtr->DieStruct), |
| 153 | sizeof (DIE_STRUCT) + DctCount * (sizeof (DCT_STRUCT) + ChannelCount * (sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK))), |
| 154 | StdHeader |
| 155 | ); |
| 156 | |
| 157 | // |
| 158 | // Fix up pointers |
| 159 | // |
| 160 | MCTPtr = (DIE_STRUCT *) BufferPtr; |
| 161 | BufferPtr += sizeof (DIE_STRUCT); |
| 162 | MCTPtr->DctData = (DCT_STRUCT *) BufferPtr; |
| 163 | BufferPtr += MCTPtr->DctCount * sizeof (DCT_STRUCT); |
| 164 | for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) { |
| 165 | MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) BufferPtr; |
| 166 | BufferPtr += MCTPtr->DctData[Dct].ChannelCount * sizeof (CH_DEF_STRUCT); |
| 167 | for (Channel = 0; Channel < MCTPtr->DctData[Dct].ChannelCount; Channel++) { |
| 168 | MCTPtr->DctData[Dct].ChData[Channel].MCTPtr = MCTPtr; |
| 169 | MCTPtr->DctData[Dct].ChData[Channel].DCTPtr = &MCTPtr->DctData[Dct]; |
| 170 | } |
| 171 | } |
| 172 | NB.PSBlock = (MEM_PS_BLOCK *) BufferPtr; |
| 173 | BufferPtr += DctCount * ChannelCount * sizeof (MEM_PS_BLOCK); |
| 174 | |
| 175 | ReturnData.DataPtr = AllocHeapParams.BufferPtr; |
| 176 | ReturnData.DataSizeInDwords = (SizeOfNewBuffer + 3) / 4; |
| 177 | ReturnData.DataTransferFlags = 0; |
| 178 | |
| 179 | // |
| 180 | // Allocate Memory for the MEM_DATA_STRUCT we will use |
| 181 | // |
| 182 | AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT); |
| 183 | AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE; |
| 184 | AllocHeapParams.Persist = HEAP_LOCAL_CACHE; |
| 185 | if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { |
| 186 | MemPtr = (MEM_DATA_STRUCT *)AllocHeapParams.BufferPtr; |
| 187 | |
| 188 | LibAmdMemCopy (&(MemPtr->StdHeader), &(EnvPtr->StdHeader), sizeof (AMD_CONFIG_PARAMS), StdHeader); |
| 189 | |
| 190 | // |
| 191 | // Copy Parameters from environment |
| 192 | // |
| 193 | ParameterList.HoleBase = EnvPtr->HoleBase; |
| 194 | ParameterList.BottomIo = EnvPtr->BottomIo; |
| 195 | ParameterList.UmaSize = EnvPtr->UmaSize; |
| 196 | ParameterList.SysLimit = EnvPtr->SysLimit; |
| 197 | ParameterList.TableBasedAlterations = EnvPtr->TableBasedAlterations; |
| 198 | ParameterList.PlatformMemoryConfiguration = EnvPtr->PlatformMemoryConfiguration; |
| 199 | MemPtr->ParameterListPtr = &ParameterList; |
| 200 | |
| 201 | for (p = 0; p < MAX_PLATFORM_TYPES; p++) { |
| 202 | MemPtr->GetPlatformCfg[p] = EnvPtr->GetPlatformCfg[p]; |
| 203 | } |
| 204 | |
| 205 | MemPtr->ErrorHandling = EnvPtr->ErrorHandling; |
| 206 | // |
| 207 | // Create Local NBBlock and Tech Block |
| 208 | // |
| 209 | EnvPtr->NBBlockCtor (&NB, MCTPtr, EnvPtr->FeatPtr); |
| 210 | NB.RefPtr = &ParameterList; |
| 211 | NB.MemPtr = MemPtr; |
| 212 | i = 0; |
| 213 | while (memTechInstalled[i] != NULL) { |
| 214 | if (memTechInstalled[i] (&TB, &NB)) { |
| 215 | break; |
| 216 | } |
| 217 | i++; |
| 218 | } |
| 219 | NB.TechPtr = &TB; |
| 220 | NB.TechBlockSwitch (&NB); |
| 221 | |
| 222 | // |
| 223 | // Setup CPU Mem Type MSRs on the AP |
| 224 | // |
| 225 | NB.CpuMemTyping (&NB); |
| 226 | |
| 227 | IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", NB.Node); |
| 228 | // |
| 229 | // Call Technology Specific Training routine |
| 230 | // |
| 231 | NB.TrainingFlow (&NB); |
| 232 | // |
| 233 | // Copy training data to ReturnData buffer |
| 234 | // |
| 235 | LibAmdMemCopy ( BufferPtr, |
| 236 | MCTPtr->DctData[0].ChData[0].RcvEnDlys, |
| 237 | ((DctCount * ChannelCount) * ( |
| 238 | (RowCount * ColumnCount * NUMBER_OF_DELAY_TABLES) + |
| 239 | (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) + |
| 240 | (MAX_DIMMS_PER_CHANNEL * MAX_NUMBER_LANES) |
| 241 | ) |
| 242 | ), |
| 243 | StdHeader); |
| 244 | |
| 245 | HeapDeallocateBuffer (AMD_MEM_DATA_HANDLE, StdHeader); |
| 246 | // |
| 247 | // Restore pointers |
| 248 | // |
| 249 | for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) { |
| 250 | for (Channel = 0; Channel < MCTPtr->DctData[Dct].ChannelCount; Channel++) { |
| 251 | MCTPtr->DctData[Dct].ChData[Channel].MCTPtr = &EnvPtr->DieStruct; |
| 252 | MCTPtr->DctData[Dct].ChData[Channel].DCTPtr = &EnvPtr->DieStruct.DctData[Dct]; |
| 253 | |
| 254 | MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RcvEnDlys; |
| 255 | MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDqsDlys; |
| 256 | MCTPtr->DctData[Dct].ChData[Channel].RdDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsDlys; |
| 257 | MCTPtr->DctData[Dct].ChData[Channel].RdDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsDlys; |
| 258 | MCTPtr->DctData[Dct].ChData[Channel].WrDatDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatDlys; |
| 259 | MCTPtr->DctData[Dct].ChData[Channel].RdDqs2dDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqs2dDlys; |
| 260 | MCTPtr->DctData[Dct].ChData[Channel].RdDqsMinDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsMinDlys; |
| 261 | MCTPtr->DctData[Dct].ChData[Channel].RdDqsMaxDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsMaxDlys; |
| 262 | MCTPtr->DctData[Dct].ChData[Channel].WrDatMinDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatMinDlys; |
| 263 | MCTPtr->DctData[Dct].ChData[Channel].WrDatMaxDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatMaxDlys; |
| 264 | MCTPtr->DctData[Dct].ChData[Channel].FailingBitMask = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].FailingBitMask; |
| 265 | } |
| 266 | MCTPtr->DctData[Dct].ChData = EnvPtr->DieStruct.DctData[Dct].ChData; |
| 267 | } |
| 268 | MCTPtr->DctData = EnvPtr->DieStruct.DctData; |
| 269 | } |
| 270 | |
| 271 | // |
| 272 | // Signal to BSP that training is complete and Send Results |
| 273 | // |
| 274 | ASSERT (ReturnData.DataPtr != NULL); |
| 275 | ApUtilTransmitBuffer (EnvPtr->BspSocket, EnvPtr->BspCore, &ReturnData, StdHeader); |
| 276 | |
| 277 | // |
| 278 | // Clean up and exit. |
| 279 | // |
| 280 | HeapDeallocateBuffer (GENERATE_MEM_HANDLE (ALLOC_PAR_TRN_HANDLE, 0, 0, 0), StdHeader); |
| 281 | } else { |
| 282 | MCTPtr = &EnvPtr->DieStruct; |
| 283 | PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_TRAINING_DATA, MCTPtr->NodeId, 0, 0, 0, StdHeader); |
| 284 | SetMemError (AGESA_FATAL, MCTPtr); |
| 285 | ASSERT(FALSE); // Could not allocate heap for buffer for parallel training data |
| 286 | } |
| 287 | return TRUE; |
| 288 | } |