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