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: 59564 $ @e \$Date: 2011-09-26 12:33:51 -0600 (Mon, 26 Sep 2011) $
16 ******************************************************************************
18 * Copyright (C) 2012 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 ******************************************************************************
46 /*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
54 #include "OptionMultiSocket.h"
55 #include "cpuRegisters.h"
56 #include "cpuFamilyTranslation.h"
58 #include "GeneralServices.h"
59 #include "cpuServices.h"
60 #include "cpuFeatures.h"
61 #include "CommonReturns.h"
62 #include "cpuL3Features.h"
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 SetRegistersFromTablesAtEarly (
87 IN CPU_SPECIFIC_SERVICES *FamilyServices,
88 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
89 IN AMD_CONFIG_PARAMS *StdHeader
92 /*----------------------------------------------------------------------------------------
93 * E X P O R T E D F U N C T I O N S
94 *----------------------------------------------------------------------------------------
96 extern BUILD_OPT_CFG UserOptions;
97 extern CPU_FAMILY_SUPPORT_TABLE L3FeatureFamilyServiceTable;
99 /*---------------------------------------------------------------------------------------*/
101 * An iterator for all the Family and Model Register Tables.
103 * RegisterTableHandle should be set to NULL to begin iteration, the first time the method is
104 * invoked. Register tables can be processed, until this method returns NULL. RegisterTableHandle
105 * should simply be passed back to the method without modification or use by the caller.
106 * The table selector allows the relevant tables for different cores to be iterated, if the family separates
107 * tables. For example, MSRs can be in a table processed by all cores and PCI registers in a table processed by
110 * @param[in] FamilySpecificServices The current Family Specific Services.
111 * @param[in] Selector Select whether to iterate over tables for either all cores, primary cores, bsp, ....
112 * @param[in,out] RegisterTableHandle IN: The handle of the current register table, or NULL if Begin.
113 * OUT: The handle of the next register table, if not End.
114 * @param[out] NumberOfEntries The number of entries in the table returned, if not End.
115 * @param[in] StdHeader Handle of Header for calling lib functions and services.
117 * @return The pointer to the next Register Table, or NULL if End.
121 *GetNextRegisterTable (
122 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
123 IN TABLE_CORE_SELECTOR Selector,
124 IN OUT REGISTER_TABLE ***RegisterTableHandle,
125 OUT UINTN *NumberOfEntries,
126 IN AMD_CONFIG_PARAMS *StdHeader
129 REGISTER_TABLE **NextTable;
130 TABLE_ENTRY_FIELDS *Entries;
132 ASSERT ((FamilySpecificServices != NULL) && (StdHeader != NULL));
133 ASSERT (Selector < TableCoreSelectorMax);
135 NextTable = *RegisterTableHandle;
136 if (NextTable == NULL) {
138 NextTable = FamilySpecificServices->RegisterTableList;
139 IDS_OPTION_HOOK (IDS_REG_TABLE, &NextTable, StdHeader);
143 // skip if not selected
144 while ((*NextTable != NULL) && (*NextTable)->Selector != Selector) {
147 if (*NextTable == NULL) {
149 *RegisterTableHandle = NULL;
152 // Iterate next table
153 *RegisterTableHandle = NextTable;
154 *NumberOfEntries = (*NextTable)->NumberOfEntries;
155 Entries = (TABLE_ENTRY_FIELDS *) (*NextTable)->Table;
160 /*---------------------------------------------------------------------------------------*/
162 * Compare counts to a pair of ranges.
164 * @param[in] FirstCount The actual count to be compared to the first range.
165 * @param[in] SecondCount The actual count to be compared to the second range.
166 * @param[in] Ranges The ranges which the counts are compared to.
168 * @retval TRUE Either one, or both, of the counts is in the range given.
169 * @retval FALSE Neither count is in the range given.
172 IsEitherCountInRange (
174 IN UINTN SecondCount,
175 IN COUNT_RANGE_FEATURE Ranges
178 // Errors: Entire Range value is zero, Min and Max reversed or not <=, ranges overlap (OK if first range is all),
179 // the real counts are too big.
180 ASSERT ((Ranges.Range0Min <= Ranges.Range0Max) &&
181 (Ranges.Range1Min <= Ranges.Range1Max) &&
182 (Ranges.Range0Max != 0) &&
183 (Ranges.Range1Max != 0) &&
184 ((Ranges.Range0Max == COUNT_RANGE_HIGH) || (Ranges.Range0Max < Ranges.Range1Min)) &&
185 ((FirstCount < COUNT_RANGE_HIGH) && (SecondCount < COUNT_RANGE_HIGH)));
187 return (BOOLEAN) (((FirstCount <= Ranges.Range0Max) && (FirstCount >= Ranges.Range0Min)) ||
188 ((SecondCount <= Ranges.Range1Max) && (SecondCount >= Ranges.Range1Min)));
191 /*-------------------------------------------------------------------------------------*/
193 * Returns the performance profile features list of the currently running processor core.
195 * @param[out] Features The performance profile features supported by this platform
196 * @param[in] PlatformConfig Config handle for platform specific information
197 * @param[in] StdHeader Header for library and services
201 GetPerformanceFeatures (
202 OUT PERFORMANCE_PROFILE_FEATS *Features,
203 IN PLATFORM_CONFIGURATION *PlatformConfig,
204 IN AMD_CONFIG_PARAMS *StdHeader
207 CPUID_DATA CpuidDataStruct;
208 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
209 L3_FEATURE_FAMILY_SERVICES *FeatureFamilyServices;
211 Features->PerformanceProfileValue = 0;
212 // Reflect Probe Filter Configuration.
213 Features->PerformanceProfileFeatures.ProbeFilter = 0;
214 if (IsFeatureEnabled (L3Features, PlatformConfig, StdHeader)) {
215 GetFeatureServicesOfCurrentCore (&L3FeatureFamilyServiceTable, (CONST VOID **)&FeatureFamilyServices, StdHeader);
216 if ((FeatureFamilyServices != NULL) &&
217 (FeatureFamilyServices->IsHtAssistSupported (FeatureFamilyServices, PlatformConfig, StdHeader))) {
218 Features->PerformanceProfileFeatures.ProbeFilter = 1;
222 // Reflect Display Refresh Requests use 32 bytes Configuration.
223 Features->PerformanceProfileFeatures.RefreshRequest32Byte = 0;
224 if (PlatformConfig->PlatformProfile.Use32ByteRefresh) {
225 Features->PerformanceProfileFeatures.RefreshRequest32Byte = 1;
227 // Reflect Mct Isoc Read Priority set to variable Configuration.
228 Features->PerformanceProfileFeatures.MctIsocVariable = 0;
229 if (PlatformConfig->PlatformProfile.UseVariableMctIsocPriority) {
230 Features->PerformanceProfileFeatures.MctIsocVariable = 1;
232 // Indicate if this boot is a warm reset.
233 Features->PerformanceProfileFeatures.IsWarmReset = 0;
234 if (IsWarmReset (StdHeader)) {
235 Features->PerformanceProfileFeatures.IsWarmReset = 1;
238 // Get L3 Cache present as indicated by CPUID
239 Features->PerformanceProfileFeatures.L3Cache = 0;
240 Features->PerformanceProfileFeatures.NoL3Cache = 1;
241 LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuidDataStruct, StdHeader);
242 if (((CpuidDataStruct.EDX_Reg & 0xFFFC0000) >> 18) != 0) {
243 Features->PerformanceProfileFeatures.L3Cache = 1;
244 Features->PerformanceProfileFeatures.NoL3Cache = 0;
247 // Get VRM select high speed from build option.
248 Features->PerformanceProfileFeatures.VrmHighSpeed = 0;
249 if (PlatformConfig->VrmProperties[CoreVrm].HiSpeedEnable) {
250 Features->PerformanceProfileFeatures.VrmHighSpeed = 1;
253 // Get some family, model specific performance type info.
254 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
255 ASSERT (FamilySpecificServices != NULL);
257 // Is the Northbridge P-State feature enabled
258 Features->PerformanceProfileFeatures.NbPstates = 0;
259 if (FamilySpecificServices->IsNbPstateEnabled (FamilySpecificServices, PlatformConfig, StdHeader)) {
260 Features->PerformanceProfileFeatures.NbPstates = 1;
264 /*---------------------------------------------------------------------------------------*/
266 * Perform the MSR Register Entry.
268 * @TableEntryTypeMethod{::MsrRegister}.
270 * Read - Modify - Write the MSR, clearing masked bits, and setting the data bits.
272 * @param[in] Entry The MSR register entry to perform
273 * @param[in] PlatformConfig Config handle for platform specific information
274 * @param[in] StdHeader Config handle for library and services.
278 SetRegisterForMsrEntry (
279 IN TABLE_ENTRY_DATA *Entry,
280 IN PLATFORM_CONFIGURATION *PlatformConfig,
281 IN AMD_CONFIG_PARAMS *StdHeader
286 // Even for only single bit fields, use those in the mask. "Mask nothing" is a bug, even if just by policy.
287 ASSERT (Entry->MsrEntry.Mask != 0);
289 LibAmdMsrRead (Entry->MsrEntry.Address, &MsrData, StdHeader);
290 MsrData = MsrData & (~(Entry->MsrEntry.Mask));
291 MsrData = MsrData | Entry->MsrEntry.Data;
292 LibAmdMsrWrite (Entry->MsrEntry.Address, &MsrData, StdHeader);
295 /*---------------------------------------------------------------------------------------*/
297 * Perform the PCI Register Entry.
299 * @TableEntryTypeMethod{::PciRegister}.
301 * Make the current core's PCI address with the function and register for the entry.
302 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
304 * @param[in] Entry The PCI register entry to perform
305 * @param[in] PlatformConfig Config handle for platform specific information
306 * @param[in] StdHeader Config handle for library and services.
310 SetRegisterForPciEntry (
311 IN TABLE_ENTRY_DATA *Entry,
312 IN PLATFORM_CONFIGURATION *PlatformConfig,
313 IN AMD_CONFIG_PARAMS *StdHeader
320 PCI_ADDR MyPciAddress;
321 AGESA_STATUS IgnoredSts;
322 TABLE_ENTRY_DATA PciEntry;
324 // Errors: Possible values in unused entry space, extra type features, value range checks.
325 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
326 // Even for only single bit fields, use those in the mask. "Mask nothing" is a bug, even if just by policy.
327 ASSERT ((Entry->InitialValues[4] == 0) &&
328 (Entry->InitialValues[3] == 0) &&
329 (Entry->PciEntry.Mask != 0));
331 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
332 PciEntry.PciEntry = Entry->PciEntry;
334 IDS_OPTION_HOOK (IDS_SET_PCI_REGISTER_ENTRY, &PciEntry, StdHeader);
336 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredSts);
337 GetPciAddress (StdHeader, MySocket, MyModule, &MyPciAddress, &IgnoredSts);
338 MyPciAddress.Address.Function = PciEntry.PciEntry.Address.Address.Function;
339 MyPciAddress.Address.Register = PciEntry.PciEntry.Address.Address.Register;
340 LibAmdPciRead (AccessWidth32, MyPciAddress, &TempVar32_a, StdHeader);
341 TempVar32_a = TempVar32_a & (~(PciEntry.PciEntry.Mask));
342 TempVar32_a = TempVar32_a | PciEntry.PciEntry.Data;
343 LibAmdPciWrite (AccessWidth32, MyPciAddress, &TempVar32_a, StdHeader);
346 /*---------------------------------------------------------------------------------------*/
348 * Perform the Family Specific Workaround Register Entry.
350 * @TableEntryTypeMethod{::FamSpecificWorkaround}.
352 * Call the function, passing the data.
354 * See if you can use the other entries or make an entry that covers the fix.
355 * After all, the purpose of having a table entry is to @b NOT have code which
356 * isn't generic feature code, but is family/model code specific to one case.
358 * @param[in] Entry The Family Specific Workaround register entry to perform
359 * @param[in] PlatformConfig Config handle for platform specific information
360 * @param[in] StdHeader Config handle for library and services.
364 SetRegisterForFamSpecificWorkaroundEntry (
365 IN TABLE_ENTRY_DATA *Entry,
366 IN PLATFORM_CONFIGURATION *PlatformConfig,
367 IN AMD_CONFIG_PARAMS *StdHeader
370 ASSERT (Entry->FamSpecificEntry.DoAction != NULL);
372 Entry->FamSpecificEntry.DoAction (Entry->FamSpecificEntry.Data, StdHeader);
375 /*---------------------------------------------------------------------------------------*/
377 * Program HT Phy PCI registers using BKDG values.
379 * @TableEntryTypeMethod{::HtPhyRegister}.
382 * @param[in] Entry The type specific entry data to be implemented (that is written).
383 * @param[in] PlatformConfig Config handle for platform specific information
384 * @param[in] StdHeader Config params for library, services.
388 SetRegisterForHtPhyEntry (
389 IN TABLE_ENTRY_DATA *Entry,
390 IN PLATFORM_CONFIGURATION *PlatformConfig,
391 IN AMD_CONFIG_PARAMS *StdHeader
397 AGESA_STATUS IgnoredStatus;
399 CPU_LOGICAL_ID CpuFamilyRevision;
400 PCI_ADDR CapabilitySet;
401 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
402 BOOLEAN MatchedSublink1;
403 HT_FREQUENCIES Freq0;
404 HT_FREQUENCIES Freq1;
406 // Errors: Possible values in unused entry space, extra type features, value range checks.
407 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
408 ASSERT ((Entry->InitialValues[4] == 0) &&
409 ((Entry->HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL | HTPHY_LINKTYPE_SL0_AND | HTPHY_LINKTYPE_SL1_AND)) == 0) &&
410 (Entry->HtPhyEntry.Address < HTPHY_REGISTER_MAX));
412 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
413 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
414 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
415 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
417 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
418 FamilySpecificServices,
421 &Entry->HtPhyEntry.TypeFeats,
426 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &Entry->HtPhyEntry, CapabilitySet, Link, StdHeader);
430 /*---------------------------------------------------------------------------------------*/
432 * Program a range of HT Phy PCI registers using BKDG values.
434 * @TableEntryTypeMethod{::HtPhyRangeRegister}.
437 * @param[in] Entry The type specific entry data to be implemented (that is written).
438 * @param[in] PlatformConfig Config handle for platform specific information
439 * @param[in] StdHeader Config params for library, services.
443 SetRegisterForHtPhyRangeEntry (
444 IN TABLE_ENTRY_DATA *Entry,
445 IN PLATFORM_CONFIGURATION *PlatformConfig,
446 IN AMD_CONFIG_PARAMS *StdHeader
452 AGESA_STATUS IgnoredStatus;
454 CPU_LOGICAL_ID CpuFamilyRevision;
455 PCI_ADDR CapabilitySet;
456 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
457 HT_PHY_TYPE_ENTRY_DATA CurrentHtPhyRegister;
458 BOOLEAN MatchedSublink1;
459 HT_FREQUENCIES Freq0;
460 HT_FREQUENCIES Freq1;
462 // Errors: Possible values in unused entry space, extra type features, value range checks.
463 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
464 ASSERT (((Entry->HtPhyRangeEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
465 (Entry->HtPhyRangeEntry.LowAddress <= Entry->HtPhyRangeEntry.HighAddress) &&
466 (Entry->HtPhyRangeEntry.HighAddress < HTPHY_REGISTER_MAX) &&
467 (Entry->HtPhyRangeEntry.HighAddress != 0));
469 CurrentHtPhyRegister.Mask = Entry->HtPhyRangeEntry.Mask;
470 CurrentHtPhyRegister.Data = Entry->HtPhyRangeEntry.Data;
471 CurrentHtPhyRegister.TypeFeats = Entry->HtPhyRangeEntry.TypeFeats;
473 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
474 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
475 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
476 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
478 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
479 FamilySpecificServices,
482 &Entry->HtPhyRangeEntry.TypeFeats,
487 for (CurrentHtPhyRegister.Address = Entry->HtPhyRangeEntry.LowAddress;
488 CurrentHtPhyRegister.Address <= Entry->HtPhyRangeEntry.HighAddress;
489 CurrentHtPhyRegister.Address++) {
490 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &CurrentHtPhyRegister, CapabilitySet, Link, StdHeader);
495 /*----------------------------------------------------------------------------------------*/
497 * Is PackageLink an Internal Link?
499 * This is a test for the logical link match codes in the user interface, not a test for
500 * the actual northbridge links.
502 * @param[in] PackageLink The link
504 * @retval TRUE This is an internal link
505 * @retval FALSE This is not an internal link
509 IsDeemphasisLinkInternal (
510 IN UINT32 PackageLink
513 return (BOOLEAN) ((PackageLink <= HT_LIST_MATCH_INTERNAL_LINK_2) && (PackageLink >= HT_LIST_MATCH_INTERNAL_LINK_0));
516 /*----------------------------------------------------------------------------------------*/
518 * Get the Package Link number, for the current node and real link number.
520 * Based on the link to package link mapping from BKDG, look up package link for
521 * the input link on the internal node number corresponding to the current core's node.
522 * For single module processors, the northbridge link and package link are the same.
524 * @param[in] Link the link on the current node.
525 * @param[in] FamilySpecificServices CPU specific support interface.
526 * @param[in] StdHeader Config params for library, services.
528 * @return the Package Link, HT_LIST_TERMINAL Not connected in package, HT_LIST_MATCH_INTERNAL_LINK package internal link.
535 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
536 IN AMD_CONFIG_PARAMS *StdHeader
539 UINT32 PackageLinkMapItem;
541 AP_MAIL_INFO ApMailbox;
543 PackageLink = HT_LIST_TERMINAL;
545 GetApMailbox (&ApMailbox.Info, StdHeader);
547 if (ApMailbox.Fields.ModuleType != 0) {
548 ASSERT (FamilySpecificServices->PackageLinkMap != NULL);
549 // Use table to find this module's package link
550 PackageLinkMapItem = 0;
551 while ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link != HT_LIST_TERMINAL) {
552 if (((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Module == ApMailbox.Fields.Module) &&
553 ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link == Link)) {
554 PackageLink = (*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].PackageLink;
557 PackageLinkMapItem++;
565 /*---------------------------------------------------------------------------------------*/
567 * Get the platform's specified deemphasis levels for the current link.
569 * Search the platform's list for a match to the current link and also matching frequency.
570 * If a match is found, use the specified deemphasis levels.
572 * @param[in] Socket The current Socket.
573 * @param[in] Link The link on that socket.
574 * @param[in] Frequency The frequency the link is set to.
575 * @param[in] PlatformConfig Config handle for platform specific information
576 * @param[in] FamilySpecificServices CPU specific support interface.
577 * @param[in] StdHeader Config params for library, services.
579 * @return The Deemphasis values for the link.
586 IN HT_FREQUENCIES Frequency,
587 IN PLATFORM_CONFIGURATION *PlatformConfig,
588 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
589 IN AMD_CONFIG_PARAMS *StdHeader
593 CPU_HT_DEEMPHASIS_LEVEL *Match;
596 PackageLink = LookupPackageLink (Link, FamilySpecificServices, StdHeader);
597 // All External and Internal links have deemphasis level none as the default.
598 // However, it is expected that the platform BIOS will provide deemphasis levels for the external links.
599 Result = ((DCV_LEVEL_NONE) | (DEEMPHASIS_LEVEL_NONE));
601 if (PlatformConfig->PlatformDeemphasisList != NULL) {
602 Match = PlatformConfig->PlatformDeemphasisList;
603 while (Match->Socket != HT_LIST_TERMINAL) {
604 if (((Match->Socket == Socket) || (Match->Socket == HT_LIST_MATCH_ANY)) &&
605 ((Match->Link == PackageLink) ||
606 ((Match->Link == HT_LIST_MATCH_ANY) && (!IsDeemphasisLinkInternal (PackageLink))) ||
607 ((Match->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsDeemphasisLinkInternal (PackageLink)))) &&
608 ((Match->LoFreq <= Frequency) && (Match->HighFreq >= Frequency))) {
609 // Found a match, get the deemphasis value.
610 ASSERT ((MaxPlatformDeemphasisLevel > Match->DcvDeemphasis) | (MaxPlatformDeemphasisLevel > Match->ReceiverDeemphasis));
611 Result = ((1 << Match->DcvDeemphasis) | (1 << Match->ReceiverDeemphasis));
621 /*---------------------------------------------------------------------------------------*/
623 * Program Deemphasis registers using BKDG values, for the platform specified levels.
625 * @TableEntryTypeMethod{::DeemphasisRegister}.
628 * @param[in] Entry The type specific entry data to be implemented (that is written).
629 * @param[in] PlatformConfig Config handle for platform specific information
630 * @param[in] StdHeader Config params for library, services.
634 SetRegisterForDeemphasisEntry (
635 IN TABLE_ENTRY_DATA *Entry,
636 IN PLATFORM_CONFIGURATION *PlatformConfig,
637 IN AMD_CONFIG_PARAMS *StdHeader
643 AGESA_STATUS IgnoredStatus;
645 CPU_LOGICAL_ID CpuFamilyRevision;
646 PCI_ADDR CapabilitySet;
647 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
648 BOOLEAN MatchedSublink1;
649 HT_FREQUENCIES Freq0;
650 HT_FREQUENCIES Freq1;
652 // Errors: Possible values in unused entry space, extra type features, value range checks.
653 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
654 ASSERT (((Entry->DeemphasisEntry.Levels.DeemphasisValues & ~(VALID_DEEMPHASIS_LEVELS)) == 0) &&
655 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
656 (Entry->DeemphasisEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
658 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
659 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
660 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
661 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
663 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
664 FamilySpecificServices,
667 &Entry->DeemphasisEntry.HtPhyEntry.TypeFeats,
672 if (DoesEntryTypeSpecificInfoMatch (
675 (MatchedSublink1 ? (Link + 4) : Link),
676 (MatchedSublink1 ? Freq1 : Freq0),
678 FamilySpecificServices,
680 Entry->DeemphasisEntry.Levels.DeemphasisValues)) {
681 FamilySpecificServices->SetHtPhyRegister (
682 FamilySpecificServices,
683 &Entry->DeemphasisEntry.HtPhyEntry,
688 IDS_HDT_CONSOLE (HT_TRACE, "Socket %d Module %d Sub-link %1d :\n ----> running on HT3, %s Level is %s\n",
690 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & HTPHY_LINKTYPE_SL0_ALL) != 0) ? Link : (Link + 4),
691 ((Entry->DeemphasisEntry.Levels.DeemphasisValues & DCV_LEVELS_ALL) != 0) ? "DCV" : "Deemphasis",
692 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL_NONE) ? " 0 dB" :
693 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__3) ? " - 3 dB" :
694 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
695 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
696 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__8) ? " - 8 dB" :
697 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11) ? " - 11 dB" :
698 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11_8) ? " - 11 dB postcursor with - 8 dB precursor" :
699 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL_NONE) ? " 0 dB" :
700 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__2) ? " - 2 dB" :
701 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__3) ? " - 3 dB" :
702 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__5) ? " - 5 dB" :
703 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__6) ? " - 6 dB" :
704 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__7) ? " - 7 dB" :
705 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__8) ? " - 8 dB" :
706 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__9) ? " - 9 dB" :
707 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__11) ? " - 11 dB" : "Undefined");
712 /*---------------------------------------------------------------------------------------*/
714 * Program HT Phy PCI registers which have complex frequency dependencies.
716 * @TableEntryTypeMethod{::HtPhyFreqRegister}.
718 * After matching a link for HT Features, check if the HT frequency matches the given range.
719 * If it does, get the northbridge frequency limits for implemented NB P-states and check if
720 * each matches the given range - range 0 and range 1 for each NB frequency, respectively.
721 * If all matches, apply the entry.
723 * @param[in] Entry The type specific entry data to be implemented (that is written).
724 * @param[in] PlatformConfig Config handle for platform specific information
725 * @param[in] StdHeader Config params for library, services.
729 SetRegisterForHtPhyFreqEntry (
730 IN TABLE_ENTRY_DATA *Entry,
731 IN PLATFORM_CONFIGURATION *PlatformConfig,
732 IN AMD_CONFIG_PARAMS *StdHeader
738 AGESA_STATUS IgnoredStatus;
740 CPU_LOGICAL_ID CpuFamilyRevision;
741 PCI_ADDR CapabilitySet;
742 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
743 BOOLEAN MatchedSublink1;
744 HT_FREQUENCIES Freq0;
745 HT_FREQUENCIES Freq1;
753 // Errors: extra type features, value range checks.
754 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
755 ASSERT (((Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
756 (Entry->HtPhyFreqEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
758 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
759 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
760 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
761 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
763 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
764 FamilySpecificServices,
767 &Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats,
772 // Check the HT Frequency for match to the range.
773 if (IsEitherCountInRange (
774 (MatchedSublink1 ? Freq1 : Freq0),
775 (MatchedSublink1 ? Freq1 : Freq0),
776 Entry->HtPhyFreqEntry.HtFreqCounts.HtFreqCountRanges)) {
777 // Get the NB Frequency, convert to 100's of MHz, then convert to equivalent HT encoding. This supports
778 // NB frequencies from 800 MHz to 2600 MHz, which is currently greater than any processor supports.
779 OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
788 if (OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
796 ASSERT (NbDivisor1 != 0);
797 NbFreq1 = (NbFreq1 / NbDivisor1);
798 NbFreq1 = (NbFreq1 / 100);
799 NbFreq1 = (NbFreq1 / 2) + 1;
804 ASSERT (NbDivisor0 != 0);
805 NbFreq0 = (NbFreq0 / NbDivisor0);
806 NbFreq0 = (NbFreq0 / 100);
807 NbFreq0 = (NbFreq0 / 2) + 1;
808 if (IsEitherCountInRange (NbFreq0, NbFreq1, Entry->HtPhyFreqEntry.NbFreqCounts.HtFreqCountRanges)) {
809 FamilySpecificServices->SetHtPhyRegister (
810 FamilySpecificServices,
811 &Entry->HtPhyFreqEntry.HtPhyEntry,
820 /*---------------------------------------------------------------------------------------*/
822 * Perform the Performance Profile PCI Register Entry.
824 * @TableEntryTypeMethod{::ProfileFixup}.
826 * Check the entry's performance profile features to the platform's and do the
827 * PCI register entry if they match.
829 * @param[in] Entry The Performance Profile register entry to perform
830 * @param[in] PlatformConfig Config handle for platform specific information
831 * @param[in] StdHeader Config handle for library and services.
835 SetRegisterForPerformanceProfileEntry (
836 IN TABLE_ENTRY_DATA *Entry,
837 IN PLATFORM_CONFIGURATION *PlatformConfig,
838 IN AMD_CONFIG_PARAMS *StdHeader
841 PERFORMANCE_PROFILE_FEATS PlatformProfile;
842 TABLE_ENTRY_DATA PciEntry;
844 // Errors: Possible values in unused entry space, extra type features, value range checks.
845 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
846 ASSERT (((Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
847 (Entry->InitialValues[4] == 0));
849 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
850 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
851 Entry->FixupEntry.TypeFeats.PerformanceProfileValue)) {
852 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
853 PciEntry.PciEntry = Entry->FixupEntry.PciEntry;
854 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
858 /*---------------------------------------------------------------------------------------*/
860 * Perform the HT Phy Performance Profile Register Entry.
862 * @TableEntryTypeMethod{::HtPhyProfileRegister}.
864 * @param[in] Entry The HT Phy register entry to perform
865 * @param[in] PlatformConfig Config handle for platform specific information
866 * @param[in] StdHeader Config handle for library and services.
870 SetRegisterForHtPhyProfileEntry (
871 IN TABLE_ENTRY_DATA *Entry,
872 IN PLATFORM_CONFIGURATION *PlatformConfig,
873 IN AMD_CONFIG_PARAMS *StdHeader
876 PERFORMANCE_PROFILE_FEATS PlatformProfile;
877 TABLE_ENTRY_DATA HtPhyEntry;
879 // Errors: Possible values in unused entry space, extra type features, value range checks.
880 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
881 ASSERT (((Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
882 (Entry->InitialValues[5] == 0));
884 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
885 if (DoesEntryTypeSpecificInfoMatch (
886 PlatformProfile.PerformanceProfileValue,
887 Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue)) {
888 LibAmdMemFill (&HtPhyEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
889 HtPhyEntry.HtPhyEntry = Entry->HtPhyProfileEntry.HtPhyEntry;
890 SetRegisterForHtPhyEntry (&HtPhyEntry, PlatformConfig, StdHeader);
894 /*---------------------------------------------------------------------------------------*/
896 * Perform the HT Host PCI Register Entry.
898 * @TableEntryTypeMethod{::HtHostPciRegister}.
900 * Make the current core's PCI address with the function and register for the entry.
901 * For all HT links, check the link's feature set for a match to the entry.
902 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
904 * @param[in] Entry The PCI register entry to perform
905 * @param[in] PlatformConfig Config handle for platform specific information
906 * @param[in] StdHeader Config handle for library and services.
910 SetRegisterForHtHostEntry (
911 IN TABLE_ENTRY_DATA *Entry,
912 IN PLATFORM_CONFIGURATION *PlatformConfig,
913 IN AMD_CONFIG_PARAMS *StdHeader
919 AGESA_STATUS IgnoredStatus;
921 CPU_LOGICAL_ID CpuFamilyRevision;
922 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
923 PCI_ADDR CapabilitySet;
925 HT_HOST_FEATS HtHostFeats;
928 // Errors: Possible values in unused entry space, extra type features, value range checks.
929 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
930 ASSERT ((Entry->InitialValues[4] == 0) &&
931 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
932 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
934 HtHostFeats.HtHostValue = 0;
935 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
936 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
937 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
938 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
940 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
941 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtHostEntry.TypeFeats.HtHostValue)) {
942 // Do the HT Host PCI register update.
943 PciAddress = CapabilitySet;
944 PciAddress.Address.Register += Entry->HtHostEntry.Address.Address.Register;
945 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
946 RegisterData = RegisterData & (~(Entry->HtHostEntry.Mask));
947 RegisterData = RegisterData | Entry->HtHostEntry.Data;
948 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
953 /*---------------------------------------------------------------------------------------*/
955 * Perform the HT Host Performance PCI Register Entry.
957 * @TableEntryTypeMethod{::HtHostPerfPciRegister}.
959 * Make the current core's PCI address with the function and register for the entry.
960 * For all HT links, check the link's feature set for a match to the entry.
961 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
963 * @param[in] Entry The PCI register entry to perform
964 * @param[in] PlatformConfig Config handle for platform specific information
965 * @param[in] StdHeader Config handle for library and services.
969 SetRegisterForHtHostPerfEntry (
970 IN TABLE_ENTRY_DATA *Entry,
971 IN PLATFORM_CONFIGURATION *PlatformConfig,
972 IN AMD_CONFIG_PARAMS *StdHeader
975 PERFORMANCE_PROFILE_FEATS PlatformProfile;
976 TABLE_ENTRY_DATA HtHostPciTypeEntryData;
978 // Errors: Possible values in unused entry space, extra type features, value range checks.
979 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
980 ASSERT ((Entry->InitialValues[5] == 0) &&
981 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
982 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
984 // Check for any performance profile features.
985 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
986 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
987 Entry->HtHostPerfEntry.PerformanceFeats.PerformanceProfileValue)) {
988 // Perform HT Host entry process.
989 LibAmdMemFill (&HtHostPciTypeEntryData, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
990 HtHostPciTypeEntryData.HtHostEntry = Entry->HtHostPerfEntry.HtHostEntry;
991 SetRegisterForHtHostEntry (&HtHostPciTypeEntryData, PlatformConfig, StdHeader);
995 /*---------------------------------------------------------------------------------------*/
997 * Set the HT Link Token Count registers.
999 * @TableEntryTypeMethod{::HtTokenPciRegister}.
1001 * Make the current core's PCI address with the function and register for the entry.
1002 * Check the performance profile features.
1003 * For all HT links, check the link's feature set for a match to the entry.
1004 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
1006 * @param[in] Entry The Link Token register entry to perform
1007 * @param[in] PlatformConfig Config handle for platform specific information
1008 * @param[in] StdHeader Config handle for library and services.
1012 SetRegisterForHtLinkTokenEntry (
1013 IN TABLE_ENTRY_DATA *Entry,
1014 IN PLATFORM_CONFIGURATION *PlatformConfig,
1015 IN AMD_CONFIG_PARAMS *StdHeader
1021 AGESA_STATUS IgnoredStatus;
1023 CPU_LOGICAL_ID CpuFamilyRevision;
1024 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1025 PCI_ADDR CapabilitySet;
1026 HT_HOST_FEATS HtHostFeats;
1027 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1028 UINTN ProcessorCount;
1030 UINT32 RegisterData;
1031 PCI_ADDR PciAddress;
1033 // Errors: Possible values in unused entry space, extra type features, value range checks.
1034 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1035 ASSERT (((Entry->HtTokenEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
1036 ((Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
1037 (Entry->HtTokenEntry.Mask != 0));
1039 HtHostFeats.HtHostValue = 0;
1040 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1041 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1042 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1043 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1045 // Check if the actual processor count and SystemDegree are in either range.
1046 ProcessorCount = GetNumberOfProcessors (StdHeader);
1047 SystemDegree = GetSystemDegree (StdHeader);
1048 if (IsEitherCountInRange (ProcessorCount, SystemDegree, Entry->HtTokenEntry.ConnectivityCount.ConnectivityCountRanges)) {
1049 // Check for any performance profile features.
1050 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1051 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
1052 Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue)) {
1053 // Check the link features.
1055 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1056 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtTokenEntry.LinkFeats.HtHostValue)) {
1057 // Do the HT Host PCI register update. Token register are four registers, sublink 0 and 1 share fields.
1058 // If sublink 0 is unconnected, we should let sublink 1 match. If the links are ganged, of course only sublink 0 matches.
1059 // If the links are unganged and both connected, the BKDG settings are for both coherent.
1060 PciAddress = CapabilitySet;
1061 PciAddress.Address.Register = Entry->HtTokenEntry.Address.Address.Register +
1062 ((Link > 3) ? (((UINT32)Link - 4) * 4) : ((UINT32)Link * 4));
1063 PciAddress.Address.Function = Entry->HtTokenEntry.Address.Address.Function;
1064 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
1065 RegisterData = RegisterData & (~(Entry->HtTokenEntry.Mask));
1066 RegisterData = RegisterData | Entry->HtTokenEntry.Data;
1067 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
1074 /*---------------------------------------------------------------------------------------*/
1076 * Perform the Core Counts Performance PCI Register Entry.
1078 * @TableEntryTypeMethod{::CoreCountsPciRegister}.
1080 * Check the performance profile.
1081 * Check the actual core count to the range pair given, and apply if matched.
1083 * @param[in] Entry The PCI register entry to perform
1084 * @param[in] PlatformConfig Config handle for platform specific information
1085 * @param[in] StdHeader Config handle for library and services.
1089 SetRegisterForCoreCountsPerformanceEntry (
1090 IN TABLE_ENTRY_DATA *Entry,
1091 IN PLATFORM_CONFIGURATION *PlatformConfig,
1092 IN AMD_CONFIG_PARAMS *StdHeader
1095 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1096 UINTN ActualCoreCount;
1097 TABLE_ENTRY_DATA PciEntry;
1099 // Errors: Possible values in unused entry space, extra type features, value range checks.
1100 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1101 ASSERT (((Entry->CoreCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1103 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1104 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->CoreCountEntry.TypeFeats.PerformanceProfileValue)) {
1105 ActualCoreCount = GetActiveCoresInCurrentModule (StdHeader);
1106 // Check if the actual core count is in either range.
1107 if (IsEitherCountInRange (ActualCoreCount, ActualCoreCount, Entry->CoreCountEntry.CoreCounts.CoreRanges)) {
1108 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1109 PciEntry.PciEntry = Entry->CoreCountEntry.PciEntry;
1110 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1115 /*---------------------------------------------------------------------------------------*/
1117 * Perform the Processor Counts PCI Register Entry.
1119 * @TableEntryTypeMethod{::ProcCountsPciRegister}.
1121 * Check the performance profile.
1122 * Check the actual processor count (not node count!) to the range pair given, and apply if matched.
1124 * @param[in] Entry The PCI register entry to perform
1125 * @param[in] PlatformConfig Config handle for platform specific information
1126 * @param[in] StdHeader Config handle for library and services.
1130 SetRegisterForProcessorCountsEntry (
1131 IN TABLE_ENTRY_DATA *Entry,
1132 IN PLATFORM_CONFIGURATION *PlatformConfig,
1133 IN AMD_CONFIG_PARAMS *StdHeader
1136 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1137 UINTN ProcessorCount;
1138 TABLE_ENTRY_DATA PciEntry;
1140 // Errors: Possible values in unused entry space, extra type features, value range checks.
1141 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1142 ASSERT (((Entry->ProcCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1144 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1145 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->ProcCountEntry.TypeFeats.PerformanceProfileValue)) {
1146 ProcessorCount = GetNumberOfProcessors (StdHeader);
1147 // Check if the actual processor count is in either range.
1148 if (IsEitherCountInRange (ProcessorCount, ProcessorCount, Entry->ProcCountEntry.ProcessorCounts.ProcessorCountRanges)) {
1149 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1150 PciEntry.PciEntry = Entry->ProcCountEntry.PciEntry;
1151 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1156 /*---------------------------------------------------------------------------------------*/
1158 * Perform the Compute Unit Counts PCI Register Entry.
1160 * @TableEntryTypeMethod{::CompUnitCountsPciRegister}.
1162 * Check the entry's performance profile features and the compute unit count
1163 * to the platform's and do the PCI register entry if they match.
1165 * @param[in] Entry The PCI register entry to perform
1166 * @param[in] PlatformConfig Config handle for platform specific information
1167 * @param[in] StdHeader Config handle for library and services.
1171 SetRegisterForComputeUnitCountsEntry (
1172 IN TABLE_ENTRY_DATA *Entry,
1173 IN PLATFORM_CONFIGURATION *PlatformConfig,
1174 IN AMD_CONFIG_PARAMS *StdHeader
1177 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1178 UINTN ComputeUnitCount;
1179 TABLE_ENTRY_DATA PciEntry;
1181 // Errors: Possible values in unused entry space, extra type features, value range checks.
1182 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1183 ASSERT (((Entry->CompUnitCountEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1185 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1186 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->CompUnitCountEntry.TypeFeats.PerformanceProfileValue)) {
1187 ComputeUnitCount = GetNumberOfCompUnitsInCurrentModule (StdHeader);
1188 // Check if the actual compute unit count is in either range.
1189 if (IsEitherCountInRange (ComputeUnitCount, ComputeUnitCount, Entry->CompUnitCountEntry.ComputeUnitCounts.ComputeUnitRanges)) {
1190 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1191 PciEntry.PciEntry = Entry->CompUnitCountEntry.PciEntry;
1192 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1197 /*---------------------------------------------------------------------------------------*/
1199 * Perform the Compute Unit Counts MSR Register Entry.
1201 * @TableEntryTypeMethod{::CompUnitCountsMsr}.
1203 * Check the entry's compute unit count to the platform's and do the
1204 * MSR entry if they match.
1206 * @param[in] Entry The PCI register entry to perform
1207 * @param[in] PlatformConfig Config handle for platform specific information
1208 * @param[in] StdHeader Config handle for library and services.
1212 SetMsrForComputeUnitCountsEntry (
1213 IN TABLE_ENTRY_DATA *Entry,
1214 IN PLATFORM_CONFIGURATION *PlatformConfig,
1215 IN AMD_CONFIG_PARAMS *StdHeader
1218 UINTN ComputeUnitCount;
1219 TABLE_ENTRY_DATA MsrEntry;
1221 ComputeUnitCount = GetNumberOfCompUnitsInCurrentModule (StdHeader);
1222 // Check if the actual compute unit count is in either range.
1223 if (IsEitherCountInRange (ComputeUnitCount, ComputeUnitCount, Entry->CompUnitCountMsrEntry.ComputeUnitCounts.ComputeUnitRanges)) {
1224 LibAmdMemFill (&MsrEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1225 MsrEntry.MsrEntry = Entry->CompUnitCountMsrEntry.MsrEntry;
1226 SetRegisterForMsrEntry (&MsrEntry, PlatformConfig, StdHeader);
1230 /*---------------------------------------------------------------------------------------*/
1232 * Perform the Processor Token Counts PCI Register Entry.
1234 * @TableEntryTypeMethod{::TokenPciRegister}.
1236 * The table criteria then translate as:
1237 * - 2 Socket, half populated == Degree 1
1238 * - 4 Socket, half populated == Degree 2
1239 * - 2 Socket, fully populated == Degree 3
1240 * - 4 Socket, fully populated == Degree > 3. (4 or 5 if 3P, 6 if 4P)
1242 * @param[in] Entry The PCI register entry to perform
1243 * @param[in] PlatformConfig Config handle for platform specific information
1244 * @param[in] StdHeader Config handle for library and services.
1248 SetRegisterForTokenPciEntry (
1249 IN TABLE_ENTRY_DATA *Entry,
1250 IN PLATFORM_CONFIGURATION *PlatformConfig,
1251 IN AMD_CONFIG_PARAMS *StdHeader
1254 PERFORMANCE_PROFILE_FEATS PlatformProfile;
1256 UINT32 ProcessorPackageType;
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.PackageType.PackageTypeValue & ~(PACKAGE_TYPE_ALL)) == 0);
1262 ASSERT (((Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
1264 ProcessorPackageType = LibAmdGetPackageType (StdHeader);
1265 if (DoesEntryTypeSpecificInfoMatch (ProcessorPackageType, Entry->TokenPciEntry.PackageType.PackageTypeValue)) {
1266 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
1267 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue)) {
1268 SystemDegree = GetSystemDegree (StdHeader);
1269 // Check if the system degree is in the range.
1270 if (IsEitherCountInRange (SystemDegree, SystemDegree, Entry->TokenPciEntry.ConnectivityCount.ConnectivityCountRanges)) {
1271 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1272 PciEntry.PciEntry = Entry->TokenPciEntry.PciEntry;
1273 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1279 /*---------------------------------------------------------------------------------------*/
1281 * Perform the HT Link Feature PCI Register Entry.
1283 * @TableEntryTypeMethod{::HtFeatPciRegister}.
1285 * Set a single field (that is, the register field is not in HT Host capability or a
1286 * set of per link registers) in PCI config, based on HT link features and package type.
1287 * This code is used for two cases: single link processors and multilink processors.
1288 * For single link cases, the link will be tested for a match to the HT Features for the link.
1289 * For multilink processors, the entry will match if @b any link is found which matches.
1290 * For example, a setting can be applied based on coherent HT3 by matching coherent AND HT3.
1292 * Make the core's PCI address. Check the package type (currently more important to the single link case),
1293 * and if matching, iterate through all links checking for an HT feature match until found or exhausted.
1294 * If a match was found, pass the PCI entry data to the implementer for writing for the current core.
1296 * @param[in] Entry The PCI register entry to perform
1297 * @param[in] PlatformConfig Config handle for platform specific information
1298 * @param[in] StdHeader Config handle for library and services.
1302 SetRegisterForHtFeaturePciEntry (
1303 IN TABLE_ENTRY_DATA *Entry,
1304 IN PLATFORM_CONFIGURATION *PlatformConfig,
1305 IN AMD_CONFIG_PARAMS *StdHeader
1311 AGESA_STATUS IgnoredStatus;
1313 CPU_LOGICAL_ID CpuFamilyRevision;
1314 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1315 PCI_ADDR CapabilitySet;
1316 HT_HOST_FEATS HtHostFeats;
1317 UINT32 ProcessorPackageType;
1319 TABLE_ENTRY_DATA PciEntry;
1321 // Errors: Possible values in unused entry space, extra type features, value range checks.
1322 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1323 ASSERT ((Entry->HtFeatPciEntry.PciEntry.Mask != 0) &&
1324 ((Entry->HtFeatPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
1326 HtHostFeats.HtHostValue = 0;
1327 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1328 PciEntry.PciEntry = Entry->HtFeatPciEntry.PciEntry;
1329 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1330 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1331 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1332 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1334 ASSERT ((Entry->HtFeatPciEntry.PackageType.PackageTypeValue & ~(PACKAGE_TYPE_ALL)) == 0);
1336 ProcessorPackageType = LibAmdGetPackageType (StdHeader);
1337 if (DoesEntryTypeSpecificInfoMatch (ProcessorPackageType, Entry->HtFeatPciEntry.PackageType.PackageTypeValue)) {
1339 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1340 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtFeatPciEntry.LinkFeats.HtHostValue)) {
1346 // Do the PCI register update.
1347 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1352 /*---------------------------------------------------------------------------------------*/
1354 * Perform the HT Link PCI Register Entry.
1356 * @TableEntryTypeMethod{::HtLinkPciRegister}.
1358 * Make the current core's PCI address with the function and register for the entry.
1359 * Registers are processed for match per link, assuming sequential PCI address per link.
1360 * Read - Modify - Write each matching link's PCI register, clearing masked bits, and setting the data bits.
1362 * @param[in] Entry The PCI register entry to perform
1363 * @param[in] PlatformConfig Config handle for platform specific information
1364 * @param[in] StdHeader Config handle for library and services.
1368 SetRegisterForHtLinkPciEntry (
1369 IN TABLE_ENTRY_DATA *Entry,
1370 IN PLATFORM_CONFIGURATION *PlatformConfig,
1371 IN AMD_CONFIG_PARAMS *StdHeader
1377 AGESA_STATUS IgnoredStatus;
1379 CPU_LOGICAL_ID CpuFamilyRevision;
1380 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1381 PCI_ADDR CapabilitySet;
1382 HT_HOST_FEATS HtHostFeats;
1383 TABLE_ENTRY_DATA PciEntry;
1385 // Errors: Possible values in unused entry space, extra type features, value range checks.
1386 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
1387 ASSERT ((Entry->HtLinkPciEntry.PciEntry.Mask != 0) &&
1388 ((Entry->HtLinkPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
1390 HtHostFeats.HtHostValue = 0;
1391 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
1392 PciEntry.PciEntry = Entry->HtLinkPciEntry.PciEntry;
1393 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
1394 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
1395 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
1396 GetCpuServicesFromLogicalId (&CpuFamilyRevision, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1399 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
1400 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtLinkPciEntry.LinkFeats.HtHostValue)) {
1401 // Do the update to the link's non-Host PCI register, based on the entry address.
1402 PciEntry.PciEntry.Address = Entry->HtLinkPciEntry.PciEntry.Address;
1403 PciEntry.PciEntry.Address.Address.Register = PciEntry.PciEntry.Address.Address.Register + ((UINT32)Link * 4);
1404 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
1409 /* -----------------------------------------------------------------------------*/
1411 * Returns the platform features list of the currently running processor core.
1413 * @param[out] Features The Features supported by this platform
1414 * @param[in] PlatformConfig Config handle for platform specific information
1415 * @param[in] StdHeader Header for library and services
1419 GetPlatformFeatures (
1420 OUT PLATFORM_FEATS *Features,
1421 IN PLATFORM_CONFIGURATION *PlatformConfig,
1422 IN AMD_CONFIG_PARAMS *StdHeader
1425 PCI_ADDR PciAddress;
1426 UINT32 CapabilityReg;
1428 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1432 Features->PlatformValue = 0;
1434 switch (PlatformConfig->PlatformProfile.PlatformControlFlowMode) {
1436 Features->PlatformFeatures.PlatformNfcm = 1;
1439 Features->PlatformFeatures.PlatformUma = 1;
1442 Features->PlatformFeatures.PlatformUmaIfcm = 1;
1445 Features->PlatformFeatures.PlatformIfcm = 1;
1448 Features->PlatformFeatures.PlatformIommu = 1;
1453 // Check - Single Link?
1454 // This is based on the implemented links on the package regardless of their
1455 // connection status. All processors must match the BSP, so we only check it and
1456 // not the current node. We don't care exactly how many links there are, as soon
1457 // as we find more than one we are done.
1459 PciAddress.AddressValue = MAKE_SBDFO (0, 0, PCI_DEV_BASE, FUNC_0, 0);
1460 // Until either all capabilities are done or until the desired link is found,
1461 // keep looking for HT Host Capabilities.
1463 LibAmdPciFindNextCap (&PciAddress, StdHeader);
1464 if (PciAddress.AddressValue != ILLEGAL_SBDFO) {
1465 LibAmdPciRead (AccessWidth32, PciAddress, &CapabilityReg, StdHeader);
1466 if ((CapabilityReg & 0xE00000FF) == 0x20000008) {
1469 // A capability other than an HT capability, keep looking.
1471 // end of capabilities
1476 Features->PlatformFeatures.PlatformSingleLink = 1;
1478 Features->PlatformFeatures.PlatformMultiLink = 1;
1481 // Set the legacy core count bits.
1482 GetActiveCoresInCurrentSocket (&CoreCount, StdHeader);
1483 switch (CoreCount) {
1485 Features->PlatformFeatures.PlatformSingleCore = 1;
1488 Features->PlatformFeatures.PlatformDualCore = 1;
1491 Features->PlatformFeatures.PlatformMultiCore = 1;
1495 // Get some specific platform type info, VC...etc.
1497 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1498 ASSERT (FamilySpecificServices != NULL);
1499 FamilySpecificServices->GetPlatformTypeSpecificInfo (FamilySpecificServices, Features, StdHeader);
1503 /*---------------------------------------------------------------------------------------*/
1505 * Checks if a register table entry applies to the executing core.
1507 * This function uses a combination of logical ID and platform features to
1508 * determine whether or not a register table entry applies to the executing core.
1510 * @param[in] CoreCpuRevision The current core's logical ID
1511 * @param[in] EntryCpuRevision The entry's desired logical IDs
1512 * @param[in] PlatformFeatures The platform features
1513 * @param[in] EntryFeatures The entry's desired platform features
1515 * @retval TRUE This entry should be applied
1516 * @retval FALSE This entry does not apply
1521 DoesEntryMatchPlatform (
1522 IN CPU_LOGICAL_ID CoreCpuRevision,
1523 IN CPU_LOGICAL_ID EntryCpuRevision,
1524 IN PLATFORM_FEATS PlatformFeatures,
1525 IN PLATFORM_FEATS EntryFeatures
1532 if (((CoreCpuRevision.Family & EntryCpuRevision.Family) != 0) &&
1533 ((CoreCpuRevision.Revision & EntryCpuRevision.Revision) != 0)) {
1534 if (EntryFeatures.PlatformFeatures.AndPlatformFeats == 0) {
1535 // Match if ANY entry feats match a platform feat (an OR test)
1536 if ((EntryFeatures.PlatformValue & PlatformFeatures.PlatformValue) != 0) {
1540 // Match if ALL entry feats match a platform feat (an AND test)
1541 if ((EntryFeatures.PlatformValue & ~(AMD_PF_AND)) ==
1542 (EntryFeatures.PlatformValue & PlatformFeatures.PlatformValue)) {
1551 /*---------------------------------------------------------------------------------------*/
1553 * Checks register table entry type specific criteria to the platform.
1555 * Entry Data Type implementer methods can use this generically to check their own
1556 * specific criteria. The method collects the actual platform characteristics and
1557 * provides them along with the table entry's criteria to this service.
1559 * There are a couple considerations for any implementer method using this service.
1560 * The criteria value has to be representable as a UINT32. The MSB, Bit 31, has to
1561 * be used as a AND test request if set in the entry. (The platform value should never
1562 * have that bit set.)
1564 * @param[in] PlatformTypeSpecificFeatures The platform features
1565 * @param[in] EntryTypeFeatures The entry's desired platform features
1567 * @retval TRUE This entry should be applied
1568 * @retval FALSE This entry does not apply
1572 DoesEntryTypeSpecificInfoMatch (
1573 IN UINT32 PlatformTypeSpecificFeatures,
1574 IN UINT32 EntryTypeFeatures
1581 if ((EntryTypeFeatures & BIT31) == 0) {
1582 // Match if ANY entry feats match a platform feat (an OR test)
1583 if ((EntryTypeFeatures & PlatformTypeSpecificFeatures) != 0) {
1587 // Match if ALL entry feats match a platform feat (an AND test)
1588 if ((EntryTypeFeatures & ~(BIT31)) == (EntryTypeFeatures & PlatformTypeSpecificFeatures)) {
1595 /*---------------------------------------------------------------------------------------*/
1597 * Determine this core's Selector matches.
1599 * @param[in] Selector Is the current core this selector type?
1600 * @param[in] StdHeader Config handle for library and services.
1602 * @retval TRUE Yes, it is.
1603 * @retval FALSE No, it is not.
1608 IN TABLE_CORE_SELECTOR Selector,
1609 IN AMD_CONFIG_PARAMS *StdHeader
1613 AGESA_STATUS CalledStatus;
1616 ASSERT (Selector < TableCoreSelectorMax);
1618 if ((Selector == PrimaryCores) && !IsCurrentCorePrimary (StdHeader)) {
1621 if ((Selector == CorePairPrimary) && !IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader)) {
1624 if ((Selector == BscCore) && (!IsBsp (StdHeader, &CalledStatus))) {
1630 /*---------------------------------------------------------------------------------------*/
1632 * Set the registers for this core based on entries in a list of Register Tables.
1634 * Determine the platform features and this core's logical id. Get the specific table
1635 * entry type implementations for the logical model, which may be either generic (the ones
1636 * in this file) or specific.
1638 * Scan the tables starting the with ones for all cores and progressively narrowing the selection
1639 * based on this core's role (ex. primary core). For a selected table, check for each entry
1640 * matching the current core and platform, and call the implementer method to perform the
1641 * register set operation if it matches.
1643 * @param[in] PlatformConfig Config handle for platform specific information
1644 * @param[in] StdHeader Config handle for library and services.
1648 SetRegistersFromTables (
1649 IN PLATFORM_CONFIGURATION *PlatformConfig,
1650 IN AMD_CONFIG_PARAMS *StdHeader
1653 CPU_LOGICAL_ID CpuLogicalId;
1654 PLATFORM_FEATS PlatformFeatures;
1655 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1656 TABLE_ENTRY_FIELDS *Entries;
1657 TABLE_CORE_SELECTOR Selector;
1658 TABLE_ENTRY_TYPE EntryType;
1659 REGISTER_TABLE **TableHandle;
1660 UINTN NumberOfEntries;
1661 UINTN CurrentEntryCount;
1662 TABLE_ENTRY_TYPE_DESCRIPTOR *TypeImplementer;
1663 PF_DO_TABLE_ENTRY DoTableEntry[TableEntryTypeMax];
1665 // Did you really mean to increase the size of ALL table entries??!!
1666 // While it is not necessarily a bug to increase the size of table entries:
1667 // - Is this warning a surprise? Please fix it.
1668 // - If expected, is this really a feature which is worth the increase? Then let other entries also use the space.
1669 ASSERT (sizeof (TABLE_ENTRY_DATA) == (MAX_ENTRY_TYPE_ITEMS32 * sizeof (UINT32)));
1671 PlatformFeatures.PlatformValue = 0;
1672 GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
1673 GetPlatformFeatures (&PlatformFeatures, PlatformConfig, StdHeader);
1674 GetCpuServicesFromLogicalId (&CpuLogicalId, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1676 // Build a non-sparse table of implementer methods, so we don't have to keep searching.
1677 // It is a bug to not include a descriptor for a type that is in the table (but the
1678 // descriptor can point to a non-assert stub).
1679 // Also, it is not a bug to have no register table implementations, but it is a bug to have none and call this routine.
1680 for (EntryType = MsrRegister; EntryType < TableEntryTypeMax; EntryType++) {
1681 DoTableEntry[EntryType] = (PF_DO_TABLE_ENTRY)CommonAssert;
1683 TypeImplementer = FamilySpecificServices->TableEntryTypeDescriptors;
1684 ASSERT (TypeImplementer != NULL);
1685 while (TypeImplementer->EntryType < TableEntryTypeMax) {
1686 DoTableEntry[TypeImplementer->EntryType] = TypeImplementer->DoTableEntry;
1690 for (Selector = AllCores; Selector < TableCoreSelectorMax; Selector++) {
1691 if (IsCoreSelector (Selector, StdHeader)) {
1692 // If the current core is the selected type of core, work the table list for tables for that type of core.
1694 Entries = GetNextRegisterTable (FamilySpecificServices, Selector, &TableHandle, &NumberOfEntries, StdHeader);
1695 while (Entries != NULL) {
1696 for (CurrentEntryCount = 0; CurrentEntryCount < NumberOfEntries; CurrentEntryCount++, Entries++) {
1697 if (DoesEntryMatchPlatform (CpuLogicalId, Entries->CpuRevision, PlatformFeatures, Entries->Features)) {
1698 // The entry matches this config, Do It!
1699 // Find the implementer for this entry type and pass the entry data to it.
1700 ASSERT (Entries->EntryType < TableEntryTypeMax);
1701 DoTableEntry[Entries->EntryType] (&Entries->Entry, PlatformConfig, StdHeader);
1704 Entries = GetNextRegisterTable (FamilySpecificServices, Selector, &TableHandle, &NumberOfEntries, StdHeader);
1707 // Once a selector does not match the current core, quit looking.
1713 /*---------------------------------------------------------------------------------------*/
1715 * Set the registers for this core based on entries in a list of Register Tables.
1717 * This function acts as a wrapper for calling the SetRegistersFromTables
1718 * routine at AmdInitEarly.
1720 * @param[in] FamilyServices The current Family Specific Services.
1721 * @param[in] EarlyParams Service parameters.
1722 * @param[in] StdHeader Config handle for library and services.
1726 SetRegistersFromTablesAtEarly (
1727 IN CPU_SPECIFIC_SERVICES *FamilyServices,
1728 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
1729 IN AMD_CONFIG_PARAMS *StdHeader
1732 AGESA_TESTPOINT (TpProcCpuProcessRegisterTables, StdHeader);
1733 SetRegistersFromTables (&EarlyParams->PlatformConfig, StdHeader);