diff options
author | Brian Horton <brianh@linux.ibm.com> | 2015-06-02 10:13:20 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-09-03 14:33:02 -0500 |
commit | 06e40c4aa3efe6f006dc7971ad58f08f42117ea3 (patch) | |
tree | e7bcc5a38340a630c17126bc3782064e2c0b9274 /src/usr/errl/errlmanager.C | |
parent | 4ae690e4eeb9297ed59ff932cc4184d23896234d (diff) | |
download | talos-hostboot-06e40c4aa3efe6f006dc7971ad58f08f42117ea3.tar.gz talos-hostboot-06e40c4aa3efe6f006dc7971ad58f08f42117ea3.zip |
add support to write errlog to PNOR during runtime
Change-Id: Ia2b211d8ebf489e92f2bc3d281d92175a6b61f30
Depends-On: I170d6586062b6e4684a55782df83a1b19ed7d937
Depends-On: Id8c44b0dcdb5714c163ac6485a53216786f9fbcf
Depends-On: I626bce5c8c0c8b7d0a44408280de178c7a86a83f
RTC: 123419
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/18233
Tested-by: Jenkins Server
Tested-by: Jenkins OP Build CI
Reviewed-by: STEPHEN M. CPREK <smcprek@us.ibm.com>
Tested-by: Jenkins OP HW
Reviewed-by: WILLIAM G. HOFFA <wghoffa@us.ibm.com>
Tested-by: FSP CI Jenkins
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/errl/errlmanager.C')
-rw-r--r-- | src/usr/errl/errlmanager.C | 436 |
1 files changed, 1 insertions, 435 deletions
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 3ae08dde2..dea951ce4 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -92,10 +92,6 @@ char* g_ErrlStorage; #endif -const uint32_t PNOR_ERROR_LENGTH = 4096; -const uint32_t EMPTY_ERRLOG_IN_PNOR = 0xFFFFFFFF; -const uint32_t FIRST_BYTE_ERRLOG = 0xF0000000; - // Comparator function to check if a eid and a plid are equal bool compareEidToPlid(const uint32_t i_plid, const std::pair<errlHndl_t, uint8_t> i_pair) @@ -754,13 +750,6 @@ void ErrlManager::saveErrLogEntry( errlHndl_t& io_err ) /////////////////////////////////////////////////////////////////////////////// -// Atomically increment log id and return it. -uint32_t ErrlManager::getUniqueErrId() -{ - return (__sync_add_and_fetch(&iv_currLogId, 1)); -} - -/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ErrlManager::setHwasProcessCalloutFn(HWAS::processCalloutFn i_fn) { @@ -771,21 +760,6 @@ void ErrlManager::setHwasProcessCalloutFn(HWAS::processCalloutFn i_fn) } /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// Global function (not a method on an object) to commit the error log. -void errlCommit(errlHndl_t& io_err, compId_t i_committerComp ) -{ - ERRORLOG::theErrlManager::instance().commitErrLog(io_err, i_committerComp ); - return; -} - -// Global function (not a method on an object) to get the hidden logs flag. -uint8_t getHiddenLogsEnable( ) -{ - return ERRORLOG::theErrlManager::instance().iv_hiddenErrLogsEnable; -} - -/////////////////////////////////////////////////////////////////////////////// // Global function (not a method on an object) to commit the error log. void ErrlManager::errlResourceReady(errlManagerNeeds i_needs) { @@ -946,15 +920,7 @@ void ErrlManager::errlogShutdown() // Ensure that all the error logs are pushed out to PNOR // prior to the PNOR resource provider shutting down. - int l_rc = mm_remove_pages(FLUSH, (void *) iv_pnorAddr, - iv_maxErrlInPnor * PNOR_ERROR_LENGTH); - if( l_rc ) - { - //If mm_remove_pages returns none zero for error then - //log an error trace in this case. - TRACFCOMP(g_trac_errl, ERR_MRK "Fail to flush the page %p size %d", - iv_pnorAddr, iv_maxErrlInPnor * PNOR_ERROR_LENGTH); - } + PNOR::flush(PNOR::HB_ERRLOGS); // Un-register error log message queue from the shutdown INITSERVICE::unregisterShutdownEvent( iv_msgQ); @@ -976,355 +942,6 @@ void ErrlManager::errlogShutdown() return; } -// ------------------------------------------------------------------ -// setupPnorInfo -// ------------------------------------------------------------------ -void ErrlManager::setupPnorInfo() -{ - TRACFCOMP( g_trac_errl, ENTER_MRK"setupPnorInfo" ); - - do - { - // Get SPD PNOR section info from PNOR RP - PNOR::SectionInfo_t info; - errlHndl_t err = PNOR::getSectionInfo( PNOR::HB_ERRLOGS, info ); - - if (err) - { - TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo getSectionInfo failed"); - assert(err == NULL); - break; - } - - TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo sectionInfo id %d name \"%s\" size %d", - info.id, info.name, info.size ); - - // Set the globals appropriately - iv_pnorAddr = reinterpret_cast<char *> (info.vaddr); - iv_maxErrlInPnor = info.size / PNOR_ERROR_LENGTH; - - TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo iv_pnorAddr %p maxErrlInPnor %d", - iv_pnorAddr, iv_maxErrlInPnor ); - - // initial value, in case PNOR is empty - start at this end slot - // so that our first save will increment and wrap correctly - iv_pnorOpenSlot = (iv_maxErrlInPnor - 1); - - // walk thru memory, finding error logs and determine the highest ID - uint32_t l_maxId = 0; - for (uint32_t i = 0; i < iv_maxErrlInPnor; i++) - { - if (!isSlotEmpty(i)) - { - uint32_t l_id = readEidFromFlattened(i); - // If id is not from HB (0x9XXXXXXX) grab plid instead - if ( (l_id & FIRST_BYTE_ERRLOG) != ERRLOG_PLID_BASE ) - { - l_id = readPlidFromFlattened(i); - } - if (l_id > l_maxId ) - { - l_maxId = l_id; - - // set this - start at this 'max' slot so that our first - // save will increment correctly - iv_pnorOpenSlot = i; - } - // also check if it's ACKed or not - if (!isSlotACKed(i)) - { - TRACFCOMP( g_trac_errl, - INFO_MRK"setupPnorInfo slot %d eid %.8X was not ACKed.", - i, l_id); - -#ifdef CONFIG_BMC_IPMI - // for IPMI systems, unflatten to send down to the BMC - err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, 0,0); - char *l_errlAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i); - uint64_t rc = err->unflatten(l_errlAddr, PNOR_ERROR_LENGTH); - if (rc != 0) - { - // unflatten didn't work, nothing we can do - TRACFCOMP( g_trac_errl, - ERR_MRK"setupPnorInfo unflatten failed on slot %d eid %.8X.", - i, l_id); - } - else - { - // Decide if we need to skip the error log - setErrlSkipFlag(err); - if(err->getSkipShowingLog()) - { - // skip it, go to the next one - continue; - } - if (iv_isIpmiEnabled) - { - // convert to SEL/eSEL and send to BMC over IPMI - sendErrLogToBmc(err); - delete err; - } - else - { - TRACFCOMP( g_trac_errl, - INFO_MRK"setupPnorInfo pushing slot %d eid %.8X to iv_errList.", - i, l_id); - // Pair with IPMI flag to add to the errlList - // so that it'll get sent down when IPMI is up -#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY - ErrlFlagPair_t l_pair(err, IPMI_FLAG | ERRLDISP_FLAG); -#else - ErrlFlagPair_t l_pair(err, IPMI_FLAG); -#endif - iv_errlList.push_back(l_pair); - } - } -#else - // for FSP system, this shouldn't ever happen. - setACKInFlattened(i); -#endif - } // not ACKed - } // not empty - } // for - - // bump the current eid to 1 past the max eid found - while (!__sync_bool_compare_and_swap(&iv_currLogId, iv_currLogId, - (iv_currLogId & ERRLOG_PLID_BASE_MASK) + - (l_maxId & ERRLOG_PLID_MASK) + 1)); - TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo reseting LogId 0x%X", iv_currLogId); - - // if error(s) came in before PNOR was ready, - // the error log(s) would be on this list. save now. - ErrlListItr_t it = iv_errlList.begin(); - while(it != iv_errlList.end()) - { - // Check if PNOR processing is needed - if (_isFlagSet(*it, PNOR_FLAG)) - { - //ACK it if no one is there to receive - bool l_savedToPnor = saveErrLogToPnor(it->first); - - // check if we actually saved the msg to PNOR - if (l_savedToPnor) - { - // Mark PNOR processing complete - _clearFlag(*it, PNOR_FLAG); - _updateErrlListIter(it); - } - else - { - // still couldn't save it (PNOR maybe full) so - // it's still on the list. - break; // get out of this while loop. - } - } - else - { - ++it; - } - } - } while (0); - - TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo"); -} // setupPnorInfo - -/////////////////////////////////////////////////////////////////////////////// -// ErrlManager::incrementPnorOpenSlot() -/////////////////////////////////////////////////////////////////////////////// -bool ErrlManager::incrementPnorOpenSlot() -{ - uint32_t initialSlot = iv_pnorOpenSlot; // starting slot - do - { - iv_pnorOpenSlot++; - if (iv_pnorOpenSlot == iv_maxErrlInPnor) - { // wrap - iv_pnorOpenSlot = 0; - } - } while ( !isSlotEmpty(iv_pnorOpenSlot) && - !isSlotACKed(iv_pnorOpenSlot) && - (iv_pnorOpenSlot != initialSlot)); - - // if we got a different slot, return true; else false - no open slots - return (iv_pnorOpenSlot != initialSlot); -} // incrementPnorOpenSlot - -/////////////////////////////////////////////////////////////////////////////// -// ErrlManager::saveErrLogToPnor() -/////////////////////////////////////////////////////////////////////////////// -bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err) -{ - bool rc = false; - TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid()); - - do - { - // Decide whether or not to skip error log - if( io_err->getSkipShowingLog() ) - { - TRACFCOMP( g_trac_errl, INFO_MRK"saveErrLogToPnor: INFORMATIONAL/RECOVERED log, skipping"); - break; - } - - // save our current slot, and see if there's an open slot - uint32_t l_previousSlot = iv_pnorOpenSlot; // in case flatten fails - - if ((iv_pnorAddr != NULL) && incrementPnorOpenSlot()) - { - // flatten into PNOR, truncate to the slot size - char *l_pnorAddr = - iv_pnorAddr + (PNOR_ERROR_LENGTH * iv_pnorOpenSlot); - TRACDBIN( g_trac_errl, INFO_MRK"saveErrLogToPnor: l_pnorAddr before", - l_pnorAddr, 128); - uint64_t l_errSize = io_err->flatten(l_pnorAddr, - PNOR_ERROR_LENGTH, true); - if (l_errSize !=0) - { - TRACFCOMP( g_trac_errl, INFO_MRK"saveErrLogToPnor: %d bytes flattened into %p, slot %d", - l_errSize, l_pnorAddr, iv_pnorOpenSlot ); - - TRACDBIN( g_trac_errl, INFO_MRK"saveErrLogToPnor: l_pnorAddr after", - l_pnorAddr, 128); - - // Ensure that this error log is pushed out to PNOR - int l_rc = mm_remove_pages(FLUSH, - (void *) l_pnorAddr, l_errSize); - if( l_rc ) - { - //If mm_remove_pages returns none zero for error then - //log an error trace in this case. - TRACFCOMP(g_trac_errl, ERR_MRK "Fail to flush the page %p size %d", - l_pnorAddr, PNOR_ERROR_LENGTH); - } - } - else - { - // flatten didn't work, so still return true - we don't want - // to try to save this errlog. - - TRACFCOMP( g_trac_errl, ERR_MRK"saveErrLogToPnor: could not flatten data"); - // restore slot so that our next save will find this slot - iv_pnorOpenSlot = l_previousSlot; - } - rc = true; - } - // else no open slot - return false - } while( 0 ); - - TRACFCOMP( g_trac_errl, EXIT_MRK"saveErrLogToPnor returning %s", - rc ? "true" : "false"); - return rc; -} // saveErrLogToPnor - -/////////////////////////////////////////////////////////////////////////////// -// ErrlManager::ackErrLogInPnor() -/////////////////////////////////////////////////////////////////////////////// -bool ErrlManager::ackErrLogInPnor( uint32_t i_errEid ) -{ - TRACFCOMP( g_trac_errl, ENTER_MRK"ackErrLogInPnor(%.8x)", i_errEid); - bool rc = true; - - // look for an un-ACKed log that matches this eid - uint32_t i; - for (i = 0; i < iv_maxErrlInPnor; i++) - { - if (!isSlotEmpty(i) && !isSlotACKed(i)) - { - uint32_t l_eid = readEidFromFlattened(i); - if (l_eid == i_errEid) - { - TRACDCOMP( g_trac_errl, INFO_MRK"ackErrLogInPnor: match in slot %d", i); - setACKInFlattened(i); - break; - } - } - } // for - - // if we made it through the loop w/out breaking early - if (i == iv_maxErrlInPnor) - { - //could not find the errorlog to mark for acknowledgment - TRACDCOMP( g_trac_errl, ERR_MRK"ackErrLogInPnor failed to find the error log" ); - rc = false; - } - - TRACFCOMP( g_trac_errl, EXIT_MRK"ackErrLogInPnor returning %s", - rc ? "true" : "false"); - return rc; -} // ackErrLogInPnor - - -bool ErrlManager::isSlotEmpty(uint32_t i_position) -{ - // checks the first word of the flattened errlog, which should be a - // pelsectionheader - which will NEVER be 0xFFFFFFFF if it's valid. - char * l_pnorAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i_position); - bool rc = (memcmp(l_pnorAddr, &EMPTY_ERRLOG_IN_PNOR, sizeof(uint32_t)) - == 0); - TRACDCOMP( g_trac_errl, "isSlotEmpty: slot %d @ %p is %s", - i_position, l_pnorAddr, rc ? "empty" : "not empty"); - return rc; -} - -// readEidFromFlattened() -// i_position MUST be valid errlog (not EMPTY_ERRLOG_IN_PNOR) -uint32_t ErrlManager::readEidFromFlattened(uint32_t i_position) -{ - const char * l_pnorAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i_position); - const pelPrivateHeaderSection_t *pPH = - reinterpret_cast<const pelPrivateHeaderSection_t *>(l_pnorAddr); - TRACDCOMP(g_trac_errl, "readEid(%d): eid %.8x", i_position, pPH->eid); - - return pPH->eid; -} - -// readPlidFromFlattened() -// i_position MUST be valid errlog (not EMPTY_ERRLOG_IN_PNOR) -uint32_t ErrlManager::readPlidFromFlattened(uint32_t i_position) -{ - const char * l_pnorAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i_position); - const pelPrivateHeaderSection_t *pPH = - reinterpret_cast<const pelPrivateHeaderSection_t *>(l_pnorAddr); - TRACDCOMP(g_trac_errl, "readEid(%d): plid %.8x", i_position, pPH->plid); - - return pPH->plid; -} - -// isSlotACKed() -// i_position MUST be valid errlog (not EMPTY_ERRLOG_IN_PNOR) -bool ErrlManager::isSlotACKed(uint32_t i_position) -{ - const char * l_pnorAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i_position); - l_pnorAddr += sizeof(pelPrivateHeaderSection_t); - l_pnorAddr += sizeof(pelUserHeaderSection_t); - const pelSRCSection_t *pSRC = - reinterpret_cast<const pelSRCSection_t *>(l_pnorAddr); - - TRACDCOMP(g_trac_errl, "isSlotACKed(%d): word5 %08x - %s", - i_position, pSRC->word5, - (pSRC->word5 & ErrlSrc::ACK_BIT) ? "not ACKed" : "ACKed"); - - return (pSRC->word5 & ErrlSrc::ACK_BIT) ? false : true; -} - -// setACKInFlattened() -void ErrlManager::setACKInFlattened(uint32_t i_position) -{ - char * l_pnorErrlAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i_position); - char * l_pnorAddr = l_pnorErrlAddr + sizeof(pelPrivateHeaderSection_t); - l_pnorAddr += sizeof(pelUserHeaderSection_t); - pelSRCSection_t *pSRC = reinterpret_cast<pelSRCSection_t *>(l_pnorAddr); - - pSRC->word5 &= ~(ErrlSrc::ACK_BIT); - - TRACDCOMP(g_trac_errl, "setACKInFlattened(%d): word5 %08x - %s", - i_position, pSRC->word5, - (pSRC->word5 & ErrlSrc::ACK_BIT) ? "not ACKed" : "ACKed"); - - return; -} - bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) { bool l_removed = false; @@ -1344,55 +961,4 @@ bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) return l_removed; } -void ErrlManager::setErrlSkipFlag(errlHndl_t io_err) -{ - // Note: iv_skipShowingLog is set to True by default - //0 = Prevent INFORMATIONAL/RECOVERED error logs from being processed. - //1 = Send only INFORMATIONAL error logs. - //2 = Send only RECOVERED error logs. - //3 = Allow all hidden error logs to be processed. - - //Check severity - switch (io_err->sev()) - { - case ERRORLOG::ERRL_SEV_INFORMATIONAL: - - // check if we are allowing info logs through. - if((iv_hiddenErrLogsEnable == - TARGETING:: - HIDDEN_ERRLOGS_ENABLE_ALLOW_INFORMATIONAL)|| - (iv_hiddenErrLogsEnable == - TARGETING:: - HIDDEN_ERRLOGS_ENABLE_ALLOW_ALL_LOGS)) - { - io_err->setSkipShowingLog(false); - } - break; - - case ERRORLOG::ERRL_SEV_RECOVERED: - - // check if we are allowing recovered logs through. - if(((iv_hiddenErrLogsEnable == - TARGETING:: - HIDDEN_ERRLOGS_ENABLE_ALLOW_RECOVERED) || - (iv_hiddenErrLogsEnable == - TARGETING:: - HIDDEN_ERRLOGS_ENABLE_ALLOW_ALL_LOGS)) && - !iv_isSpBaseServices) - { - //Recovered error logs that are encountered - //before targeting and initservice are loaded, - //will still be queued for sending to PNOR/IPMI - io_err->setSkipShowingLog(false); - } - break; - - default: - - // For any error log that is not INFORMATIONAL - // or RECOVERED, we want to show the log - io_err->setSkipShowingLog(false); - } -} // setErrlSkipFlag - } // End namespace |