Skip to content

Commit

Permalink
Cache VERSION Partition
Browse files Browse the repository at this point in the history
This commit adds logic to cache the VERSION partition so that
errl commit function is able to use the cached data instead of sending
messages to SPnorRP queue. Said messages also cause deadlocks
if secureboot verifications fail, since the code attempts to
send a synch message to the SPnorRP queue while it's handling
another synch message. These changes only impact OP systems and
code paths.

Change-Id: I9eeb05878d98fb2891fe76adc06ad376edc77fbe
CQ: SW465038
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/82304
Reviewed-by: Nicholas E Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Glenn Miles <milesg@ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
Ilya Smirnov authored and dcrowell77 committed Aug 29, 2019
1 parent c4df5e9 commit 3db6c14
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 85 deletions.
65 changes: 64 additions & 1 deletion src/include/usr/errl/errlmanager.H
Expand Up @@ -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. */
/* */
Expand Down Expand Up @@ -81,6 +81,32 @@ void errlCommit(errlHndl_t& io_err, compId_t i_committerComp );
*/
uint8_t getHiddenLogsEnable();

/**
* @brief Returns the cached VERSION partition, if any. Makes a call to
* ErrlManager::getCachedVersionPartition
* @return uint8_t* The pointer to the binary contents of the VERSION
* partition; nullptr will be returned if VERSION hasn't been
* cached yet of if there was an error during caching
*/
const uint8_t* getCachedVersionPartition();

/**
* @brief Returns the size of the cached VERSION partition. Makes a call
* to ErrlManager::getCachedVersionPartitionSize
* @return size_t The size of the cached VERSION partition. A 0 will be
* returned if VERSION hasn't been cached yet or if there was an
* error during caching
*/
size_t getCachedVersionPartitionSize();

/*
* @brief Call to ErrlManager to cache the VERSION PNOR partition into an
* internal buffer.
*
* @return errlHndl_t nullptr on success; non-nullptr on error.
*/
errlHndl_t cacheVersionPartition();

/**
* @brief Global enums used by static errlResourceReady function
*/
Expand Down Expand Up @@ -209,6 +235,34 @@ public:
*/
static bool errlCommittedThisBoot();

/**
* @brief Returns the cached VERSION partition, if any
* @return uint8_t* The pointer to the binary contents of the VERSION
* partition
*/
const uint8_t* getCachedVersionPartition() const;

/**
* @brief Returns the size of the cached VERSION partition
* @return size_t The size of the cached VERSION partition
*/
size_t getCachedVersionPartitionSize() const;

/**
* @brief Cache the VERSION PNOR partition into a member buffer. The
* buffer is dynamically allocated here to hold the contents of the
* partition. If any error occurs during the execution, the buffer
* is deleted and the error is returned. This function is not
* supposed to be called within ErrlManager message handler, since
* the function itself makes synchronous calls to various message
* handlers. Note that once the partition is cached, the cache is
* never purged to make sure all possible error logs receive the
* VERSION field. No-op on FSP systems.
*
* @return errlHndl_t nullptr on success; non-nullptr on error.
*/
errlHndl_t cacheVersionPartition();


