diff options
Diffstat (limited to 'src/usr/errl/errlmanager.C')
-rw-r--r-- | src/usr/errl/errlmanager.C | 167 |
1 files changed, 164 insertions, 3 deletions
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index c32c2b2b7..2e787d2e0 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -50,15 +50,18 @@ #include <arch/pirformat.H> #include <errldisplay/errldisplay.H> #include <console/consoleif.H> -#include <config.h> #include <functional> #include <hwas/common/deconfigGard.H> #include <kernel/terminate.H> #include <debugpointers.H> +#include <sys/sync.h> namespace ERRORLOG { +// Used in VERSION partition caching +mutex_t g_errlMutex = MUTEX_INITIALIZER; + extern trace_desc_t* g_trac_errl; #ifdef STORE_ERRL_IN_L3 @@ -103,6 +106,20 @@ bool compareEidToPlid(const uint32_t i_plid, return (i_pair.first->eid() == i_plid); } +const uint8_t* getCachedVersionPartition() +{ + return Singleton<ErrlManager>::instance().getCachedVersionPartition(); +} + +size_t getCachedVersionPartitionSize() +{ + return Singleton<ErrlManager>::instance().getCachedVersionPartitionSize(); +} + +errlHndl_t cacheVersionPartition() +{ + return Singleton<ErrlManager>::instance().cacheVersionPartition(); +} class AtLoadFunctions { @@ -120,6 +137,7 @@ AtLoadFunctions atLoadFunction; /////////////////////////////////////////////////////////////////////////////// ErrlManager::ErrlManager() : iv_pnorReadyForErrorLogs(false), + iv_recvdShutdownEvent(false), iv_hwasProcessCalloutFn(NULL), iv_msgQ(NULL), iv_pnorAddr(NULL), @@ -129,7 +147,9 @@ ErrlManager::ErrlManager() : iv_isMboxEnabled(false), // assume mbox isn't ready yet.. iv_isIpmiEnabled(false), // assume ipmi isn't ready yet.. iv_nonInfoCommitted(false), - iv_isErrlDisplayEnabled(false) + iv_isErrlDisplayEnabled(false), + iv_versionPartitionCache(nullptr), + iv_versionPartitionCacheSize(0) { TRACFCOMP( g_trac_errl, ENTER_MRK "ErrlManager::ErrlManager constructor" ); @@ -270,6 +290,30 @@ void ErrlManager::errlogMsgHndlr () msg_t * theMsg = msg_wait( iv_msgQ ); TRACFCOMP( g_trac_errl, INFO_MRK"Got an error log Msg - Type: 0x%08x", theMsg->type ); + + // if we've been shut down then do nothing except delete the msg or send + // a response depending on the message type. + if(iv_recvdShutdownEvent) + { + TRACFCOMP( g_trac_errl, INFO_MRK "Error log service is shutdown. " + "Message will be ignored."); + switch( theMsg->type ) + { + // Shutdown and flush message types expect a response + case ERRLOG_SHUTDOWN_TYPE: + case ERRLOG_FLUSH_TYPE: + msg_respond ( iv_msgQ, theMsg ); + break; + + // All other messages just need to be freed + default: + msg_free(theMsg); + break; + } + // wait for next message + continue; + } + //Process message just received switch( theMsg->type ) { @@ -1009,6 +1053,9 @@ void ErrlManager::errlogShutdown() // prior to the PNOR resource provider shutting down. PNOR::flush(PNOR::HB_ERRLOGS); + // Remember that we have recieved the shutdown event + iv_recvdShutdownEvent = true; + return; } @@ -1031,4 +1078,118 @@ bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) return l_removed; } +const uint8_t* ErrlManager::getCachedVersionPartition() const +{ + mutex_lock(&g_errlMutex); + const uint8_t* l_versionPtr = iv_versionPartitionCache; + mutex_unlock(&g_errlMutex); + return l_versionPtr; +} + +size_t ErrlManager::getCachedVersionPartitionSize() const +{ + mutex_lock(&g_errlMutex); + size_t l_versionSize = iv_versionPartitionCacheSize; + mutex_unlock(&g_errlMutex); + return l_versionSize; +} + +errlHndl_t ErrlManager::cacheVersionPartition() +{ + errlHndl_t l_errl = nullptr; + bool l_versionPartitionLoaded = false; + + do { + + if(iv_isVersionPartitionCached || + !PNOR::isSectionAvailable(PNOR::VERSION)) + { + // No need to try to cache more than once or if + // there is no VERSION partition + break; + } + +#ifdef CONFIG_SECUREBOOT + l_errl = PNOR::loadSecureSection(PNOR::VERSION); + if(l_errl) + { + TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not load VERSION partition"); + break; + } + + l_versionPartitionLoaded = true; +#endif + + PNOR::SectionInfo_t l_pnorVersionSectionInfo; + l_errl = getSectionInfo(PNOR::VERSION, l_pnorVersionSectionInfo); + if(l_errl) + { + TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not get VERSION section info"); + break; + } + + // Since multiple errls may be at different stages of commit at the same + // time, lock the mutex to prevent atomicity issues + mutex_lock(&g_errlMutex); + + iv_versionPartitionCacheSize = 0; + + const char* l_versionSectionPtr = + reinterpret_cast<char*>(l_pnorVersionSectionInfo.vaddr); + + // The actual size of the text in the VERSION partition is likely to be less + // than the declared size. Calculate the actual size here. + while((l_versionSectionPtr[iv_versionPartitionCacheSize] != '\0') && + (iv_versionPartitionCacheSize < l_pnorVersionSectionInfo.size)) + { + ++iv_versionPartitionCacheSize; + } + iv_versionPartitionCache = new uint8_t[iv_versionPartitionCacheSize]; + + memcpy(const_cast<uint8_t*>(iv_versionPartitionCache), + reinterpret_cast<uint8_t*>(l_pnorVersionSectionInfo.vaddr), + iv_versionPartitionCacheSize); + + mutex_unlock(&g_errlMutex); + + } while(0); + + if(l_versionPartitionLoaded) + { +#ifdef CONFIG_SECUREBOOT + errlHndl_t l_unloadSecErr = PNOR::unloadSecureSection(PNOR::VERSION); + if(l_unloadSecErr) + { + TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not unload VERSION partition"); + if(l_errl) + { + l_unloadSecErr->plid(l_errl->plid()); + errlCommit(l_unloadSecErr, ERRL_COMP_ID); + } + else + { + l_errl = l_unloadSecErr; + l_unloadSecErr = nullptr; + } + } +#endif + } + + if(l_errl) + { + if(iv_versionPartitionCache) + { + delete[] iv_versionPartitionCache; + iv_versionPartitionCache = nullptr; + } + iv_versionPartitionCacheSize = 0; + } + + // Set the cache attrmpted flag regardless of whether we actually + // were able to cache the partition + iv_isVersionPartitionCached = true; + + return l_errl; +} + } // End namespace |