summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/tools/listdeps.pl2
-rw-r--r--src/include/usr/errl/errlmanager.H123
-rw-r--r--src/include/usr/errldisplay/errldisplay.H162
-rw-r--r--src/makefile1
-rw-r--r--src/usr/errl/errlmanager.C368
-rwxr-xr-xsrc/usr/errl/parser/genErrlParsers.pl64
-rw-r--r--src/usr/errl/parser/makefile2
-rw-r--r--src/usr/errldisplay/errldisplay.C195
-rw-r--r--src/usr/errldisplay/makefile37
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H17
-rw-r--r--src/usr/makefile1
11 files changed, 800 insertions, 172 deletions
diff --git a/src/build/tools/listdeps.pl b/src/build/tools/listdeps.pl
index 9e389948c..1bfbad4a7 100755
--- a/src/build/tools/listdeps.pl
+++ b/src/build/tools/listdeps.pl
@@ -211,7 +211,7 @@ my %resident_modules = (
"libgpio.so" => '1',
"liblpc.so" => '1',
"libconsole.so" => '1',
-
+ "liberrldisplay.so" => '1',
);
# has with library to istep list file were the DepMod array is kept
diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H
index 1063c6bff..02c47a8d2 100644
--- a/src/include/usr/errl/errlmanager.H
+++ b/src/include/usr/errl/errlmanager.H
@@ -6,6 +6,7 @@
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -34,17 +35,19 @@
/*****************************************************************************/
// I n c l u d e s
/*****************************************************************************/
+#include <config.h>
#include <util/singleton.H>
#include <errl/errlentry.H>
+#include <errldisplay/errldisplay.H>
#include <sys/sync.h>
#include <kernel/timemgr.H>
#include <hbotcompid.H>
#include <hwas/common/hwasCallout.H>
#include <mbox/mbox_queues.H>
#include <mbox/mboxif.H>
+#include <utility>
#include <list>
-
namespace ERRORLOG
{
@@ -77,6 +80,7 @@ enum errlManagerNeeds
PNOR,
TARG,
MBOX,
+ ERRLDISP,
} ;
@@ -216,6 +220,7 @@ private:
ERRLOG_ACCESS_PNOR_TYPE = 0x00000034 | MBOX::FIRST_SECURE_MSG,
ERRLOG_ACCESS_MBOX_TYPE = 0x00000035 | MBOX::FIRST_SECURE_MSG,
ERRLOG_ACCESS_TARG_TYPE = 0x00000036 | MBOX::FIRST_SECURE_MSG,
+ ERRLOG_ACCESS_ERRLDISP_TYPE = 0x00000037 | MBOX::FIRST_SECURE_MSG,
};
/**
@@ -293,11 +298,9 @@ private:
* @brief Create a mailbox message with the error log and send it to Fsp.
*
* @param[in,out] io_err Error log handle to be committed
- * @return msg_t pointer - NULL if msg sent, allocated msg if
- * couldn't send
*
*/
- msg_t *sendErrLogToMbox ( errlHndl_t& io_err );
+ void sendErrLogToMbox ( errlHndl_t& io_err );
/**
* @brief Create a mailbox message with the error log and send it to Fsp.
@@ -438,13 +441,117 @@ private:
char *iv_pnorAddr; // HBEL section in PNOR
uint32_t iv_maxErrlInPnor; // max number of errorlogs that will fit
uint32_t iv_pnorOpenSlot; // current open slot available for an errorlog
- std::list<errlHndl_t> iv_errlToSave; // errlogs still to be saved to PNOR
-
bool iv_isSpBaseServices; // do we need to send to FSP
bool iv_isMboxEnabled; // are we able to send to FSP
- std::list<msg_t *> iv_errlToSend; // msgs still to be sent to FSP
-
bool iv_nonInfoCommitted; //< Keeps track of any non-informational logs.
+ bool iv_isErrlDisplayEnabled; // are we able to use the errorDisplay
+
+ // Errl flags which represent processing needed by the errl
+ // represented as a bit field (8 bits)
+ // Note: When adding a new flag, add to the trace in errlogShutdown()
+ enum ERRLOG_FLAGS
+ {
+ PNOR_FLAG = 0x01,
+ MBOX_FLAG = 0x02,
+ ERRLDISP_FLAG = 0x04,
+ #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY
+ ALL_FLAGS = PNOR_FLAG | MBOX_FLAG | ERRLDISP_FLAG,
+ #else
+ ALL_FLAGS = PNOR_FLAG | MBOX_FLAG,
+ #endif
+ };
+
+ // List of messages errl manager needs to handle
+ // The unint8_t is a bit field to indiciate what needs to be done
+ std::list<std::pair<errlHndl_t, uint8_t> > iv_errlList;
+
+ typedef std::list<std::pair<errlHndl_t, uint8_t> >::iterator ErrlListItr_t;
+
+ /**
+ * @brief checks if the pnor flag is set
+ *
+ * @param[in] i_pair - pair of errl and bitfield of flags
+ * @return True if PNOR flag is set
+ *
+ */
+ static bool _isPnorFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair)
+ {
+ return (i_pair.second & PNOR_FLAG);
+ }
+
+ /**
+ * @brief checks if the mbox flag is set
+ *
+ * @param[in] i_pair - pair of errl and bitfield of flagst
+ * @return True if mbox flag is set
+ *
+ */
+ static bool _isMboxFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair)
+ {
+ return (i_pair.second & MBOX_FLAG);
+ }
+
+ /**
+ * @brief checks if the errldisp flag is set
+ *
+ * @param[in] i_pair - pair of errl and bitfield of flags
+ * @return True if errldisp flag is set
+ *
+ */
+ static bool _isErrlDispFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair)
+ {
+ return (i_pair.second & ERRLDISP_FLAG);
+ }
+
+ /**
+ * @brief clears the pnor flag, indicating complete
+ *
+ * @param[in/out] io_pair - pair of errl and bitfield of flags
+ * @return NA
+ *
+ */
+ static void _clearPnorFlag(std::pair<errlHndl_t, uint8_t> &io_pair)
+ {
+ io_pair.second &= ~PNOR_FLAG;
+ }
+
+ /**
+ * @brief clears the mbox flag, indicating complete
+ *
+ * @param[in/out] io_pair - pair of errl and bitfield of flags
+ * @return NA
+ *
+ */
+ static void _clearMboxFlag(std::pair<errlHndl_t, uint8_t> &io_pair)
+ {
+ io_pair.second &= ~MBOX_FLAG;
+ }
+
+ /**
+ * @brief clears the errldisp flag, indicating complete
+ *
+ * @param[in/out] io_pair - pair of errl and bitfield of flags
+ * @return NA
+ *
+ */
+ static void _clearErrlDispFlag(std::pair<errlHndl_t, uint8_t> &io_pair)
+ {
+ io_pair.second &= ~ERRLDISP_FLAG;
+ }
+
+ /**
+ * @brief Checks if all flags are cleared for a errlhndl.
+ * If so deletes and NULLs the errl and removes from errl list.
+ * It then updates the iterator accordingly, done in this function
+ * to properly handle when a list.erase() happens
+ *
+ * @param[in/out] io_it - iterator for the iv_errlList
+ * @return True if an erase occurred, otherwise false
+ *
+ */
+ bool _updateErrlListIter(std::list< std::pair<errlHndl_t, uint8_t> >
+ ::iterator & io_it);
+
};
} // End namespace
diff --git a/src/include/usr/errldisplay/errldisplay.H b/src/include/usr/errldisplay/errldisplay.H
new file mode 100644
index 000000000..fdd67ea58
--- /dev/null
+++ b/src/include/usr/errldisplay/errldisplay.H
@@ -0,0 +1,162 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/errldisplay/errldisplay.H $ */
+/* */
+/* 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 */
+#ifndef ERRLDISPLAY_H
+#define ERRLDISPLAY_H
+/**
+ * @file src/include/usr/errldisplay/errldisplay.H
+ *
+ * @brief Error Log display for Host Boot environment
+ *
+ */
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <config.h>
+#include <errl/errlentry.H>
+
+namespace ERRORLOGDISPLAY
+{
+
+/*****************************************************************************/
+// Forward class declarations
+/*****************************************************************************/
+
+class ErrLogDisplay;
+
+/**
+ * @brief Returns a reference to the error log display singleton
+ *
+ * @return Reference to the error log display
+ */
+ErrLogDisplay& errLogDisplay();
+
+/**
+ * @brief Error log display module
+ * This class provides a log dump function for host boot.
+ */
+class ErrLogDisplay
+{
+
+public:
+
+ /**
+ * @struct errLogInfo
+ *
+ * Structure that holds human-readable strings describing errors
+ */
+ struct errLogInfo
+ {
+ uint8_t moduleId;
+ uint16_t reasonCode;
+ const char * descriptString;
+ const char * moduleName;
+ const char * reasonString;
+ const char * userData1String;
+ const char * userData2String;
+ };
+
+ /**
+ * @struct compTableInfo
+ *
+ * Structure that holds human readable strings for component IDs.
+ */
+ struct compTableInfo
+ {
+ const compId_t value;
+ const char * name;
+ };
+
+ // Sort function to compare errLogInfo structs
+ static bool errorLogInfoCompare(const errLogInfo e1, const errLogInfo e2)
+ {
+ if (e1.moduleId == e2.moduleId)
+ {
+ return (e1.reasonCode < e2.reasonCode);
+ }
+ return (e1.moduleId < e2.moduleId);
+ }
+
+ // Sort function to compare compTableInfo structs
+ static bool compTableCompare(const compTableInfo c1, const compTableInfo c2)
+ {
+ return (c1.value < c2.value);
+ }
+
+ /**
+ * @brief Display a human-readable error log entry.
+ *
+ * @param[in] i_err Error log handle to be displayed
+ * @param[in] i_committerComp The id of the component that is
+ * committing this error log entry
+ *
+ * @return None
+ */
+ static void msgDisplay (const errlHndl_t &i_err, compId_t i_committerComp);
+
+ /**
+ * @brief Initialization for the error log display function.
+ * This registers with the core error logging to provide human-readable
+ * output for errors.
+ */
+ errlHndl_t init();
+
+private:
+
+ // Auto-generated data tables that hold error information.
+ static errLogInfo errorInfo [];
+ static uint16_t errorInfoTableSize;
+ static compTableInfo compTable [];
+ static uint16_t compTableSize;
+
+ /**
+ * @brief Find the error log info struture that corresponds to the given
+ * module ID & reason code.
+ *
+ * @param[in] moduleId The id of the module which errored.
+ * @param[in] reasonCode The reason of the error.
+ *
+ * @return the error log info stucture that matches the module/reason code.
+ * or NULL, if there is no structure found.
+ */
+ static const errLogInfo* findErrLogInfo (uint8_t i_moduleId,
+ uint16_t i_reasonCode);
+
+ /**
+ * @brief Find the component name that corresponds to the given ID.
+ *
+ * @param[in] compId The id of the component to be identified.
+ *
+ * @return a string with the name of the component, or "unknown" if the
+ * module name is not found.
+ */
+ static const char * findComponentName (compId_t i_compId);
+
+};
+
+} // End namespace
+
+#endif //ERRLDISPLAY_H
diff --git a/src/makefile b/src/makefile
index 3dacfc1ba..f33622541 100644
--- a/src/makefile
+++ b/src/makefile
@@ -162,6 +162,7 @@ EXTENDED_MODULES += sbe
EXTENDED_MODULES += proc_hwreconfig
EXTENDED_MODULES += $(if $(CONFIG_GPIODD),gpio,)
EXTENDED_MODULES += $(if $(CONFIG_CONSOLE),console)
+EXTENDED_MODULES += $(if $(CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY),errldisplay)
EXTENDED_MODULES += $(if $(CONFIG_SET_NOMINAL_PSTATE),pstates)
TESTCASE_MODULES += cxxtest
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
OpenPOWER on IntegriCloud