/** * Initialize Machine Check Architecture registers * * This function initializes the MCA MSRs. On cold reset, these registers * have an invalid data that must be cleared on all cores. * * @param[in] StdHeader Config handle for library and services * *--------------------------------------------------------------------------------------- */ VOID McaInitialization ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT16 TempVar16_a; UINT32 MsrAddress; UINT64 MsrData; CPUID_DATA CpuIdDataStruct; if (!(IsWarmReset (StdHeader))) { // Run CPUID to verify that the processor supports MCE and MCA // i.e. edx[7], and edx[14] // CPUID_MODEL = 1 LibAmdCpuidRead (1, &CpuIdDataStruct, StdHeader); if ((CpuIdDataStruct.EDX_Reg & 0x4080) != 0) { // Check to see if the MCG_CTL_P bit is set // MCG = Global Machine Check Exception Reporting Control Register LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader); if ((MsrData & MCG_CTL_P) != 0) { TempVar16_a = (UINT16) ((MsrData & 0x000000FF) << 2); TempVar16_a += MSR_MC0_CTL; // Initialize the data MsrData = 0; for (MsrAddress = MSR_MC0_CTL; MsrAddress < TempVar16_a; MsrAddress++) { LibAmdMsrWrite (MsrAddress, &MsrData, StdHeader); } } } } }
/** * Get this AP's system core number from hardware. * * @CpuServiceMethod{::F_CPU_GET_AP_CORE_NUMBER}. * * Returns the system core number from the scratch MSR, where * it was saved at heap initialization. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * * @return The AP's unique core number */ UINT32 F16MlGetApCoreNumber ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CONFIG_PARAMS *StdHeader ) { CPUID_DATA Cpuid; LibAmdCpuidRead (0x1, &Cpuid, StdHeader); return ((Cpuid.EBX_Reg >> 24) & 0xFF); }
/** * Return the number of cores (1 based count) on Node. * * @TopoNbMethod{::F_GET_NUM_CORES_ON_NODE} * * @param[in] Node the Node that will be examined * @param[in] Nb this northbridge * * @return the number of cores */ UINT8 Fam16GetNumCoresOnNode ( IN UINT8 Node, IN NORTHBRIDGE *Nb ) { CPUID_DATA CpuidData; ASSERT (Node == 0); LibAmdCpuidRead (0x80000008, &CpuidData, Nb->ConfigHandle); return (UINT8) ((CpuidData.ECX_Reg & 0xFF) + 1); }
/** * Get number of processor cores to be used in determining the brand string. * * @CpuServiceMethod{::F_CPU_NUMBER_OF_BRANDSTRING_CORES}. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * * @return The number of cores to be used in brand string calculation. */ UINT8 F14GetNumberOfCoresForBrandstring ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CONFIG_PARAMS *StdHeader ) { CPUID_DATA CpuId; // //CPUID.80000008h.ECX.NC + 1, 000b = 1, 001b = 2, etc. // LibAmdCpuidRead (CPUID_LONG_MODE_ADDR, &CpuId, StdHeader); return ((UINT8) ((CpuId.ECX_Reg & 0xff) + 1)); }
/** * ValidateFchVariant - Validate FCH Variant * * * * @param[in] FchDataPtr * */ VOID ValidateFchVariant ( IN VOID *FchDataPtr ) { CPUID_DATA CpuId; FCH_DATA_BLOCK *LocalCfgPtr; AMD_CONFIG_PARAMS *StdHeader; LocalCfgPtr = (FCH_DATA_BLOCK *) FchDataPtr; StdHeader = LocalCfgPtr->StdHeader; LibAmdCpuidRead (CPUID_FMF, &CpuId, StdHeader); LocalCfgPtr->Misc.FchCpuId = ( UINT32 ) (CpuId.EAX_Reg & 0xFFFFFFFF); }
/** * Get CPU pstate current. * * @CpuServiceMethod{::F_CPU_GET_IDD_MAX}. * * This function returns the ProcIddMax. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] Pstate The P-state to check. * @param[out] ProcIddMax P-state current in mA. * @param[in] StdHeader Handle of Header for calling lib functions and services. * * @retval TRUE P-state is enabled * @retval FALSE P-state is disabled */ BOOLEAN F15OrGetProcIddMax ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN UINT8 Pstate, OUT UINT32 *ProcIddMax, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 IddDiv; UINT32 NumberOfPhysicalCores; UINT32 MsrAddress; UINT64 PstateMsr; BOOLEAN IsPstateEnabled; CPUID_DATA CpuId; IsPstateEnabled = FALSE; MsrAddress = (UINT32) (Pstate + PS_REG_BASE); ASSERT (MsrAddress <= PS_MAX_REG); LibAmdMsrRead (MsrAddress, &PstateMsr, StdHeader); if (((PSTATE_MSR *) &PstateMsr)->PsEnable == 1) { switch (((PSTATE_MSR *) &PstateMsr)->IddDiv) { case 0: IddDiv = 1000; break; case 1: IddDiv = 100; break; case 2: IddDiv = 10; break; default: // IddDiv = 3 is reserved. Use 10 IddDiv = 10; break; } LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuId, StdHeader); NumberOfPhysicalCores = ((CpuId.ECX_Reg & 0xFF) + 1); *ProcIddMax = (UINT32) ((PSTATE_MSR *) &PstateMsr)->IddValue * IddDiv * NumberOfPhysicalCores; IsPstateEnabled = TRUE; } return IsPstateEnabled; }
/** * ProgramSpecificFchInitEnvAcpiMmio - Config HwAcpi MMIO before * PCI emulation * * * * @param[in] FchDataPtr Fch configuration structure pointer. * */ VOID ProgramSpecificFchInitEnvAcpiMmio ( IN VOID *FchDataPtr ) { CPUID_DATA CpuId; FCH_DATA_BLOCK *LocalCfgPtr; AMD_CONFIG_PARAMS *StdHeader; LocalCfgPtr = (FCH_DATA_BLOCK *) FchDataPtr; StdHeader = LocalCfgPtr->StdHeader; ProgramFchAcpiMmioTbl ((ACPI_REG_WRITE*) (&FchYangtzeInitEnvSpecificHwAcpiMmioTable[0]), StdHeader); LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuId, StdHeader); if ((LocalCfgPtr->HwAcpi.AnyHt200MhzLink) || ((CpuId.EAX_Reg & 0x00ff00f0) == 0x100080) || ((CpuId.EAX_Reg & 0x00ff00f0) == 0x100090) || ((CpuId.EAX_Reg & 0x00ff00f0) == 0x1000A0)) { RwMem (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG94, AccessWidth8, 0, 0x0A); RwMem (ACPI_MMIO_BASE + PMIO_BASE + 0x80 + 3, AccessWidth8, 0xFE, 0x28); } else { RwMem (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG94, AccessWidth8, 0, 0x01); RwMem (ACPI_MMIO_BASE + PMIO_BASE + 0x80 + 3, AccessWidth8, 0xFE, 0x20); } RwMem (ACPI_MMIO_BASE + MISC_BASE + FCH_MISC_REG6C + 2, AccessWidth8, 0x5F, 0xA0); // // Ac Loss Control // AcLossControl ((UINT8) LocalCfgPtr->HwAcpi.PwrFailShadow); // // FCH VGA Init // FchVgaInit (); // // Set ACPIMMIO by OEM Input table // ProgramFchAcpiMmioTbl ((ACPI_REG_WRITE *) (LocalCfgPtr->HwAcpi.OemProgrammingTablePtr), StdHeader); }
/** * This function initializes the heap for each CPU core. * * Check for already initialized. If not, determine offset of local heap in CAS and * setup initial heap markers and bookkeeping status. Also create an initial event log. * * @param[in] StdHeader Handle of Header for calling lib functions and services. * * @retval AGESA_SUCCESS This core's heap is initialized * @retval AGESA_FATAL This core's heap cannot be initialized due to any reasons below: * - current processor family cannot be identified. * */ AGESA_STATUS HeapManagerInit ( IN AMD_CONFIG_PARAMS *StdHeader ) { // First Time Initialization // Note: First 16 bytes of buffer is reserved for Heap Manager use UINT16 HeapAlreadyInitSizeDword; UINT32 HeapAlreadyRead; UINT8 L2LineSize; UINT8 *HeapBufferPtr; UINT8 *HeapInitPtr; UINT32 *HeapDataPtr; UINT64 MsrData; UINT64 MsrMask; UINT8 Ignored; CPUID_DATA CpuId; BUFFER_NODE *FreeSpaceNode; CACHE_INFO *CacheInfoPtr; CPU_SPECIFIC_SERVICES *FamilySpecificServices; CPU_LOGICAL_ID CpuFamilyRevision; // Check whether this is a known processor family. GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader); if ((CpuFamilyRevision.Family == 0) && (CpuFamilyRevision.Revision == 0)) { IDS_ERROR_TRAP; return AGESA_FATAL; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader); HeapBufferPtr = (UINT8 *) StdHeader->HeapBasePtr; // Check whether the heap manager is already initialized LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrData, StdHeader); if (!IsSecureS3 (StdHeader)) { if (MsrData == (CacheInfoPtr->VariableMtrrMask & AMD_HEAP_MTRR_MASK)) { LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader); if ((MsrData & CacheInfoPtr->HeapBaseMask) == ((UINT64) (UINTN) HeapBufferPtr & CacheInfoPtr->HeapBaseMask)) { if (((HEAP_MANAGER *) HeapBufferPtr)->Signature == HEAP_SIGNATURE_VALID) { // This is not a bug, there are multiple premem basic entry points, // and each will call heap init to make sure create struct will succeed. // If that is later deemed a problem, there needs to be a reasonable test // for the calling code to make to determine if it needs to init heap or not. // In the mean time, add this to the event log PutEventLog (AGESA_SUCCESS, CPU_ERROR_HEAP_IS_ALREADY_INITIALIZED, 0, 0, 0, 0, StdHeader); return AGESA_SUCCESS; } } } // Set variable MTRR base and mask MsrData = ((UINT64) (UINTN) HeapBufferPtr & CacheInfoPtr->HeapBaseMask); MsrMask = CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK; MsrData |= 0x06; LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader); LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrMask, StdHeader); // Set top of memory to a temp value LibAmdMsrRead (TOP_MEM, &MsrData, StdHeader); if (AMD_TEMP_TOM > MsrData) { MsrData = (UINT64) (AMD_TEMP_TOM); LibAmdMsrWrite (TOP_MEM, &MsrData, StdHeader); } } // Enable variable MTTRs LibAmdMsrRead (SYS_CFG, &MsrData, StdHeader); MsrData |= AMD_VAR_MTRR_ENABLE_BIT; LibAmdMsrWrite (SYS_CFG, &MsrData, StdHeader); // Initialize Heap Space // BIOS may store to a line only after it has been allocated by a load LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuId, StdHeader); L2LineSize = (UINT8) (CpuId.ECX_Reg); HeapInitPtr = HeapBufferPtr ; for (HeapAlreadyRead = 0; HeapAlreadyRead < AMD_HEAP_SIZE_PER_CORE; (HeapAlreadyRead = HeapAlreadyRead + L2LineSize)) { Ignored = *HeapInitPtr; HeapInitPtr += L2LineSize; } HeapDataPtr = (UINT32 *) HeapBufferPtr; for (HeapAlreadyInitSizeDword = 0; HeapAlreadyInitSizeDword < AMD_HEAP_SIZE_DWORD_PER_CORE; HeapAlreadyInitSizeDword++) { *HeapDataPtr = 0; HeapDataPtr++; } // Note: We are reserving the first 16 bytes for Heap Manager use // UsedSize indicates the size of heap spaced is used for HEAP_MANAGER, BUFFER_NODE, // Pad for 16-byte alignment, buffer data, and IDS SENTINEL. // FirstActiveBufferOffset is initalized as invalid heap offset, AMD_HEAP_INVALID_HEAP_OFFSET. // FirstFreeSpaceOffset is initalized as the byte right after HEAP_MANAGER header. // Then we set Signature of HEAP_MANAGER header as valid, HEAP_SIGNATURE_VALID. ((HEAP_MANAGER*) HeapBufferPtr)->UsedSize = sizeof (HEAP_MANAGER); ((HEAP_MANAGER*) HeapBufferPtr)->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET; ((HEAP_MANAGER*) HeapBufferPtr)->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER); ((HEAP_MANAGER*) HeapBufferPtr)->Signature = HEAP_SIGNATURE_VALID; // Create free space link FreeSpaceNode = (BUFFER_NODE *) (HeapBufferPtr + sizeof (HEAP_MANAGER)); FreeSpaceNode->BufferSize = AMD_HEAP_SIZE_PER_CORE - sizeof (HEAP_MANAGER) - sizeof (BUFFER_NODE); FreeSpaceNode->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; StdHeader->HeapStatus = HEAP_LOCAL_CACHE; EventLogInitialization (StdHeader); return AGESA_SUCCESS; }