diff options
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/errl/errlmanager.C | 368 | ||||
-rwxr-xr-x | src/usr/errl/parser/genErrlParsers.pl | 64 | ||||
-rw-r--r-- | src/usr/errl/parser/makefile | 2 | ||||
-rw-r--r-- | src/usr/errldisplay/errldisplay.C | 195 | ||||
-rw-r--r-- | src/usr/errldisplay/makefile | 37 | ||||
-rw-r--r-- | src/usr/initservice/extinitsvc/extinitsvctasks.H | 17 | ||||
-rw-r--r-- | src/usr/makefile | 1 |
7 files changed, 521 insertions, 163 deletions
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 14a58b05f..0da331a44 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -6,6 +6,7 @@ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +47,10 @@ #include <pnor/pnorif.H> #include <sys/mm.h> #include <intr/interrupt.H> +#include <errldisplay/errldisplay.H> +#include <console/consoleif.H> +#include <config.h> +#include <functional> namespace ERRORLOG { @@ -87,6 +92,13 @@ 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) +{ + return (i_pair.first->eid() == i_plid); +} + class AtLoadFunctions { public: @@ -109,7 +121,8 @@ ErrlManager::ErrlManager() : iv_pnorOpenSlot(0), iv_isSpBaseServices(true), // queue msgs for fsp until we find we shouldnt iv_isMboxEnabled(false), // but mbox isn't ready yet.. - iv_nonInfoCommitted(false) + iv_nonInfoCommitted(false), + iv_isErrlDisplayEnabled(false) { TRACFCOMP( g_trac_errl, ENTER_MRK "ErrlManager::ErrlManager constructor" ); @@ -258,15 +271,15 @@ void ErrlManager::errlogMsgHndlr () { iv_isSpBaseServices = false; - // if there are queued msgs, delete them - while (!iv_errlToSend.empty()) + // if there are queued msgs, delete the errors that + // have been fully processed + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) { - msg_t * msg = iv_errlToSend.front(); - free( msg->extra_data ); - msg_free( msg ); - // delete from the list - iv_errlToSend.pop_front(); - } // while items on iv_errlToSend list + // Mark MBOX processing complete + _clearMboxFlag(*it); + _updateErrlListIter(it); + } } //We are done with the msg @@ -313,38 +326,29 @@ void ErrlManager::errlogMsgHndlr () // if error(s) came in before MBOX was ready, // the msg(s) would be on this list. send it now. - while (!iv_errlToSend.empty()) + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) { - msg_t * msg = iv_errlToSend.front(); - - l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); - if( l_err ) + // Check if MBOX processing is needed + if (_isMboxFlagSet(*it)) { - TRACFCOMP(g_trac_errl, ERR_MRK "Failed sending error log to FSP"); - - //Free the extra data due to the error - free( msg->extra_data ); - msg_free( msg ); - - delete l_err; - l_err = NULL; + // Mark MBOX processing complete + sendErrLogToMbox(it->first); + _clearMboxFlag(*it); } - - // delete from the list - iv_errlToSend.pop_front(); - } // while items on list + _updateErrlListIter(it); + } } else { - // if there are queued msgs, delete them - while (!iv_errlToSend.empty()) + // Delete errors that have been completely processed + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) { - msg_t * msg = iv_errlToSend.front(); - free( msg->extra_data ); - msg_free( msg ); - // delete from the list - iv_errlToSend.pop_front(); - } // while items on iv_errlToSend list + // Mark MBOX processing complete + _clearMboxFlag(*it); + _updateErrlListIter(it); + } } //We are done with the msg @@ -353,9 +357,37 @@ void ErrlManager::errlogMsgHndlr () // go back and wait for a next msg break; } + case ERRLOG_ACCESS_ERRLDISP_TYPE: + { +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY + // Errldisplay now ready + iv_isErrlDisplayEnabled = true; + + CONSOLE::displayf("ERRL", + "Dumping errors reported prior to registration\n"); + + // Display errlogs to errldisplay + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) + { + // Check if ERRLDISP processing is needed + if (_isErrlDispFlagSet(*it)) + { + ERRORLOGDISPLAY::errLogDisplay().msgDisplay + (it->first, + ((it->first->reasonCode()) & 0xFF00)); + // Mark ERRLDISP processing complete + _clearErrlDispFlag(*it); + } + _updateErrlListIter(it); + } +#endif + //We are done with the msg + msg_free(theMsg); + } case ERRLOG_NEEDS_TO_BE_COMMITTED_TYPE: { - //Extract error log handle from the message. We need the + // Extract error log handle from the message. We need the // error log handle to pass along to saveErrLogEntry and // sendErrLogToMbox errlHndl_t l_err = (errlHndl_t) theMsg->extra_data; @@ -363,25 +395,47 @@ void ErrlManager::errlogMsgHndlr () //Ask the ErrlEntry to assign commit component, commit time l_err->commit( (compId_t) theMsg->data[0] ); + // Pair with all flags set to add to the errlList + std::pair<errlHndl_t, uint8_t> l_pair(l_err, ALL_FLAGS); + + // Display errl to errldisplay +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY + if (iv_isErrlDisplayEnabled) + { + ERRORLOGDISPLAY::errLogDisplay().msgDisplay + (l_err, + ( (l_err->reasonCode()) & 0xFF00)); + // Mark ERRLDISP processing complete on this error + _clearErrlDispFlag(l_pair); + } +#endif //Save the error log to PNOR bool l_savedToPnor = saveErrLogToPnor(l_err); + // Check if we actually saved the msg to PNOR + if (l_savedToPnor) + { + // Mark PNOR processing complete on this error + _clearPnorFlag(l_pair); + } + #ifdef STORE_ERRL_IN_L3 //Write the error log to L3 memory //useful ONLY for the hb-errl tool saveErrLogEntry ( l_err ); #endif - //Try to send the error log if someone is there to receive - if (iv_isSpBaseServices) + // Try to send the error log if someone is there to receive + if (!iv_isSpBaseServices) { - msg_t *l_sentToMbox = sendErrLogToMbox ( l_err ); - if (l_sentToMbox != NULL) - { - // we were supposed to send it and couldn't; - // save it on the queue. - iv_errlToSend.push_back(l_sentToMbox); - } + // Mark MBOX processing complete on this error + _clearMboxFlag(l_pair); + } + else if (iv_isSpBaseServices && iv_isMboxEnabled) + { + sendErrLogToMbox(l_err); + // Mark MBOX processing complete on this error + _clearMboxFlag(l_pair); } //Ask the ErrlEntry to process any callouts @@ -400,17 +454,16 @@ void ErrlManager::errlogMsgHndlr () INFO_MRK"shutdown in progress" ); } - // check if we actually saved the msg to PNOR - if (l_savedToPnor) + // If l_errl has not been fully proccessed delete it + // otherwise add to list + if (l_pair.second == 0) { - //done with the error log handle so delete it. delete l_err; l_err = NULL; } else - { // save didn't work - push into a list to do when - // the next ACK gets processed. - iv_errlToSave.push_back(l_err); + { + iv_errlList.push_back(l_pair); } //We are done with the msg @@ -427,53 +480,43 @@ void ErrlManager::errlogMsgHndlr () TRACFCOMP( g_trac_errl, INFO_MRK"ack: %.8x", l_tmpPlid); bool didAck = ackErrLogInPnor(l_tmpPlid); - if (!didAck) { // couldn't find that errlog in PNOR, look in our - // ToSave list - maybe it's there waiting - for (std::list<errlHndl_t>::iterator - it = iv_errlToSave.begin(); - it != iv_errlToSave.end(); - it++) + // errlMsgList - maybe it's there waiting + ErrlListItr_t it = std::find_if(iv_errlList.begin(), + iv_errlList.end(), + std::bind1st(ptr_fun(&compareEidToPlid) + ,l_tmpPlid)); + // Check if such errl was found + if (it != iv_errlList.end()) { - errlHndl_t l_err = *it; - if (l_err->eid() == l_tmpPlid) - { - // we found it - // done with the error log handle so delete it. - delete l_err; - l_err = NULL; - - // delete from the list - iv_errlToSave.erase(it); - - // break out of the for loop - we're done - break; - } - } // for + // We found the errlog + // Mark PNOR processing complete + _clearPnorFlag(*it); + _updateErrlListIter(it); + } } msg_free(theMsg); - if (!iv_errlToSave.empty()) - { - //we didn't have room before in PNOR to save an - // error log, so try now since we just ACKed one. - errlHndl_t l_err = iv_errlToSave.front(); + // We didn't have room before in PNOR to save an + // error log, so try now since we just ACKed one. + ErrlListItr_t it = std::find_if(iv_errlList.begin(), + iv_errlList.end(), + _isPnorFlagSet); - bool l_savedToPnor = saveErrLogToPnor(l_err); + // Check if such errl was found + if (it != iv_errlList.end()) + { + bool l_savedToPnor = saveErrLogToPnor(it->first); // check if we actually saved the msg to PNOR if (l_savedToPnor) - { // if so, we're done - clean up - - //done with the error log handle so delete it. - delete l_err; - l_err = NULL; - - // delete from the list - iv_errlToSave.pop_front(); + { + // Mark PNOR processing complete + _clearPnorFlag(*it); + _updateErrlListIter(it); } // else, still couldn't save it (for some reason) so // it's still on the list. @@ -513,7 +556,7 @@ void ErrlManager::errlogMsgHndlr () /////////////////////////////////////////////////////////////////////////////// // ErrlManager::sendErrLogToMbox() /////////////////////////////////////////////////////////////////////////////// -msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) +void ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) { msg_t *msg = NULL; @@ -532,50 +575,35 @@ msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) msg->data[0] = io_err->eid(); msg->data[1] = l_msgSize; - void * temp_buff = NULL; - if( iv_isMboxEnabled ) - { - temp_buff = MBOX::allocate( l_msgSize ); - } - else - { - temp_buff = malloc( l_msgSize ); - } + void * temp_buff = MBOX::allocate( l_msgSize ); io_err->flatten ( temp_buff, l_msgSize ); msg->extra_data = temp_buff; TRACDCOMP( g_trac_errl, INFO_MRK"Send msg to FSP for errlogId %.8x", io_err->eid() ); - - if (iv_isMboxEnabled) + errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); + if( !l_err ) { - errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); - if( !l_err ) - { - // clear this - we're done with the message; - // the receiver will free the storage when it's done - msg = NULL; - } - else - { - TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP"); + // clear this - we're done with the message; + // the receiver will free the storage when it's done + msg = NULL; + } + else + { + TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP"); - //Free the extra data due to the error - MBOX::deallocate( msg->extra_data ); - msg_free( msg ); - msg = NULL; + //Free the extra data due to the error + MBOX::deallocate( msg->extra_data ); + msg_free( msg ); + msg = NULL; - delete l_err; - l_err = NULL; - } + delete l_err; + l_err = NULL; } - // else, we created the msg, but couldn't send it - return it so that - // it can be saved and sent later when the MBOX is up. } while (0); - TRACFCOMP( g_trac_errl, EXIT_MRK"sendErrLogToMbox() returning %p", msg); - return msg; + TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrLogToMbox" ); } // sendErrLogToMbox /////////////////////////////////////////////////////////////////////////////// @@ -695,7 +723,6 @@ void errlCommit(errlHndl_t& io_err, compId_t i_committerComp ) } /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// // Global function (not a method on an object) to commit the error log. void ErrlManager::errlResourceReady(errlManagerNeeds i_needs) { @@ -721,6 +748,9 @@ void ErrlManager::sendResourcesMsg(errlManagerNeeds i_needs) case MBOX: msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_MBOX_TYPE; break; + case ERRLDISP: + msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_ERRLDISP_TYPE; + break; default: { TRACFCOMP( g_trac_errl, ERR_MRK "bad msg!!"); @@ -797,30 +827,22 @@ void ErrlManager::sendErrlogToMessageQueue ( errlHndl_t& io_err, /////////////////////////////////////////////////////////////////////////////// void ErrlManager::errlogShutdown() { - // if there are errorlogs that didn't get sent via the MBOX to FSP, - // trace them and clean up - while (!iv_errlToSend.empty()) + // if there are errorlogs that didn't get fully processed, trace them + // and clean up + while (!iv_errlList.empty()) { - msg_t * msg = iv_errlToSend.front(); - TRACDCOMP(g_trac_errl, INFO_MRK "Failed to send to FSP: eid %.8x", - msg->data[0]); - free( msg->extra_data ); - msg_free( msg ); - // delete from the list - iv_errlToSend.pop_front(); - } // while items on iv_errlToSend list + // Get errl and its flags + std::pair<errlHndl_t, uint8_t> l_pair = iv_errlList.front(); + // If still true that means it was not processed - // if there are errorlogs that didn't get stored in PNOR, - // trace them and clean up - while (!iv_errlToSave.empty()) - { - errlHndl_t l_err = iv_errlToSave.front(); - TRACFCOMP(g_trac_errl, ERR_MRK "Failed to store to PNOR: eid %.8x", - l_err->eid()); - delete l_err; + TRACFCOMP(g_trac_errl, INFO_MRK "Failed to fully process Errl(eid %.8x) - Errl Flags Bitfield = 0x%X", + l_pair.second); + + delete l_pair.first; + l_pair.first = NULL; // delete from the list - iv_errlToSave.pop_front(); - } // while items on iv_errlToSave list + iv_errlList.pop_front(); + } // while items on iv_errlList list // Ensure that all the error logs are pushed out to PNOR // prior to the PNOR resource provider shutting down. @@ -928,32 +950,34 @@ void ErrlManager::setupPnorInfo() // if error(s) came in before PNOR was ready, // the error log(s) would be on this list. save now. - while (!iv_errlToSave.empty()) + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) { - errlHndl_t l_err = iv_errlToSave.front(); - - //ACK it if no one is there to receive - bool l_savedToPnor = saveErrLogToPnor(l_err); - - // check if we actually saved the msg to PNOR - if (l_savedToPnor) - { // if so, we're done - clean up - - //done with the error log handle so delete it. - delete l_err; - l_err = NULL; + // Check if PNOR processing is needed + if (_isPnorFlagSet(*it)) + { + //ACK it if no one is there to receive + bool l_savedToPnor = saveErrLogToPnor(it->first); - // delete from the list - iv_errlToSave.pop_front(); + // check if we actually saved the msg to PNOR + if (l_savedToPnor) + { + // Mark PNOR processing complete + _clearPnorFlag(*it); + _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 { - // still couldn't save it (PNOR maybe full) so - // it's still on the list. - break; // get out of this while loop. + ++it; } - } // while entries on list - + } } while (0); TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo"); @@ -985,8 +1009,8 @@ bool ErrlManager::incrementPnorOpenSlot() /////////////////////////////////////////////////////////////////////////////// bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err) { - TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid()); bool rc = false; + TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid()); // actually, if it's an INFORMATIONAL log, we don't want to waste the write // cycles, so we'll just 'say' that we saved it and go on. @@ -1041,9 +1065,8 @@ bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err) } // else no open slot - return false } - TRACFCOMP( g_trac_errl, EXIT_MRK"saveErrLogToPnor returning %s", - rc ? "true" : "false"); + rc ? "true" : "false"); return rc; } // saveErrLogToPnor @@ -1155,4 +1178,23 @@ void ErrlManager::setACKInFlattened(uint32_t i_position) return; } +bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) +{ + bool l_removed = false; + // Delete if this error has been fully processed (flags cleared) + if (io_it->second == 0) + { + // Delete errl + delete io_it->first; + io_it->first = NULL; + io_it = iv_errlList.erase(io_it); + l_removed = true; + } + else + { + ++io_it; + } + return l_removed; +} + } // End namespace diff --git a/src/usr/errl/parser/genErrlParsers.pl b/src/usr/errl/parser/genErrlParsers.pl index 626b6b763..7fb516683 100755 --- a/src/usr/errl/parser/genErrlParsers.pl +++ b/src/usr/errl/parser/genErrlParsers.pl @@ -7,6 +7,7 @@ # OpenPOWER HostBoot Project # # Contributors Listed Below - COPYRIGHT 2013,2014 +# [+] Google Inc. # [+] International Business Machines Corp. # # @@ -442,6 +443,7 @@ close(OFILE); my %compValueToParseHash; my %rcModValuesUsed; my %srcList; +my %displayDataEntries; foreach my $file (@filesToParse) { @@ -479,6 +481,7 @@ foreach my $file (@filesToParse) my $rc = ""; my $rcValue = ""; my @userData; + my @userDataTextOnly; my $desc = ""; my $cdesc = ""; @@ -607,6 +610,7 @@ foreach my $file (@filesToParse) my $udString = "\"$udDesc\", \"$udText\""; push(@userData, $udString); + push(@userDataTextOnly, $udText); } elsif ($line =~ /\@devdesc\s+(\S+.*)/i) { @@ -740,12 +744,26 @@ foreach my $file (@filesToParse) } $parserCode .= " break;\n\n"; + # Create the data entry code for this error + my $dataEntryCode = " {\n" + . " 0x$modIdValue, // Module Id\n" + . " 0x$rcValue, // ReasonCode\n" + . " \"$desc\",\n" + . " \"$modId\",\n" + . " \"$rc\",\n" + . " \"$userDataTextOnly[0]\",\n" + . " \"$userDataTextOnly[1]\"\n" + . " },\n\n"; + # The component value is the first two characters of the 4 character rc my $compValue = $rcValue; $compValue =~ s/..$//; # Add the parser code to compValueToParseHash $compValueToParseHash{$compValue} .= $parserCode; + + # Add the data entry code to displayDataEntries + $displayDataEntries{$modIdValue}{$rcValue} = $dataEntryCode; } } @@ -1028,6 +1046,52 @@ print OFILE "\n\n.include<\${RULES_MK}>\n"; close(OFILE); #------------------------------------------------------------------------------ +# Generate the errldisplaydata.C file that contains the set of Hostboot +# component IDs and detailed error data. +# Note: This file is placed one directory up from the other generated files +# because this is actually part of hostboot. +#------------------------------------------------------------------------------ +$outputFileName = $outputDir . "/../errldisplaydata.C"; +open(OFILE, ">", $outputFileName) or die("Cannot open: $outputFileName: $!"); + +print OFILE "/*\n"; +print OFILE " * Automatically generated by Hostboot's $0\n"; +print OFILE " * Do not modify this file in the hostboot tree, it is automatically\n"; +print OFILE " * generated every build.\n"; +print OFILE " *\n"; +print OFILE " * TimeStamp: $timestamp\n"; +print OFILE " * Image Id: $imageId\n"; +print OFILE " *\n"; +print OFILE " */\n\n"; +print OFILE "#include <errldisplay/errldisplay.H>\n"; +print OFILE "#include <stdlib.h>\n\n"; +print OFILE "namespace ERRORLOGDISPLAY\n{\n\n"; +print OFILE "// Error Info Table\n"; +print OFILE "ErrLogDisplay::errLogInfo ErrLogDisplay::errorInfo [] = {\n"; +foreach my $modID (sort keys %displayDataEntries) +{ + foreach my $rc (sort keys %{$displayDataEntries{$modID}}) + { + print OFILE $displayDataEntries{$modID}{$rc}; + } +} + +print OFILE "};\n"; +print OFILE "uint16_t ErrLogDisplay::errorInfoTableSize = sizeof(errorInfo) / sizeof(errorInfo[0]);\n\n"; +print OFILE "\n\n// Component Id Table\n"; +print OFILE "#include <hbotcompid.H>\n"; +print OFILE "ErrLogDisplay::compTableInfo ErrLogDisplay::compTable [] = {\n"; +foreach my $key (sort keys %compIdToValueHash) +{ + $key = substr($key,0,length($key)-3); + print OFILE " {" . $key . "_ID, " . $key . "_NAME},\n"; +} +print OFILE "};\n"; +print OFILE "uint16_t ErrLogDisplay::compTableSize = sizeof(compTable) / sizeof(compTable[0]);\n\n"; +print OFILE "} // End Namespace\n"; +close(OFILE); + +#------------------------------------------------------------------------------ # Subroutine that prints the usage #------------------------------------------------------------------------------ sub usage diff --git a/src/usr/errl/parser/makefile b/src/usr/errl/parser/makefile index e008e6974..05a3ab0fa 100644 --- a/src/usr/errl/parser/makefile +++ b/src/usr/errl/parser/makefile @@ -6,6 +6,7 @@ # OpenPOWER HostBoot Project # # Contributors Listed Below - COPYRIGHT 2011,2014 +# [+] Google Inc. # [+] International Business Machines Corp. # # @@ -96,6 +97,7 @@ clean: rm -f ${GENDIR}/comps.C rm -f ${IMGDIR}/errlparser rm -fr ${OBJDIR} + rm -f ${GENDIR}/errldisplaydata.C debug: ls -l ${GENDIR} diff --git a/src/usr/errldisplay/errldisplay.C b/src/usr/errldisplay/errldisplay.C new file mode 100644 index 000000000..f3a80b839 --- /dev/null +++ b/src/usr/errldisplay/errldisplay.C @@ -0,0 +1,195 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/errldisplay/errldisplay.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] 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 */ +/** + * @file /src/usr/errl/display/errldisplay.C + * + * @brief Implementation of ErrlDisplay class + * This will display human-readable dumps of error log entries. + * + * The strings displayed are automatically extracted from source code by + * the script ../errl/parser/genErrlParsers.pl + * + * The base image is limited to 512K, and inclusion of the error strings + * in the base make it grow beyond that limit, so the text and display + * functions are put into the extended image. + * + * The errl module in the base image will provide an interface for the + * display functions to register with it. + * When an errl is generated, the base image will see if a display function + * has been registered. If so, then it will be called to display the error. + * If not, then the base image will display the raw error data and save the + * error information into a list. + * When the display function does register itself, the errl module in the + * base image will pretty-print all of the pending errors from the list + * it generated before that point. + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <trace/interface.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <errldisplay/errldisplay.H> +#include <stdlib.h> +#include <string.h> +#include <initservice/taskargs.H> +#include <algorithm> +#include <console/consoleif.H> + +namespace ERRORLOGDISPLAY +{ + +// Trace definition +trace_desc_t* g_trac_errldisp = NULL; +TRAC_INIT(&g_trac_errldisp, "ERRLDISP", KILOBYTE, TRACE::BUFFER_SLOW); + +/** + * @brief Default error log to display when we can't find one in the errorInfo + * table. + * + * The data tables and size variables + * static errLogInfo errorInfo [] + * static compTableInfo compTable [] + * static uint16_t errorInfoTableSize + * static uint16_t compTableSize + * are automatically generated by the ../errl/parser/genErrlTable.pl script + * and placed in the file $GENDIR/errldisplaydata.C + */ +static const ErrLogDisplay::errLogInfo unknownErrorInfo = { + 0, // Module Id + 0, // Reason Code + "<none>", // Description + "unknown", // Module Name + "unknown", // Reason + "unknown", // User Data 1 string + "unknown" // User Data 2 string +}; + + +ErrLogDisplay& errLogDisplay() +{ + return Singleton<ErrLogDisplay>::instance(); +} + +const ErrLogDisplay::errLogInfo* ErrLogDisplay::findErrLogInfo ( + uint8_t i_moduleId, uint16_t i_reasonCode) +{ + // Create local errLogInfo to search for + struct ErrLogDisplay::errLogInfo l_errLogInfo = {i_moduleId,i_reasonCode, + NULL,NULL,NULL,NULL,NULL}; + + errLogInfo* l_result = std::lower_bound(errorInfo, + errorInfo + errorInfoTableSize, + l_errLogInfo, + ErrLogDisplay::errorLogInfoCompare); + + // Check if the lower_bound found the correct result + if ( (l_result != (errorInfo + errorInfoTableSize)) && + (l_result->moduleId == i_moduleId) && + (l_result->reasonCode == i_reasonCode) ) + { + return l_result; + } + + // Couldn't find it, so return the default unknown structure. + return &unknownErrorInfo; +} + +const char * ErrLogDisplay::findComponentName (compId_t i_compId) +{ + // Create local compTableInfo to search for + struct ErrLogDisplay::compTableInfo l_compTableInfo = {i_compId, NULL}; + + compTableInfo* l_result = std::lower_bound(compTable, + compTable + compTableSize, + l_compTableInfo, + ErrLogDisplay::compTableCompare); + + // Check if the lower_bound found the correct result + if ( (l_result != (compTable + errorInfoTableSize)) && + (l_result->value == i_compId) ) + { + return l_result->name; + } + return "unknown"; +} + +void ErrLogDisplay::msgDisplay (const errlHndl_t &i_err, + compId_t i_committerComp) +{ + TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::msgDisplay" ); + + const ErrLogDisplay::errLogInfo* info = findErrLogInfo(i_err->moduleId(), + i_err->reasonCode()); + + CONSOLE::displayf(NULL, + "================================================\n"); + CONSOLE::displayf(NULL, "Error reported by %s (0x%04X)\n", + findComponentName(i_committerComp), i_committerComp); + CONSOLE::displayf(NULL, " %s\n", info->descriptString); + CONSOLE::displayf(NULL, " ModuleId 0x%02x %s\n", + i_err->moduleId(), info->moduleName); + CONSOLE::displayf(NULL, " ReasonCode 0x%04x %s\n", + i_err->reasonCode(), info->reasonString); + CONSOLE::displayf(NULL, " UserData1 %s : 0x%016lx\n", + info->userData1String, i_err->getUserData1()); + CONSOLE::displayf(NULL, " UserData2 %s : 0x%016lx\n", + info->userData2String, i_err->getUserData2()); + + CONSOLE::flush(); + + TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::msgDisplay" ); +} + + +/** + * @brief This is the task entry point. It will register ErrlDisplay module with + * the base image Errl module. + * + * @param[in/out] io_taskRetErrl Errl module to register with ErrlDisplay + * instance + * + * @return None + */ +static void errLogDisplayEntryPoint (errlHndl_t &io_taskRetErrl) +{ + TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::errLogDisplayEntryPoint" ); + + io_taskRetErrl = Singleton<ErrLogDisplay>::instance().init(); + + TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::errLogDisplayEntryPoint" ); +} +TASK_ENTRY_MACRO( errLogDisplayEntryPoint ); + + +errlHndl_t ErrLogDisplay::init() +{ + ERRORLOG::ErrlManager::errlResourceReady(ERRORLOG::ERRLDISP); + return NULL; +} + +} // End namespace diff --git a/src/usr/errldisplay/makefile b/src/usr/errldisplay/makefile new file mode 100644 index 000000000..7c70f2bb5 --- /dev/null +++ b/src/usr/errldisplay/makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/errldisplay/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2014 +# [+] Google Inc. +# [+] 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 + +ROOTPATH = ../../.. +MODULE = errldisplay + +OBJS += errldisplay.o +OBJS += errldisplaydata.o + +include ${ROOTPATH}/config.mk + +# To find errldisplaydata.C - it is generated +# by ../errl/parser/genErrlParsers.pl +vpath %.C ${GENDIR} diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H index 19fe70a84..9996bc994 100644 --- a/src/usr/initservice/extinitsvc/extinitsvctasks.H +++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H @@ -120,6 +120,23 @@ const TaskInfo g_exttaskinfolist[] = { } }, +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY + /** + * @brief Human readable error log display + * Note: Because of dependencies, this must come after libmbox.so + * or hostboot will hang with an Inst Storage exception + * (the ErrlManager constructor tries to talk to MBOX.) + */ + { + "liberrldisplay.so", // taskname + NULL, // no ptr to fnct + { + START_TASK, // task type + EXT_IMAGE, // Extended Module + } + }, +#endif + /** * @brief Trace daemon */ diff --git a/src/usr/makefile b/src/usr/makefile index 746868f18..02f622520 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -62,5 +62,6 @@ SUBDIRS += sbe.d SUBDIRS += gpio.d SUBDIRS += lpc.d SUBDIRS += console.d +SUBDIRS += errldisplay.d include ${ROOTPATH}/config.mk |