Add constants for fast path resume copying
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / CPU / cpuBrandId.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU BrandId related functions.
6  *
7  * Contains code that provides CPU BrandId information
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 37640 $   @e \$Date: 2010-09-08 23:01:59 +0800 (Wed, 08 Sep 2010) $
13  *
14  */
15 /*
16  *****************************************************************************
17  *
18  * Copyright (c) 2011, 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 /*----------------------------------------------------------------------------------------
48  *                             M O D U L E S    U S E D
49  *----------------------------------------------------------------------------------------
50  */
51 #include "AGESA.h"
52 #include "amdlib.h"
53 #include "OptionPstate.h"
54 #include "cpuRegisters.h"
55 #include "cpuFamilyTranslation.h"
56 #include "cpuEarlyInit.h"
57 #include "cpuRegisters.h"
58 #include "heapManager.h"
59 #include "GeneralServices.h"
60 #include "Filecode.h"
61 CODE_GROUP (G1_PEICC)
62 RDATA_GROUP (G1_PEICC)
63 #define FILECODE PROC_CPU_CPUBRANDID_FILECODE
64 /*----------------------------------------------------------------------------------------
65  *                   D E F I N I T I O N S    A N D    M A C R O S
66  *----------------------------------------------------------------------------------------
67  */
68
69 /*----------------------------------------------------------------------------------------
70  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
71  *----------------------------------------------------------------------------------------
72  */
73 CONST CHAR8 ROMDATA strEngSample[] = "AMD Engineering Sample";
74 CONST CHAR8 ROMDATA strTtkSample[] = "AMD Thermal Test Kit";
75 CONST CHAR8 ROMDATA strUnknown[] = "AMD Processor Model Unknown";
76
77 CONST AMD_CPU_BRAND ROMDATA EngSample_Str = {0, 0, 0, SOCKET_IGNORE, strEngSample, sizeof (strEngSample)};
78 CONST AMD_CPU_BRAND ROMDATA TtkSample_Str = {0, 1, 0, SOCKET_IGNORE, strTtkSample, sizeof (strTtkSample)};
79 CONST AMD_CPU_BRAND ROMDATA Dflt_Str1 = {0, 0, 0, SOCKET_IGNORE, strUnknown, sizeof (strUnknown)};
80 CONST AMD_CPU_BRAND ROMDATA Dflt_Str2 = {0, 0, 0, SOCKET_IGNORE, DR_NO_STRING, DR_NO_STRING};
81
82
83 /*----------------------------------------------------------------------------------------
84  *           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
85  *----------------------------------------------------------------------------------------
86  */
87
88 VOID
89 SetBrandIdRegistersAtEarly (
90   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
91   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
92   IN       AMD_CONFIG_PARAMS      *StdHeader
93   );
94
95 /*----------------------------------------------------------------------------------------
96  *                          E X P O R T E D    F U N C T I O N S
97  *----------------------------------------------------------------------------------------
98  */
99
100 /*---------------------------------------------------------------------------------------*/
101 /**
102  * Program BrandID registers (CPUIDNameStringPtr[0-5])
103  *
104  * This function determines the appropriate brand string for the executing
105  * core, and programs the namestring MSRs.
106  *
107  * @param[in,out] StdHeader   Config handle for library and services.
108  *
109  */
110 VOID
111 SetBrandIdRegisters (
112   IN OUT   AMD_CONFIG_PARAMS *StdHeader
113   )
114 {
115   UINT8   SocketIndex;
116   UINT8   SuffixStatus;
117   UINT8   TableElements;
118   UINT8   TableEntryCount;
119   UINT8   TableEntryIndex;
120   CHAR8   TempChar;
121   CHAR8   *NameStringPtr;
122   CHAR8   *SuffixStringPtr;
123   CHAR8   *BrandStringPtr;
124   CHAR8   *TempNameCharPtr;
125   UINT32  MsrIndex;
126   UINT32  Quotient;
127   UINT32  Remainder;
128   UINT64  *MsrNameStringPtrPtr;
129   CPUID_DATA    CpuId;
130   CPU_LOGICAL_ID CpuLogicalId;
131   CPU_BRAND_TABLE *SocketTableEntry;
132   CPU_BRAND_TABLE **SocketTableEntry1;
133   AMD_CPU_BRAND *SocketTablePtr;
134   AMD_CPU_BRAND_DATA Data;
135   ALLOCATE_HEAP_PARAMS AllocHeapParams;
136   CPU_SPECIFIC_SERVICES *FamilySpecificServices;
137
138   SuffixStatus = 0;
139   FamilySpecificServices = NULL;
140   SocketTablePtr = NULL;
141   SocketTableEntry = NULL;
142
143   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
144   // Step1: Allocate 48 bytes from Heap space
145   AllocHeapParams.RequestedBufferSize = CPU_BRAND_ID_LENGTH;
146   AllocHeapParams.BufferHandle = AMD_BRAND_ID_BUFFER_HANDLE;
147   AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
148   if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
149     // Clear NameBuffer
150     BrandStringPtr = (CHAR8 *) AllocHeapParams.BufferPtr;
151     LibAmdMemFill (BrandStringPtr, 0, CPU_BRAND_ID_LENGTH, StdHeader);
152   } else {
153     PutEventLog (
154       AGESA_ERROR,
155       CPU_ERROR_BRANDID_HEAP_NOT_AVAILABLE,
156       0, 0, 0, 0, StdHeader
157       );
158     return;
159   }
160
161   // Step2: Get brandid from model number and model string
162   LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, StdHeader);
163
164   // Step3: Figure out Socket/Page/Model/String1/String2/Core Number
165   Data.String2 = (UINT8) (CpuId.EBX_Reg & 0x0f);
166   Data.Model   = (UINT8) ((CpuId.EBX_Reg >> 4) & 0x7f);
167   Data.String1 = (UINT8) ((CpuId.EBX_Reg >> 11) & 0x0f);
168   Data.Page    = (UINT8) ((CpuId.EBX_Reg >> 15) & 0x01);
169   Data.Socket  = (UINT8) ((CpuId.EBX_Reg >> 28) & 0x0f);
170   Data.Cores = FamilySpecificServices->GetNumberOfCoresForBrandstring (FamilySpecificServices, StdHeader);
171
172   // Step4: If NN = 0, we have an engineering sample, no suffix; then jump to Step6
173   if (Data.Model == 0) {
174     if (Data.Page == 0) {
175       SocketTablePtr = (AMD_CPU_BRAND *)&EngSample_Str;
176     } else {
177       SocketTablePtr = (AMD_CPU_BRAND *)&TtkSample_Str;
178     }
179   } else {
180
181     // Model is not equal to zero, so decrement it
182     // For family 10 if PkgType[3:0] is greater than or equal to 2h and families >= 12h
183     GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
184     if ((((CpuLogicalId.Family & AMD_FAMILY_10) != 0) && (Data.Socket >= DR_SOCKET_S1G3)) ||
185         ((CpuLogicalId.Family & AMD_FAMILY_GE_12) != 0)) {
186       Data.Model--;
187     }
188
189     // Step5: Search for String1 (there can be only 1)
190     FamilySpecificServices->GetBrandString1 (FamilySpecificServices, (const VOID **) &SocketTableEntry, &TableEntryCount, StdHeader);
191     SocketTableEntry1 = (CPU_BRAND_TABLE **) SocketTableEntry;
192     for (TableEntryIndex = 0; ((TableEntryIndex < TableEntryCount)
193          && (SuffixStatus == 0)); TableEntryIndex++, SocketTableEntry1++) {
194       if (*SocketTableEntry1 == NULL) {
195         break;
196       }
197       SocketTablePtr = (AMD_CPU_BRAND *) (*SocketTableEntry1)->Table;
198       TableElements = (*SocketTableEntry1)->NumberOfEntries;
199       for (SocketIndex = 0; (SocketIndex < TableElements)
200            && SuffixStatus == 0; SocketIndex++) {
201         if ((SocketTablePtr->Page == Data.Page) &&
202             (SocketTablePtr->Index == Data.String1) &&
203             (SocketTablePtr->Socket == Data.Socket) &&
204             (SocketTablePtr->Cores == Data.Cores)) {
205           SuffixStatus = 1;
206         } else {
207           SocketTablePtr++;
208         }
209       }
210     }
211     if (SuffixStatus == 0) {
212       SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str1;  // We did not find one, make 'Unknown'
213     }
214   }
215
216   // Step6: Copy String into NameBuffer
217   // We now have data structure pointing to correct type in (*SocketTablePtr)
218   LibAmdMemCopy  (BrandStringPtr,
219                   (CHAR8 *)SocketTablePtr->Stringstart,
220                   SocketTablePtr->Stringlength,
221                   StdHeader);
222
223   // Step7: Get suffix, determine addition to BRANDSPEED
224   if (SuffixStatus != 0) {
225     // Turn our value into a decimal string
226     // We have a value like 37d which we need to turn into '3' '7'
227     // Divide by 10, store remainder as an ASCII char on stack, repeat until Quotient is 0
228     NameStringPtr = BrandStringPtr + SocketTablePtr->Stringlength - 1;
229     TempNameCharPtr = NameStringPtr;
230     Quotient = Data.Model;
231     do {
232       Remainder = Quotient % 10;
233       Quotient = Quotient / 10;
234       *TempNameCharPtr++ = (CHAR8) (Remainder + '0');   // Put suffix into our NameBuffer
235     } while (Quotient != 0);
236     if (Data.Model < 10) {
237       *TempNameCharPtr++ = '0';
238     }
239
240     // Step8: Reverse the string sequence and copy into NameBuffer
241     SuffixStringPtr = TempNameCharPtr--;
242     while (NameStringPtr < TempNameCharPtr) {
243       TempChar = *NameStringPtr;
244       *NameStringPtr = *TempNameCharPtr;
245       *TempNameCharPtr = TempChar;
246       NameStringPtr++;
247       TempNameCharPtr--;
248     }
249
250     // Step9: Search for String2
251     SuffixStatus = 0;
252     FamilySpecificServices->GetBrandString2 (FamilySpecificServices, (const VOID **) &SocketTableEntry, &TableEntryCount, StdHeader);
253     SocketTableEntry1 = (CPU_BRAND_TABLE **) SocketTableEntry;
254     for (TableEntryIndex = 0; ((TableEntryIndex < TableEntryCount)
255          && (SuffixStatus == 0)); TableEntryIndex++, SocketTableEntry1++) {
256       if (*SocketTableEntry1 == NULL) {
257         break;
258       }
259       SocketTablePtr = (AMD_CPU_BRAND *) (*SocketTableEntry1)->Table;
260       TableElements = (*SocketTableEntry1)->NumberOfEntries;
261       for (SocketIndex = 0; (SocketIndex < TableElements)
262            && SuffixStatus == 0; SocketIndex++) {
263         if ((SocketTablePtr->Page == Data.Page) &&
264             (SocketTablePtr->Index == Data.String2) &&
265             (SocketTablePtr->Socket == Data.Socket) &&
266             (SocketTablePtr->Cores == Data.Cores)) {
267           SuffixStatus = 1;
268         } else {
269           SocketTablePtr++;
270         }
271       }
272     }
273     if (SuffixStatus == 0) {
274       SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str2;
275     }
276
277     // Step10: Copy String2 into our NameBuffer
278     if (SocketTablePtr->Stringlength != 0) {
279       LibAmdMemCopy (SuffixStringPtr,
280                       (CHAR8 *)SocketTablePtr->Stringstart,
281                       SocketTablePtr->Stringlength,
282                       StdHeader);
283     }
284   }
285
286   // Step11: Put values into name MSRs,  Always write the full 48 bytes
287   MsrNameStringPtrPtr = (UINT64 *) BrandStringPtr;
288   for (MsrIndex = MSR_CPUID_NAME_STRING0; MsrIndex <= MSR_CPUID_NAME_STRING5; MsrIndex++) {
289     LibAmdMsrWrite (MsrIndex, MsrNameStringPtrPtr, StdHeader);
290     MsrNameStringPtrPtr++;
291   }
292   HeapDeallocateBuffer (AMD_BRAND_ID_BUFFER_HANDLE, StdHeader);
293 }
294
295 /*---------------------------------------------------------------------------------------*/
296 /**
297  * Program BrandID registers (CPUIDNameStringPtr[0-5])
298  *
299  * This function acts as a wrapper for calling the SetBrandIdRegisters
300  * routine at AmdInitEarly.
301  *
302  *  @param[in]   FamilyServices      The current Family Specific Services.
303  *  @param[in]   EarlyParams         Service parameters.
304  *  @param[in]   StdHeader           Config handle for library and services.
305  *
306  */
307 VOID
308 SetBrandIdRegistersAtEarly (
309   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
310   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
311   IN       AMD_CONFIG_PARAMS      *StdHeader
312   )
313 {
314   AGESA_TESTPOINT (TpProcCpuSetBrandID, StdHeader);
315   SetBrandIdRegisters (StdHeader);
316 }