diff options
Diffstat (limited to 'src/usr/scom/centaurScomCache.C')
-rw-r--r-- | src/usr/scom/centaurScomCache.C | 878 |
1 files changed, 878 insertions, 0 deletions
diff --git a/src/usr/scom/centaurScomCache.C b/src/usr/scom/centaurScomCache.C new file mode 100644 index 000000000..99ccc73fd --- /dev/null +++ b/src/usr/scom/centaurScomCache.C @@ -0,0 +1,878 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/centaurScomCache.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* [+] 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/scom/centaurScomCache.C + * + * @brief Implementation for Centaur SCOM register cache + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +#include <assert.h> +#include <devicefw/driverif.H> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <errl/errludtarget.H> +#include <targeting/common/utilFilter.H> +#include <scom/scomreasoncodes.H> + +#include <scom/centaurScomCache.H> +#include "scom.H" +#include "errlud_cache.H" + +namespace SECUREBOOT +{ + +namespace CENTAUR_SECURITY +{ + +const bool ADD_HI_PRI_HB_SW_CALLOUT=true; +const bool NO_HB_SW_CALLOUT=false; + +ScomCache::ScomCache() + : iv_pScomRegDefs(_initScomRegDefs()), + iv_cacheEnabled(false) +{ + // Sort SCOM register defintion records by register address so that we + // can look up a given register using std::lower_bound in O(log n) + // algorithmic complexity and then jump to same index within local + // Centaur SCOM cache to find the current value, yielding overall + // algorithmic complexity of O(log n) for lookup of any given Centaur's + // cached SCOM register + std::sort( + iv_pScomRegDefs->begin(), + iv_pScomRegDefs->end(), + [](const ScomRegDef& i_lhs,const ScomRegDef &i_rhs) + { + return (i_lhs.addr<i_rhs.addr); + }); + + _enforceScomRegDefUniqueness(); + + _validateScomRegDefs(); + + _optimizeScomRegDefs(); +} + +ScomCache::~ScomCache() +{ + delete iv_pScomRegDefs; + iv_pScomRegDefs=nullptr; +} + +void ScomCache::_enforceScomRegDefUniqueness() const +{ + // Assumes the register definitions are already sorted + auto scomRegDefDupStartItr = + std::unique(iv_pScomRegDefs->begin(), iv_pScomRegDefs->end(), + [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs) + { + return (i_lhs.addr==i_rhs.addr); + } + ); + + auto scomRegDefDupItr = scomRegDefDupStartItr; + while(scomRegDefDupItr != iv_pScomRegDefs->end()) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "Found duplicate SCOM register definition for address 0x%016llX", + scomRegDefDupItr->addr); + ++scomRegDefDupItr; + } + + assert(scomRegDefDupStartItr == iv_pScomRegDefs->end(), + "BUG! Duplicate Centaur SCOM register " + "definitions found"); +} + +void ScomCache::_validateScomRegDefs() const +{ + for(const auto& scomRegDef : *iv_pScomRegDefs) + { + assert(scomRegDef.addr != 0,"BUG! Centaur SCOM register definition " + "address is 0"); + + // Index fixup should happen later; starts out as DEFAULT_BASE_INDEX + assert(scomRegDef.baseIndex == ScomRegDef::DEFAULT_BASE_INDEX, + "Centaur SCOM register " + "definition has non DEFAULT_BASE_INDEX baseIndex for " + "register address 0x%016llX.", + scomRegDef.addr); + + if(scomRegDef.hasBaseAddr()) + { + assert(!(scomRegDef.isWandReg && scomRegDef.isWorReg), + "BUG! Centaur SCOM register definition should only have " + "one of isWandReg or isWorReg set. Actual isWandReg = %d, " + "isWorReg = %d for " + "register address 0x%016llX.", + scomRegDef.isWandReg,scomRegDef.isWorReg,scomRegDef.addr); + assert(scomRegDef.baseAddr != ScomRegDef::DEFAULT_BASE_ADDR, + "BUG! Centaur SCOM register " + "definition should have a base register, but it is " + "DEFAULT_BASE_ADDR " + "for register address 0x%016llX.",scomRegDef.addr); + assert( scomRegDef.expectedHwInitValue + == ScomRegDef::DEFAULT_EXPECTED_HW_INIT_VALUE, + "BUG! Centaur SCOM " + "register definition having base address should have an " + "expected HW init value of DEFAULT_EXPECTED_HW_INIT_VALUE but " + "it is 0x%016llX for address 0x%016llX.", + scomRegDef.expectedHwInitValue,scomRegDef.addr); + assert(!scomRegDef.mask, + "BUG! Centaur SCOM register " + "definition having base address should have a mask of " + "all 0b0's, but it is 0x%016llX for address 0x%016llX.", + scomRegDef.mask,scomRegDef.addr); + } + else + { + assert(!scomRegDef.baseAddr, "BUG! Centaur SCOM register " + "definition should not have a base register, but it's " + "0x%016llX for address 0x%016llX.", + scomRegDef.baseAddr,scomRegDef.addr); + assert(scomRegDef.mask, "BUG! Centaur SCOM register " + "definition should have a mask of !0 " + "but it is 0 for address 0x%016llX.", + scomRegDef.addr); + } + } +} + +void ScomCache::_optimizeScomRegDefs() +{ + for(auto scomRegDefItr=iv_pScomRegDefs->begin(); + scomRegDefItr != iv_pScomRegDefs->end(); + ++scomRegDefItr) + { + if(scomRegDefItr->hasBaseAddr()) + { + ScomRegDef regToFind(scomRegDefItr->baseAddr); + auto scomBaseRegDefItr=std::lower_bound( + iv_pScomRegDefs->begin(), + iv_pScomRegDefs->end(), + regToFind, + [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs) + { + return (i_lhs.addr<i_rhs.addr); + } + ); + assert( (scomBaseRegDefItr!=iv_pScomRegDefs->end()) + && (scomBaseRegDefItr->addr==scomRegDefItr->baseAddr), + "BUG! Could not find base register 0x%016llX for register " + "0x%016llX.",scomRegDefItr->baseAddr,scomRegDefItr->addr); + scomRegDefItr->baseIndex=scomBaseRegDefItr-iv_pScomRegDefs->begin(); + } + else + { + scomRegDefItr->baseIndex=scomRegDefItr-iv_pScomRegDefs->begin(); + } + } +} + +void ScomCache::init() const +{ + destroy(); + + std::vector<uint64_t> registerCache(iv_pScomRegDefs->size(),0); + auto registerCacheItr = registerCache.begin(); + for (const auto& scomRegDef : *iv_pScomRegDefs) + { + if(!scomRegDef.hasBaseAddr()) + { + (*registerCacheItr) = scomRegDef.expectedHwInitValue; + } + ++registerCacheItr; + } + + // Find functional Centaurs + TARGETING::TargetHandleList centaurTargets; + (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF); + + for(auto& pCentaur : centaurTargets) + { + if( pCentaur->getAttr<TARGETING::ATTR_MODEL>() + != TARGETING::MODEL_CENTAUR) + { + continue; + } + + const std::vector<uint64_t>* pCache + =_getCachePtr(pCentaur); + assert(pCache==nullptr,"BUG! Centaur cache detected prior to init"); + + // Clone the initialized cache into each Centaur target and transfer + // memory ownership + pCache = new std::vector<uint64_t>(registerCache); + _setCachePtr(pCentaur,pCache); + pCache=nullptr; + } +} + +void ScomCache::destroy() const +{ + // Grab all blueprint Centaurs in case a Centaur got deconfigured after + // Hostboot configured its cache + TARGETING::TargetHandleList centaurTargets; + (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF, false); + + for(auto& pCentaur : centaurTargets) + { + if( pCentaur->getAttr<TARGETING::ATTR_MODEL>() + != TARGETING::MODEL_CENTAUR) + { + continue; + } + + std::vector<uint64_t>* pCache = _getCachePtr(pCentaur); + if(pCache) + { + delete pCache; + pCache = nullptr; + _setCachePtr(pCentaur,pCache); + } + } +} + +errlHndl_t ScomCache::write( + TARGETING::Target* const i_pMembuf, + const uint64_t i_addr, + const uint64_t i_value) const +{ + TRACDCOMP(g_trac_scom,INFO_MRK + "ScomCache::write: register 0x%016llX, value 0x%016llX, HUID 0x%08X", + i_addr,i_value,TARGETING::get_huid(i_pMembuf)); + + errlHndl_t pError=nullptr; + + do { + + if(i_pMembuf==nullptr) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! API usage error! Caller passed a nullptr target"); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_WRITE_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_BAD_TARGET + * @devdesc Caller passed a nullptr target when attempting to + * write the SCOM cache + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_WRITE_CENTAUR_CACHE, + SCOM::SCOM_BAD_TARGET, + 0, + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + if( cacheEnabled() + && ( i_pMembuf->getAttr<TARGETING::ATTR_MODEL>() + == TARGETING::MODEL_CENTAUR) ) + { + // This is logically still the input + TARGETING::Target* const i_pCentaur = i_pMembuf; + + std::vector<uint64_t>* const pCache = _getCachePtr(i_pCentaur); + if(pCache==nullptr) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! Sequence error! Cache for Centaur with HUID " + "0x%08X is not properly initialized", + TARGETING::get_huid(i_pCentaur)); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_WRITE_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR + * @userdata1 HUID of Centaur whose cache was not initialized + * @devdesc Caller attempted to write a Centaur cache that + * is not initialized. + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_WRITE_CENTAUR_CACHE, + SCOM::SCOM_CACHE_SEQ_ERROR, + TARGETING::get_huid(i_pCentaur), + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + ssize_t index=ScomRegDef::DEFAULT_BASE_INDEX; + ScomRegDef regToFind(i_addr); + auto scomRegDefItr=std::lower_bound( + iv_pScomRegDefs->begin(), + iv_pScomRegDefs->end(), + regToFind, + [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs) + { + return (i_lhs.addr<i_rhs.addr); + } ); + if( (scomRegDefItr!=iv_pScomRegDefs->end()) + && (scomRegDefItr->addr==i_addr)) + { + index=scomRegDefItr->baseIndex; + + if(scomRegDefItr->isWandReg) + { + (*pCache)[index] &= i_value; + } + else if(scomRegDefItr->isWorReg) + { + (*pCache)[index] |= i_value; + } + else + { + (*pCache)[index] = i_value; + } + } + // else ... + // Not a cacheable register = noop + } + + } while(0); + + if(pError) + { + // Collect interesting traces + pError->collectTrace(SCOM_COMP_NAME); + pError->collectTrace(SECURE_COMP_NAME); + } + + return pError; +} + +errlHndl_t ScomCache::read( + TARGETING::Target* i_pMembuf, + const uint64_t i_addr, + bool& o_cacheHit, + uint64_t& o_value) const +{ + TRACDCOMP(g_trac_scom,INFO_MRK + "ScomCache::read: register 0x%016llX, HUID 0x%08X", + i_addr,TARGETING::get_huid(i_pMembuf)); + + errlHndl_t pError=nullptr; + auto cacheHit = false; + + do { + + if(i_pMembuf==nullptr) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! API usage error! Caller passed a nullptr target"); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_READ_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_BAD_TARGET + * @devdesc Caller passed a nullptr target when attempting to + * read the SCOM cache + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_READ_CENTAUR_CACHE, + SCOM::SCOM_BAD_TARGET, + 0, + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + if( cacheEnabled() + && ( i_pMembuf->getAttr<TARGETING::ATTR_MODEL>() + == TARGETING::MODEL_CENTAUR) ) + { + // This is logically still the input + TARGETING::Target* const i_pCentaur = i_pMembuf; + + std::vector<uint64_t>* const pCache = _getCachePtr(i_pCentaur); + if(pCache==nullptr) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! Sequence error! Cache for Centaur with HUID " + "0x%08X is not properly initialized", + TARGETING::get_huid(i_pCentaur)); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_READ_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR + * @userdata1 HUID of Centaur whose cache was not initialized + * @devdesc Caller attempted to read a Centaur cache that + * is not initialized. + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_READ_CENTAUR_CACHE, + SCOM::SCOM_CACHE_SEQ_ERROR, + TARGETING::get_huid(i_pCentaur), + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + ScomRegDef regToFind(i_addr); + auto scomRegDefItr=std::lower_bound( + iv_pScomRegDefs->begin(), + iv_pScomRegDefs->end(), + regToFind, + [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs) + { + return (i_lhs.addr<i_rhs.addr); + } ); + if( (scomRegDefItr!=iv_pScomRegDefs->end()) + && (scomRegDefItr->addr==i_addr) ) + { + if(!scomRegDefItr->hasBaseAddr()) + { + o_value = (*pCache)[scomRegDefItr->baseIndex]; + cacheHit = true; + } + // else ... + // Attempt to read WAND/WOR register is not allowed; + // Force a cache miss and let SCOM code handle + // getting an error on the HW read + } + // else ... + // No cache entry for this address + } + // else ... + // Cache not applicable + + } while(0); + + o_cacheHit=cacheHit; + if(!o_cacheHit) + { + o_value=0; + } + + if(pError) + { + // Collect interesting traces + pError->collectTrace(SCOM_COMP_NAME); + pError->collectTrace(SECURE_COMP_NAME); + } + + return pError; +} + +errlHndl_t ScomCache::verify() const +{ + errlHndl_t pError=nullptr; + + do { + + if(cacheEnabled()) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! Sequence error! Cannot verify cache when it's enabled"); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_BAD_CACHE_VERIFY_SEQ + * @devdesc Centaurs' SCOM cache cannot be verified when caching + * is enabled + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_VERIFY_CENTAUR_CACHE, + SCOM::SCOM_BAD_CACHE_VERIFY_SEQ, + 0, + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + TRACFCOMP(g_trac_scom,INFO_MRK + "Verifying Centaur SCOM caches against hardware"); + + TARGETING::TargetHandleList centaurTargets; + (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF); + + for(auto& pCentaur : centaurTargets) + { + if( pCentaur->getAttr<TARGETING::ATTR_MODEL>() + != TARGETING::MODEL_CENTAUR) + { + continue; + } + + std::vector<uint64_t>* const pCache = _getCachePtr(pCentaur); + if(pCache==nullptr) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "BUG! Sequence error! Cache for Centaur with HUID " + "0x%08X is not properly initialized", + TARGETING::get_huid(pCentaur)); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE + * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR + * @userdata1 HUID of Centaur whose cache was not initialized + * @devdesc Caller attempted to read a Centaur cache that + * is not initialized. + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_VERIFY_CENTAUR_CACHE, + SCOM::SCOM_CACHE_SEQ_ERROR, + TARGETING::get_huid(pCentaur), + 0, + ADD_HI_PRI_HB_SW_CALLOUT); + + break; + } + + TRACFCOMP(g_trac_scom,INFO_MRK + "Verifying Centaur SCOM cache for HUID=0x%08X", + TARGETING::get_huid(pCentaur)); + + size_t index=0; + for(const auto& scomRegDef : *iv_pScomRegDefs) + { + if(!scomRegDef.hasBaseAddr()) + { + uint64_t actualValue = 0; + const size_t expSize = sizeof(actualValue); + auto reqSize = expSize; + pError = deviceRead(pCentaur, + &actualValue, + reqSize, + DEVICE_SCOM_ADDRESS( + scomRegDef.addr)); + if(pError) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "ScomCache::verify: SCOM deviceRead call failed for " + "Target HUID 0x%08X and address 0x%016llX. " + TRACE_ERR_FMT, + TARGETING::get_huid(pCentaur), + scomRegDef.addr, + TRACE_ERR_ARGS(pError)); + + // save the PLID from the error before committing + const auto plid = pError->plid(); + ERRORLOG::errlCommit(pError, SCOM_COMP_ID); + + /*@ + * @errortype + * @reasoncode SCOM::SCOM_SENSITIVE_REG_READ_FAIL + * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE + * @userdata1 HUID of offending Centaur + * @userdata2 SCOM address + * @devdesc Failed attempting to read current value of + * sensitive Centaur SCOM register after locking down + * the Centaur. The Centaur will be deconfigured in + * order to maintain system security. + * @custdesc Secure Boot failure + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_VERIFY_CENTAUR_CACHE, + SCOM::SCOM_SENSITIVE_REG_READ_FAIL, + TARGETING::get_huid(pCentaur), + scomRegDef.addr, + NO_HB_SW_CALLOUT); + + // Link to the original PLID + pError->plid(plid); + + // Most likely a hardware problem + pError->addHwCallout( + pCentaur, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_NULL); + + // Next most likely a software issue + pError->addProcedureCallout( + HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_MED); + + break; + } + else + { + assert(reqSize==expSize,"ScomCache::verify: SCOM " + "deviceRead didn't return expected data size " + "of %d (it was %d)", + expSize,reqSize); + const auto expectedValue = (*pCache)[index]; + if( (expectedValue & scomRegDef.mask) + != (actualValue & scomRegDef.mask) ) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "For Centaur with HUID of 0x%08X, found " + "discrepancy between expected and actual " + "security sensitive SCOM register values.", + TARGETING::get_huid(pCentaur)); + TRACFCOMP(g_trac_scom,ERR_MRK + " Register: 0x%016llX, " + "Expected value (masked): 0x%016llX, " + "Actual value (masked): 0x%016llX, ", + scomRegDef.addr, + expectedValue & scomRegDef.mask, + actualValue & scomRegDef.mask); + TRACFCOMP(g_trac_scom,ERR_MRK + " Unmasked cache value: 0x%016llX, " + "Unmasked register value: 0x%016llX, " + "Mask: 0x%016llX.", + expectedValue, + actualValue, + scomRegDef.mask); + + /*@ + * @errortype + * @reasoncode SCOM::SCOM_CACHE_VERIFY_FAILURE + * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE + * @userdata1 HUID of Centaur being verified + * @userdata2 SCOM address registering the mismatch + * @devdesc Secure Boot detected an unexpected + * discrepancy between the expected and actual + * values of a security sensitive Centaur SCOM + * register after locking down the Centaur. The + * Centaur will be deconfigured in order to + * maintain system security. + * @custdesc Secure Boot failure + */ + + // Most likely a software bug + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM::SCOM_VERIFY_CENTAUR_CACHE, + SCOM::SCOM_CACHE_VERIFY_FAILURE, + TARGETING::get_huid(pCentaur), + scomRegDef.addr, + ADD_HI_PRI_HB_SW_CALLOUT); + + UdCentaurCacheMismatch ffdc( + scomRegDef.addr, + expectedValue, + actualValue, + scomRegDef.mask); + ffdc.addToLog(pError); + + // Next most likely a hardware issue + pError->addHwCallout( + pCentaur, + HWAS::SRCI_PRIORITY_MED, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_NULL); + + break; + } + } + } + // else ... + // Not a meaningful register to cache verify, no-op it + + ++index; + } + + if(pError) + { + // Log the target information + ERRORLOG::ErrlUserDetailsTarget(pCentaur). + addToLog(pError); + + // Collect interesting traces + pError->collectTrace(SCOM_COMP_NAME); + pError->collectTrace(SECURE_COMP_NAME); + + // Commit it + ERRORLOG::errlCommit(pError,SCOM_COMP_ID); + } + } + + } while(0); + + if(pError) + { + // Collect interesting traces + pError->collectTrace(SCOM_COMP_NAME); + pError->collectTrace(SECURE_COMP_NAME); + } + + return pError; +} + +void ScomCache::dump(void) const +{ + errlHndl_t pError=nullptr; + + do { + + if(cacheEnabled()) + { + TRACFCOMP(g_trac_scom,INFO_MRK + "**WARNING** Centaur SCOM cache dump HW reads being pulled " + "from cache instead of actual hardware"); + } + + TARGETING::TargetHandleList centaurTargets; + (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF); + + for(auto& pCentaur : centaurTargets) + { + if( pCentaur->getAttr<TARGETING::ATTR_MODEL>() + != TARGETING::MODEL_CENTAUR) + { + continue; + } + + std::vector<uint64_t>* const pCache = _getCachePtr(pCentaur); + if(pCache) + { + TRACFCOMP(g_trac_scom,INFO_MRK + "Dumping Centaur cache for: HUID=0x%08X", + TARGETING::get_huid(pCentaur)); + + size_t index=0; + for(const auto& scomRegDef : *iv_pScomRegDefs) + { + if(!scomRegDef.hasBaseAddr()) + { + uint64_t actualValue = 0; + const size_t expSize = sizeof(actualValue); + auto reqSize = expSize; + pError = deviceRead(pCentaur, + &actualValue, + reqSize, + DEVICE_SCOM_ADDRESS( + scomRegDef.addr)); + if(pError) + { + TRACFCOMP(g_trac_scom,ERR_MRK + "ScomCache::dump: SCOM deviceRead call failed for " + "Target HUID 0x%08X and address 0x%016llX. " + TRACE_ERR_FMT "Ignoring and continuing on.", + TARGETING::get_huid(pCentaur), + scomRegDef.addr, + TRACE_ERR_ARGS(pError)); + + pError->collectTrace(SCOM_COMP_NAME); + pError->collectTrace(SECURE_COMP_NAME); + + errlCommit(pError,SCOM_COMP_ID); + } + else + { + assert(reqSize==expSize,"ScomCache::verify: SCOM " + "deviceRead didn't return expected data size " + "of %d (it was %d)", + expSize,reqSize); + const auto expectedValue = (*pCache)[index]; + const auto expectedValueMasked = + expectedValue & scomRegDef.mask; + const auto actualValueMasked = + actualValue & scomRegDef.mask; + + // Split trace for readability + TRACFCOMP(g_trac_scom,INFO_MRK + "Register: 0x%016llX, " + "Expected value (masked): 0x%016llX, " + "Actual value (masked): 0x%016llX%s, ", + scomRegDef.addr, + expectedValueMasked, + actualValueMasked, + ( expectedValueMasked + == actualValueMasked) ? "" : " (MISMATCH!)"); + TRACFCOMP(g_trac_scom,INFO_MRK + " Unmasked cache value: 0x%016llX, " + "Unmasked register value: 0x%016llX, " + "Mask: 0x%016llX.", + expectedValue, + actualValue, + scomRegDef.mask); + } + } + // else ... + // Not a meaningful register to dump + + ++index; + } + } + else // No cache entry for this Centaur + { + TRACFCOMP(g_trac_scom,INFO_MRK + "Warning: No cache for Centaur with HUID of 0x%08X.", + TARGETING::get_huid(pCentaur)); + } + } + + } while(0); +} + +bool ScomCache::cacheEnabled() const +{ + return iv_cacheEnabled; +} + +void ScomCache::enableCache() +{ + TRACFCOMP(g_trac_scom,INFO_MRK + "Enabling Centaur SCOM cache"); + iv_cacheEnabled=true; +} + +void ScomCache::disableCache() +{ + TRACFCOMP(g_trac_scom,INFO_MRK + "Disabling Centaur SCOM cache"); + iv_cacheEnabled=false; +} + +ScomCache& ScomCache::getInstance() +{ + return Singleton<ScomCache>::instance(); +} + +} // end CENTAUR_SECURITY namespace + +} // end SECUREBOOT namespace + |