5 * AMD CPU Microcode Patch Related Functions
7 * Contains code to program a microcode into the CPU
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 17:16:51 +0800 (Wed, 22 Dec 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.
42 ******************************************************************************
45 /*---------------------------------------------------------------------------------------
46 * M O D U L E S U S E D
47 *---------------------------------------------------------------------------------------
52 #include "cpuRegisters.h"
53 #include "cpuFamilyTranslation.h"
54 #include "cpuEarlyInit.h"
55 #include "GeneralServices.h"
56 #include "cpuServices.h"
59 RDATA_GROUP (G1_PEICC)
61 #define FILECODE PROC_CPU_CPUMICROCODEPATCH_FILECODE
62 /*----------------------------------------------------------------------------------------
63 * D E F I N I T I O N S A N D M A C R O S
64 *----------------------------------------------------------------------------------------
68 /*----------------------------------------------------------------------------------------
69 * T Y P E D E F S A N D S T R U C T U R E S
70 *----------------------------------------------------------------------------------------
74 PATCH_LOADER_MSR BitFields;
77 /*----------------------------------------------------------------------------------------
78 * 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
79 *----------------------------------------------------------------------------------------
84 IN MICROCODE_PATCH *MicrocodePatchPtr,
85 IN OUT AMD_CONFIG_PARAMS *StdHeader
90 GetPatchEquivalentId (
91 IN OUT UINT16 *ProcessorEquivalentId,
92 IN OUT AMD_CONFIG_PARAMS *StdHeader
98 IN MICROCODE_PATCH *MicrocodePatchPtr,
99 IN UINT16 ProcessorEquivalentId,
100 IN OUT AMD_CONFIG_PARAMS *StdHeader
105 GetMicrocodeVersion (
106 OUT UINT32 *pMicrocodeVersion,
107 IN OUT AMD_CONFIG_PARAMS *StdHeader
110 /*----------------------------------------------------------------------------------------
111 * E X P O R T E D F U N C T I O N S
112 *----------------------------------------------------------------------------------------
115 LoadMicrocodePatchAtEarly (
116 IN CPU_SPECIFIC_SERVICES *FamilyServices,
117 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
118 IN AMD_CONFIG_PARAMS *StdHeader
122 /* -----------------------------------------------------------------------------*/
124 * Update microcode patch in current processor.
126 * Then reads the patch id, and compare it to the expected, in the Microprocessor
129 * @param[in] StdHeader - Config handle for library and services.
131 * @retval TRUE - Patch Loaded Successfully.
132 * @retval FALSE - Patch Did Not Get Loaded.
137 IN OUT AMD_CONFIG_PARAMS *StdHeader
142 UINT16 ProcessorEquivalentId;
144 MICROCODE_PATCH **MicrocodePatchPtr;
145 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
149 if (IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader)) {
150 // Get the patch pointer
151 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
152 FamilySpecificServices->GetMicroCodePatchesStruct (FamilySpecificServices, (const VOID **) &MicrocodePatchPtr, &TotalPatches, StdHeader);
154 IDS_OPTION_HOOK (IDS_UCODE, &TotalPatches, StdHeader);
156 // Get the processor microcode path equivalent ID
157 if (GetPatchEquivalentId (&ProcessorEquivalentId, StdHeader)) {
158 // parse the patch table to see if we have one for the current cpu
159 for (PatchNumber = 0; PatchNumber < TotalPatches; PatchNumber++) {
160 if (ValidateMicrocode (MicrocodePatchPtr[PatchNumber], ProcessorEquivalentId, StdHeader)) {
161 if (LoadMicrocode (MicrocodePatchPtr[PatchNumber], StdHeader)) {
164 PutEventLog (AGESA_ERROR,
165 CPU_ERROR_MICRO_CODE_PATCH_IS_NOT_LOADED,
166 0, 0, 0, 0, StdHeader);
168 break; // Once we find a microcode patch that matches the processor, exit the for loop
176 /*---------------------------------------------------------------------------------------
177 * L O C A L F U N C T I O N S
178 *---------------------------------------------------------------------------------------
181 /* -----------------------------------------------------------------------------*/
186 * Update microcode patch in current processor, then reads the
187 * patch id, and compare it to the expected, in the Microprocessor
190 * @param[in] MicrocodePatchPtr - Pointer to Microcode Patch.
191 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
193 * @retval TRUE - Patch Loaded Successfully.
194 * @retval FALSE - Patch Did Not Get Loaded.
200 IN MICROCODE_PATCH *MicrocodePatchPtr,
201 IN OUT AMD_CONFIG_PARAMS *StdHeader
204 UINT32 MicrocodeVersion;
205 PATCH_LOADER PatchLoaderMsr;
207 // Load microcode patch into CPU
208 PatchLoaderMsr.RawData = (UINT64) MicrocodePatchPtr;
209 PatchLoaderMsr.BitFields.SBZ = 0;
210 LibAmdMsrWrite (MSR_PATCH_LOADER, &PatchLoaderMsr.RawData, StdHeader);
212 // Do ucode patch Authentication
213 // Read microcode version back from CPU, determine if
214 // it is the same patch level as contained in the source
215 // microprocessor patch block passed in
216 GetMicrocodeVersion (&MicrocodeVersion, StdHeader);
217 if (MicrocodeVersion == MicrocodePatchPtr->PatchID) {
225 /* -----------------------------------------------------------------------------*/
228 * GetPatchEquivalentId
230 * Return the equivalent ID for microcode patching
232 * @param[in,out] ProcessorEquivalentId - Pointer to Processor Equivalent ID table.
233 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
235 * @retval TRUE - ID Found.
236 * @retval FALSE - ID Not Found.
241 GetPatchEquivalentId (
242 IN OUT UINT16 *ProcessorEquivalentId,
243 IN OUT AMD_CONFIG_PARAMS *StdHeader
247 UINT8 EquivalencyEntries;
248 UINT16 ProcessorRevisionId;
249 UINT16 *MicrocodeEquivalenceTable;
250 CPUID_DATA CpuIdData;
251 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
254 // compute the processor revision ID
256 LibAmdCpuidRead (AMD_CPUID_FMF, &CpuIdData, StdHeader);
257 // high byte contains extended model and extended family
258 ProcessorRevisionId = (UINT16) ((CpuIdData.EAX_Reg & (CPU_EMODEL | CPU_EFAMILY)) >> 8);
259 // low byte contains model and family
260 ProcessorRevisionId |= (CpuIdData.EAX_Reg & (CPU_STEPPING | CPU_MODEL));
263 // find the equivalent ID for microcode purpose using the equivalence table
265 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
267 FamilySpecificServices->GetMicrocodeEquivalenceTable (FamilySpecificServices,
268 (const VOID **)&MicrocodeEquivalenceTable,
272 // parse the equivalence table
273 for (i = 0; i < (EquivalencyEntries * 2); i += 2) {
274 // check for equivalence
275 if (ProcessorRevisionId == MicrocodeEquivalenceTable[i]) {
276 *ProcessorEquivalentId = MicrocodeEquivalenceTable[i + 1];
280 // end of table reach, this processor is not supported
281 *ProcessorEquivalentId = 0x0000;
285 /*---------------------------------------------------------------------------------------*/
290 * Determine if the microcode patch block, currently pointed to
291 * is valid, and is appropriate for the current processor
293 * @param[in] MicrocodePatchPtr - Pointer to Microcode Patch.
294 * @param[in] ProcessorEquivalentId - Pointer to Processor Equivalent ID table.
295 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
297 * @retval TRUE - Patch Found.
298 * @retval FALSE - Patch Not Found.
304 IN MICROCODE_PATCH *MicrocodePatchPtr,
305 IN UINT16 ProcessorEquivalentId,
306 IN OUT AMD_CONFIG_PARAMS *StdHeader
309 BOOLEAN Chipset1Matched;
310 BOOLEAN Chipset2Matched;
312 UINT32 PciDeviceVidDid;
313 UINT8 PciDeviceRevision;
316 UINT32 Chipset1DeviceID;
317 UINT32 Chipset2DeviceID;
320 Chipset1Matched = FALSE;
321 Chipset2Matched = FALSE;
323 PciDeviceRevision = 0;
324 Chipset1DeviceID = MicrocodePatchPtr->Chipset1DeviceID;
325 Chipset2DeviceID = MicrocodePatchPtr->Chipset2DeviceID;
329 // parse the supplied microcode to see if it is compatible with the processor
331 if (MicrocodePatchPtr->ProcessorRevisionID != ProcessorEquivalentId) {
335 if (Chipset1DeviceID == 0) {
336 Chipset1Matched = TRUE;
338 if (Chipset2DeviceID == 0) {
339 Chipset2Matched = TRUE;
342 if ((!Chipset1Matched) || (!Chipset2Matched)) {
344 // Scan all PCI devices in Bus 0, try to find out matched case.
346 for (DevCount = 0; DevCount < 32; DevCount++) {
347 for (FunCount = 0; FunCount < 8; FunCount++) {
348 PciAddress.AddressValue = MAKE_SBDFO (0, 0, DevCount, FunCount, 0);
349 LibAmdPciRead (AccessWidth32, PciAddress, &PciDeviceVidDid, StdHeader);
350 if (PciDeviceVidDid == 0xFFFFFFFF) {
357 PciAddress.Address.Register = 0x8;
358 LibAmdPciRead (AccessWidth8, PciAddress, &PciDeviceRevision, StdHeader);
359 if ((!Chipset1Matched) && (PciDeviceVidDid == Chipset1DeviceID)) {
360 if (PciDeviceRevision == MicrocodePatchPtr->Chipset1RevisionID) {
361 Chipset1Matched = TRUE;
364 if ((!Chipset2Matched) && (PciDeviceVidDid == Chipset2DeviceID)) {
365 if (PciDeviceRevision == MicrocodePatchPtr->Chipset2RevisionID) {
366 Chipset2Matched = TRUE;
369 if (Chipset1Matched && Chipset2Matched) {
373 // Check multi-function. If it doesen't exist, we don't have to loop functions to 7.
377 PciAddress.Address.Register = 0xE;
378 LibAmdPciRead (AccessWidth8, PciAddress, &MulitFunction, StdHeader);
379 if ((MulitFunction & 0x80) == 0) {
383 } // end FunCount for loop.
385 if (Chipset1Matched && Chipset2Matched) {
388 } // end DevCount for loop.
391 return (Chipset1Matched && Chipset2Matched);
395 /*---------------------------------------------------------------------------------------*/
398 * GetMicrocodeVersion
400 * Return the version of the currently loaded microcode patch, if any.
401 * Read from the patch level MSR, return the value in eax. If no patch
402 * has been loaded, 0 will be returned.
404 * @param[out] pMicrocodeVersion - Pointer to Microcode Version.
405 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
410 GetMicrocodeVersion (
411 OUT UINT32 *pMicrocodeVersion,
412 IN OUT AMD_CONFIG_PARAMS *StdHeader
418 LibAmdMsrRead (MSR_PATCH_LEVEL, &MsrData, StdHeader);
420 *pMicrocodeVersion = (UINT32) MsrData;
424 /*---------------------------------------------------------------------------------------*/
426 * Update microcode patch in current processor.
428 * This function acts as a wrapper for calling the LoadMicrocodePatch
429 * routine at AmdInitEarly.
431 * @param[in] FamilyServices The current Family Specific Services.
432 * @param[in] EarlyParams Service parameters.
433 * @param[in] StdHeader Config handle for library and services.
437 LoadMicrocodePatchAtEarly (
438 IN CPU_SPECIFIC_SERVICES *FamilyServices,
439 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
440 IN AMD_CONFIG_PARAMS *StdHeader
443 AGESA_TESTPOINT (TpProcCpuLoadUcode, StdHeader);
444 LoadMicrocodePatch (StdHeader);