/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/usr/targeting/runtime/start_rt.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ /* implied. See the License for the specific language governing */ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ #include #include #include #include #include #include using namespace TARGETING; namespace RT_TARG { void adjustTargeting4Runtime(); static void initTargeting() __attribute__((constructor)); static void initTargeting() { errlHndl_t l_errl = NULL; AttrRP::init(l_errl); if (l_errl) { errlCommit(l_errl, TARG_COMP_ID); assert(false); } TargetService& l_targetService = targetService(); l_targetService.init(Singleton::instance().getNodeCount()); // Reset hb mutex attributes in case they got stuck in a locked state l_targetService.resetMutexAttributes(); adjustTargeting4Runtime(); // set global that TARG is ready Util::setIsTargetingLoaded(); } // Make any adjustments needed to targeting for runtime void adjustTargeting4Runtime() { TRACDCOMP(g_trac_targeting,"adjustTargeting4Runtime"); // Loop through all targets and fix those with ATTR_PEER_TARGETs. // // ATTR_PEER_TARGET is the only attribute using the Target_t type. // The value of a Target_t attribute is a Target * "pointer" to // another target. The value is set up by the targeting scripts at // build time. Targeting uses a translate function to nagivate through // the targeting binary. There is a runtime translation function used // at run time to account for the location of the targeting binary // being at a different spot at runtime. The Target_t * value of // the attribute remains pointing into where the targeting binary // was at IPL. Using this "old" address would seg fault at run time. // The value of the ATTR_PEER_TARGET attributes must be translated // for run time. // The _trySetAttr is used directly to avoid the trySetAttr template // error check that ATTR_PEER_TARGET is only readable, not writable. // adjustTargeting4Runtime has been included as a friend to allow // access to the private target class methods. size_t l_xlateCnt = 0; uint8_t l_maxNodeId = TARGETING::targetService().getNumInitializedNodes(); for(uint8_t l_nodeId = NODE0; l_nodeId < l_maxNodeId; ++l_nodeId) { for (TargetIterator target = targetService().begin(l_nodeId); target != targetService().end(); ++target) { const TARGETING::Target * l_target = *target; TARGETING::Target * l_peer = static_cast(NULL); bool l_hasPeer = l_target->tryGetAttr(l_peer); if (l_hasPeer && (l_peer != nullptr)) { TRACDCOMP(g_trac_targeting, "translate the peer target %p for HUID %x", l_peer, get_huid(l_target)); ATTR_PEER_TARGET_type l_xlated = (TARGETING::Target *) Singleton::instance(). AttrRP::translateAddr(l_peer,l_target); bool l_fixed = false; l_fixed = l_target->_trySetAttr(ATTR_PEER_TARGET, sizeof(l_xlated), &l_xlated); if (l_fixed) { TRACDCOMP(g_trac_targeting, " to=%p", l_xlated); l_xlateCnt++; } // Not good if could not be fixed. But might not be // referenced. A segment fault will occur if used. else { TRACFCOMP(g_trac_targeting, "failed to translate peer target for HUID=0x%x", get_huid(l_target)); } } else if(l_hasPeer && l_peer == nullptr) { TRACDCOMP(g_trac_targeting, "looking up peer path and target for HUID %x", get_huid(l_target)); // Create variables entity path variable to write PEER_PATH into // as well as a Target pointer to set once we get the PEER_PATH TARGETING::EntityPath l_peerPath; TARGETING::Target * l_newTargPtr; // Look up the PEER_PATH attribute if it exists on the target bool l_hasPeerPath = l_target->tryGetAttr(l_peerPath); //If we find a PEER_PATH we need to next look up the PEER_TARGET if(l_hasPeerPath) { TRACDCOMP(g_trac_targeting, "Found peer path for HUID %x",get_huid(l_target)); // Look up the PEER_TARGET based on what the PEER_PATH is l_newTargPtr = targetService().toTarget(l_peerPath); bool l_fixed = false; // If the pointer returned from toTarget isn't null then // we will try to set PEER_TARGET with that value if(l_newTargPtr != nullptr) { l_fixed = l_target->_trySetAttr(ATTR_PEER_TARGET, sizeof(l_newTargPtr), &l_newTargPtr); } if (l_fixed) { TRACDCOMP(g_trac_targeting, "Peer target for HUID %x found to be %p", get_huid(l_target), l_newTargPtr); l_xlateCnt++; } // Not good if could not be fixed. But might not be // referenced. A segment fault will occur if used. else { TRACFCOMP(g_trac_targeting, "failed to find peer target for HUID=0x%x", get_huid(l_target)); } } else { TRACFCOMP(g_trac_targeting, "Failed to find peer path for HUID=0x%x", get_huid(l_target)); } } } } TRACFCOMP(g_trac_targeting, "adjustTargeting4Runtime: %d peer target addresses " "translated on %d nodes", l_xlateCnt, l_maxNodeId); } }