5 * AMD CPU Register Table Related Functions
7 * Set registers according to a set of register tables
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 50057 $ @e \$Date: 2011-04-01 13:30:57 +0800 (Fri, 01 Apr 2011) $
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 *----------------------------------------------------------------------------------------
53 #include "OptionMultiSocket.h"
54 #include "cpuRegisters.h"
55 #include "cpuFamilyTranslation.h"
57 #include "GeneralServices.h"
58 #include "cpuServices.h"
59 #include "cpuFeatures.h"
60 #include "CommonReturns.h"
61 #include "cpuL3Features.h"
62 #include "cpuEarlyInit.h"
65 RDATA_GROUP (G1_PEICC)
67 #define FILECODE PROC_CPU_TABLE_FILECODE
69 extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
71 /*----------------------------------------------------------------------------------------
72 * D E F I N I T I O N S A N D M A C R O S
73 *----------------------------------------------------------------------------------------
76 /*----------------------------------------------------------------------------------------
77 * T Y P E D E F S A N D S T R U C T U R E S
78 *----------------------------------------------------------------------------------------
81 /*----------------------------------------------------------------------------------------
82 * 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
83 *----------------------------------------------------------------------------------------
86 /*----------------------------------------------------------------------------------------
87 * E X P O R T E D F U N C T I O N S
88 *----------------------------------------------------------------------------------------
91 SetRegistersFromTablesAtEarly (
92 IN CPU_SPECIFIC_SERVICES *FamilyServices,
93 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
94 IN AMD_CONFIG_PARAMS *StdHeader
97 extern BUILD_OPT_CFG UserOptions;
98 extern CPU_FAMILY_SUPPORT_TABLE L3FeatureFamilyServiceTable;
100 /*---------------------------------------------------------------------------------------*/
102 * An iterator for all the Family and Model Register Tables.
104 * RegisterTableHandle should be set to NULL to begin iteration, the first time the method is
105 * invoked. Register tables can be processed, until this method returns NULL. RegisterTableHandle
106 * should simply be passed back to the method without modification or use by the caller.
107 * The table selector allows the relevant tables for different cores to be iterated, if the family separates
108 * tables. For example, MSRs can be in a table processed by all cores and PCI registers in a table processed by
111 * @param[in] FamilySpecificServices The current Family Specific Services.
112 * @param[in] Selector Select whether to iterate over tables for either all cores, primary cores, bsp, ....
113 * @param[in,out] RegisterTableHandle IN: The handle of the current register table, or NULL if Begin.
114 * OUT: The handle of the next register table, if not End.
115 * @param[out] NumberOfEntries The number of entries in the table returned, if not End.
116 * @param[in] StdHeader Handle of Header for calling lib functions and services.
118 * @return The pointer to the next Register Table, or NULL if End.
122 *GetNextRegisterTable (
123 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
124 IN TABLE_CORE_SELECTOR Selector,
125 IN OUT REGISTER_TABLE ***RegisterTableHandle,
126 OUT UINTN *NumberOfEntries,
127 IN AMD_CONFIG_PARAMS *StdHeader
130 REGISTER_TABLE **NextTable;
131 TABLE_ENTRY_FIELDS *Entries;
133 ASSERT ((FamilySpecificServices != NULL) && (StdHeader != NULL));
134 ASSERT (Selector < TableCoreSelectorMax);
136 NextTable = *RegisterTableHandle;
137 if (NextTable == NULL) {
139 NextTable = FamilySpecificServices->RegisterTableList;
140 IDS_OPTION_HOOK (IDS_REG_TABLE, &NextTable, StdHeader);
144 // skip if not selected
145 while ((*NextTable != NULL) && (*NextTable)->Selector != Selector) {
148 if (*NextTable == NULL) {
150 *RegisterTableHandle = NULL;
153 // Iterate next table
154 *RegisterTableHandle = NextTable;
155 *NumberOfEntries = (*NextTable)->NumberOfEntries;
156 Entries = (TABLE_ENTRY_FIELDS *) (*NextTable)->Table;
161 /*---------------------------------------------------------------------------------------*/
163 * Compare counts to a pair of ranges.
165 * @param[in] FirstCount The actual count to be compared to the first range.
166 * @param[in] SecondCount The actual count to be compared to the second range.
167 * @param[in] Ranges The ranges which the counts are compared to.
169 * @retval TRUE Either one, or both, of the counts is in the range given.
170 * @retval FALSE Neither count is in the range given.
173 IsEitherCountInRange (
175 IN UINTN SecondCount,
176 IN COUNT_RANGE_FEATURE Ranges
179 // Errors: Entire Range value is zero, Min and Max reversed or not <=, ranges overlap (OK if first range is all),
180 // the real counts are too big.
181 ASSERT ((Ranges.Range0Min <= Ranges.Range0Max) &&
182 (Ranges.Range1Min <= Ranges.Range1Max) &&
183 (Ranges.Range0Max != 0) &&
184 (Ranges.Range1Max != 0) &&
185 ((Ranges.Range0Max == COUNT_RANGE_HIGH) || (Ranges.Range0Max < Ranges.Range1Min)) &&
186 ((FirstCount < COUNT_RANGE_HIGH) && (SecondCount < COUNT_RANGE_HIGH)));
188 return (BOOLEAN) (((FirstCount <= Ranges.Range0Max) && (FirstCount >= Ranges.Range0Min)) ||
189 ((SecondCount <= Ranges.Range1Max) && (SecondCount >= Ranges.Range1Min)));
192 /*-------------------------------------------------------------------------------------*/
194 * Returns the performance profile features list of the currently running processor core.
196 * @param[out] Features The performance profile features supported by this platform
197 * @param[in] PlatformConfig Config handle for platform specific information
198 * @param[in] StdHeader Header for library and services
202 GetPerformanceFeatures (
203 OUT PERFORMANCE_PROFILE_FEATS *Features,
204 IN PLATFORM_CONFIGURATION *PlatformConfig,
205 IN AMD_CONFIG_PARAMS *StdHeader
208 CPUID_DATA CpuidDataStruct;
209 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
210 L3_FEATURE_FAMILY_SERVICES *FeatureFamilyServices;
212 Features->PerformanceProfileValue = 0;
213 // Reflect Probe Filter Configuration.
214 Features->PerformanceProfileFeatures.ProbeFilter = 0;
215 if (IsFeatureEnabled (L3Features, PlatformConfig, StdHeader)) {
216 GetFeatureServicesOfCurrentCore (&L3FeatureFamilyServiceTable, (const VOID **) &FeatureFamilyServices, StdHeader);
217 if ((FeatureFamilyServices != NULL) &&
218 (FeatureFamilyServices->IsHtAssistSupported (FeatureFamilyServices, PlatformConfig, StdHeader))) {
219 Features->PerformanceProfileFeatures.ProbeFilter = 1;
223 // Reflect Display Refresh Requests use 32 bytes Configuration.
224 Features->PerformanceProfileFeatures.RefreshRequest32Byte = 0;
225 if (PlatformConfig->PlatformProfile.Use32ByteRefresh) {
226 Features->PerformanceProfileFeatures.RefreshRequest32Byte = 1;
228 // Reflect Mct Isoc Read Priority set to variable Configuration.
229 Features->PerformanceProfileFeatures.MctIsocVariable = 0;
230 if (PlatformConfig->PlatformProfile.UseVariableMctIsocPriority) {
231 Features->PerformanceProfileFeatures.MctIsocVariable = 1;
233 // Indicate if this boot is a warm reset.
234 Features->PerformanceProfileFeatures.IsWarmReset = 0;
235 if (IsWarmReset (StdHeader)) {
236 Features->PerformanceProfileFeatures.IsWarmReset = 1;
239 // Get L3 Cache present as indicated by CPUID
240 Features->PerformanceProfileFeatures.L3Cache = 0;
241 Features->PerformanceProfileFeatures.NoL3Cache = 1;
242 LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuidDataStruct, StdHeader);
243 if (((CpuidDataStruct.EDX_Reg & 0xFFFC0000) >> 18) != 0) {
244 Features->PerformanceProfileFeatures.L3Cache = 1;
245 Features->PerformanceProfileFeatures.NoL3Cache = 0;
248 // Get VRM select high speed from build option.
249 Features->PerformanceProfileFeatures.VrmHighSpeed = 0;
250 if (PlatformConfig->VrmProperties[CoreVrm].HiSpeedEnable) {
251 Features->PerformanceProfileFeatures.VrmHighSpeed = 1;
254 // Get some family, model specific performance type info.
255 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
256 ASSERT (FamilySpecificServices != NULL);
258 // Is the Northbridge P-State feature enabled
259 Features->PerformanceProfileFeatures.NbPstates = 0;
260 if (FamilySpecificServices->IsNbPstateEnabled (FamilySpecificServices, PlatformConfig, StdHeader)) {
261 Features->PerformanceProfileFeatures.NbPstates = 1;
265 /*---------------------------------------------------------------------------------------*/
267 * Perform the MSR Register Entry.
269 * @TableEntryTypeMethod{::MsrRegister}.
271 * Read - Modify - Write the MSR, clearing masked bits, and setting the data bits.
273 * @param[in] Entry The MSR register entry to perform
274 * @param[in] PlatformConfig Config handle for platform specific information
275 * @param[in] StdHeader Config handle for library and services.
279 SetRegisterForMsrEntry (
280 IN TABLE_ENTRY_DATA *Entry,
281 IN PLATFORM_CONFIGURATION *PlatformConfig,
282 IN AMD_CONFIG_PARAMS *StdHeader
287 // Even for only single bit fields, use those in the mask. "Mask nothing" is a bug, even if just by policy.
288 ASSERT (Entry->MsrEntry.Mask != 0);
290 LibAmdMsrRead (Entry->MsrEntry.Address, &MsrData, StdHeader);
291 MsrData = MsrData & (~(Entry->MsrEntry.Mask));
292 MsrData = MsrData | Entry->MsrEntry.Data;
293 LibAmdMsrWrite (Entry->MsrEntry.Address, &MsrData, StdHeader);
296 /*---------------------------------------------------------------------------------------*/
298 * Perform the PCI Register Entry.
300 * @TableEntryTypeMethod{::PciRegister}.
302 * Make the current core's PCI address with the function and register for the entry.
303 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
305 * @param[in] Entry The PCI register entry to perform
306 * @param[in] PlatformConfig Config handle for platform specific information
307 * @param[in] StdHeader Config handle for library and services.
311 SetRegisterForPciEntry (
312 IN TABLE_ENTRY_DATA *Entry,
313 IN PLATFORM_CONFIGURATION *PlatformConfig,
314 IN AMD_CONFIG_PARAMS *StdHeader
321 PCI_ADDR MyPciAddress;
322 AGESA_STATUS IgnoredSts;
323 TABLE_ENTRY_DATA PciEntry;
325 // Errors: Possible values in unused entry space, extra type features, value range checks.
326 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
327 // Even for only single bit fields, use those in the mask. "Mask nothing" is a bug, even if just by policy.
328 ASSERT ((Entry->InitialValues[4] == 0) &&
329 (Entry->InitialValues[3] == 0) &&
330 (Entry->PciEntry.Mask != 0));
332 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
333 PciEntry.PciEntry = Entry->PciEntry;
335 IDS_OPTION_HOOK (IDS_SET_PCI_REGISTER_ENTRY, &PciEntry, StdHeader);
337 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredSts);
338 GetPciAddress (StdHeader, MySocket, MyModule, &MyPciAddress, &IgnoredSts);
339 MyPciAddress.Address.Function = PciEntry.PciEntry.Address.Address.Function;
340 MyPciAddress.Address.Register = PciEntry.PciEntry.Address.Address.Register;
341 LibAmdPciRead (AccessWidth32, MyPciAddress, &TempVar32_a, StdHeader);
342 TempVar32_a = TempVar32_a & (~(PciEntry.PciEntry.Mask));
343 TempVar32_a = TempVar32_a | PciEntry.PciEntry.Data;
344 LibAmdPciWrite (AccessWidth32, MyPciAddress, &TempVar32_a, StdHeader);
347 /*---------------------------------------------------------------------------------------*/
349 * Perform the Family Specific Workaround Register Entry.
351 * @TableEntryTypeMethod{::FamSpecificWorkaround}.
353 * Call the function, passing the data.
355 * See if you can use the other entries or make an entry that covers the fix.
356 * After all, the purpose of having a table entry is to @b NOT have code which
357 * isn't generic feature code, but is family/model code specific to one case.
359 * @param[in] Entry The Family Specific Workaround register entry to perform
360 * @param[in] PlatformConfig Config handle for platform specific information
361 * @param[in] StdHeader Config handle for library and services.
365 SetRegisterForFamSpecificWorkaroundEntry (
366 IN TABLE_ENTRY_DATA *Entry,
367 IN PLATFORM_CONFIGURATION *PlatformConfig,
368 IN AMD_CONFIG_PARAMS *StdHeader
371 ASSERT (Entry->FamSpecificEntry.DoAction != NULL);
373 Entry->FamSpecificEntry.DoAction (Entry->FamSpecificEntry.Data, StdHeader);
376 /*---------------------------------------------------------------------------------------*/
378 * Program HT Phy PCI registers using BKDG values.
380 * @TableEntryTypeMethod{::HtPhyRegister}.
383 * @param[in] Entry The type specific entry data to be implemented (that is written).
384 * @param[in] PlatformConfig Config handle for platform specific information
385 * @param[in] StdHeader Config params for library, services.
389 SetRegisterForHtPhyEntry (
390 IN TABLE_ENTRY_DATA *Entry,
391 IN PLATFORM_CONFIGURATION *PlatformConfig,
392 IN AMD_CONFIG_PARAMS *StdHeader
398 AGESA_STATUS IgnoredStatus;
400 CPU_LOGICAL_ID CpuFamilyRevision;
401 PCI_ADDR CapabilitySet;
402 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
403 BOOLEAN MatchedSublink1;
404 HT_FREQUENCIES Freq0;
405 HT_FREQUENCIES Freq1;
407 // Errors: Possible values in unused entry space, extra type features, value range checks.
408 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
409 ASSERT ((Entry->InitialValues[4] == 0) &&
410 ((Entry->HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL | HTPHY_LINKTYPE_SL0_AND | HTPHY_LINKTYPE_SL1_AND)) == 0) &&
411 (Entry->HtPhyEntry.Address < HTPHY_REGISTER_MAX));
413 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
414 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
415 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
416 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
418 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
419 FamilySpecificServices,
422 &Entry->HtPhyEntry.TypeFeats,
427 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &Entry->HtPhyEntry, CapabilitySet, Link, StdHeader);
431 /*---------------------------------------------------------------------------------------*/
433 * Program a range of HT Phy PCI registers using BKDG values.
435 * @TableEntryTypeMethod{::HtPhyRangeRegister}.
438 * @param[in] Entry The type specific entry data to be implemented (that is written).
439 * @param[in] PlatformConfig Config handle for platform specific information
440 * @param[in] StdHeader Config params for library, services.
444 SetRegisterForHtPhyRangeEntry (
445 IN TABLE_ENTRY_DATA *Entry,
446 IN PLATFORM_CONFIGURATION *PlatformConfig,
447 IN AMD_CONFIG_PARAMS *StdHeader
453 AGESA_STATUS IgnoredStatus;
455 CPU_LOGICAL_ID CpuFamilyRevision;
456 PCI_ADDR CapabilitySet;
457 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
458 HT_PHY_TYPE_ENTRY_DATA CurrentHtPhyRegister;
459 BOOLEAN MatchedSublink1;
460 HT_FREQUENCIES Freq0;
461 HT_FREQUENCIES Freq1;
463 // Errors: Possible values in unused entry space, extra type features, value range checks.
464 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
465 ASSERT (((Entry->HtPhyRangeEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
466 (Entry->HtPhyRangeEntry.LowAddress <= Entry->HtPhyRangeEntry.HighAddress) &&
467 (Entry->HtPhyRangeEntry.HighAddress < HTPHY_REGISTER_MAX) &&
468 (Entry->HtPhyRangeEntry.HighAddress != 0));
470 CurrentHtPhyRegister.Mask = Entry->HtPhyRangeEntry.Mask;
471 CurrentHtPhyRegister.Data = Entry->HtPhyRangeEntry.Data;
472 CurrentHtPhyRegister.TypeFeats = Entry->HtPhyRangeEntry.TypeFeats;
474 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
475 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
476 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
477 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
479 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
480 FamilySpecificServices,
483 &Entry->HtPhyRangeEntry.TypeFeats,
488 for (CurrentHtPhyRegister.Address = Entry->HtPhyRangeEntry.LowAddress;
489 CurrentHtPhyRegister.Address <= Entry->HtPhyRangeEntry.HighAddress;
490 CurrentHtPhyRegister.Address++) {
491 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &CurrentHtPhyRegister, CapabilitySet, Link, StdHeader);
496 /*----------------------------------------------------------------------------------------*/
498 * Is PackageLink an Internal Link?
500 * This is a test for the logical link match codes in the user interface, not a test for
501 * the actual northbridge links.
503 * @param[in] PackageLink The link
505 * @retval TRUE This is an internal link
506 * @retval FALSE This is not an internal link
510 IsDeemphasisLinkInternal (
511 IN UINT32 PackageLink
514 return (BOOLEAN) ((PackageLink <= HT_LIST_MATCH_INTERNAL_LINK_2) && (PackageLink >= HT_LIST_MATCH_INTERNAL_LINK_0));
517 /*----------------------------------------------------------------------------------------*/
519 * Get the Package Link number, for the current node and real link number.
521 * Based on the link to package link mapping from BKDG, look up package link for
522 * the input link on the internal node number corresponding to the current core's node.
523 * For single module processors, the northbridge link and package link are the same.
525 * @param[in] Link the link on the current node.
526 * @param[in] FamilySpecificServices CPU specific support interface.
527 * @param[in] StdHeader Config params for library, services.
529 * @return the Package Link, HT_LIST_TERMINAL Not connected in package, HT_LIST_MATCH_INTERNAL_LINK package internal link.
536 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
537 IN AMD_CONFIG_PARAMS *StdHeader
540 UINT32 PackageLinkMapItem;
542 AP_MAIL_INFO ApMailbox;
544 PackageLink = HT_LIST_TERMINAL;
546 GetApMailbox (&ApMailbox.Info, StdHeader);
548 if (ApMailbox.Fields.ModuleType != 0) {
549 ASSERT (FamilySpecificServices->PackageLinkMap != NULL);
550 // Use table to find this module's package link
551 PackageLinkMapItem = 0;
552 while ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link != HT_LIST_TERMINAL) {
553 if (((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Module == ApMailbox.Fields.Module) &&
554 ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link == Link)) {
555 PackageLink = (*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].PackageLink;
558 PackageLinkMapItem++;
566 /*---------------------------------------------------------------------------------------*/
568 * Get the platform's specified deemphasis levels for the current link.
570 * Search the platform's list for a match to the current link and also matching frequency.
571 * If a match is found, use the specified deemphasis levels.
573 * @param[in] Socket The current Socket.
574 * @param[in] Link The link on that socket.
575 * @param[in] Frequency The frequency the link is set to.
576 * @param[in] PlatformConfig Config handle for platform specific information
577 * @param[in] FamilySpecificServices CPU specific support interface.
578 * @param[in] StdHeader Config params for library, services.
580 * @return The Deemphasis values for the link.
587 IN HT_FREQUENCIES Frequency,
588 IN PLATFORM_CONFIGURATION *PlatformConfig,
589 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
590 IN AMD_CONFIG_PARAMS *StdHeader
594 CPU_HT_DEEMPHASIS_LEVEL *Match;
597 PackageLink = LookupPackageLink (Link, FamilySpecificServices, StdHeader);
598 // All External and Internal links have deemphasis level none as the default.
599 // However, it is expected that the platform BIOS will provide deemphasis levels for the external links.
600 Result = ((DCV_LEVEL_NONE) | (DEEMPHASIS_LEVEL_NONE));
602 if (PlatformConfig->PlatformDeemphasisList != NULL) {
603 Match = PlatformConfig->PlatformDeemphasisList;
604 while (Match->Socket != HT_LIST_TERMINAL) {
605 if (((Match->Socket == Socket) || (Match->Socket == HT_LIST_MATCH_ANY)) &&
606 ((Match->Link == PackageLink) ||
607 ((Match->Link == HT_LIST_MATCH_ANY) && (!IsDeemphasisLinkInternal (PackageLink))) ||
608 ((Match->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsDeemphasisLinkInternal (PackageLink)))) &&
609 ((Match->LoFreq <= Frequency) && (Match->HighFreq >= Frequency))) {
610 // Found a match, get the deemphasis value.
611 ASSERT ((MaxPlatformDeemphasisLevel > Match->DcvDeemphasis) | (MaxPlatformDeemphasisLevel > Match->ReceiverDeemphasis));
612 Result = ((1 << Match->DcvDeemphasis) | (1 << Match->ReceiverDeemphasis));
622 /*---------------------------------------------------------------------------------------*/
624 * Program Deemphasis registers using BKDG values, for the platform specified levels.
626 * @TableEntryTypeMethod{::DeemphasisRegister}.
629 * @param[in] Entry The type specific entry data to be implemented (that is written).
630 * @param[in] PlatformConfig Config handle for platform specific information
631 * @param[in] StdHeader Config params for library, services.
635 SetRegisterForDeemphasisEntry (
636 IN TABLE_ENTRY_DATA *Entry,
637 IN PLATFORM_CONFIGURATION *PlatformConfig,
638 IN AMD_CONFIG_PARAMS *StdHeader
644 AGESA_STATUS IgnoredStatus;
646 CPU_LOGICAL_ID CpuFamilyRevision;
647 PCI_ADDR CapabilitySet;
648 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
649 BOOLEAN MatchedSublink1;
650 HT_FREQUENCIES Freq0;
651 HT_FREQUENCIES Freq1;
653 // Errors: Possible values in unused entry space, extra type features, value range checks.
654 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
655 ASSERT (((Entry->DeemphasisEntry.Levels.DeemphasisValues & ~(VALID_DEEMPHASIS_LEVELS)) == 0) &&
656 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
657 (Entry->DeemphasisEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
659 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
660 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
661 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
662 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
664 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
665 FamilySpecificServices,
668 &Entry->DeemphasisEntry.HtPhyEntry.TypeFeats,
673 if (DoesEntryTypeSpecificInfoMatch (
676 (MatchedSublink1 ? (Link + 4) : Link),
677 (MatchedSublink1 ? Freq1 : Freq0),
679 FamilySpecificServices,
681 Entry->DeemphasisEntry.Levels.DeemphasisValues)) {
682 FamilySpecificServices->SetHtPhyRegister (
683 FamilySpecificServices,
684 &Entry->DeemphasisEntry.HtPhyEntry,
689 IDS_HDT_CONSOLE (HT_TRACE, "Socket %d Module %d Sub-link %1d :\n ----> running on HT3, %s Level is %s\n",
691 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & HTPHY_LINKTYPE_SL0_ALL) != 0) ? Link : (Link + 4),
692 ((Entry->DeemphasisEntry.Levels.DeemphasisValues & DCV_LEVELS_ALL) != 0) ? "DCV" : "Deemphasis",
693 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL_NONE) ? " 0 dB" :
694 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__3) ? " - 3 dB" :
695 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
696 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
697 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__8) ? " - 8 dB" :
698 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11) ? " - 11 dB" :
699 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11_8) ? " - 11 dB postcursor with - 8 dB precursor" :
700 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL_NONE) ? " 0 dB" :
701 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__2) ? " - 2 dB" :
702 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__3) ? " - 3 dB" :
703 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__5) ? " - 5 dB" :
704 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__6) ? " - 6 dB" :
705 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__7) ? " - 7 dB" :
706 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__8) ? " - 8 dB" :
707 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__9) ? " - 9 dB" :
708 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__11) ? " - 11 dB" : "Undefined");
713 /*---------------------------------------------------------------------------------------*/
715 * Program HT Phy PCI registers which have complex frequency dependencies.
717 * @TableEntryTypeMethod{::HtPhyFreqRegister}.
719 * After matching a link for HT Features, check if the HT frequency matches the given range.
720 * If it does, get the northbridge frequency limits for implemented NB P-states and check if
721 * each matches the given range - range 0 and range 1 for each NB frequency, respectively.
722 * If all matches, apply the entry.
724 * @param[in] Entry The type specific entry data to be implemented (that is written).
725 * @param[in] PlatformConfig Config handle for platform specific information
726 * @param[in] StdHeader Config params for library, services.
730 SetRegisterForHtPhyFreqEntry (
731 IN TABLE_ENTRY_DATA *Entry,
732 IN PLATFORM_CONFIGURATION *PlatformConfig,
733 IN AMD_CONFIG_PARAMS *StdHeader
739 AGESA_STATUS IgnoredStatus;
741 CPU_LOGICAL_ID CpuFamilyRevision;
742 PCI_ADDR CapabilitySet;
743 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
744 BOOLEAN MatchedSublink1;
745 HT_FREQUENCIES Freq0;
746 HT_FREQUENCIES Freq1;
754 // Errors: extra type features, value range checks.
755 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
756 ASSERT (((Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
757 (Entry->HtPhyFreqEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
759 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
760 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
761 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
762 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
764 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
765 FamilySpecificServices,
768 &Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats,
773 // Check the HT Frequency for match to the range.
774 if (IsEitherCountInRange (
775 (MatchedSublink1 ? Freq1 : Freq0),
776 (MatchedSublink1 ? Freq1 : Freq0),
777 Entry->HtPhyFreqEntry.HtFreqCounts.HtFreqCountRanges)) {
778 // Get the NB Frequency, convert to 100's of MHz, then convert to equivalent HT encoding. This supports
779 // NB frequencies from 800 MHz to 2600 MHz, which is currently greater than any processor supports.
780 OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
789 if (OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
797 ASSERT (NbDivisor1 != 0);
798 NbFreq1 = (NbFreq1 / NbDivisor1);
799 NbFreq1 = (NbFreq1 / 100);
800 NbFreq1 = (NbFreq1 / 2) + 1;
805 ASSERT (NbDivisor0 != 0);
806 NbFreq0 = (NbFreq0 / NbDivisor0);
807 NbFreq0 = (NbFreq0 / 100);
808 NbFreq0 = (NbFreq0 / 2) + 1;
809 if (IsEitherCountInRange (NbFreq0, NbFreq1, Entry->HtPhyFreqEntry.NbFreqCounts.HtFreqCountRanges)) {
810 FamilySpecificServices->SetHtPhyRegister (
811 FamilySpecificServices,
812 &Entry->HtPhyFreqEntry.HtPhyEntry,
821 /*---------------------------------------------------------------------------------------*/
823 * Perform the Performance Profile PCI Register Entry.
825 * @TableEntryTypeMethod{::ProfileFixup}.
827 * Check the entry's performance profile features to the platform's and do the
828 * PCI register entry if they match.
830 * @param[in] Entry The Performance Profile register entry to perform
831 * @param[in] PlatformConfig Config handle for platform specific information
832 * @param[in] StdHeader Config handle for library and services.
836 SetRegisterForPerformanceProfileEntry (
837 IN TABLE_ENTRY_DATA *Entry,
838 IN PLATFORM_CONFIGURATION *PlatformConfig,
839 IN AMD_CONFIG_PARAMS *StdHeader
842 PERFORMANCE_PROFILE_FEATS PlatformProfile;
843 TABLE_ENTRY_DATA PciEntry;
845 // Errors: Possible values in unused entry space, extra type features, value range checks.
846 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
847 ASSERT (((Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
848 (Entry->InitialValues[4] == 0));
850 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
851 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
852 Entry->FixupEntry.TypeFeats.PerformanceProfileValue)) {
853 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
854 PciEntry.PciEntry = Entry->FixupEntry.PciEntry;
855 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
859 /*---------------------------------------------------------------------------------------*/
861 * Perform the HT Phy Performance Profile Register Entry.
863 * @TableEntryTypeMethod{::HtPhyProfileRegister}.
865 * @param[in] Entry The HT Phy register entry to perform
866 * @param[in] PlatformConfig Config handle for platform specific information
867 * @param[in] StdHeader Config handle for library and services.
871 SetRegisterForHtPhyProfileEntry (
872 IN TABLE_ENTRY_DATA *Entry,
873 IN PLATFORM_CONFIGURATION *PlatformConfig,
874 IN AMD_CONFIG_PARAMS *StdHeader
877 PERFORMANCE_PROFILE_FEATS PlatformProfile;
878 TABLE_ENTRY_DATA HtPhyEntry;
880 // Errors: Possible values in unused entry space, extra type features, value range checks.
881 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
882 ASSERT (((Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
883 (Entry->InitialValues[5] == 0));
885 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
886 if (DoesEntryTypeSpecificInfoMatch (
887 PlatformProfile.PerformanceProfileValue,
888 Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue)) {
889 LibAmdMemFill (&HtPhyEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
890 HtPhyEntry.HtPhyEntry = Entry->HtPhyProfileEntry.HtPhyEntry;
891 SetRegisterForHtPhyEntry (&HtPhyEntry, PlatformConfig, StdHeader);
895 /*---------------------------------------------------------------------------------------*/
897 * Perform the HT Host PCI Register Entry.
899 * @TableEntryTypeMethod{::HtHostPciRegister}.
901 * Make the current core's PCI address with the function and register for the entry.
902 * For all HT links, check the link's feature set for a match to the entry.
903 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
905 * @param[in] Entry The PCI register entry to perform
906 * @param[in] PlatformConfig Config handle for platform specific information
907 * @param[in] StdHeader Config handle for library and services.
911 SetRegisterForHtHostEntry (
912 IN TABLE_ENTRY_DATA *Entry,
913 IN PLATFORM_CONFIGURATION *PlatformConfig,
914 IN AMD_CONFIG_PARAMS *StdHeader
920 AGESA_STATUS IgnoredStatus;
922 CPU_LOGICAL_ID CpuFamilyRevision;
923 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
924 PCI_ADDR CapabilitySet;
926 HT_HOST_FEATS HtHostFeats;
929 // Errors: Possible values in unused entry space, extra type features, value range checks.
930 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
931 ASSERT ((Entry->InitialValues[4] == 0) &&
932 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
933 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
935 HtHostFeats.HtHostValue = 0;
936 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
937 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
938 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
939 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
941 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
942 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtHostEntry.TypeFeats.HtHostValue)) {
943 // Do the HT Host PCI register update.
944 PciAddress = CapabilitySet;
945 PciAddress.Address.Register += Entry->HtHostEntry.Address.Address.Register;
946 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
947 RegisterData = RegisterData & (~(Entry->HtHostEntry.Mask));
948 RegisterData = RegisterData | Entry->HtHostEntry.Data;
949 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
954 /*---------------------------------------------------------------------------------------*/
956 * Perform the HT Host Performance PCI Register Entry.
958 * @TableEntryTypeMethod{::HtHostPerfPciRegister}.
960 * Make the current core's PCI address with the function and register for the entry.
961 * For all HT links, check the link's feature set for a match to the entry.
962 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
964 * @param[in] Entry The PCI register entry to perform
965 * @param[in] PlatformConfig Config handle for platform specific information
966 * @param[in] StdHeader Config handle for library and services.
970 SetRegisterForHtHostPerfEntry (
971 IN TABLE_ENTRY_DATA *Entry,
972 IN PLATFORM_CONFIGURATION *PlatformConfig,
973 IN AMD_CONFIG_PARAMS *StdHeader
976 PERFORMANCE_PROFILE_FEATS PlatformProfile;
977 TABLE_ENTRY_DATA HtHostPciTypeEntryData;
979 // Errors: Possible values in unused entry space, extra type features, value range checks.
980 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
981 ASSERT ((Entry->InitialValues[5] == 0) &&
982 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
983 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
985 // Check for any performance profile features.
986 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
987 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
988 Entry->HtHostPerfEntry.PerformanceFeats.PerformanceProfileValue)) {
989 // Perform HT Host entry process.
990 LibAmdMemFill (&HtHostPciTypeEntryData, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
991 HtHostPciTypeEntryData.HtHostEntry = Entry->HtHostPerfEntry.HtHostEntry;
992 SetRegisterForHtHostEntry (&HtHostPciTypeEntryData, PlatformConfig, StdHeader);
996 /*---------------------------------------------------------------------------------------*/
998 * Set the HT Link Token Count registers.
1000 * @TableEntryTypeMethod{::HtTokenPciRegister}.
1002 * Make the current core's PCI address with the function and register for the entry.
1003 * Check the performance profile features.
1004 * For all HT links, check the link's feature set for a match to the entry.
1005 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
1007 * @param[in] Entry The Link Token register entry to perform
1008 * @param[in] PlatformConfig Config handle for platform specific information
1009 * @param[in] StdHeader Config handle for library and services.
1013 SetRegisterForHtLinkTokenEntry (
1014 IN TABLE_ENTRY_DATA *Entry,
1015 IN PLATFORM_CONFIGURATION *PlatformConfig,
1016 IN AMD_CONFIG_PARAMS *StdHeader
1022 AGESA_STATUS IgnoredStatus;
1024 CPU_LOGICAL_ID CpuFamilyRevision;
1025 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1026 PCI_ADDR CapabilitySet;
1027 HT_HOST_FEATS HtHostFeats;
1028 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1029 UINTN ProcessorCount;
1031 UINT32 RegisterData;
1032 PCI_ADDR PciAddress;
1034 // Errors: Possible values in unused entry space, extra type features, value range checks.
1035 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1036 ASSERT (((Entry->HtTokenEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
1037 ((Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
1038 (Entry->HtTokenEntry.Mask != 0));
1040 HtHostFeats.HtHostValue = 0;
1041 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1042 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1043 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1044 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1046 // Check if the actual processor count and SystemDegree are in either range.
1047 ProcessorCount = GetNumberOfProcessors (StdHeader);
1048 SystemDegree = GetSystemDegree (StdHeader);
1049 if (IsEitherCountInRange (ProcessorCount, SystemDegree, Entry->HtTokenEntry.ConnectivityCount.ConnectivityCountRanges)) {
1050 // Check for any performance profile features.
1051 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1052 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
1053 Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue)) {
1054 // Check the link features.
1056 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1057 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtTokenEntry.LinkFeats.HtHostValue)) {
1058 // Do the HT Host PCI register update. Token register are four registers, sublink 0 and 1 share fields.
1059 // If sublink 0 is unconnected, we should let sublink 1 match. If the links are ganged, of course only sublink 0 matches.
1060 // If the links are unganged and both connected, the BKDG settings are for both coherent.
1061 PciAddress = CapabilitySet;
1062 PciAddress.Address.Register = Entry->HtTokenEntry.Address.Address.Register +
1063 ((Link > 3) ? (((UINT32)Link - 4) * 4) : ((UINT32)Link * 4));
1064 PciAddress.Address.Function = Entry->HtTokenEntry.Address.Address.Function;
1065 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
1066 RegisterData = RegisterData & (~(Entry->HtTokenEntry.Mask));
1067 RegisterData = RegisterData | Entry->HtTokenEntry.Data;
1068 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
1075 /*---------------------------------------------------------------------------------------*/
1077 * Perform the Core Counts Performance PCI Register Entry.
1079 * @TableEntryTypeMethod{::CoreCountsPciRegister}.
1081 * Check the performance profile.
1082 * Check the actual core count to the range pair given, and apply if matched.
1084 * @param[in] Entry The PCI register entry to perform
1085 * @param[in] PlatformConfig Config handle for platform specific information
1086 * @param[in] StdHeader Config handle for library and services.
1090 SetRegisterForCoreCountsPerformanceEntry (
1091 IN TABLE_ENTRY_DATA *Entry,
1092 IN PLATFORM_CONFIGURATION *PlatformConfig,
1093 IN AMD_CONFIG_PARAMS *StdHeader
1096 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1097 UINTN ActualCoreCount;
1098 TABLE_ENTRY_DATA PciEntry;
1100 // Errors: Possible values in unused entry space, extra type features, value range checks.
1101 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1102 ASSERT (((Entry->CoreCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1104 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1105 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->CoreCountEntry.TypeFeats.PerformanceProfileValue)) {
1106 ActualCoreCount = GetActiveCoresInCurrentModule (StdHeader);
1107 // Check if the actual core count is in either range.
1108 if (IsEitherCountInRange (ActualCoreCount, ActualCoreCount, Entry->CoreCountEntry.CoreCounts.CoreRanges)) {
1109 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1110 PciEntry.PciEntry = Entry->CoreCountEntry.PciEntry;
1111 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1116 /*---------------------------------------------------------------------------------------*/
1118 * Perform the Processor Counts PCI Register Entry.
1120 * @TableEntryTypeMethod{::ProcCountsPciRegister}.
1122 * Check the performance profile.
1123 * Check the actual processor count (not node count!) to the range pair given, and apply if matched.
1125 * @param[in] Entry The PCI register entry to perform
1126 * @param[in] PlatformConfig Config handle for platform specific information
1127 * @param[in] StdHeader Config handle for library and services.
1131 SetRegisterForProcessorCountsEntry (
1132 IN TABLE_ENTRY_DATA *Entry,
1133 IN PLATFORM_CONFIGURATION *PlatformConfig,
1134 IN AMD_CONFIG_PARAMS *StdHeader
1137 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1138 UINTN ProcessorCount;
1139 TABLE_ENTRY_DATA PciEntry;
1141 // Errors: Possible values in unused entry space, extra type features, value range checks.
1142 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1143 ASSERT (((Entry->ProcCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1145 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1146 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->ProcCountEntry.TypeFeats.PerformanceProfileValue)) {
1147 ProcessorCount = GetNumberOfProcessors (StdHeader);
1148 // Check if the actual processor count is in either range.
1149 if (IsEitherCountInRange (ProcessorCount, ProcessorCount, Entry->ProcCountEntry.ProcessorCounts.ProcessorCountRanges)) {
1150 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1151 PciEntry.PciEntry = Entry->ProcCountEntry.PciEntry;
1152 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1157 /*---------------------------------------------------------------------------------------*/
1159 * Perform the Compute Unit Counts PCI Register Entry.
1161 * @TableEntryTypeMethod{::CompUnitCountsPciRegister}.
1163 * Check the entry's performance profile features and the compute unit count
1164 * to the platform's and do the PCI register entry if they match.
1166 * @param[in] Entry The PCI register entry to perform
1167 * @param[in] PlatformConfig Config handle for platform specific information
1168 * @param[in] StdHeader Config handle for library and services.
1172 SetRegisterForComputeUnitCountsEntry (
1173 IN TABLE_ENTRY_DATA *Entry,
1174 IN PLATFORM_CONFIGURATION *PlatformConfig,
1175 IN AMD_CONFIG_PARAMS *StdHeader
1178 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1179 UINTN ComputeUnitCount;
1180 TABLE_ENTRY_DATA PciEntry;
1182 // Errors: Possible values in unused entry space, extra type features, value range checks.
1183 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1184 ASSERT (((Entry->CompUnitCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1186 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1187 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->CompUnitCountEntry.TypeFeats.PerformanceProfileValue)) {
1188 ComputeUnitCount = GetNumberOfCompUnitsInCurrentModule (StdHeader);
1189 // Check if the actual compute unit count is in either range.
1190 if (IsEitherCountInRange (ComputeUnitCount, ComputeUnitCount, Entry->CompUnitCountEntry.ComputeUnitCounts.ComputeUnitRanges)) {
1191 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1192 PciEntry.PciEntry = Entry->CompUnitCountEntry.PciEntry;
1193 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1198 /*---------------------------------------------------------------------------------------*/
1200 * Perform the Compute Unit Counts MSR Register Entry.
1202 * @TableEntryTypeMethod{::CompUnitCountsMsr}.
1204 * Check the entry's compute unit count to the platform's and do the
1205 * MSR entry if they match.
1207 * @param[in] Entry The PCI register entry to perform
1208 * @param[in] PlatformConfig Config handle for platform specific information
1209 * @param[in] StdHeader Config handle for library and services.
1213 SetMsrForComputeUnitCountsEntry (
1214 IN TABLE_ENTRY_DATA *Entry,
1215 IN PLATFORM_CONFIGURATION *PlatformConfig,
1216 IN AMD_CONFIG_PARAMS *StdHeader
1219 UINTN ComputeUnitCount;
1220 TABLE_ENTRY_DATA MsrEntry;
1222 ComputeUnitCount = GetNumberOfCompUnitsInCurrentModule (StdHeader);
1223 // Check if the actual compute unit count is in either range.
1224 if (IsEitherCountInRange (ComputeUnitCount, ComputeUnitCount, Entry->CompUnitCountMsrEntry.ComputeUnitCounts.ComputeUnitRanges)) {
1225 LibAmdMemFill (&MsrEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1226 MsrEntry.MsrEntry = Entry->CompUnitCountMsrEntry.MsrEntry;
1227 SetRegisterForMsrEntry (&MsrEntry, PlatformConfig, StdHeader);
1231 /*---------------------------------------------------------------------------------------*/
1233 * Perform the Processor Token Counts PCI Register Entry.
1235 * @TableEntryTypeMethod{::TokenPciRegister}.
1237 * The table criteria then translate as:
1238 * - 2 Socket, half populated == Degree 1
1239 * - 4 Socket, half populated == Degree 2
1240 * - 2 Socket, fully populated == Degree 3
1241 * - 4 Socket, fully populated == Degree > 3. (4 or 5 if 3P, 6 if 4P)
1243 * @param[in] Entry The PCI register entry to perform
1244 * @param[in] PlatformConfig Config handle for platform specific information
1245 * @param[in] StdHeader Config handle for library and services.
1249 SetRegisterForTokenPciEntry (
1250 IN TABLE_ENTRY_DATA *Entry,
1251 IN PLATFORM_CONFIGURATION *PlatformConfig,
1252 IN AMD_CONFIG_PARAMS *StdHeader
1255 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1257 TABLE_ENTRY_DATA PciEntry;
1259 // Errors: Possible values in unused entry space, extra type features, value range checks.
1260 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1261 ASSERT (((Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1263 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1264 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue)) {
1265 SystemDegree = GetSystemDegree (StdHeader);
1266 // Check if the system degree is in the range.
1267 if (IsEitherCountInRange (SystemDegree, SystemDegree, Entry->TokenPciEntry.ConnectivityCount.ConnectivityCountRanges)) {
1268 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1269 PciEntry.PciEntry = Entry->TokenPciEntry.PciEntry;
1270 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1275 /*---------------------------------------------------------------------------------------*/
1277 * Perform the HT Link Feature PCI Register Entry.
1279 * @TableEntryTypeMethod{::HtFeatPciRegister}.
1281 * Set a single field (that is, the register field is not in HT Host capability or a
1282 * set of per link registers) in PCI config, based on HT link features and package type.
1283 * This code is used for two cases: single link processors and multilink processors.
1284 * For single link cases, the link will be tested for a match to the HT Features for the link.
1285 * For multilink processors, the entry will match if @b any link is found which matches.
1286 * For example, a setting can be applied based on coherent HT3 by matching coherent AND HT3.
1288 * Make the core's PCI address. Check the package type (currently more important to the single link case),
1289 * and if matching, iterate through all links checking for an HT feature match until found or exhausted.
1290 * If a match was found, pass the PCI entry data to the implementer for writing for the current core.
1292 * @param[in] Entry The PCI register entry to perform
1293 * @param[in] PlatformConfig Config handle for platform specific information
1294 * @param[in] StdHeader Config handle for library and services.
1298 SetRegisterForHtFeaturePciEntry (
1299 IN TABLE_ENTRY_DATA *Entry,
1300 IN PLATFORM_CONFIGURATION *PlatformConfig,
1301 IN AMD_CONFIG_PARAMS *StdHeader
1307 AGESA_STATUS IgnoredStatus;
1309 CPU_LOGICAL_ID CpuFamilyRevision;
1310 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1311 PCI_ADDR CapabilitySet;
1312 HT_HOST_FEATS HtHostFeats;
1313 UINT32 ProcessorPackageType;
1315 TABLE_ENTRY_DATA PciEntry;
1317 // Errors: Possible values in unused entry space, extra type features, value range checks.
1318 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1319 ASSERT ((Entry->HtFeatPciEntry.PciEntry.Mask != 0) &&
1320 ((Entry->HtFeatPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
1322 HtHostFeats.HtHostValue = 0;
1323 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1324 PciEntry.PciEntry = Entry->HtFeatPciEntry.PciEntry;
1325 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1326 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1327 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1328 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1330 ASSERT ((Entry->HtFeatPciEntry.PackageType.PackageTypeValue & ~(PACKAGE_TYPE_ALL)) == 0);
1332 ProcessorPackageType = LibAmdGetPackageType (StdHeader);
1333 if (DoesEntryTypeSpecificInfoMatch (ProcessorPackageType, Entry->HtFeatPciEntry.PackageType.PackageTypeValue)) {
1335 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1336 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtFeatPciEntry.LinkFeats.HtHostValue)) {
1342 // Do the PCI register update.
1343 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1348 /*---------------------------------------------------------------------------------------*/
1350 * Perform the HT Link PCI Register Entry.
1352 * @TableEntryTypeMethod{::HtLinkPciRegister}.
1354 * Make the current core's PCI address with the function and register for the entry.
1355 * Registers are processed for match per link, assuming sequential PCI address per link.
1356 * Read - Modify - Write each matching link's PCI register, clearing masked bits, and setting the data bits.
1358 * @param[in] Entry The PCI register entry to perform
1359 * @param[in] PlatformConfig Config handle for platform specific information
1360 * @param[in] StdHeader Config handle for library and services.
1364 SetRegisterForHtLinkPciEntry (
1365 IN TABLE_ENTRY_DATA *Entry,
1366 IN PLATFORM_CONFIGURATION *PlatformConfig,
1367 IN AMD_CONFIG_PARAMS *StdHeader
1373 AGESA_STATUS IgnoredStatus;
1375 CPU_LOGICAL_ID CpuFamilyRevision;
1376 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1377 PCI_ADDR CapabilitySet;
1378 HT_HOST_FEATS HtHostFeats;
1379 TABLE_ENTRY_DATA PciEntry;
1381 // Errors: Possible values in unused entry space, extra type features, value range checks.
1382 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1383 ASSERT ((Entry->HtLinkPciEntry.PciEntry.Mask != 0) &&
1384 ((Entry->HtLinkPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
1386 HtHostFeats.HtHostValue = 0;
1387 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1388 PciEntry.PciEntry = Entry->HtLinkPciEntry.PciEntry;
1389 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1390 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1391 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1392 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1395 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1396 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtLinkPciEntry.LinkFeats.HtHostValue)) {
1397 // Do the update to the link's non-Host PCI register, based on the entry address.
1398 PciEntry.PciEntry.Address = Entry->HtLinkPciEntry.PciEntry.Address;
1399 PciEntry.PciEntry.Address.Address.Register = PciEntry.PciEntry.Address.Address.Register + ((UINT32)Link * 4);
1400 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1405 /* -----------------------------------------------------------------------------*/
1407 * Returns the platform features list of the currently running processor core.
1409 * @param[out] Features The Features supported by this platform
1410 * @param[in] PlatformConfig Config handle for platform specific information
1411 * @param[in] StdHeader Header for library and services
1415 GetPlatformFeatures (
1416 OUT PLATFORM_FEATS *Features,
1417 IN PLATFORM_CONFIGURATION *PlatformConfig,
1418 IN AMD_CONFIG_PARAMS *StdHeader
1421 PCI_ADDR PciAddress;
1422 UINT32 CapabilityReg;
1424 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1428 Features->PlatformValue = 0;
1430 switch (PlatformConfig->PlatformProfile.PlatformControlFlowMode) {
1432 Features->PlatformFeatures.PlatformNfcm = 1;
1435 Features->PlatformFeatures.PlatformUma = 1;
1438 Features->PlatformFeatures.PlatformUmaIfcm = 1;
1441 Features->PlatformFeatures.PlatformIfcm = 1;
1444 Features->PlatformFeatures.PlatformIommu = 1;
1449 // Check - Single Link?
1450 // This is based on the implemented links on the package regardless of their
1451 // connection status. All processors must match the BSP, so we only check it and
1452 // not the current node. We don't care exactly how many links there are, as soon
1453 // as we find more than one we are done.
1455 PciAddress.AddressValue = MAKE_SBDFO (0, 0, PCI_DEV_BASE, FUNC_0, 0);
1456 // Until either all capabilities are done or until the desired link is found,
1457 // keep looking for HT Host Capabilities.
1459 LibAmdPciFindNextCap (&PciAddress, StdHeader);
1460 if (PciAddress.AddressValue != ILLEGAL_SBDFO) {
1461 LibAmdPciRead (AccessWidth32, PciAddress, &CapabilityReg, StdHeader);
1462 if ((CapabilityReg & 0xE00000FF) == 0x20000008) {
1465 // A capability other than an HT capability, keep looking.
1467 // end of capabilities
1472 Features->PlatformFeatures.PlatformSingleLink = 1;
1474 Features->PlatformFeatures.PlatformMultiLink = 1;
1477 // Set the legacy core count bits.
1478 GetActiveCoresInCurrentSocket (&CoreCount, StdHeader);
1479 switch (CoreCount) {
1481 Features->PlatformFeatures.PlatformSingleCore = 1;
1484 Features->PlatformFeatures.PlatformDualCore = 1;
1487 Features->PlatformFeatures.PlatformMultiCore = 1;
1491 // Get some specific platform type info, VC...etc.
1493 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1494 ASSERT (FamilySpecificServices != NULL);
1495 FamilySpecificServices->GetPlatformTypeSpecificInfo (FamilySpecificServices, Features, StdHeader);
1499 /*---------------------------------------------------------------------------------------*/
1501 * Checks if a register table entry applies to the executing core.
1503 * This function uses a combination of logical ID and platform features to
1504 * determine whether or not a register table entry applies to the executing core.
1506 * @param[in] CoreCpuRevision The current core's logical ID
1507 * @param[in] EntryCpuRevision The entry's desired logical IDs
1508 * @param[in] PlatformFeatures The platform features
1509 * @param[in] EntryFeatures The entry's desired platform features
1511 * @retval TRUE This entry should be applied
1512 * @retval FALSE This entry does not apply
1517 DoesEntryMatchPlatform (
1518 IN CPU_LOGICAL_ID CoreCpuRevision,
1519 IN CPU_LOGICAL_ID EntryCpuRevision,
1520 IN PLATFORM_FEATS PlatformFeatures,
1521 IN PLATFORM_FEATS EntryFeatures
1528 if (((CoreCpuRevision.Family & EntryCpuRevision.Family) != 0) &&
1529 ((CoreCpuRevision.Revision & EntryCpuRevision.Revision) != 0)) {
1530 if (EntryFeatures.PlatformFeatures.AndPlatformFeats == 0) {
1531 // Match if ANY entry feats match a platform feat (an OR test)
1532 if ((EntryFeatures.PlatformValue & PlatformFeatures.PlatformValue) != 0) {
1536 // Match if ALL entry feats match a platform feat (an AND test)
1537 if ((EntryFeatures.PlatformValue & ~(AMD_PF_AND)) ==
1538 (EntryFeatures.PlatformValue & PlatformFeatures.PlatformValue)) {
1547 /*---------------------------------------------------------------------------------------*/
1549 * Checks register table entry type specific criteria to the platform.
1551 * Entry Data Type implementer methods can use this generically to check their own
1552 * specific criteria. The method collects the actual platform characteristics and
1553 * provides them along with the table entry's criteria to this service.
1555 * There are a couple considerations for any implementer method using this service.
1556 * The criteria value has to be representable as a UINT32. The MSB, Bit 31, has to
1557 * be used as a AND test request if set in the entry. (The platform value should never
1558 * have that bit set.)
1560 * @param[in] PlatformTypeSpecificFeatures The platform features
1561 * @param[in] EntryTypeFeatures The entry's desired platform features
1563 * @retval TRUE This entry should be applied
1564 * @retval FALSE This entry does not apply
1568 DoesEntryTypeSpecificInfoMatch (
1569 IN UINT32 PlatformTypeSpecificFeatures,
1570 IN UINT32 EntryTypeFeatures
1577 if ((EntryTypeFeatures & BIT31) == 0) {
1578 // Match if ANY entry feats match a platform feat (an OR test)
1579 if ((EntryTypeFeatures & PlatformTypeSpecificFeatures) != 0) {
1583 // Match if ALL entry feats match a platform feat (an AND test)
1584 if ((EntryTypeFeatures & ~(BIT31)) == (EntryTypeFeatures & PlatformTypeSpecificFeatures)) {
1591 /*---------------------------------------------------------------------------------------*/
1593 * Determine this core's Selector matches.
1595 * @param[in] Selector Is the current core this selector type?
1596 * @param[in] StdHeader Config handle for library and services.
1598 * @retval TRUE Yes, it is.
1599 * @retval FALSE No, it is not.
1604 IN TABLE_CORE_SELECTOR Selector,
1605 IN AMD_CONFIG_PARAMS *StdHeader
1609 AGESA_STATUS CalledStatus;
1612 ASSERT (Selector < TableCoreSelectorMax);
1614 if ((Selector == PrimaryCores) && !IsCurrentCorePrimary (StdHeader)) {
1617 if ((Selector == CorePairPrimary) && !IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader)) {
1620 if ((Selector == BscCore) && (!IsBsp (StdHeader, &CalledStatus))) {
1626 /*---------------------------------------------------------------------------------------*/
1628 * Set the registers for this core based on entries in a list of Register Tables.
1630 * Determine the platform features and this core's logical id. Get the specific table
1631 * entry type implementations for the logical model, which may be either generic (the ones
1632 * in this file) or specific.
1634 * Scan the tables starting the with ones for all cores and progressively narrowing the selection
1635 * based on this core's role (ex. primary core). For a selected table, check for each entry
1636 * matching the current core and platform, and call the implementer method to perform the
1637 * register set operation if it matches.
1639 * @param[in] PlatformConfig Config handle for platform specific information
1640 * @param[in] StdHeader Config handle for library and services.
1644 SetRegistersFromTables (
1645 IN PLATFORM_CONFIGURATION *PlatformConfig,
1646 IN AMD_CONFIG_PARAMS *StdHeader
1649 CPU_LOGICAL_ID CpuLogicalId;
1650 PLATFORM_FEATS PlatformFeatures;
1651 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1652 TABLE_ENTRY_FIELDS *Entries;
1653 TABLE_CORE_SELECTOR Selector;
1654 TABLE_ENTRY_TYPE EntryType;
1655 REGISTER_TABLE **TableHandle;
1656 UINTN NumberOfEntries;
1657 UINTN CurrentEntryCount;
1658 TABLE_ENTRY_TYPE_DESCRIPTOR *TypeImplementer;
1659 PF_DO_TABLE_ENTRY DoTableEntry[TableEntryTypeMax];
1661 // Did you really mean to increase the size of ALL table entries??!!
1662 // While it is not necessarily a bug to increase the size of table entries:
1663 // - Is this warning a surprise? Please fix it.
1664 // - If expected, is this really a feature which is worth the increase? Then let other entries also use the space.
1665 ASSERT (sizeof (TABLE_ENTRY_DATA) == (MAX_ENTRY_TYPE_ITEMS32 * sizeof (UINT32)));
1667 PlatformFeatures.PlatformValue = 0;
1668 GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
1669 GetPlatformFeatures (&PlatformFeatures, PlatformConfig, StdHeader);
1670 GetCpuServicesFromLogicalId (&CpuLogicalId, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1672 // Build a non-sparse table of implementer methods, so we don't have to keep searching.
1673 // It is a bug to not include a descriptor for a type that is in the table (but the
1674 // descriptor can point to a non-assert stub).
1675 // Also, it is not a bug to have no register table implementations, but it is a bug to have none and call this routine.
1676 for (EntryType = MsrRegister; EntryType < TableEntryTypeMax; EntryType++) {
1677 DoTableEntry[EntryType] = (PF_DO_TABLE_ENTRY)CommonAssert;
1679 TypeImplementer = FamilySpecificServices->TableEntryTypeDescriptors;
1680 ASSERT (TypeImplementer != NULL);
1681 while (TypeImplementer->EntryType < TableEntryTypeMax) {
1682 DoTableEntry[TypeImplementer->EntryType] = TypeImplementer->DoTableEntry;
1686 for (Selector = AllCores; Selector < TableCoreSelectorMax; Selector++) {
1687 if (IsCoreSelector (Selector, StdHeader)) {
1688 // If the current core is the selected type of core, work the table list for tables for that type of core.
1690 Entries = GetNextRegisterTable (FamilySpecificServices, Selector, &TableHandle, &NumberOfEntries, StdHeader);
1691 while (Entries != NULL) {
1692 for (CurrentEntryCount = 0; CurrentEntryCount < NumberOfEntries; CurrentEntryCount++, Entries++) {
1693 if (DoesEntryMatchPlatform (CpuLogicalId, Entries->CpuRevision, PlatformFeatures, Entries->Features)) {
1694 // The entry matches this config, Do It!
1695 // Find the implementer for this entry type and pass the entry data to it.
1696 ASSERT (Entries->EntryType < TableEntryTypeMax);
1697 DoTableEntry[Entries->EntryType] (&Entries->Entry, PlatformConfig, StdHeader);
1700 Entries = GetNextRegisterTable (FamilySpecificServices, Selector, &TableHandle, &NumberOfEntries, StdHeader);
1703 // Once a selector does not match the current core, quit looking.
1709 /*---------------------------------------------------------------------------------------*/
1711 * Set the registers for this core based on entries in a list of Register Tables.
1713 * This function acts as a wrapper for calling the SetRegistersFromTables
1714 * routine at AmdInitEarly.
1716 * @param[in] FamilyServices The current Family Specific Services.
1717 * @param[in] EarlyParams Service parameters.
1718 * @param[in] StdHeader Config handle for library and services.
1722 SetRegistersFromTablesAtEarly (
1723 IN CPU_SPECIFIC_SERVICES *FamilyServices,
1724 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
1725 IN AMD_CONFIG_PARAMS *StdHeader
1728 AGESA_TESTPOINT (TpProcCpuProcessRegisterTables, StdHeader);
1729 SetRegistersFromTables (&EarlyParams->PlatformConfig, StdHeader);