5 * AMD CPU BrandId related functions.
7 * Contains code that provides CPU BrandId information
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 37640 $ @e \$Date: 2010-09-08 23:01:59 +0800 (Wed, 08 Sep 2010) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
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.
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.
43 * ***************************************************************************
47 /*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
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"
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 *----------------------------------------------------------------------------------------
69 /*----------------------------------------------------------------------------------------
70 * T Y P E D E F S A N D S T R U C T U R E S
71 *----------------------------------------------------------------------------------------
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";
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};
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 *----------------------------------------------------------------------------------------
89 SetBrandIdRegistersAtEarly (
90 IN CPU_SPECIFIC_SERVICES *FamilyServices,
91 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
92 IN AMD_CONFIG_PARAMS *StdHeader
95 /*----------------------------------------------------------------------------------------
96 * E X P O R T E D F U N C T I O N S
97 *----------------------------------------------------------------------------------------
100 /*---------------------------------------------------------------------------------------*/
102 * Program BrandID registers (CPUIDNameStringPtr[0-5])
104 * This function determines the appropriate brand string for the executing
105 * core, and programs the namestring MSRs.
107 * @param[in,out] StdHeader Config handle for library and services.
111 SetBrandIdRegisters (
112 IN OUT AMD_CONFIG_PARAMS *StdHeader
118 UINT8 TableEntryCount;
119 UINT8 TableEntryIndex;
121 CHAR8 *NameStringPtr;
122 CHAR8 *SuffixStringPtr;
123 CHAR8 *BrandStringPtr;
124 CHAR8 *TempNameCharPtr;
128 UINT64 *MsrNameStringPtrPtr;
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;
139 FamilySpecificServices = NULL;
140 SocketTablePtr = NULL;
141 SocketTableEntry = NULL;
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) {
150 BrandStringPtr = (CHAR8 *) AllocHeapParams.BufferPtr;
151 LibAmdMemFill (BrandStringPtr, 0, CPU_BRAND_ID_LENGTH, StdHeader);
155 CPU_ERROR_BRANDID_HEAP_NOT_AVAILABLE,
156 0, 0, 0, 0, StdHeader
161 // Step2: Get brandid from model number and model string
162 LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, StdHeader);
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);
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;
177 SocketTablePtr = (AMD_CPU_BRAND *)&TtkSample_Str;
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)) {
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) {
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)) {
211 if (SuffixStatus == 0) {
212 SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str1; // We did not find one, make 'Unknown'
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,
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;
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';
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;
250 // Step9: Search for String2
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) {
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)) {
273 if (SuffixStatus == 0) {
274 SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str2;
277 // Step10: Copy String2 into our NameBuffer
278 if (SocketTablePtr->Stringlength != 0) {
279 LibAmdMemCopy (SuffixStringPtr,
280 (CHAR8 *)SocketTablePtr->Stringstart,
281 SocketTablePtr->Stringlength,
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++;
292 HeapDeallocateBuffer (AMD_BRAND_ID_BUFFER_HANDLE, StdHeader);
295 /*---------------------------------------------------------------------------------------*/
297 * Program BrandID registers (CPUIDNameStringPtr[0-5])
299 * This function acts as a wrapper for calling the SetBrandIdRegisters
300 * routine at AmdInitEarly.
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.
308 SetBrandIdRegistersAtEarly (
309 IN CPU_SPECIFIC_SERVICES *FamilyServices,
310 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
311 IN AMD_CONFIG_PARAMS *StdHeader
314 AGESA_TESTPOINT (TpProcCpuSetBrandID, StdHeader);
315 SetBrandIdRegisters (StdHeader);