/* $NoKeywords:$ */ /** * @file * * AMD PSTATE, ACPI table related API functions. * * Contains code that generates the _PSS, _PCT, and other ACPI tables. * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: CPU * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ * */ /***************************************************************************** * * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Advanced Micro Devices, Inc. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************** */ /* *---------------------------------------------------------------------------- * MODULES USED * *---------------------------------------------------------------------------- */ #include "AGESA.h" #include "amdlib.h" #include "OptionPstate.h" #include "cpuLateInit.h" #include "cpuRegisters.h" #include "cpuFamilyTranslation.h" #include "GeneralServices.h" #include "cpuServices.h" #include "heapManager.h" #include "Ids.h" #include "Filecode.h" #include "GeneralServices.h" #include "cpuPstateTables.h" #include "cpuFeatures.h" #include "cpuIoCstate.h" CODE_GROUP (G3_DXE) RDATA_GROUP (G3_DXE) #define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE /*---------------------------------------------------------------------------- * DEFINITIONS AND MACROS * *---------------------------------------------------------------------------- */ extern OPTION_PSTATE_LATE_CONFIGURATION OptionPstateLateConfiguration; // global user config record extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable; extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable; STATIC ACPI_TABLE_HEADER ROMDATA CpuSsdtHdrStruct = { {'S','S','D','T'}, 0, 1, 0, {0}, {0}, 1, {'A','M','D',' '}, 1 }; /*---------------------------------------------------------------------------- * TYPEDEFS AND STRUCTURES * *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * PROTOTYPES OF LOCAL FUNCTIONS * *---------------------------------------------------------------------------- */ UINT32 STATIC CalAcpiTablesSize ( IN S_CPU_AMD_PSTATE *AmdPstatePtr, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ); AGESA_STATUS GenerateSsdtStub ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT VOID **SsdtPtr ); UINT32 CreateAcpiTablesStub ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ); UINT32 CreatePStateAcpiTables ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ); UINT32 CreateCStateAcpiTables ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ); AGESA_STATUS GenerateSsdt ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT VOID **SsdtPtr ); /** *--------------------------------------------------------------------------------------- * * CalAcpiTablesSize * * Description: * This function will calculate the size of ACPI PState tables * * Parameters: * @param[in] *AmdPstatePtr * @param[in] *PlatformConfig * @param[in] *StdHeader * * @retval UINT32 * *--------------------------------------------------------------------------------------- */ UINT32 STATIC CalAcpiTablesSize ( IN S_CPU_AMD_PSTATE *AmdPstatePtr, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 ScopeSize; UINT32 CoreCount; UINT32 SocketCount; UINT32 MaxCoreNumberInCurrentSocket; UINT32 MaxSocketNumberInSystem; UINT32 MaxPstateNumberInCurrentCore; UINT32 CstateAcpiObjSize; PSTATE_LEVELING *PStateLevelingBufferStructPtr; IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices; ScopeSize = sizeof (ACPI_TABLE_HEADER); CstateAcpiObjSize = 0; IoCstateFamilyServices = NULL; PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc; MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem; if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) { GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader); if (IoCstateFamilyServices != NULL) { CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader); } } for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) { MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode; for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) { MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1; ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core ScopeSize += CstateAcpiObjSize; // C-State ACPI objects size per core // Add P-State ACPI Objects size per core if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) { ScopeSize += (PCT_STRUCT_SIZE + PSS_HEADER_STRUCT_SIZE + (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) + XPSS_HEADER_STRUCT_SIZE + (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) + PSD_HEADER_STRUCT_SIZE + PSD_BODY_STRUCT_SIZE + PPC_HEADER_BODY_STRUCT_SIZE); } } ScopeSize += MaxCoreNumberInCurrentSocket; PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES))); } AmdPstatePtr->SizeOfBytes = ScopeSize; return ScopeSize; } /**-------------------------------------------------------------------------------------- * * GenerateSsdtStub * * Description: * This is the default routine for use when both PState and CState option is NOT * requested. The option install process will create and fill the transfer vector * with the address of the proper routine (Main or Stub). The link optimizer will * strip out of the .DLL the routine that is not used. * * Parameters: * @param[in] StdHeader Handle to config for library and services * @param[in] PlatformConfig Contains the power cap parameter * @param[in,out] SsdtPtr ACPI SSDT table pointer * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- **/ AGESA_STATUS GenerateSsdtStub ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT VOID **SsdtPtr ) { return AGESA_UNSUPPORTED; } /** *--------------------------------------------------------------------------------------- * * GenerateSsdt * * Description: * This function will populate the SSDT with ACPI P-States and C-States Objects, whenever * necessary * This function should be called only from BSP * * Parameters: * @param[in] StdHeader Handle to config for library and services * @param[in] PlatformConfig Contains the power cap parameter * @param[in,out] SsdtPtr ACPI SSDT pointer * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- */ AGESA_STATUS GenerateSsdt ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT VOID **SsdtPtr ) { UINT32 i; UINT32 j; UINT32 TempVar8_a; UINT32 CurrSize; UINT32 TempVar_a; UINT32 TempVar_b; UINT32 ScopeSize; UINT32 CoreCount; UINT32 SocketCount; UINT32 MaxCorePerNode; UINT8 LocalApicId; UINT8 *IntermediatePtr; AGESA_STATUS AgesaStatus; LOCATE_HEAP_PTR LocateHeapParams; ALLOCATE_HEAP_PARAMS AllocateHeapParams; S_CPU_AMD_PSTATE *AmdPstatePtr; PSTATE_LEVELING *PStateLevelingBufferStructPtr; SCOPE *ScopeAcpiTablesStructPtr; SCOPE *ScopeAcpiTablesStructPtrTemp; AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader); ASSERT (IsBsp (StdHeader, &AgesaStatus)); // If P-State and C-State ACPI tables do not need to be generated, exit this routine if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) { AgesaStatus = AGESA_UNSUPPORTED; return AgesaStatus; } // Initialize data variables ScopeSize = 0; CoreCount = 0; LocalApicId = 0; CurrSize = 0; // Locate P-State data buffer LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE; AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader); if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) { return AGESA_ERROR; } AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader); AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr; PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc; // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL if (*SsdtPtr == NULL) { //Do not know the actual size.. pre-calculate it. AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader); AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE; AllocateHeapParams.Persist = HEAP_SYSTEM_MEM; AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader); if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) { return AGESA_ERROR; } AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader); *SsdtPtr = AllocateHeapParams.BufferPtr; } IDS_HDT_CONSOLE (CPU_TRACE, " SSDT is created\n"); // Copy SSDT header into allocated buffer LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader); // Update table OEM fields. LibAmdMemCopy ((VOID *) ((ACPI_TABLE_HEADER *) *SsdtPtr)->OemId, (VOID *) &OptionPstateLateConfiguration.OemIdString, sizeof (OptionPstateLateConfiguration.OemIdString), StdHeader); LibAmdMemCopy ((VOID *) ((ACPI_TABLE_HEADER *) *SsdtPtr)->OemTableId, (VOID *) &OptionPstateLateConfiguration.OemTableIdString, sizeof (OptionPstateLateConfiguration.OemTableIdString), StdHeader); IntermediatePtr = (UINT8 *) *SsdtPtr; ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)]; SocketCount = AmdPstatePtr->TotalSocketInSystem; // Generate name scope and ACPI objects for every core in the system for (i = 0; i < SocketCount; i++) { MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode; for (j = 0; j < MaxCorePerNode; j++) { CoreCount++; // Set Name Scope for CPU0, 1, 2, ..... n // CPU0 to CPUn will name as C000 to Cnnn // ----------------------------------------- ScopeAcpiTablesStructPtr->ScopeOpcode = SCOPE_OPCODE; // This value will be filled at the end of this function // Since at this time, we don't know how many Pstates we // would have ScopeAcpiTablesStructPtr->ScopeLength = 0; ScopeAcpiTablesStructPtr->ScopeValue1 = SCOPE_VALUE1; ScopeAcpiTablesStructPtr->ScopeValue2 = SCOPE_VALUE2; ScopeAcpiTablesStructPtr->ScopeNamePt1a__ = SCOPE_NAME__; if (PlatformConfig->ProcessorScopeInSb) { ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_S; ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_B; } else { ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_P; ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_R; } ScopeAcpiTablesStructPtr->ScopeNamePt1b__ = SCOPE_NAME__; ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z')); ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \ ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \ (PlatformConfig->ProcessorScopeName1 == '_')); ScopeAcpiTablesStructPtr->ScopeNamePt2a_C = PlatformConfig->ProcessorScopeName0; ScopeAcpiTablesStructPtr->ScopeNamePt2a_P = PlatformConfig->ProcessorScopeName1; TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F; ScopeAcpiTablesStructPtr->ScopeNamePt2a_U = (UINT8) (SCOPE_NAME_0 + TempVar8_a); TempVar8_a = (CoreCount - 1) & 0x0F; if (TempVar8_a < 0xA) { ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_0 + TempVar8_a); } else { ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA); } // Increment and typecast the pointer ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr; ScopeAcpiTablesStructPtrTemp++; // Get the Local Apic Id for each core LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j; // Create P-State ACPI Objects CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader)); // Create C-State ACPI Objects CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader)); // Now update the SCOPE Length field { CurrSize += (SCOPE_STRUCT_SIZE - 1); ScopeSize += CurrSize; TempVar_b = ((CurrSize << 4) & 0x0000FF00); TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040); TempVar_a = TempVar_b; ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a; CurrSize = 0; } ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp; } //Calculate next node buffer address PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES))); } //Update SSDT header Checksum ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER)); ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader); return AGESA_SUCCESS; } /**-------------------------------------------------------------------------------------- * * CreateAcpiTablesStub * * Description: * This is the default routine for use when the P-State or C-State option is NOT * requested. The option install process will create and fill the transfer vector * with the address of the proper routine (Main or Stub). The link optimizer will * strip out of the .DLL the routine that is not used. * * Parameters: * @param[in] PlatformConfig Platform operational characteristics; power cap * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information * @param[in,out] SsdtPtr ACPI SSDT table pointer * @param[in] LocalApicId Local Apic Id * @param[in] StdHeader Handle to config for library and services * * @retval Size of generated ACPI objects * *--------------------------------------------------------------------------------------- **/ UINT32 CreateAcpiTablesStub ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ) { return 0; } /**-------------------------------------------------------------------------------------- * * CreatePStateAcpiTables * * Description: * This is the common routine for creating ACPI P-State objects * * Parameters: * @param[in] PlatformConfig Platform operational characteristics; power cap * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information * @param[in,out] SsdtPtr ACPI SSDT table pointer * @param[in] LocalApicId Local Apic Id * @param[in] StdHeader Handle to config for library and services * * @retval Size of generated ACPI P-States objects * *--------------------------------------------------------------------------------------- **/ UINT32 CreatePStateAcpiTables ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PstateCapLevelSupport; UINT8 PStateMaxValueOnCurrentCore; BOOLEAN PstateCapEnable; BOOLEAN PstateCapLevelSupportDetermined; BOOLEAN IsPsdDependent; UINT32 k; UINT32 TempVar_a; UINT32 TempVar_b; UINT32 TempVar_c; UINT32 PstateCapInputMilliWatts; UINT32 CurrSize; UINT32 PstateCount; UINT32 CoreCount1; UINT32 TransAndBusMastLatency; UINT32 EffectivePstatesPsdPolicy; AGESA_STATUS IgnoredStatus; PCI_ADDR PciAddress; PCT_HEADER_BODY *pPctAcpiTables; PSS_HEADER *pPssHeaderAcpiTables; PSS_BODY *pPssBodyAcpiTables; XPSS_HEADER *pXpssHeaderAcpiTables; XPSS_BODY *pXpssBodyAcpiTables; PSD_HEADER *pPsdHeaderAcpiTables; PSD_BODY *pPsdBodyAcpiTables; PPC_HEADER_BODY *pPpcAcpiTables; PSTATE_CPU_FAMILY_SERVICES *FamilyServices; CurrSize = 0; PstateCount = 0; PstateCapEnable = FALSE; PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP; PstateCapLevelSupportDetermined = TRUE; PstateCapInputMilliWatts = PlatformConfig->PowerCeiling; ASSERT (PlatformConfig->PstatesPsdPolicy < PsdPolicyMax); EffectivePstatesPsdPolicy = PlatformConfig->PstatesPsdPolicy; // Runtime P-state dependence settings conflict check and consolidation if (PlatformConfig->ForcePstateIndependent) { switch (EffectivePstatesPsdPolicy) { case PsdPolicyProcessorDefault: // Consolidate P-state dependence setings EffectivePstatesPsdPolicy = PsdPolicyIndependent; break; case PsdPolicyDependent: // Ensure P-state dependence settings do not conflict IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD dependence settings conflict between ForcePstateIndependent and PstatesPsdPolicy. PstatesPsdPolicy will take precedence.\n"); ASSERT (FALSE); break; case PsdPolicyIndependent: // Do nothing. Two interfaces have the same setting. break; default: // Invalid setting, overrides to processor default. IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD dependence settings invalid! Override PstatesPsdPolicy to PsdPolicyProcessorDefault.\n"); EffectivePstatesPsdPolicy = PsdPolicyProcessorDefault; break; } } TransAndBusMastLatency = 0; if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) { pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr; //Check Pstate Capability if (PstateCapInputMilliWatts != 0) { PstateCapEnable = TRUE; PstateCapLevelSupportDetermined = FALSE; } PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue; if (OptionPstateLateConfiguration.CfgPstatePct) { // Set _PCT Table // -------------- pPctAcpiTables->NameOpcode = NAME_OPCODE; pPctAcpiTables->PctName_a__ = PCT_NAME__; pPctAcpiTables->PctName_a_P = PCT_NAME_P; pPctAcpiTables->PctName_a_C = PCT_NAME_C; pPctAcpiTables->PctName_a_T = PCT_NAME_T; pPctAcpiTables->Value1 = PCT_VALUE1; pPctAcpiTables->Value2 = PCT_VALUE2; pPctAcpiTables->Value3 = PCT_VALUE3; pPctAcpiTables->GenericRegDescription1 = GENERIC_REG_DESCRIPTION; pPctAcpiTables->Length1 = PCT_LENGTH; pPctAcpiTables->AddressSpaceId1 = PCT_ADDRESS_SPACE_ID; pPctAcpiTables->RegisterBitWidth1 = PCT_REGISTER_BIT_WIDTH; pPctAcpiTables->RegisterBitOffset1 = PCT_REGISTER_BIT_OFFSET; pPctAcpiTables->Reserved1 = PCT_RESERVED; pPctAcpiTables->ControlRegAddressLo = PCT_CONTROL_REG_LO; pPctAcpiTables->ControlRegAddressHi = PCT_CONTROL_REG_HI; pPctAcpiTables->Value4 = PCT_VALUE4; pPctAcpiTables->Value5 = PCT_VALUE5; pPctAcpiTables->GenericRegDescription2 = GENERIC_REG_DESCRIPTION; pPctAcpiTables->Length2 = PCT_LENGTH; pPctAcpiTables->AddressSpaceId2 = PCT_ADDRESS_SPACE_ID; pPctAcpiTables->RegisterBitWidth2 = PCT_REGISTER_BIT_WIDTH; pPctAcpiTables->RegisterBitOffset2 = PCT_REGISTER_BIT_OFFSET; pPctAcpiTables->Reserved2 = PCT_RESERVED; pPctAcpiTables->StatusRegAddressLo = PCT_STATUS_REG_LO; pPctAcpiTables->StatusRegAddressHi = PCT_STATUS_REG_HI; pPctAcpiTables->Value6 = PCT_VALUE6; // Increment and then typecast the pointer pPctAcpiTables++; CurrSize += PCT_STRUCT_SIZE; *SsdtPtr = pPctAcpiTables; } // end of OptionPstateLateConfiguration.CfgPstatePct pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables; pPssBodyAcpiTables = (PSS_BODY *) pPctAcpiTables; if (OptionPstateLateConfiguration.CfgPstatePss) { // Set _PSS Header // Note: Set pssLength and numOfItemsInPss later //--------------------------------------------------- pPssHeaderAcpiTables->NameOpcode = NAME_OPCODE; pPssHeaderAcpiTables->PssName_a__ = PSS_NAME__; pPssHeaderAcpiTables->PssName_a_P = PSS_NAME_P; pPssHeaderAcpiTables->PssName_a_S = PSS_NAME_S; pPssHeaderAcpiTables->PssName_b_S = PSS_NAME_S; pPssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; pPssHeaderAcpiTables++; pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables; // Restore the pPssHeaderAcpiTables pPssHeaderAcpiTables--; // Set _PSS Body //--------------- PstateCount = 0; // Calculate PCI address for socket only GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus); TransAndBusMastLatency = 0; GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader); ASSERT (FamilyServices != NULL); FamilyServices->GetPstateLatency ( FamilyServices, PStateLevelingBuffer, &PciAddress, &TransAndBusMastLatency, StdHeader); for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) { pPssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; pPssBodyAcpiTables->PkgLength = PSS_PKG_LENGTH; pPssBodyAcpiTables->NumOfElements = PSS_NUM_OF_ELEMENTS; pPssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->Frequency = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq; pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->Power = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power; if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) { PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; PstateCapLevelSupportDetermined = TRUE; } pPssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency; pPssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency; pPssBodyAcpiTables->DwordPrefixOpcode5 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->Control = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE; pPssBodyAcpiTables->Status = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; pPssBodyAcpiTables++; PstateCount++; } } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++) if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) { PstateCapLevelSupport = PStateMaxValueOnCurrentCore; } // Set _PSS Header again // Now Set pssLength and numOfItemsInPss //--------------------------------------- TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3; TempVar_b = TempVar_a; TempVar_c = ((TempVar_b << 4) & 0x0000FF00); TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040); TempVar_a = (UINT16) TempVar_c; pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a; pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount; CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE)); *SsdtPtr = pPssBodyAcpiTables; } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss // Set XPSS Table //--------------- // Typecast the pointer pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables; pXpssBodyAcpiTables = (XPSS_BODY *) pPssBodyAcpiTables; if (OptionPstateLateConfiguration.CfgPstateXpss) { // Set XPSS Header // Note: Set the pssLength and numOfItemsInPss later //--------------------------------------------------- pXpssHeaderAcpiTables->NameOpcode = NAME_OPCODE; pXpssHeaderAcpiTables->XpssName_a_X = PSS_NAME_X; pXpssHeaderAcpiTables->XpssName_a_P = PSS_NAME_P; pXpssHeaderAcpiTables->XpssName_a_S = PSS_NAME_S; pXpssHeaderAcpiTables->XpssName_b_S = PSS_NAME_S; pXpssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; // Increment and then typecast the pointer pXpssHeaderAcpiTables++; pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables; // Restore the pXpssHeaderAcpiTables pXpssHeaderAcpiTables--; // Set XPSS Body //--------------- for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) { pXpssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; pXpssBodyAcpiTables->PkgLength = XPSS_PKG_LENGTH; pXpssBodyAcpiTables->NumOfElements = XPSS_NUM_OF_ELEMENTS; pXpssBodyAcpiTables->XpssValueTbd = 04; pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; pXpssBodyAcpiTables->Frequency = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq; pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; pXpssBodyAcpiTables->Power = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power; pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; pXpssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency; pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE; pXpssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency; pXpssBodyAcpiTables->ControlBuffer = XPSS_ACPI_BUFFER; pXpssBodyAcpiTables->ControlLo = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; pXpssBodyAcpiTables->ControlHi = 0; pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER; pXpssBodyAcpiTables->StatusLo = PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; pXpssBodyAcpiTables->StatusHi = 0; pXpssBodyAcpiTables->ControlMaskBuffer = XPSS_ACPI_BUFFER; pXpssBodyAcpiTables->ControlMaskLo = 0; pXpssBodyAcpiTables->ControlMaskHi = 0; pXpssBodyAcpiTables->StatusMaskBuffer = XPSS_ACPI_BUFFER; pXpssBodyAcpiTables->StatusMaskLo = 0; pXpssBodyAcpiTables->StatusMaskHi = 0; pXpssBodyAcpiTables++; } } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++) // Set XPSS Header again // Now set pssLength and numOfItemsInPss //--------------------------------------- TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3; TempVar_b = TempVar_a; TempVar_c = ((TempVar_b << 4) & 0x0000FF00); TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040); TempVar_a = (UINT16) TempVar_c; pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a; pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount; CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE)); *SsdtPtr = pXpssBodyAcpiTables; } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss // Set _PSD Table //--------------- // Typecast the pointer pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables; pPsdBodyAcpiTables = (PSD_BODY *) pXpssBodyAcpiTables; // Get Total Cores Per Node if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) { GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader); ASSERT (FamilyServices != NULL); if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) && FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) { // Set _PSD Header //---------------- pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE; pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH; pPsdHeaderAcpiTables->Value1 = PSD_VALUE1; pPsdHeaderAcpiTables->PsdName_a__ = PSD_NAME__; pPsdHeaderAcpiTables->PsdName_a_P = PSD_NAME_P; pPsdHeaderAcpiTables->PsdName_a_S = PSD_NAME_S; pPsdHeaderAcpiTables->PsdName_a_D = PSD_NAME_D; // Typecast the pointer pPsdHeaderAcpiTables++; CurrSize += PSD_HEADER_STRUCT_SIZE; pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables; pPsdHeaderAcpiTables--; // Set _PSD Body //-------------- pPsdBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; pPsdBodyAcpiTables->PkgLength = PSD_PKG_LENGTH; pPsdBodyAcpiTables->NumOfEntries = NUM_OF_ENTRIES; pPsdBodyAcpiTables->BytePrefixOpcode1 = BYTE_PREFIX_OPCODE; pPsdBodyAcpiTables->PsdNumOfEntries = PSD_NUM_OF_ENTRIES; pPsdBodyAcpiTables->BytePrefixOpcode2 = BYTE_PREFIX_OPCODE; pPsdBodyAcpiTables->PsdRevision = PSD_REVISION; pPsdBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; if (EffectivePstatesPsdPolicy == PsdPolicyProcessorDefault) { IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader); } else { if (EffectivePstatesPsdPolicy == PsdPolicyDependent) { IsPsdDependent = TRUE; } else { IsPsdDependent = FALSE; } IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD is forced by interface choice as dependent: %d\n", IsPsdDependent); } if (IsPsdDependent) { pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN; pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL; pPsdBodyAcpiTables->NumOfProcessors = CoreCount1; } else { switch (GetComputeUnitMapping (StdHeader)) { case AllCoresMapping: // All cores are in their own compute unit. pPsdBodyAcpiTables->DependencyDomain = LocalApicId; pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY; pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS; break; case EvenCoresMapping: // Two cores per compute unit. pPsdBodyAcpiTables->DependencyDomain = LocalApicId >> 1; pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL; pPsdBodyAcpiTables->NumOfProcessors = PSD_TWO_CORES_PER_COMPUTE_UNIT; break; case TripleCoresMapping: // Three cores per compute unit. pPsdBodyAcpiTables->DependencyDomain = LocalApicId / 3; pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL; pPsdBodyAcpiTables->NumOfProcessors = PSD_THREE_CORES_PER_COMPUTE_UNIT; break; case QuadCoresMapping: // Four cores per compute unit. pPsdBodyAcpiTables->DependencyDomain = LocalApicId >> 2; pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL; pPsdBodyAcpiTables->NumOfProcessors = PSD_FOUR_CORES_PER_COMPUTE_UNIT; break; default: ASSERT (FALSE); } } pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; pPsdBodyAcpiTables++; *SsdtPtr = pPsdBodyAcpiTables; CurrSize += PSD_BODY_STRUCT_SIZE; } }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd) // Typecast the pointer pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables; // Set _PPC Table //--------------- if (OptionPstateLateConfiguration.CfgPstatePpc) { // Name (PPCV, value) pPpcAcpiTables->NameOpcode = NAME_OPCODE; pPpcAcpiTables->PpcName_a_P = PPC_NAME_P; pPpcAcpiTables->PpcName_b_P = PPC_NAME_P; pPpcAcpiTables->PpcName_a_C = PPC_NAME_C; pPpcAcpiTables->PpcName_a_V = PPC_NAME_V; pPpcAcpiTables->Value1 = PPC_VALUE1; pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport; // Method (_PPC) { return (PPCV) } pPpcAcpiTables->MethodOpcode = METHOD_OPCODE; pPpcAcpiTables->PpcLength = PPC_METHOD_LENGTH; pPpcAcpiTables->PpcName_a__ = PPC_NAME__; pPpcAcpiTables->PpcName_c_P = PPC_NAME_P; pPpcAcpiTables->PpcName_d_P = PPC_NAME_P; pPpcAcpiTables->PpcName_b_C = PPC_NAME_C; pPpcAcpiTables->MethodFlags = PPC_METHOD_FLAGS; pPpcAcpiTables->ReturnOpcode = RETURN_OPCODE; pPpcAcpiTables->PpcName_e_P = PPC_NAME_P; pPpcAcpiTables->PpcName_f_P = PPC_NAME_P; pPpcAcpiTables->PpcName_c_C = PPC_NAME_C; pPpcAcpiTables->PpcName_b_V = PPC_NAME_V; CurrSize += PPC_HEADER_BODY_STRUCT_SIZE; // Increment and typecast the pointer pPpcAcpiTables++; *SsdtPtr = pPpcAcpiTables; }// end of OptionPstateLateConfiguration.CfgPstatePpc } return CurrSize; } /**-------------------------------------------------------------------------------------- * * CreateCStateAcpiTables * * Description: * This is the common routine for creating ACPI C-State objects * * Parameters: * @param[in] PlatformConfig Platform operational characteristics; power cap * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information * @param[in,out] SsdtPtr ACPI SSDT table pointer * @param[in] LocalApicId Local Apic Id * @param[in] StdHeader Handle to config for library and services * * @retval Size of ACPI C-States objects generated * *--------------------------------------------------------------------------------------- **/ UINT32 CreateCStateAcpiTables ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN PSTATE_LEVELING *PStateLevelingBuffer, IN OUT VOID **SsdtPtr, IN UINT8 LocalApicId, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 ObjSize; IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices; ObjSize = 0; if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) { GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader); if (IoCstateFamilyServices != NULL) { IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader); ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader); } } return ObjSize; }