/** * @brief This function updates the NVDIMM firmware code */ void call_nvdimm_update() { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ENTER_MRK"call_nvdimm_update()"); TARGETING::TargetHandleList l_nvdimmTargetList; TARGETING::TargetHandleList l_procList; TARGETING::getAllChips(l_procList, TARGETING::TYPE_PROC, false); // grab the NVDIMMs under each processor and add to overall list for (auto l_proc : l_procList) { TARGETING::TargetHandleList tmpList = TARGETING::getProcNVDIMMs(l_proc); l_nvdimmTargetList.insert(l_nvdimmTargetList.end(), tmpList.begin(), tmpList.end()); } // Run the nvdimm update function if the list is not empty if ( !l_nvdimmTargetList.empty() ) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "call_nvdimm_update(): found %d nvdimms to check for update", l_nvdimmTargetList.size()); bool updateWorked = NVDIMM::nvdimm_update(l_nvdimmTargetList); if (!updateWorked) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "call_nvdimm_update(): nvdimm update failed"); } } TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,EXIT_MRK"call_nvdimm_update()"); }
//Swaps chip at location 0 with a chip at location i_chipToFront void FabricDomain::MoveToFrontInTheseChips(uint32_t i_chipToFront, TARGETING::TargetHandleList & i_chips) { using namespace TARGETING; for (TargetHandleList::iterator i = i_chips.begin()+i_chipToFront; i != i_chips.begin(); i--) { std::swap((*i), (*(i-1))); } }
//Analyze a subset of chips in a Domain... //This is a mini analysis of some of the chips in the Fabric Domain. int32_t FabricDomain::AnalyzeTheseChips(STEP_CODE_DATA_STRUCT & serviceData, ATTENTION_TYPE attentionType, TARGETING::TargetHandleList & i_chips) { using namespace TARGETING ; PRDF_DENTER( "FabricDomain::AnalyzeTheseChips" ); int32_t l_rc = ~SUCCESS; PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips:: Domain ID = 0x%X", GetId() ); if(i_chips.size() != 0) { for (TargetHandleList::iterator i = i_chips.begin(); i != i_chips.end(); ++i) { PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips::Before--chip=0x%X", PlatServices::getHuid(*i)); } OrderTheseChips(attentionType, i_chips); for (TargetHandleList::iterator i = i_chips.begin(); i != i_chips.end(); ++i) { PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips::After--chip=0x%X", PlatServices::getHuid(*i) ); } //After the Order function is called the first chip should contain the chip to look at. //Look here for the correct LookUp function. I don't think this is working. RuleChip * l_fabChip = FindChipInTheseChips(i_chips[0], i_chips); PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips::Analyzing this one: 0x%X", l_fabChip->GetId() ); if(NULL != l_fabChip) { l_rc = l_fabChip->Analyze(serviceData, attentionType); } else { PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips::l_fabChip is NULL" ); l_rc = ~SUCCESS; } } else { PRDF_DTRAC( "FabricDomain::AnalyzeTheseChips::i_chips = %d", i_chips.size() ); } //Get P7 chip Global FIR data for FFDC for (TargetHandleList::iterator i = i_chips.begin(); i != i_chips.end(); ++i) { RuleChip * l_fabChip = FindChipInTheseChips(*i, i_chips); l_fabChip->CaptureErrorData( serviceData.service_data->GetCaptureData(), Util::hashString("GlobalFIRs")); } PRDF_DEXIT( "FabricDomain::AnalyzeTheseChips" ); return l_rc; }
//***************************************************************************** // resetBackupTopology //***************************************************************************** errlHndl_t resetBackupTopology( uint32_t i_oscPos, const TARGETING::TargetHandle_t& i_procOscTgt, const TARGETING::TargetHandleList& i_badChipList, bool i_informPhyp) { TOD_ENTER("resetBackupTopology"); errlHndl_t l_err = nullptr; // Put the handle to the firmware_request request struct // out here so it is easier to free later hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr; hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr; do { if ((nullptr == g_hostInterfaces) || (nullptr == g_hostInterfaces->firmware_request)) { TOD_ERR("resetBackupTopology: " "Hypervisor firmware_request interface not linked"); /*@ * @errortype * @severity ERRL_SEV_UNRECOVERABLE * @moduleid TOD_RT_TOPOLOGY_RESET_BACKUP * @reasoncode TOD_RT_NULL_FIRMWARE_REQUEST_PTR * @userdata1 None * @userdata2 None * @devdesc Host interfaces are not initialized * @custdesc An internal error occurred. This will * force the Time of Day function to run * with complete redundancy. */ l_err = new ErrlEntry( ERRL_SEV_UNRECOVERABLE, TOD_RT_TOPOLOGY_RESET_BACKUP, TOD_RT_NULL_FIRMWARE_REQUEST_PTR, 0, 0, true); break; } // The format of the data to be sent, according to the document // "Handle PRD Request for resetting backup TOD topology" is as follows // All data members below are 4 bytes long (32 bits) // Ordinal ID - 0xFFFFFFFF means no OSC to be avoided // HUID of the node - This field should be considered only if Ordinal // ID is NOT set to 0xFFFFFFFF otherwise it is set // to 0 // HUID of the first processor // HUID of the second processor, etc // Check if we get conflicting data, if so send a Trace out if ((0xFFFFFFFF == i_oscPos) && (nullptr != i_procOscTgt)) { TOD_ERR("Conflicting input data, input oscillator position " "(i_oscPos) has value 0xFFFFFFFF, meaning no oscillator " "to be avoided but input oscillator target (i_procOscTgt) " "has a valid value" ); } else if ((0xFFFFFFFF != i_oscPos) && (nullptr == i_procOscTgt)) { TOD_ERR("Conflicting input data, input oscillator position " "(i_oscPos) has value 0x%X, meaning avoid oscillator " "but input oscillator target (i_procOscTgt) " "has a NULL value", i_oscPos); } // Flag to determine if the OSC data will be added to the data bool l_addOscData = (0xFFFFFFFF != i_oscPos) && (nullptr != i_procOscTgt); // Default the request data size to the size of the // GenericFspMboxMessage_t minus the size of the // GenericFspMboxMessage_t's data. The size of the // GenericFspMboxMessage_t's data will be added later uint32_t l_req_data_size = sizeof(GenericFspMboxMessage_t) - sizeof(GenericFspMboxMessage_t::data); // Add to the request data size iff there is data needing to be passed if (i_badChipList.size() > 0) { // if the bad chip list has any items then increase size to // accommodate for an ordinal ID and a HUID, regardless if // they have relevant data or not, because they are expected // before the HUID list. l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)) + (i_badChipList.size() * sizeof(uint32_t)); } else if (l_addOscData) { // if there is a valid OSC then accommodate for an ordinal ID // and HUID of node, but don't need space for HUID list because, // if we are here, the list is empty l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)); } // The request data size must be at a minimum the size of the // FSP generic message (sizeof(GenericFspMboxMessage_t)) if (l_req_data_size < sizeof(GenericFspMboxMessage_t)) { l_req_data_size = sizeof(GenericFspMboxMessage_t); } // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to // the previous calculated request data size uint64_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + l_req_data_size; // Create the firmware_request request struct to send data l_req_fw_msg = (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); // Initialize the firmware_request request struct l_req_fw_msg->generic_msg.initialize(); // Populate the firmware_request request struct with given data l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; l_req_fw_msg->generic_msg.dataSize = l_req_data_size; l_req_fw_msg->generic_msg.msgq = MBOX::FSP_TOD_MSGQ; l_req_fw_msg->generic_msg.msgType = (false == i_informPhyp ? GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET: GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET_INFORM_PHYP); l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST; // A convenient way to populate the data uint32_t* l_dataPtr = reinterpret_cast<uint32_t*>(&(l_req_fw_msg->generic_msg.data)); if (i_badChipList.size() > 0) { // set the ordinal ID l_dataPtr[MSG_OSC_ORDINAL_ID_LOC] = i_oscPos; // attach the HUIDs from bad chip list to end of struct size_t i = MSG_OSC_HUIDS_LOC; for (auto l_target : i_badChipList) { l_dataPtr[i++] = GETHUID(l_target); } } // Set the HUID of the ordinal node if need be if (l_addOscData) { // set the ordinal ID l_dataPtr[MSG_OSC_ORDINAL_ID_LOC] = i_oscPos; // Get the parent node target TARGETING::TargetHandleList l_list; TARGETING::targetService().getAssociated(l_list, i_procOscTgt, TARGETING::TargetService::PARENT, TARGETING::TargetService::IMMEDIATE); if (l_list.size() == 1) { l_dataPtr[MSG_OSC_ORDINAL_NODE_HUID_LOC] = GETHUID(l_list[0]); } else { /*@ * @errortype * @severity ERRL_SEV_UNRECOVERABLE * @moduleid TOD_RT_TOPOLOGY_RESET_BACKUP * @reasoncode TOD_INVALID_TARGET * @userdata1 The number of parents found osc target * @userdata2 None * @devdesc No/Multiple parent(s) found for * processor osc target * @custdesc An internal error occurred. This will * force the Time of Day function to run * with complete redundancy. */ l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, TOD_RT_TOPOLOGY_RESET_BACKUP, TOD_INVALID_TARGET, l_list.size(), 0, true); break; } } // Create the firmware_request response struct to receive data // NOTE: For messages to the FSP the response size must match // the request size uint64_t l_resp_fw_msg_size = l_req_fw_msg_size; l_resp_fw_msg = (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size); memset(l_resp_fw_msg, 0, l_resp_fw_msg_size); // Trace out the request structure TRACFBIN(ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK"TOD::Sending firmware_request", l_req_fw_msg, l_req_fw_msg_size); // Make the firmware_request call l_err = firmware_request_helper(l_req_fw_msg_size, l_req_fw_msg, &l_resp_fw_msg_size, l_resp_fw_msg); if (l_err) { break; } } while (0); // Release the firmware messages free(l_req_fw_msg); free(l_resp_fw_msg); l_req_fw_msg = l_resp_fw_msg = nullptr; TOD_EXIT("resetBackupTopology"); return l_err; } // end resetBackupTopology
int32_t FabricDomain::OrderTheseChips(ATTENTION_TYPE attentionType, TARGETING::TargetHandleList & i_chips) { using namespace PluginDef; using namespace TARGETING; PRDF_DENTER( "FabricDomain::OrderTheseChips" ); uint32_t l_internalOnlyCount = 0; uint64_t l_externalDrivers[i_chips.size()]; uint64_t l_wofValues[i_chips.size()]; bool l_internalCS[i_chips.size()]; union { uint64_t * u; CPU_WORD * c; } ptr; uint32_t l_chip = 0; uint32_t l_chipToFront = 0; // Get internal setting and external driver list for each chip. for (TargetHandleList::iterator i = i_chips.begin(); i != i_chips.end(); ++i) { RuleChip * l_fabChip = FindChipInTheseChips(*i, i_chips); ptr.u = &l_externalDrivers[l_chip]; BitString l_externalChips(i_chips.size(), ptr.c); TargetHandleList l_tmpList; if(l_fabChip != NULL) { // Call "GetCheckstopInfo" plugin. ExtensibleChipFunction * l_extFunc = l_fabChip->getExtensibleFunction("GetCheckstopInfo"); (*l_extFunc)(l_fabChip, bindParm<bool &, TargetHandleList &, uint64_t &> (l_internalCS[l_chip], l_tmpList, l_wofValues[l_chip] ) ); } else { l_internalCS[l_chip] = false; PRDF_DTRAC( "FabricDomain::OrderTheseChips: l_fabChip is NULL" ); } //If we are just checking for internal errors then there is no need for //a list of what chips sent checkstops where. // Update bit buffer. for (TargetHandleList::iterator j = l_tmpList.begin(); j != l_tmpList.end(); ++j) { for (uint32_t k = 0; k < i_chips.size(); k++) if ((*j) == LookUp(k)->GetChipHandle()) l_externalChips.Set(k); }; // Check if is internal. if (l_internalCS[l_chip]) { l_internalOnlyCount++; l_chipToFront = l_chip; } l_chip++; //Move to next chip in the list. } // Check if we are done... only one with an internal error. if (1 == l_internalOnlyCount) { MoveToFrontInTheseChips(l_chipToFront, i_chips); return(SUCCESS); } PRDF_DEXIT( "FabricDomain::OrderTheseChips" ); return(SUCCESS); }
// Notify HTMGT that an OCC has failed and needs to be reset void processOccReset(TARGETING::Target * i_proc) { TMGT_INF(">>processOccReset(0x%p)", i_proc); errlHndl_t errl = NULL; TARGETING::Target * failedOccTarget = NULL; TARGETING::Target* sys = NULL; TARGETING::targetService().getTopLevelTarget(sys); uint8_t safeMode = 0; // If the system is in safemode then ignore request to reset OCCs if(sys && sys->tryGetAttr<TARGETING::ATTR_HTMGT_SAFEMODE>(safeMode) && safeMode) { return; } // Get functional OCC (one per proc) TARGETING::TargetHandleList pOccs; getChildChiplets(pOccs, i_proc, TARGETING::TYPE_OCC); if (pOccs.size() > 0) { failedOccTarget = pOccs[0]; } if(NULL != failedOccTarget) { uint32_t huid = failedOccTarget->getAttr<TARGETING::ATTR_HUID>(); TMGT_INF("processOccReset(HUID=0x%08X) called", huid); } else { uint32_t huid = i_proc->getAttr<TARGETING::ATTR_HUID>(); TMGT_INF("processOccReset: Invalid OCC target (proc huid=0x08X)" "resetting OCCs anyway", huid); /*@ * @errortype * @reasoncode HTMGT_RC_INVALID_PARAMETER * @moduleid HTMGT_MOD_PROCESS_OCC_RESET * @userdata1[0:7] Processor HUID * @devdesc No OCC target found for proc Target, */ bldErrLog(errl, HTMGT_MOD_PROCESS_OCC_RESET, HTMGT_RC_INVALID_PARAMETER, huid, 0, 0, 1, ERRORLOG::ERRL_SEV_INFORMATIONAL); // Add HB firmware callout errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_MED); ERRORLOG::errlCommit(errl, HTMGT_COMP_ID); // sets errl to NULL } errl = OccManager::resetOccs(failedOccTarget); if(errl) { ERRORLOG::errlCommit(errl, HTMGT_COMP_ID); // sets errl to NULL } TMGT_INF("<<processOccReset()"); } // end processOccReset()
// Notify HTMGT that an OCC has an error to report void processOccError(TARGETING::Target * i_procTarget) { TMGT_INF(">>processOccError(0x%p)", i_procTarget); TARGETING::Target* sys = NULL; TARGETING::targetService().getTopLevelTarget(sys); uint8_t safeMode = 0; // If the system is in safemode then can't talk to OCCs - // ignore call to processOccError if(sys && sys->tryGetAttr<TARGETING::ATTR_HTMGT_SAFEMODE>(safeMode) && safeMode) { return; } bool polledOneOcc = false; errlHndl_t err = OccManager::buildOccs(); if (NULL == err) { if (i_procTarget != NULL) { const uint32_t l_huid = i_procTarget->getAttr<TARGETING::ATTR_HUID>(); TMGT_INF("processOccError(HUID=0x%08X) called", l_huid); TARGETING::TargetHandleList pOccs; getChildChiplets(pOccs, i_procTarget, TARGETING::TYPE_OCC); if (pOccs.size() > 0) { // Poll specified OCC flushing any errors errlHndl_t err = OccManager::sendOccPoll(true, pOccs[0]); if (err) { ERRORLOG::errlCommit(err, HTMGT_COMP_ID); } polledOneOcc = true; } } if ((OccManager::getNumOccs() > 1) || (false == polledOneOcc)) { // Send POLL command to all OCCs to flush any other errors errlHndl_t err = OccManager::sendOccPoll(true); if (err) { ERRORLOG::errlCommit(err, HTMGT_COMP_ID); } } if (OccManager::occNeedsReset()) { TMGT_ERR("processOccError(): OCCs need to be reset"); // Don't pass failed target as OCC should have already // been marked as failed during the poll. errlHndl_t err = OccManager::resetOccs(NULL); if(err) { ERRORLOG::errlCommit(err, HTMGT_COMP_ID); } } } else { // OCC build failed... TMGT_ERR("processOccError() called, but unable to find OCCs"); ERRORLOG::errlCommit(err, HTMGT_COMP_ID); } TMGT_INF("<<processOccError()"); } // end processOccError()
/** * @brief Returns the runtime target ID for a given targeting target for all * hypervisors other than PHyp * @param[in] i_pTarget Targeting target, must not be NULL (asserts * otherwise) * @param[out] o_rtTargetId Runtime target ID which maps to the given targeting * target * @return Error log handle * @retval NULL Computed a valid runtime target ID for the given input * targeting target and returned it in the output parameter. * @retval !NULL Failed to compute a runtime target ID for the given input * targeting target. Ignore output parameter. */ errlHndl_t computeNonPhypRtTarget( const TARGETING::Target* i_pTarget, RT_TARG::rtChipId_t& o_rtTargetId) { assert(i_pTarget != NULL); errlHndl_t pError = NULL; do { if(i_pTarget == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL) { TARGETING::Target* masterProcChip = NULL; TARGETING::targetService(). masterProcChipTargetHandle(masterProcChip); i_pTarget = masterProcChip; } auto targetingTargetType = i_pTarget->getAttr<TARGETING::ATTR_TYPE>(); if(targetingTargetType == TARGETING::TYPE_PROC) { uint32_t fabId = i_pTarget->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>(); uint32_t procPos = i_pTarget->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>(); o_rtTargetId = PIR_t::createChipId( fabId, procPos ); } else if( targetingTargetType == TARGETING::TYPE_MEMBUF) { //MEMBUF // 0b1000.0000.0000.0000.0000.0GGG.GCCC.MMMM // where GGGG is group, CCC is chip, MMMM is memory channel // TARGETING::TargetHandleList targetList; getParentAffinityTargets(targetList, i_pTarget, TARGETING::CLASS_UNIT, TARGETING::TYPE_DMI); if( targetList.empty() ) { auto huid = get_huid(i_pTarget); TRACFCOMP(g_trac_runtime, ERR_MRK "No associated DMI targeting target(s) found for MEMBUF " "targeting target with HUID of 0x%08X", huid); /*@ * @error * @moduleid RUNTIME::MOD_CUST_COMP_NON_PHYP_RT_TARGET * @reasoncode RUNTIME::RT_UNIT_TARGET_NOT_FOUND * @userdata1 MEMBUF targeting target's HUID * @devdesc No associated DMI targeting target(s) found for * given MEMBUF targeting target */ pError = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, RUNTIME::MOD_CUST_COMP_NON_PHYP_RT_TARGET, RUNTIME::RT_UNIT_TARGET_NOT_FOUND, huid, 0, true); ERRORLOG::ErrlUserDetailsTarget(i_pTarget,"Targeting Target"). addToLog(pError); break; } auto target = targetList[0]; auto pos = target->getAttr<TARGETING::ATTR_CHIP_UNIT>(); targetList.clear(); getParentAffinityTargets(targetList, target, TARGETING::CLASS_CHIP, TARGETING::TYPE_PROC); if(targetList.empty()) { pError = createProcNotFoundError(target); break; } auto procTarget = targetList[0]; pError = computeNonPhypRtTarget(procTarget, o_rtTargetId); if(pError) { break; } o_rtTargetId = (o_rtTargetId << RT_TARG::MEMBUF_ID_SHIFT); o_rtTargetId += pos; o_rtTargetId |= HBRT_MEMBUF_TYPE; } else if(targetingTargetType == TARGETING::TYPE_CORE) { // CORE // 0b0100.0000.0000.0000.0000.GGGG.CCCP.PPPP // GGGG is group, CCC is chip, PPPPP is core auto pos = i_pTarget->getAttr<TARGETING::ATTR_CHIP_UNIT>(); const TARGETING::Target* procTarget = getParentChip(i_pTarget); if(procTarget == NULL) { pError = createProcNotFoundError(i_pTarget); break; } pError = computeNonPhypRtTarget(procTarget, o_rtTargetId); if(pError) { break; } o_rtTargetId = PIR_t::createCoreId(o_rtTargetId,pos); o_rtTargetId |= HBRT_CORE_TYPE; } else { auto huid = get_huid(i_pTarget); TRACFCOMP(g_trac_runtime,ERR_MRK "Targeting target type 0x%08X not supported. Cannot " "convert targeting target with HUID of 0x%08X into a " "runtime target ID", targetingTargetType, huid); /*@ * @errortype * @moduleid RUNTIME::MOD_CUST_COMP_NON_PHYP_RT_TARGET * @reasoncode RUNTIME::RT_TARGET_TYPE_NOT_SUPPORTED * @userdata1 Targeting target's HUID * @userdata2 Targeting target's type * @devdesc The targeting type of the input targeting target is * not supported by runtime code */ pError = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, RUNTIME::MOD_CUST_COMP_NON_PHYP_RT_TARGET, RUNTIME::RT_TARGET_TYPE_NOT_SUPPORTED, huid, targetingTargetType, true); ERRORLOG::ErrlUserDetailsTarget(i_pTarget,"Targeting Target"). addToLog(pError); } } while(0); return pError; }
//****************************************************************************** // fenceAttachedMembufs - helper function for hwp proc_cen_ref_clk_enable //****************************************************************************** void fenceAttachedMembufs( TARGETING::Target * i_procTarget ) { errlHndl_t l_errl = NULL; TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Fencing attached (present) membuf chips downstream from " "proc chip with HUID of 0x%08X", i_procTarget->getAttr<TARGETING::ATTR_HUID>()); // Get list of membuf chips downstream from the given proc chip TARGETING::TargetHandleList MembufChipList; getChildAffinityTargetsByState( MembufChipList, const_cast<TARGETING::Target*>(i_procTarget ), TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF, TARGETING::UTIL_FILTER_PRESENT); // loop through the membufs for(TARGETING::TargetHandleList::const_iterator pTargetItr = MembufChipList.begin(); pTargetItr != MembufChipList.end(); pTargetItr++) { //Get CFAM "1012" -- FSI GP3 and set bits 23-27 (various fence bits) //Note 1012 is ecmd addressing, real address is 0x1048 (byte) uint64_t l_addr = 0x1048; const uint32_t l_fence_bits= 0x000001F0; uint32_t l_data = 0; size_t l_size = sizeof(uint32_t); l_errl = deviceRead(*pTargetItr, &l_data, l_size, DEVICE_FSI_ADDRESS(l_addr)); if (l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Failed getcfam 1012 to HUID 0x%08X, ignoring, skipping", (*pTargetItr)->getAttr<TARGETING::ATTR_HUID>()); delete l_errl; l_errl = NULL; continue; } l_data |= l_fence_bits; l_errl = deviceWrite(*pTargetItr, &l_data, l_size, DEVICE_FSI_ADDRESS(l_addr)); if (l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Failed putcfam 1012 to HUID 0x%08X, ignoring, skipping", (*pTargetItr)->getAttr<TARGETING::ATTR_HUID>()); delete l_errl; l_errl = NULL; continue; } } }
//****************************************************************************** // call_proc_cen_ref_clock_enable //****************************************************************************** void* call_proc_cen_ref_clk_enable(void *io_pArgs ) { errlHndl_t l_errl = NULL; IStepError l_stepError; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_cen_ref_clock_enable enter" ); TARGETING::TargetHandleList functionalProcChipList; getAllChips(functionalProcChipList, TYPE_PROC, true); // loop thru the list of processors for (TargetHandleList::const_iterator l_proc_iter = functionalProcChipList.begin(); l_proc_iter != functionalProcChipList.end(); ++l_proc_iter) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "target HUID %.8X", TARGETING::get_huid( *l_proc_iter )); uint8_t l_membufsAttached = 0; // get a bit mask of present/functional dimms assocated with // this processor l_membufsAttached = getMembufsAttachedBitMask( *l_proc_iter ); //Perform a workaround for GA1 to raise fences on centaurs //to prevent FSP from analyzing if HB TIs for recoverable //errors //RTC 106276 fenceAttachedMembufs( *l_proc_iter ); TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "passing target HUID %.8X and 0x%x mask", TARGETING::get_huid( *l_proc_iter ), l_membufsAttached ); if( l_membufsAttached ) { fapi::Target l_fapiProcTarget( fapi::TARGET_TYPE_PROC_CHIP, *l_proc_iter ); // Invoke the HWP passing in the proc target and // a bit mask indicating connected centaurs FAPI_INVOKE_HWP(l_errl, proc_cen_ref_clk_enable, l_fapiProcTarget, l_membufsAttached ); if (l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "ERROR : proc_cen_ref_clk_enable", "failed, returning errorlog" ); // capture the target data in the elog ErrlUserDetailsTarget( *l_proc_iter ).addToLog( l_errl ); // Create IStep error log and cross ref error that occurred l_stepError.addErrorDetails( l_errl ); // Commit error log errlCommit( l_errl, HWPF_COMP_ID ); } else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "SUCCESS : proc_cen_ref_clk_enable", "completed ok"); } } } // endfor TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_cen_ref_clock_enable exit" ); // end task, returning any errorlogs to IStepDisp return l_stepError.getErrorHandle(); }
//****************************************************************************** // getMembufsAttachedBitMask - helper function for hwp proc_cen_ref_clk_enable //****************************************************************************** uint8_t getMembufsAttachedBitMask( TARGETING::Target * i_procTarget ) { const uint8_t MCS_WITH_ATTACHED_CENTAUR_MASK = 0x80; TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Finding functional membuf chips downstream from " "proc chip with HUID of 0x%08X", i_procTarget->getAttr<TARGETING::ATTR_HUID>()); uint8_t l_attachedMembufs = 0; // Get list of functional membuf chips downstream from the given // proc chip TARGETING::TargetHandleList functionalMembufChipList; getChildAffinityTargets( functionalMembufChipList, const_cast<TARGETING::Target*>(i_procTarget ), TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF, true); // loop through the functional membufs for(TARGETING::TargetHandleList::const_iterator pTargetItr = functionalMembufChipList.begin(); pTargetItr != functionalMembufChipList.end(); pTargetItr++) { // Find each functional membuf chip's upstream functional MCS // unit, if any, and accumulate it into the attached membuf // chips mask TARGETING::TargetHandleList functionalMcsUnitList; getParentAffinityTargets( functionalMcsUnitList, *pTargetItr, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS, true ); if(functionalMcsUnitList.empty()) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Functional membuf chip with HUID of 0x%08X " "is not attached to an upstream functional MCS", (*pTargetItr)->getAttr< TARGETING::ATTR_HUID>()); continue; } TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Found functional MCS unit with HUID of 0x%08X " "upstream from functional membuf chip with HUID of 0x%08X", ((*functionalMcsUnitList.begin())->getAttr< TARGETING::ATTR_CHIP_UNIT>()), (*pTargetItr)->getAttr< TARGETING::ATTR_HUID>()); l_attachedMembufs |= ((MCS_WITH_ATTACHED_CENTAUR_MASK) >> ((*functionalMcsUnitList.begin())->getAttr< TARGETING::ATTR_CHIP_UNIT>())); } TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Proc chip with HUID of 0x%08X has attached membuf " "mask (l_attachedMembufs) of 0x%02X", i_procTarget->getAttr<TARGETING::ATTR_HUID>(), l_attachedMembufs); // return the bitmask return l_attachedMembufs; }
// ------------------------------------------------------------------ // dimmPresenceDetect // ------------------------------------------------------------------ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, int64_t i_accessType, va_list i_args ) { errlHndl_t err = NULL; bool present = false; size_t presentSz = sizeof(present); TRACSSCOMP( g_trac_spd, ENTER_MRK"dimmPresenceDetect()" ); do { // Check to be sure that the buffer is big enough. if( !(io_buflen >= sizeof(bool)) ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() - Invalid Data Length: %d", io_buflen ); /*@ * @errortype * @reasoncode VPD::VPD_INSUFFICIENT_BUFFER_SIZE * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid VPD::VPD_SPD_PRESENCE_DETECT * @userdata1 Buffer Length * @userdata2 <UNUSED> * @devdesc Buffer for checking Presence Detect * was not the correct size. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, VPD::VPD_SPD_PRESENCE_DETECT, VPD::VPD_INSUFFICIENT_BUFFER_SIZE, TO_UINT64(io_buflen), 0x0, true /*Add HB Software Callout*/); err->collectTrace( "SPD", 256); break; } // Is the target present #ifdef CONFIG_DJVPD_READ_FROM_HW // Check if the parent MBA/MEMBUF is present. If it is not then // no reason to check the DIMM which would otherwise generate // tons of FSI errors. We can't just check if parent MBA // is functional because DIMM presence detect is called before // the parent MBA/MEMBUF is set as present/functional. TARGETING::TargetHandleList membufList; TARGETING::PredicateCTM membufPred( TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF ); TARGETING::targetService().getAssociated( membufList, i_target, TARGETING::TargetService::PARENT_BY_AFFINITY, TARGETING::TargetService::ALL, &membufPred); bool parentPresent = false; const TARGETING::TargetHandle_t membufTarget = *(membufList.begin()); err = deviceRead(membufTarget, &parentPresent, presentSz, DEVICE_PRESENT_ADDRESS()); if (err) { TRACFCOMP( g_trac_spd, "Error reading parent MEMBUF present: huid 0x%X DIMM huid 0x%X", TARGETING::get_huid(membufTarget), TARGETING::get_huid(i_target) ); break; } if (!parentPresent) { present = false; // Invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" ); } break; } #endif present = spdPresent( i_target ); if( present == false ) { TRACUCOMP( g_trac_spd, INFO_MRK"Dimm was found to be NOT present." ); } else { TRACUCOMP( g_trac_spd, INFO_MRK"Dimm was found to be present." ); } #if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR) if( present ) { // Check if the VPD data in the PNOR matches the SEEPROM err = VPD::ensureCacheIsInSync( i_target ); if( err ) { present = false; TRACFCOMP(g_trac_spd,ERR_MRK "dimmPresenceDetectt> Error during ensureCacheIsInSync (SPD)" ); break; } } else { // SPD is not present, invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" ); } } #endif if( present && !err ) { //Fsp sets PN/SN so if there is none, do it here if(!INITSERVICE::spBaseServicesEnabled()) { //populate serial and part number attributes SPD::setPartAndSerialNumberAttributes( i_target ); } // Read ATTR_CLEAR_DIMM_SPD_ENABLE attribute TARGETING::Target* l_sys = NULL; TARGETING::targetService().getTopLevelTarget(l_sys); TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE_type l_clearSPD = l_sys->getAttr<TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE>(); // If SPD clear is enabled then write 0's into magic word for // DIMM_BAD_DQ_DATA keyword // Note: If there's an error from performing the clearing, // just log the error and continue. if (l_clearSPD) { size_t l_size = 0; // Do a read to get the DIMM_BAD_DQ_DATA keyword size err = deviceRead(i_target, NULL, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP(g_trac_spd, "dimmPresenceDetect - " "Error reading DIMM_BAD_DQ_DATA keyword size"); errlCommit( err, VPD_COMP_ID ); } else { // Clear the data TRACFCOMP( g_trac_spd, "Clearing out BAD_DQ_DATA SPD on " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); uint8_t * l_data = static_cast<uint8_t*>(malloc( l_size )); memset(l_data, 0, l_size); err = deviceWrite(i_target, l_data, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP( g_trac_spd, "Error trying to clear SPD on " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); errlCommit( err, VPD_COMP_ID ); } // Free the memory if (NULL != l_data) { free(l_data); } } } } // copy present value into output buffer so caller can read it memcpy( io_buffer, &present, presentSz ); io_buflen = presentSz; } while( 0 ); TRACSSCOMP( g_trac_spd, EXIT_MRK"dimmPresenceDetect()" ); return err; } // end dimmPresenceDetect
errlHndl_t initiateDrtm() { SB_ENTER("initiateDrtm"); errlHndl_t pError = nullptr; // For DRTM, the thread has to be pinned to a core (and therefore pinned to // a chip) task_affinity_pin(); void* drtmPayloadVirtAddr = nullptr; do { const std::vector<SECUREBOOT::ProcSecurity> LLP { SECUREBOOT::ProcSecurity::LLPBit, }; const std::vector<SECUREBOOT::ProcSecurity> LLS { SECUREBOOT::ProcSecurity::LLSBit, }; // Determine which fabric group and chip this task is executing on and // create a filter to find the matching chip target auto cpuId = task_getcpuid(); auto groupId = PIR_t::groupFromPir(cpuId); auto chipId = PIR_t::chipFromPir(cpuId); TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_GROUP_ID> matchesGroup(groupId); TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_CHIP_ID> matchesChip(chipId); TARGETING::PredicatePostfixExpr matchesGroupAndChip; matchesGroupAndChip.push(&matchesGroup).push(&matchesChip).And(); // Get all the functional proc chips and find the chip we're running on TARGETING::TargetHandleList funcProcChips; TARGETING::getAllChips(funcProcChips, TARGETING::TYPE_PROC); if(funcProcChips.empty()) { // TODO: RTC 167205: GA error handling assert(false,"initiateDrtm: BUG! Functional proc chips is empty, " "yet this code is running on a functional chip!"); break; } // NOTE: std::find_if requires predicates to be copy constructable, but // predicates are not; hence use a wrapper lambda function to bypass // that limitation auto pMatch = std::find_if(funcProcChips.begin(),funcProcChips.end(), [&matchesGroupAndChip] ( TARGETING::Target* pTarget ) { return matchesGroupAndChip(pTarget); } ); if(pMatch == funcProcChips.end()) { // TODO: RTC 167205: GA error handling assert(false, "initiateDrtm: BUG! No functional chip found " "to be running this code"); break; } // Move the matching target to the end of the list. // NOTE: If reverse iterators were supported, we could have verified the // last element of the container is not the match, and done a // std::iter_swap of the match and the last element TARGETING::Target* const pMatchTarget = *pMatch; funcProcChips.erase(pMatch); funcProcChips.push_back(pMatchTarget); // Map to the DRTM payload area in mainstore const uint32_t drtmPayloadPhysAddrMb = DRTM_RIT_PAYLOAD_PHYS_ADDR_MB; drtmPayloadVirtAddr = mm_block_map( reinterpret_cast<void*>(drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE), PAGESIZE); if(drtmPayloadVirtAddr == nullptr) { // TODO: RTC 167205: GA error handling assert(false, "initiateDrtm: BUG! Failed in call to mm_block_map " "to map the DRTM payload."); break; } // Copy the DRTM payload to the DRTM payload area memcpy( reinterpret_cast<uint32_t*>(drtmPayloadVirtAddr), DRTM_RIT_PAYLOAD, sizeof(DRTM_RIT_PAYLOAD)); // The required generic sequencing to initiate DRTM is as follows: // 1) Initiating task must pin itself to a core (to ensure it // will not be accidentally queisced by SBE) // 2) It must set the DRTM payload information in the master processor // mailbox scratch registers (registers 7 and 8) before it goes // offline // 3) It must determine the processor it's currently running on // 4) It must set the late launch bit (LL) on all other processors // 4a) If the given processor is an active master, it must set // late launch primary (LLP) bit // 4b) Otherwise it must set late launch secondary (LLS) bit // 5) Finally, it must its own processor's LL bit last, according to the // rules of step 4. for(auto &pFuncProc :funcProcChips) { const auto procMasterType = pFuncProc->getAttr< TARGETING::ATTR_PROC_MASTER_TYPE>(); // If master chip, set the DRTM payload address and validity if(procMasterType == TARGETING::PROC_MASTER_TYPE_ACTING_MASTER) { (void)setDrtmPayloadPhysAddrMb(drtmPayloadPhysAddrMb); } pError = SECUREBOOT::setSecuritySwitchBits(procMasterType == TARGETING::PROC_MASTER_TYPE_ACTING_MASTER ? LLP : LLS, pFuncProc); if(pError) { SB_ERR("initiateDrtm: setSecuritySwitchBits() failed for proc " "= 0x%08X. Tried to set LLP or LLS.", get_huid(pFuncProc)); break; } } if(pError) { break; } SB_INF("initiateDrtm: SBE should eventually quiesce all cores; until " "then, endlessly yield the task"); while(1) { task_yield(); } } while(0); // If we -do- come back from this function (on error path only), then we // should unpin task_affinity_unpin(); if(drtmPayloadVirtAddr) { auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr)); if(rc != 0) { // TODO: RTC 167205: GA error handling assert(false,"initiateDrtm: BUG! mm_block_unmap failed for virtual " "address 0x%16llX.", drtmPayloadVirtAddr); } } if(pError) { SB_ERR("initiateDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X", ERRL_GETPLID_SAFE(pError), ERRL_GETEID_SAFE(pError), ERRL_GETRC_SAFE(pError)); } SB_EXIT("initiateDrtm"); return pError; }
errlHndl_t configureHbrtHypIds(const bool i_configForPhyp) { TRACDCOMP( g_trac_runtime, ENTER_MRK "configureHbrtHypIds" ); errlHndl_t pError = NULL; TARGETING::PredicateCTM isaProc( TARGETING::CLASS_CHIP, TARGETING::TYPE_PROC); TARGETING::PredicateCTM isaMembuf( TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF); TARGETING::PredicateCTM isaCore( TARGETING::CLASS_UNIT, TARGETING::TYPE_CORE); TARGETING::PredicatePostfixExpr isaProcMembufOrCore; isaProcMembufOrCore.push(&isaProc).push(&isaMembuf).Or() .push(&isaCore).Or(); TARGETING::TargetRangeFilter pIt( TARGETING::targetService().begin(), TARGETING::targetService().end(), &isaProcMembufOrCore); for (; pIt; ++pIt) { auto hbrtHypId = HBRT_HYP_ID_UNKNOWN; // Phyp is the only special case if(i_configForPhyp) { auto rtType = RT_TYPE_UNKNOWN; pError = getRtTypeForTarget(*pIt,rtType); if(pError) { break; } if( (*pIt)->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_CORE) { if(TARGETING::is_fused_mode()) { // If we're in fused core mode, all core ID's must // match that of the parent EX auto type = TARGETING::TYPE_EX; const TARGETING::Target* pEx = TARGETING::getParent(*pIt,type); // If this fails, everything is already hosed assert(pEx != NULL); hbrtHypId = (pEx)->getAttr<TARGETING::ATTR_ORDINAL_ID>(); }else { hbrtHypId = (*pIt)->getAttr<TARGETING::ATTR_ORDINAL_ID>(); } } else if( (*pIt)->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_MEMBUF ) { //MEMBUF // 0b1000.0000.0000.0000.0000.0PPP.PPPP.MMMM // where PP is the parent proc's id, MMMM is memory channel // TARGETING::TargetHandleList targetList; getParentAffinityTargets(targetList, (*pIt), TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS); assert( !targetList.empty() ); auto mcs_target = targetList[0]; auto pos = mcs_target->getAttr<TARGETING::ATTR_CHIP_UNIT>(); targetList.clear(); getParentAffinityTargets(targetList, mcs_target, TARGETING::CLASS_CHIP, TARGETING::TYPE_PROC); assert( !targetList.empty() ); auto procTarget = targetList[0]; hbrtHypId = procTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>(); hbrtHypId = (hbrtHypId << RT_TARG::MEMBUF_ID_SHIFT); hbrtHypId += pos; } else // just PROC { hbrtHypId = (*pIt)->getAttr<TARGETING::ATTR_ORDINAL_ID>(); } hbrtHypId |= rtType; } else { pError = computeNonPhypRtTarget(*pIt,hbrtHypId); if(pError) { break; } } (*pIt)->setAttr<TARGETING::ATTR_HBRT_HYP_ID>(hbrtHypId); TRACDCOMP( g_trac_runtime, "configureHbrtHypIds> " "Set ATTR_HBRT_HYP_ID attribute to 0x%016llX on targeting target " "with HUID of 0x%08X", hbrtHypId,TARGETING::get_huid(*pIt)); } TRACDCOMP( g_trac_runtime, EXIT_MRK "configureHbrtHypIds" ); return pError; }
//****************************************************************************** // wrapper function to call proc_build_smp //****************************************************************************** void* call_proc_build_smp( void *io_pArgs ) { errlHndl_t l_errl = NULL; IStepError l_StepError; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_build_smp entry" ); do { // Get all functional proc chip targets TARGETING::TargetHandleList l_cpuTargetList; getAllChips(l_cpuTargetList, TYPE_PROC); // Collect all valid abus connections and xbus connections TargetPairs_t l_abusConnections; TargetPairs_t l_xbusConnections; l_errl = PbusLinkSvc::getTheInstance().getPbusConnections( l_abusConnections, TYPE_ABUS, false ); if (l_errl) { // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails( l_errl); // Commit error errlCommit( l_errl, HWPF_COMP_ID ); } // Get XBUS connections l_errl = PbusLinkSvc::getTheInstance().getPbusConnections( l_xbusConnections, TYPE_XBUS, false ); if (l_errl) { // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails( l_errl); // Commit error errlCommit( l_errl, HWPF_COMP_ID ); } // Populate l_proc_Chips vector for each good processor chip // if a A/X-bus endpoint has a valid connection, then // obtain the proc chip target of the other endpoint of the // connection, build the fapi target to update the corresponding // chip object of this A/X-bus endpoint for the procEntry std::vector<proc_build_smp_proc_chip> l_procChips; // Get the master proc TARGETING::Target * l_masterProc = NULL; (void)TARGETING::targetService(). masterProcChipTargetHandle( l_masterProc ); for (TARGETING::TargetHandleList::const_iterator l_cpuIter = l_cpuTargetList.begin(); l_cpuIter != l_cpuTargetList.end(); ++l_cpuIter) { const TARGETING::Target* l_pTarget = *l_cpuIter; fapi::Target l_fapiproc_target( TARGET_TYPE_PROC_CHIP, (const_cast<TARGETING::Target*>(l_pTarget))); proc_build_smp_proc_chip l_procEntry; l_procEntry.this_chip = l_fapiproc_target; l_procEntry.enable_f0 = false; l_procEntry.enable_f1 = false; if (l_pTarget == l_masterProc) { l_procEntry.master_chip_sys_next = true; } else { l_procEntry.master_chip_sys_next = false; } // Get A-BUS //abus connections were found so can get the a-bus TARGETING::TargetHandleList l_abuses; getChildChiplets( l_abuses, l_pTarget, TYPE_ABUS ); for (TARGETING::TargetHandleList::const_iterator l_abusIter = l_abuses.begin(); l_abusIter != l_abuses.end(); ++l_abusIter) { const TARGETING::Target * l_target = *l_abusIter; uint8_t l_srcID = l_target->getAttr<ATTR_CHIP_UNIT>(); TargetPairs_t::iterator l_itr = l_abusConnections.find(l_target); if ( l_itr == l_abusConnections.end() ) { continue; } fapi::Target l_fapiEndpointTarget(TARGET_TYPE_ABUS_ENDPOINT, (const_cast<TARGETING::Target*>(l_itr->second)) ); switch (l_srcID) { case 0: l_procEntry.a0_chip = l_fapiEndpointTarget; break; case 1: l_procEntry.a1_chip = l_fapiEndpointTarget; break; case 2: l_procEntry.a2_chip = l_fapiEndpointTarget; break; default: break; } const TARGETING::Target *l_pParent = getParentChip( (const_cast<TARGETING::Target*>(l_itr->second))); l_procEntry.f0_node_id = static_cast<proc_fab_smp_node_id>( l_pTarget->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>()); l_procEntry.f1_node_id = static_cast<proc_fab_smp_node_id>( l_pParent->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>()); } // Get X-BUS TARGETING::TargetHandleList l_xbuses; getChildChiplets( l_xbuses, l_pTarget, TYPE_XBUS ); for (TARGETING::TargetHandleList::const_iterator l_xbusIter = l_xbuses.begin(); l_xbusIter != l_xbuses.end(); ++l_xbusIter) { const TARGETING::Target * l_target = *l_xbusIter; uint8_t l_srcID = l_target->getAttr<ATTR_CHIP_UNIT>(); TargetPairs_t::iterator l_itr = l_xbusConnections.find(l_target); if ( l_itr == l_xbusConnections.end() ) { continue; } fapi::Target l_fapiEndpointTarget(TARGET_TYPE_XBUS_ENDPOINT, (const_cast<TARGETING::Target*>(l_itr->second)) ); switch (l_srcID) { case 0: l_procEntry.x0_chip = l_fapiEndpointTarget; break; case 1: l_procEntry.x1_chip = l_fapiEndpointTarget; break; case 2: l_procEntry.x2_chip = l_fapiEndpointTarget; break; case 3: l_procEntry.x3_chip = l_fapiEndpointTarget; break; default: break; } } l_procChips.push_back( l_procEntry ); } // call the HWP with each fapi::Target FAPI_INVOKE_HWP( l_errl, proc_build_smp, l_procChips, SMP_ACTIVATE_PHASE1 ); if(l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "ERROR : proc_build_smp" ); // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails(l_errl); // Commit error errlCommit( l_errl, HWPF_COMP_ID ); break; } else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "SUCCESS : proc_build_smp" ); } // At the point where we can now change the proc chips to use // XSCOM rather than FSISCOM which is the default. TARGETING::TargetHandleList procChips; getAllChips(procChips, TYPE_PROC); TARGETING::TargetHandleList::iterator curproc = procChips.begin(); // Loop through all proc chips while(curproc != procChips.end()) { TARGETING::Target* l_proc_target = *curproc; // If the proc chip supports xscom.. if (l_proc_target->getAttr<ATTR_PRIMARY_CAPABILITIES>() .supportsXscom) { ScomSwitches l_switches = l_proc_target->getAttr<ATTR_SCOM_SWITCHES>(); // If Xscom is not already enabled. if ((l_switches.useXscom != 1) || (l_switches.useFsiScom != 0)) { l_switches.useFsiScom = 0; l_switches.useXscom = 1; // Turn off FSI scom and turn on Xscom. l_proc_target->setAttr<ATTR_SCOM_SWITCHES>(l_switches); // Reset the FSI2OPB logic on the new chips l_errl = FSI::resetPib2Opb(l_proc_target); if(l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "ERROR : resetPib2Opb on %.8X", TARGETING::get_huid(l_proc_target)); // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails(l_errl); // Commit error errlCommit( l_errl, HWPF_COMP_ID ); break; } } } // Enable PSI interrupts even if can't Xscom as // Pbus is up and interrupts can flow l_errl = INTR::enablePsiIntr(l_proc_target); if(l_errl) { // capture the target data in the elog ErrlUserDetailsTarget(l_proc_target).addToLog( l_errl ); break; } ++curproc; } } while (0); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_build_smp exit" ); // end task, returning any errorlogs to IStepDisp return l_StepError.getErrorHandle(); }
void HBVddrMsg::createVddrData( VDDR_MSG_TYPE i_requestType, RequestContainer& io_request) const { TRACFCOMP( g_trac_volt, ENTER_MRK "HBVddrMsg::createVddrData" ); // Go through all the memory buffers and gather their domains, domain // specific IDs, and domain specific voltages io_request.clear(); do{ TARGETING::TargetHandleList membufTargetList; //When request is a disable command, disable all present Centaurs // in case we go through a reconfigure loop if(i_requestType == HB_VDDR_DISABLE) { getChipResources( membufTargetList, TYPE_MEMBUF, UTIL_FILTER_PRESENT ); } //When the request is an enable command, enable only functional // centaurs. else { getAllChips(membufTargetList, TYPE_MEMBUF); } TARGETING::Target* pMembuf =NULL; for (TARGETING::TargetHandleList::const_iterator ppMembuf = membufTargetList.begin(); ppMembuf != membufTargetList.end(); ++ppMembuf) { pMembuf = *ppMembuf; if(i_requestType == HB_VDDR_ENABLE) { (void)addMemoryVoltageDomains< TARGETING::ATTR_MSS_CENT_VDD_OFFSET_DISABLE, TARGETING::ATTR_MEM_VDD_OFFSET_MILLIVOLTS, TARGETING::ATTR_MEM_VDD_OFFSET_MILLIVOLTS, TARGETING::ATTR_VDD_ID>( pMembuf, io_request); (void)addMemoryVoltageDomains< TARGETING::ATTR_MSS_CENT_AVDD_OFFSET_DISABLE, TARGETING::ATTR_MEM_AVDD_OFFSET_MILLIVOLTS, TARGETING::ATTR_MEM_AVDD_OFFSET_MILLIVOLTS, TARGETING::ATTR_AVDD_ID>( pMembuf, io_request); (void)addMemoryVoltageDomains< TARGETING::ATTR_MSS_CENT_VCS_OFFSET_DISABLE, TARGETING::ATTR_MEM_VCS_OFFSET_MILLIVOLTS, TARGETING::ATTR_MEM_VCS_OFFSET_MILLIVOLTS, TARGETING::ATTR_VCS_ID>( pMembuf, io_request); (void)addMemoryVoltageDomains< TARGETING::ATTR_MSS_VOLT_VPP_OFFSET_DISABLE, TARGETING::ATTR_MEM_VPP_OFFSET_MILLIVOLTS, TARGETING::ATTR_VPP_BASE, TARGETING::ATTR_VPP_ID>( pMembuf, io_request); } (void)addMemoryVoltageDomains< TARGETING::ATTR_MSS_VOLT_VDDR_OFFSET_DISABLE, TARGETING::ATTR_MEM_VDDR_OFFSET_MILLIVOLTS, TARGETING::ATTR_MSS_VOLT, TARGETING::ATTR_VMEM_ID>( pMembuf, io_request); } if (membufTargetList.size() > 1) { // Take out the duplicate records in io_request by first // sorting and then removing the duplicates std::sort(io_request.begin(), io_request.end(), compareVids); std::vector<hwsvPowrMemVoltDomainRequest_t>::iterator pInvalidEntries = std::unique( io_request.begin(), io_request.end(), areVidsEqual); io_request.erase(pInvalidEntries,io_request.end()); } if( ( (i_requestType == HB_VDDR_ENABLE) || (i_requestType == HB_VDDR_POST_DRAM_INIT_ENABLE) ) && (!membufTargetList.empty()) ) { // Inhibit sending any request to turn on a domain with no voltage. // When disabling we don't need to do this because the voltage is // ignored. io_request.erase( std::remove_if(io_request.begin(), io_request.end(), isUnusedVoltageDomain),io_request.end()); } } while(0); TRACFCOMP( g_trac_volt, EXIT_MRK "HBVddrMsg::createVddrData" ); return; }
//****************************************************************************** // host_gard function //****************************************************************************** void* host_gard( void *io_pArgs ) { TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard entry" ); errlHndl_t errl; do { // Check whether we're in MPIPL mode TARGETING::Target* l_pTopLevel = NULL; targetService().getTopLevelTarget( l_pTopLevel ); HWAS_ASSERT(l_pTopLevel, "HWAS host_gard: no TopLevelTarget"); if (l_pTopLevel->getAttr<ATTR_IS_MPIPL_HB>()) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "MPIPL mode"); // we only want EX units to be processed TARGETING::PredicateCTM l_exFilter(TARGETING::CLASS_UNIT, TARGETING::TYPE_EX); errl = collectGard(&l_exFilter); if (errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "collectGard returned error; breaking out"); break; } } else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Normal IPL mode"); errl = collectGard(); if(errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "collectGard returned error; breaking out"); break; } if (errl == NULL) { // check and see if we still have enough hardware to continue errl = checkMinimumHardware(); if(errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "check minimum hardware returned error; breaking out"); break; } } // If targets are deconfigured as a result of host_gard, they are // done so using the PLID as the reason for deconfiguration. This // triggers the reconfigure loop attribute to be set, which causes // undesirable behavior, so we need to reset it here: // Read current value TARGETING::ATTR_RECONFIGURE_LOOP_type l_reconfigAttr = l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(); // Turn off deconfigure bit l_reconfigAttr &= ~TARGETING::RECONFIGURE_LOOP_DECONFIGURE; // Write back to attribute l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP> (l_reconfigAttr); } // Send message to FSP sending HUID of EX chip associated with // master core msg_t * core_msg = msg_allocate(); core_msg->type = SBE::MSG_IPL_MASTER_CORE; const TARGETING::Target* l_masterCore = TARGETING::getMasterCore( ); /*@ errorlog tag * @errortype ERRL_SEV_CRITICAL_SYS_TERM * @moduleid MOD_HOST_GARD * @reasoncode RC_MASTER_CORE_NULL * @userdata1 0 * @userdata2 0 * @devdesc HWAS host_gard: no masterCore found */ if (l_masterCore == NULL) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "No masterCore Found" ); const bool hbSwError = true; errl = new ERRORLOG::ErrlEntry (ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, HWAS::MOD_HOST_GARD, HWAS::RC_MASTER_CORE_NULL, 0, 0, hbSwError); break; } // Get the EX chip associated with the master core as that is the // chip that // has the IS_MASTER_EX attribute associated with it TARGETING::TargetHandleList targetList; getParentAffinityTargets(targetList, l_masterCore, TARGETING::CLASS_UNIT, TARGETING::TYPE_EX); HWAS_ASSERT(targetList.size() == 1, "HWAS host_gard: Incorrect EX chip(s) associated with masterCore"); core_msg->data[0] = 0; core_msg->data[1] = TARGETING::get_huid( targetList[0] ); core_msg->extra_data = NULL; TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Sending MSG_MASTER_CORE message with HUID %08x", core_msg->data[1]); errl = MBOX::send(MBOX::IPL_SERVICE_QUEUE,core_msg); if (errl) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"MBOX::send failed sending Master Core message"); msg_free(core_msg); break; } } while (0); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard exit" ); return errl; }
errlHndl_t getRtTarget(const TARGETING::Target* i_target, rtChipId_t &o_chipId) { errlHndl_t err = NULL; do { if(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL) { TARGETING::Target* masterProcChip = NULL; TARGETING::targetService(). masterProcChipTargetHandle(masterProcChip); i_target = masterProcChip; } TARGETING::TYPE target_type = i_target->getAttr<TARGETING::ATTR_TYPE>(); if(target_type == TARGETING::TYPE_PROC) { // use 0b0000.0000.0000.0000.0000.0000.00NN.NCCC: uint32_t fabId = i_target->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>(); uint32_t procPos = i_target->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>(); o_chipId = (fabId << CHIPID_NODE_SHIFT) + procPos; } else if( target_type == TARGETING::TYPE_MEMBUF) { //MEMBUF // 0b1000.0000.0000.0000.0000.00NN.NCCC.MMMM // where NNN id node, CCC is chip, MMMM is memory channel // TARGETING::TargetHandleList targetList; getParentAffinityTargets(targetList, i_target, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS); if( targetList.empty() ) { uint32_t huid = get_huid(i_target); TRACFCOMP(g_trac_targeting,ERR_MRK "getRtTarget: No target found for huid: %08x", huid); /*@ * @errortype * @moduleid TARG_RT_GET_RT_TARGET * @reasoncode TARG_RT_UNIT_TARGET_NOT_FOUND * @userdata1 HUID of given MEMBUF target * @devdesc No MCS target(s) found for the * given MEMBUF target */ err = new ERRORLOG::ErrlEntry (ERRORLOG::ERRL_SEV_INFORMATIONAL, TARGETING::TARG_RT_GET_RT_TARGET, TARGETING::TARG_RT_UNIT_TARGET_NOT_FOUND, huid, 0, true); ERRORLOG::ErrlUserDetailsTarget(i_target,"Runtime Target"). addToLog(err); break; } TARGETING::Target * target = targetList[0]; uint32_t pos = target->getAttr<TARGETING::ATTR_CHIP_UNIT>(); targetList.clear(); getParentAffinityTargets(targetList, target, TARGETING::CLASS_CHIP, TARGETING::TYPE_PROC); if(targetList.empty()) { err = procRtTargetError(target); break; } TARGETING::Target * proc_target = targetList[0]; err = getRtTarget(proc_target, o_chipId); if(err) { break; } o_chipId = (o_chipId << UNIT_ID_SHIFT); o_chipId += pos; o_chipId |= MEMBUF_ID_TYPE; } else if(target_type == TARGETING::TYPE_EX || target_type == TARGETING::TYPE_CORE) { // EX/CORE // 0b0100.0000.0000.0000.0000.00NN.NCCC.PPPP // NNN is node, CCC is chip, PPPP is core uint32_t pos = i_target->getAttr<TARGETING::ATTR_CHIP_UNIT>(); const TARGETING::Target * proc_target = getParentChip(i_target); if(proc_target == NULL) { err = procRtTargetError(i_target); break; } err = getRtTarget(proc_target, o_chipId); if(err) { break; } o_chipId = (o_chipId << UNIT_ID_SHIFT); o_chipId += pos; o_chipId |= CORE_ID_TYPE; } else { uint32_t huid = get_huid(i_target); TRACFCOMP(g_trac_targeting,ERR_MRK "Runtime target type %d not supported." " huid: %08x", target_type, huid); /*@ * @errortype * @moduleid TARG_RT_GET_RT_TARGET * @reasoncode TARG_RT_TARGET_TYPE_NOT_SUPPORTED * @userdata1 HUID of the target * @userdata2 target_type * @devdesc Target type not supported by HBRT. */ err = new ERRORLOG::ErrlEntry (ERRORLOG::ERRL_SEV_INFORMATIONAL, TARGETING::TARG_RT_GET_RT_TARGET, TARGETING::TARG_RT_TARGET_TYPE_NOT_SUPPORTED, huid, target_type, true); ERRORLOG::ErrlUserDetailsTarget(i_target,"Runtime Target"). addToLog(err); } } while(0); return err; }