/**
* @brief Value to determine what logs are to be skipped. Mirrors
Expand Down Expand Up @@ -634,6 +688,15 @@ private:
bool allowCallHomeEselsToBmc(void);
#endif

const uint8_t* iv_versionPartitionCache; // The bin contents of the VERSION
// partition; once cached, the
// constents are never removed

size_t iv_versionPartitionCacheSize; // The size of the VERSION partition

bool iv_isVersionPartitionCached; // Whether the caching of the VERSION
// partition has been attempted

};


Expand Down
89 changes: 7 additions & 82 deletions src/usr/errl/errlentry.C
Expand Up @@ -657,99 +657,24 @@ void ErrlEntry::addVersionInfo()
if ( !INITSERVICE::spBaseServicesEnabled()
&& PNOR::isSectionAvailable(PNOR::VERSION))
{

// Setting variables only used in config secureboot
#ifdef CONFIG_SECUREBOOT
bool l_secureSectionLoaded = false;
errlHndl_t l_errl_loadSecureSection = nullptr;
#endif

errlHndl_t l_errl = nullptr;

do
{

#ifdef CONFIG_SECUREBOOT
l_errl_loadSecureSection = PNOR::loadSecureSection(PNOR::VERSION);
if (l_errl_loadSecureSection)
{
TRACFCOMP( g_trac_errl,
"addVersionInfo: Failed to load secure VERSION");
// Since an error occurred while attempting to add version info
// to another error log there is nothing that can be done with
// this error since attempting to commit it will lead to an
// infinite loop of committing the error and then recalling this
// function. If this error occurred then the VERSION partition
// is not added and the error log commit continues.
delete l_errl_loadSecureSection;
l_errl_loadSecureSection = nullptr;
break;
}
else
{
l_secureSectionLoaded = true;
}
#endif

// Get PNOR Version
PNOR::SectionInfo_t l_pnorVersionInfo;
l_errl = getSectionInfo(PNOR::VERSION, l_pnorVersionInfo);

if (l_errl)
{
TRACFCOMP( g_trac_errl,
"addVersionInfo: Failed to getSectionInfo");
// Since an error occurred while attempting to add version info
// to another error log there is nothing that can be done with
// this error since attempting to commit it will lead to an
// infinite loop of committing the error and then recalling this
// function. If this error occurred then the VERSION partition
// is not added and the error log commit continues.
delete l_errl;
l_errl = nullptr;
break;
}

const uint8_t* l_versionData =
reinterpret_cast<uint8_t*>(l_pnorVersionInfo.vaddr);
ERRORLOG::getCachedVersionPartition();
size_t l_versionSize =
ERRORLOG::getCachedVersionPartitionSize();

size_t l_numberOfBytes = 0;

// Determine the size of the version data. The max size is the given
// size in the SectionInfo but can be less.
while ((static_cast<char>(l_versionData[l_numberOfBytes]) != '\0')
&& l_numberOfBytes < l_pnorVersionInfo.size)
if(!l_versionData || !l_versionSize)
{
++l_numberOfBytes;
break;
}

char l_pVersionString[l_numberOfBytes + 1]={0};
char l_pVersionString[l_versionSize + 1]={0};

memcpy(l_pVersionString, l_versionData, l_numberOfBytes);
memcpy(l_pVersionString, l_versionData, l_versionSize);

ErrlUserDetailsString(l_pVersionString).addToLog(this);
} while(0);

#ifdef CONFIG_SECUREBOOT
if (l_secureSectionLoaded)
{
l_errl_loadSecureSection = PNOR::unloadSecureSection(PNOR::VERSION);
if(l_errl_loadSecureSection)
{
TRACFCOMP( g_trac_errl,
"addVersionInfo: Failed to unload secure VERSION");
// Since an error occurred while attempting to add version info
// to another error log there is nothing that can be done with
// this error since attempting to commit it will lead to an
// infinite loop of committing the error and then recalling this
// function. If this error occurred then the VERSION partition
// is not added and the error log commit continues.
delete l_errl_loadSecureSection;
l_errl_loadSecureSection = nullptr;
}
}
#endif

}

// End of IPL only block
Expand Down
138 changes: 136 additions & 2 deletions src/usr/errl/errlmanager.C
Expand Up @@ -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. */
/* */
Expand Down Expand Up @@ -55,10 +55,14 @@
#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
Expand Down Expand Up @@ -103,6 +107,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
{
Expand All @@ -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" );

Expand Down Expand Up @@ -1031,4 +1051,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
7 changes: 7 additions & 0 deletions src/usr/pnor/pnorrp.C
Expand Up @@ -214,6 +214,13 @@ void PnorRP::init( errlHndl_t &io_rtaskRetErrl )
#ifdef CONFIG_SECUREBOOT
// Extend the base image to the TPM, regardless of how it was obtained
l_errl = TRUSTEDBOOT::extendBaseImage();

// Cache the VERSION partition data for future use by the errl commit
// code.
if(!l_errl)
{
l_errl = ERRORLOG::cacheVersionPartition();
}
#endif
#endif
}
Expand Down

0 comments on commit 3db6c14

Please sign in to comment.