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; }
//****************************************************************************** // 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; }
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; }
/** * @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; }
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; }