/** * Topology Services Initialization. * * Build the system topology data structures. Initialize hardware values needed * for correct fabric operation, such as core count. * * @param[in] StdHeader Opaque handle to standard config header * @param[in] PlatformConfiguration The platform configuration options. * * @retval AGESA_SUCCESS Only information events logged. * */ AGESA_STATUS AmdTopologyInitialize ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfiguration ) { STATE_DATA State; NORTHBRIDGE Nb; State.ConfigHandle = StdHeader; State.PlatformConfiguration = PlatformConfiguration; // Initialize for status and event output State.MaxEventClass = AGESA_SUCCESS; // Allocate permanent heap structs that are interfaces to other AGESA services. NewNodeAndSocketTables (&State); if (IsBootCore (&State)) { AGESA_TESTPOINT (TpProcTopologyEntry, State.ConfigHandle); // Create the BSP's northbridge. NewNorthBridge (0, &State, &Nb); State.Nb = &Nb; CoherentInit (&State); AGESA_TESTPOINT (TpProcTopologyDone, State.ConfigHandle); } else { // Do the AP Topology Init, which produces Node and Socket Maps for the AP's use. NewNorthBridge (0, &State, &Nb); State.Nb = &Nb; InitApMaps (&State); } return State.MaxEventClass; }
/** * The top level external interface for Hypertransport Initialization. * * Create our initial internal state, initialize the coherent fabric, * initialize the non-coherent chains, and perform any required fabric tuning or * optimization. * * @param[in] StdHeader Opaque handle to standard config header * @param[in] PlatformConfiguration The platform configuration options. * @param[in] AmdHtInterface HT Interface structure. * * @retval AGESA_SUCCESS Only information events logged. * @retval AGESA_ALERT Sync Flood or CRC error logged. * @retval AGESA_WARNING Example: expected capability not found * @retval AGESA_ERROR logged events indicating some devices may not be available * @retval AGESA_FATAL Mixed Family or MP capability mismatch * */ AGESA_STATUS AmdHtInitialize ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfiguration, IN AMD_HT_INTERFACE *AmdHtInterface ) { STATE_DATA State; NORTHBRIDGE Nb; HT_FEATURES HtFeatures; HT_INTERFACE HtInterface; AGESA_STATUS DeallocateStatus; AP_MAIL_INFO ApMailboxInfo; UINT8 ApNode; ALLOCATE_HEAP_PARAMS AllocHeapParams; State.HtBlock = AmdHtInterface; State.ConfigHandle = StdHeader; State.PlatformConfiguration = PlatformConfiguration; // Get the current HT internal interface (to HtBlock data) NewHtInterface (&HtInterface, State.ConfigHandle); State.HtInterface = &HtInterface; // Get the current HT Feature Set NewHtFeatures (&HtFeatures, State.ConfigHandle); State.HtFeatures = &HtFeatures; // Initialize from static options State.IsUsingRecoveryHt = OptionHtConfiguration.IsUsingRecoveryHt; State.IsSetHtCrcFlood = OptionHtConfiguration.IsSetHtCrcFlood; State.IsUsingUnitIdClumping = OptionHtConfiguration.IsUsingUnitIdClumping; // Initialize for status and event output State.MaxEventClass = AGESA_SUCCESS; // Allocate permanent heap structs that are interfaces to other AGESA services. State.HtInterface->NewNodeAndSocketTables (&State); if (IsBootCore (&State)) { AGESA_TESTPOINT (TpProcHtEntry, State.ConfigHandle); // Allocate Bsp only interface heap structs. State.HtInterface->NewHopCountTable (&State); // Allocate heap for our temporary working space. AllocHeapParams.RequestedBufferSize = (sizeof (PORT_DESCRIPTOR) * (MAX_PLATFORM_LINKS * 2)); AllocHeapParams.BufferHandle = HT_STATE_DATA_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, State.ConfigHandle) == AGESA_SUCCESS) { State.PortList = (PORT_LIST)AllocHeapParams.BufferPtr; // Create the BSP's northbridge. NewNorthBridge (0, &State, &Nb); State.Nb = &Nb; CoherentInit (&State); NcInit (&State); LinkOptimization (&State); Tuning (&State); DeallocateStatus = HeapDeallocateBuffer (HT_STATE_DATA_HANDLE, State.ConfigHandle); ASSERT (DeallocateStatus == AGESA_SUCCESS); AGESA_TESTPOINT (TpProcHtDone, State.ConfigHandle); } else { ASSERT (FALSE); State.MaxEventClass = AGESA_ERROR; // Cannot Log entry due to heap allocate failed. } } else { // Do the AP HT Init, which produces Node and Socket Maps for the AP's use. AGESA_TESTPOINT (TpProcHtApMapEntry, State.ConfigHandle); GetApMailbox (&ApMailboxInfo.Info, State.ConfigHandle); ASSERT (ApMailboxInfo.Fields.Node < MAX_NODES); ApNode = (UINT8)ApMailboxInfo.Fields.Node; NewNorthBridge (ApNode, &State, &Nb); State.Nb = &Nb; InitApMaps (&State); AGESA_TESTPOINT (TpProcHtApMapDone, State.ConfigHandle); } return State.MaxEventClass; }
/** * Update maps with the core range for each module. * * Cores are numbered relative to a Processor, but sometimes there is a need to know the * starting and ending core ids on a particular node. This same info is also useful for * supporting the Core count on a node other than the one currently executing. * * For each Processor, get the core count of each node using the family specific PCI core count * interface. The order of cores in a processor, and whether it is special for the BSP is family * specific. But whether the processor orders core ids by module or node, iterate in the right * order and use the counts to determine each start and end range. * * Update compute unit status for each node. * * @param[in] State number of Nodes discovered. */ VOID STATIC UpdateCoreRanges ( IN STATE_DATA *State ) { UINT8 Node; UINT8 ProcessorCores; UINT8 ModuleCoreCount[MAX_DIES]; UINT8 Socket; UINT8 Module; ASSERT (State->SocketDieToNodeMap != NULL); ASSERT (State->NodeToSocketDieMap != NULL); for (Socket = 0; Socket < MAX_SOCKETS; Socket++) { // Is a Processor present in Socket? if ((*State->SocketDieToNodeMap)[Socket][0].Node != HT_LIST_TERMINAL) { // Get all the Module core counts for this processor // Note that the core counts are 1 based counts. // Since Compute Unit info is not module ordering dependent, write it now. for (Module = 0; Module < MAX_DIES; Module++) { if ((*State->SocketDieToNodeMap)[Socket][Module].Node != HT_LIST_TERMINAL) { ModuleCoreCount[Module] = State->Nb->GetNumCoresOnNode ((*State->SocketDieToNodeMap)[Socket][Module].Node, State->Nb); (*State->SocketDieToNodeMap)[Socket][Module].EnabledComputeUnits = State->Nb->GetEnabledComputeUnits ((*State->SocketDieToNodeMap)[Socket][Module].Node, State->Nb); (*State->SocketDieToNodeMap)[Socket][Module].DualCoreComputeUnits = State->Nb->GetDualCoreComputeUnits ((*State->SocketDieToNodeMap)[Socket][Module].Node, State->Nb); } else { ModuleCoreCount[Module] = 0; } } // Determine the core ordering rule for this processor. if ((((*State->NodeToSocketDieMap)[0].Socket == Socket) && State->Nb->IsOrderBSPCoresByNode) || (!State->Nb->IsOrderCoresByModule)) { // Order core ranges on this processor by Node Id. ProcessorCores = 0; for (Node = 0; Node < State->Nb->GetNodeCount (State->Nb); Node++) { // Is this node a module in this processor? if ((*State->NodeToSocketDieMap)[Node].Socket == Socket) { Module = (*State->NodeToSocketDieMap)[Node].Die; if (ModuleCoreCount[Module] != 0) { (*State->SocketDieToNodeMap)[Socket][Module].LowCore = ProcessorCores; (*State->SocketDieToNodeMap)[Socket][Module].HighCore = ProcessorCores + (ModuleCoreCount[Module] - 1); IDS_HDT_CONSOLE ( HT_TRACE, (IsBootCore (State) ? "Topology: Socket %d, Die %d, is Node %d, with Cores %d thru %d. Compute Unit status (0x%x,0x%x).\n" : ""), Socket, Module, Node, (*State->SocketDieToNodeMap)[Socket][Module].LowCore, (*State->SocketDieToNodeMap)[Socket][Module].HighCore, (*State->SocketDieToNodeMap)[Socket][Module].EnabledComputeUnits, (*State->SocketDieToNodeMap)[Socket][Module].DualCoreComputeUnits ); ProcessorCores = ProcessorCores + ModuleCoreCount[Module]; } } } } else { // Order core ranges in this processor by Module Id. ProcessorCores = 0; for (Module = 0; Module < MAX_DIES; Module++) { if (ModuleCoreCount[Module] != 0) { (*State->SocketDieToNodeMap)[Socket][Module].LowCore = ProcessorCores; (*State->SocketDieToNodeMap)[Socket][Module].HighCore = ProcessorCores + (ModuleCoreCount[Module] - 1); IDS_HDT_CONSOLE ( HT_TRACE, (IsBootCore (State) ? "Topology: Socket %d, Die %d, is Node %d, with Cores %d thru %d. Compute Unit status (0x%x,0x%x).\n" : ""), Socket, Module, (*State->SocketDieToNodeMap)[Socket][Module].Node, (*State->SocketDieToNodeMap)[Socket][Module].LowCore, (*State->SocketDieToNodeMap)[Socket][Module].HighCore, (*State->SocketDieToNodeMap)[Socket][Module].EnabledComputeUnits, (*State->SocketDieToNodeMap)[Socket][Module].DualCoreComputeUnits ); ProcessorCores = ProcessorCores + ModuleCoreCount[Module]; } } } } } }