summaryrefslogtreecommitdiffstats
path: root/src/usr/errl/errlmanager.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/errl/errlmanager.C')
-rw-r--r--src/usr/errl/errlmanager.C150
1 files changed, 124 insertions, 26 deletions
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C
index 10eccbc66..166fbe6c9 100644
--- a/src/usr/errl/errlmanager.C
+++ b/src/usr/errl/errlmanager.C
@@ -10,28 +10,79 @@
#include <errl/errlmanager.H>
#include <trace/interface.H>
#include <errl/errlentry.H>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+
namespace ERRORLOG
{
extern trace_desc_t* g_trac_errl;
+
+
+// Scaffolding
+// Store error logs in this memory buffer in L3 RAM.
+char g_ErrlStorage[ ERRL_STORAGE_SIZE ];
+
+
+/**
+* @brief
+* In storage, the flattened error logs are interspersed with "markers."
+* CBMARKER is the count of bytes in one marker.
+* CB2MARKERS is the count of bytes in two markers.
+*/
+#define CBMARKER (sizeof(marker_t))
+#define CB2MARKERS (2*sizeof(marker_t))
+
+/**
+* @brief OFFSET2MARKER()
+* Convert an offset within the buffer to a marker_t pointer.
+*/
+#define OFFSET2MARKER(off) (reinterpret_cast<marker_t*>(&g_ErrlStorage[off]))
+
+/**
+* @brief POINTER2OFFSET()
+* Convert a marker_t pointer to its offset within the buffer.
+*/
+#define POINTER2OFFSET(p) ((reinterpret_cast<char*>(p))-(g_ErrlStorage))
+
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ErrlManager::ErrlManager()
-:iv_currLogId(0)
{
- //@todo
- // This is done in order to avoid reading logID from PNOR for every
- // error log created.
- // When ErrlManager singleton instantiated:
- // 1. Parse the last committed error from PNOR
- // 2. Get the logID from that error
- // 3. Load iv_currLogId with that value.
- // 4. When next error is committed, assign the next ID value to it
- // before writing to PNOR.
+ // PNOR will be reinitialized every time hostboot runs
+ iv_currLogId = 0;
+
+ mutex_init(&iv_mutex);
+
+ // Scaffolding.
+ // For now, put error logs in a 64KB buffer in L3 RAM
+ // This buffer has a header (storage_header_t) followed by
+ // storage.
+ iv_pStorage = reinterpret_cast<storage_header_t*>(g_ErrlStorage);
+
+ // g_ErrlStorage is in BSS segment, therefore already zeroed.
+ // memset( iv_pStorage, 0, sizeof(storage_header_t));
+ // Storage size is placed here for benefit of downstream parsers.
+ iv_pStorage->cbStorage = sizeof( g_ErrlStorage );
+ // Offsets are zero-based at &g_ErrlStorage[0],
+ // so the first usable offset is just past the header.
+ iv_pStorage->offsetMarker = sizeof(storage_header_t);
+ iv_pStorage->offsetStart = sizeof(storage_header_t);
+
+ // g_ErrlStorage is in BSS segment, therefore already zeroed.
+ // Thus, the prime marker in storage is already zero.
+ // marker_t* l_pMarker = OFFSET2MARKER( iv_pStorage->offsetStart );
+ // l_pMarker->offsetNext = 0;
+ // l_pMarker->length = 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -41,41 +92,88 @@ ErrlManager::~ErrlManager()
}
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+//
+// Save and delete this error log. On output, io_err will be nul.
+//
void ErrlManager::commitErrLog(errlHndl_t& io_err)
{
- // If NULL, put out warning trace
- if (io_err == NULL)
+ do
{
- TRACFCOMP(g_trac_errl, "commitErrLog() - NULL pointer");
- }
- else
- {
- TRACFCOMP( g_trac_errl, "commitErrLog()> Reasoncode=%X, Id=%d", io_err->reasonCode(), io_err->logId() );
+ if (io_err == NULL)
+ {
+ // put out warning trace
+ TRACFCOMP(g_trac_errl, "commitErrLog() - NULL pointer");
+ break;
+ }
+
+
+ // lock sem
+ mutex_lock(&iv_mutex);
+
+ // Assign a unique error ID to the committed log
+ uint32_t l_errId = getUniqueErrId();
+ io_err->setLogId(l_errId);
+
+ // Get flattened count of bytes.
+ uint32_t l_cbActualFlat = io_err->flattenedSize();
+
+ // Round this copy up to next nearest word (32-bit) boundary.
+ uint32_t l_cbflat = ((l_cbActualFlat+3) & ~3);
+
+ // Save/flatten the error log to the storage buffer.
+ uint32_t l_extent = iv_pStorage->offsetMarker + CB2MARKERS + l_cbflat;
- //@fixme - an id is already assigned in the constructor, which one do we want?
- // Assign a unique error ID to the committed log
- //uint32_t l_errId = getUniqueErrId();
- //io_err->setLogId(l_errId);
+ if( l_extent < ERRL_STORAGE_SIZE)
+ {
+ // New data and its surrounding markers can fit between
+ // the insertion point and the end of the storage buffer.
+ // Flatten the data at the insertion point.
+ marker_t * l_pMarker = OFFSET2MARKER( iv_pStorage->offsetMarker );
+ io_err->flatten( l_pMarker+1, l_cbflat );
+ l_pMarker->length = l_cbActualFlat;
- // @todo:
- // - Flatten error into PNOR
+ // Assign offset to next marker to this marker.
+ l_pMarker->offsetNext=iv_pStorage->offsetMarker+CBMARKER+l_cbflat;
+
+ // Save new insertion point in header.
+ iv_pStorage->offsetMarker = l_pMarker->offsetNext;
+
+ // Initialize the marker at the new insertion point.
+ marker_t * pNew = OFFSET2MARKER( iv_pStorage->offsetMarker );
+ pNew->offsetNext = 0;
+ pNew->length = 0;
+ }
+
+
+ // Count of error logs called to commit, regardless if there was
+ // room to commit them or not.
+ iv_pStorage->cInserted++;
+
+
+ // unlock sem
+ mutex_unlock(&iv_mutex);
delete io_err;
io_err = NULL;
}
+ while( 0 );
return;
}
+
+
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+// This operation is protected by the callers use of a mutex.
uint32_t ErrlManager::getUniqueErrId()
{
- return (__sync_add_and_fetch(&iv_currLogId, 1));
+ /* return (__sync_add_and_fetch(&iv_currLogId, 1)); */
+ iv_currLogId++;
+ return iv_currLogId;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+// Global function (not a method on an object) to commit the error log.
void errlCommit(errlHndl_t& io_err)
{
ERRORLOG::theErrlManager::instance().commitErrLog(io_err);
OpenPOWER on IntegriCloud