summaryrefslogtreecommitdiffstats
path: root/src/usr/scom
diff options
context:
space:
mode:
authorNick Bofferding <bofferdn@us.ibm.com>2018-03-19 23:26:08 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-05-08 09:44:28 -0400
commit2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333 (patch)
tree6717b134419978a4b0836382364f98f620d1630c /src/usr/scom
parent3c2b4bf2adc3e076d7dc9e2876b64b813a799260 (diff)
downloadtalos-hostboot-2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333.tar.gz
talos-hostboot-2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333.zip
Secure Boot: Implement Centaur SCOM cache
This change implements a Centaur SCOM cache for sensitive SCOM registers. The cache is initialized and enabled before the first Centaur SCOM, and disabled just prior to locking down the Centaur configuration. Once the Centaur has been locked down, the real register values are compared to the cache entries, and the Centaur is deconfigured (not garded) on any mismatch in assumptions. RTC: 187288 Change-Id: I7b13bfd7eb6b427aba115d6944958bf55e171008 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57532 Reviewed-by: ILYA SMIRNOV <ismirno@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: Michael Baiocchi <mbaiocch@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/scom')
-rw-r--r--src/usr/scom/centaurScomCache.C878
-rw-r--r--src/usr/scom/errlud_cache.C81
-rw-r--r--src/usr/scom/errlud_cache.H98
-rwxr-xr-xsrc/usr/scom/genCentaurScomCacheRegDefs.pl399
-rw-r--r--src/usr/scom/makefile36
-rw-r--r--src/usr/scom/plugins/errludP_cache.H135
-rw-r--r--src/usr/scom/plugins/scomUdParserFactory.H8
-rw-r--r--src/usr/scom/scom.C66
8 files changed, 1695 insertions, 6 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
+
diff --git a/src/usr/scom/errlud_cache.C b/src/usr/scom/errlud_cache.C
new file mode 100644
index 000000000..014b77846
--- /dev/null
+++ b/src/usr/scom/errlud_cache.C
@@ -0,0 +1,81 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/errlud_cache.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,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 errlud_cache.C
+ *
+ * @brief Implementation of classes to log Centaur SCOM register cache
+ * mismatch FFDC
+ */
+
+#include <scom/scomreasoncodes.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <util/utilmem.H>
+#include "errlud_cache.H"
+
+SECUREBOOT::CENTAUR_SECURITY::UdCentaurCacheMismatch::UdCentaurCacheMismatch(
+ const uint64_t i_registerAddr,
+ const uint64_t i_unmaskedExpectedValue,
+ const uint64_t i_unmaskedActualValue,
+ const uint64_t i_mask)
+{
+ // Set up Ud instance variables
+ iv_CompId = SCOM_COMP_ID;
+ iv_Version = SCOM::SCOM_UDT_VERSION_1;
+ iv_SubSection = SCOM::SCOM_UDT_CENTAUR_CACHE_MISMATCH;
+
+ const auto maskedExpectedValue=i_unmaskedExpectedValue&i_mask;
+ const auto maskedActualValue =i_unmaskedActualValue&i_mask;
+
+ //***** Version SCOM_UDT_VERSION_1 Memory Layout *****
+ // 8 bytes : Centaur SCOM address with the cache miscompare
+ // 8 bytes : Expected value from cache (unmasked)
+ // 8 bytes : Actual value read from hardware (unmasked)
+ // 8 bytes : Mask of bits to compare for the two values
+ // 8 bytes : Expected value from cache (masked)
+ // 8 bytes : Actual value read from hardware (masked)
+
+ UtilMem memBuf;
+ memBuf << i_registerAddr
+ << i_unmaskedExpectedValue
+ << i_unmaskedActualValue
+ << i_mask
+ << maskedExpectedValue
+ << maskedActualValue;
+
+ auto pError = memBuf.getLastError();
+ if(pError)
+ {
+ errlCommit(pError,SCOM_COMP_ID);
+ }
+ else
+ {
+ uint8_t* const pBuf =
+ reallocUsrBuf(memBuf.size());
+ memcpy(pBuf, memBuf.base(), memBuf.size());
+ }
+}
+
diff --git a/src/usr/scom/errlud_cache.H b/src/usr/scom/errlud_cache.H
new file mode 100644
index 000000000..b7c2c7bf0
--- /dev/null
+++ b/src/usr/scom/errlud_cache.H
@@ -0,0 +1,98 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/errlud_cache.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,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 */
+
+#ifndef ERRLUD_CACHE_H
+#define ERRLUD_CACHE_H
+
+/**
+ * @file errlud_cache.H
+ *
+ * Defines the classes that log Centaur SCOM register cache failures
+ */
+
+#include <errl/errluserdetails.H>
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+/**
+ * @class UdCentaurCacheMismatch
+ *
+ * @brief Adds Centaur SCOM register cache mismatch FFDC to an error
+ * log
+ */
+class UdCentaurCacheMismatch : public ERRORLOG::ErrlUserDetails
+{
+ public:
+
+ /**
+ * @brief Constructor
+ * @param[in] i_registerAddr Register that registered a cache mismatch
+ * @param[in] i_unmaskedExpectedValue Value read from the cache
+ * @param[in] i_unmaskedActualValue Value read from the hardware
+ * @param[in] i_mask Mask of bits to compare between the two values
+ */
+ UdCentaurCacheMismatch(
+ uint64_t i_registerAddr,
+ uint64_t i_unmaskedExpectedValue,
+ uint64_t i_unmaskedActualValue,
+ uint64_t i_mask);
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~UdCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * Delete Copy Constructor
+ */
+ UdCentaurCacheMismatch(const UdCentaurCacheMismatch&) = delete;
+
+ /**
+ * Delete Copy Assignment
+ */
+ UdCentaurCacheMismatch& operator= (const UdCentaurCacheMismatch&) = delete;
+
+ /**
+ * Delete Move Constructor
+ */
+ UdCentaurCacheMismatch (UdCentaurCacheMismatch&&) = delete;
+
+ /**
+ * Delete Move Assignment
+ */
+ UdCentaurCacheMismatch& operator = (UdCentaurCacheMismatch&&) = delete;
+};
+
+} // End CENTAUR_SECURITY namespace
+
+} // End SECUREBOOT namespace
+
+#endif
diff --git a/src/usr/scom/genCentaurScomCacheRegDefs.pl b/src/usr/scom/genCentaurScomCacheRegDefs.pl
new file mode 100755
index 000000000..8e8574d42
--- /dev/null
+++ b/src/usr/scom/genCentaurScomCacheRegDefs.pl
@@ -0,0 +1,399 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/scom/genCentaurScomCacheRegDefs.pl $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2012,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
+
+use strict;
+
+################################################################################
+# Imported packages
+################################################################################
+
+use Carp;
+use Getopt::Long;
+use Pod::Usage;
+
+################################################################################
+# Initialize some globals
+################################################################################
+
+use constant OUT_FILE_BASE=>"centaurScomCacheRegDefs";
+use constant OUT_C_FILE=>OUT_FILE_BASE.".C";
+
+################################################################################
+# Process command line parameters, issue help text if needed.
+################################################################################
+
+my $cfgCsvFile ="Centaur_Register_List.csv";
+my $cfgOutputDir = ".";
+my $cfgHelp=0;
+my $cfgMan=0;
+my $cfgVerbose=0;
+
+GetOptions("csv:s" => \$cfgCsvFile,
+ "output-dir:s" => \$cfgOutputDir,
+ "help" => \$cfgHelp,
+ "man" => \$cfgMan,
+ "verbose" => \$cfgVerbose ) || pod2usage(-verbose => 0);
+
+pod2usage(-verbose => 1) if $cfgHelp;
+pod2usage(-verbose => 2) if $cfgMan;
+
+# Remove extraneous '/' from end of path names; use temporary version of $/ for
+# the chomp
+{
+ local $/ = '/';
+ chomp($cfgOutputDir);
+ $cfgOutputDir .= "/";
+}
+
+if($cfgVerbose)
+{
+ print STDOUT "CSV file = $cfgCsvFile\n";
+ print STDOUT "Output dir = $cfgOutputDir\n";
+ print STDOUT "Output file name = " . OUT_C_FILE . "\n";
+}
+
+################################################################################
+# Main logic
+################################################################################
+
+open(CSV_FILE,"<$cfgCsvFile")
+ or croak("Failed to open CSV file of $cfgCsvFile.");
+my $csvFile = *CSV_FILE;
+
+my $outSrcFile="$cfgOutputDir".OUT_C_FILE;
+open(OUT_SRC_FILE,">$outSrcFile")
+ or croak("Failed to open output source file of "
+ . "$outSrcFile");
+my $sourceFile = *OUT_SRC_FILE;
+
+writeScomRegDefSourceHeader($sourceFile);
+writeScomRegDefSourceContent($csvFile,$sourceFile);
+writeScomRegDefSourceFooter($sourceFile);
+
+close CSV_FILE or croak("Failed to close CSV file of $cfgCsvFile");
+
+close OUT_SRC_FILE or
+ croak("Failed to close output source file of $outSrcFile");
+
+################################################################################
+# @brief: Strips off leading and trailing whitespace from an input line
+# and returns it
+# @param[in] $line Line of input file
+# @return Line without leading and trailing whitespace
+################################################################################
+
+sub stripLeadingAndTrailingWhitespace {
+ my($line) = @_;
+
+ $line =~ s/^\s+|\s+$//g;
+
+ return $line;
+}
+
+################################################################################
+# @brief: Verifies an input line ends with a comma
+# @param[in] $line Line of input file
+################################################################################
+
+sub verifyEndsWithComma
+{
+ my $line = shift;
+
+ if ($line !~ m/,$/)
+ {
+ croak "BUG! CSV file doesn't end with comma\n\t$line";
+ }
+}
+
+################################################################################
+# @brief: Verifies an input line has no starting comma
+# @param[in] $line Line of input file
+################################################################################
+
+sub verifyNoStartingComma
+{
+ my $line = shift;
+
+ if ($line =~ m/^,/)
+ {
+ croak "BUG! CSV file should not start with comma\n\t$line";
+ }
+}
+
+################################################################################
+# @brief: Returns whether number is a hex number without leading 0x
+# @param[in] $number Number to verify
+# @retval 0 if not a 0x-less hex number
+# @retval 1 if a 0x-less hex number
+################################################################################
+
+sub isValidNumber
+{
+ my $number=shift;
+ my $valid=0;
+
+ my $maxLength = 16;
+
+ if ($number =~ m/^[0-9a-fA-F]{1,$maxLength}$/)
+ {
+ $valid=1;
+ }
+
+ return $valid;
+}
+
+################################################################################
+# @brief: Scrubs required register address and returns a sanitized copy
+# @param[in] $addr The register address
+# @param[in] $line Line of the input file to display on error conditions
+# @return A normalized register address
+################################################################################
+
+sub normalizeRequiredAddr
+{
+ my $addr=shift;
+ my $line=shift;
+
+ if(!defined $addr
+ || $addr eq "")
+ {
+ croak "BUG! CSV file record had undefined register "
+ . "address [$addr]\n\t$line";
+ }
+
+ if(!isValidNumber($addr))
+ {
+ croak "BUG! CSV file record has invalid address [$addr]\n\t$line";
+ }
+
+ $addr="0x".$addr."ULL";
+ return $addr;
+}
+
+################################################################################
+# @brief: Scrubs optional input value and returns a sanitized copy
+# @param[in] $value The property value read from the input file
+# @param[in] $default The default value to use if file did not specify
+# @param[in] $name Name of the property to display on error conditions
+# @param[in] $line Line of the input file to display on error conditions
+# @return A normalized value
+################################################################################
+
+sub normalizeOptionalValue
+{
+ my $value=shift;
+ my $default=shift;
+ my $name=shift;
+ my $line=shift;
+
+ if(!defined $value
+ || $value eq "")
+ {
+ $value=$default;
+ }
+
+ if(!isValidNumber($value))
+ {
+ croak "BUG! CSV file record has invalid optional $name "
+ . "value [$value]\n"
+ . "\tOffending line: $line";
+ }
+
+ $value="0x".$value."ULL";
+ return $value;
+}
+
+################################################################################
+# @brief: Writes the leading mostly non-dynamic content for the output source
+# file
+# @param[in] $outFile Name of the output source file (no path components)
+################################################################################
+
+sub writeScomRegDefSourceHeader {
+ my($outFile) = @_;
+
+print $outFile <<VERBATIM;
+
+/**
+VERBATIM
+print $outFile " * \@file ".OUT_C_FILE."\n";
+print $outFile <<VERBATIM;
+ *
+ * \@brief Automatically generated source code to initialize the Centaur
+ * SCOM cache register definition vector
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <scom/centaurScomCache.H>
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+ScomRegDefs* ScomCache::_initScomRegDefs() const
+{
+ ScomRegDefs* pScomRegDefs = new ScomRegDefs{
+VERBATIM
+}
+
+################################################################################
+# @brief: Writes the dynamic register definition content to the output file
+#
+# @param[in] $csvFile Input CSV file's handle to read from
+# @param[in] $outFile Output file's handle to write to
+################################################################################
+
+sub writeScomRegDefSourceContent {
+ my($csvFile,$outFile) = @_;
+
+ while( <$csvFile> )
+ {
+ my $line=stripLeadingAndTrailingWhitespace($_);
+
+ #Ignore comments
+ if ($line =~ m/^#/)
+ {
+ next;
+ }
+
+ verifyEndsWithComma($line);
+
+ verifyNoStartingComma($line);
+
+ my ($addr,$wandAddr,$worAddr,$init,$mask) = split(/,/,$line);
+
+ $addr = normalizeRequiredAddr($addr,$line);
+
+ $wandAddr = normalizeOptionalValue($wandAddr,"0","wand address",$line);
+
+ $worAddr = normalizeOptionalValue($worAddr,"0","wor address",$line);
+
+ $init = normalizeOptionalValue($init,"0","init",$line);
+
+ my $defaultMask = "FFFFFFFFFFFFFFFF";
+
+ $mask = normalizeOptionalValue(
+ $mask,$defaultMask,"mask",$line);
+
+ # Output columns are:
+ # Address,WAND?,WOR?,base address,base index,init,mask
+
+ if($wandAddr ne "0x0ULL")
+ {
+ print $outFile " "
+ . "{$wandAddr,0b1,0b0,$addr,-1,0x0ULL,0x0ULL},\n";
+
+ }
+
+ if($worAddr ne "0x0ULL")
+ {
+ print $outFile " "
+ . "{$worAddr,0b0,0b1,$addr,-1,0x0ULL,0x0ULL},\n";
+
+ }
+
+ print $outFile " "
+ . "{$addr,0b0,0b0,0x0ULL,-1,$init,$mask},\n";
+ }
+}
+
+################################################################################
+# @brief: Writes the trailing non-dynamic content to the output source
+# file
+# @param[in] $outFile Output file handle to write to
+################################################################################
+
+sub writeScomRegDefSourceFooter {
+ my($outFile) = @_;
+
+print $outFile <<VERBATIM;
+ };
+
+ return pScomRegDefs;
+}
+
+} // End CENTAUR_SECURITY namespace
+
+} // End SECUREBOOT namespace
+
+
+VERBATIM
+}
+
+################################################################################
+# Man page
+################################################################################
+
+1;
+
+__END__
+
+=head1 NAME
+
+genCentaurScomCacheRegDefs.pl
+
+=head1 SYNOPSIS
+
+genCentaurScomCacheRegDefs.pl --csv=FILE --output-dir=DIR
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--csv>
+
+Absolute path and file name of CSV file containing register definitions
+
+=item B<--output-dir>
+
+Output dir to write the generated source file
+
+=item B<--verbose>
+
+Prints out some internal workings
+
+=item B<--help>
+
+Print a brief help message and exits
+
+=item B<--man>
+
+Prints the manual page and exits
+
+=back
+
+=head1 DESCRIPTION
+
+B<getCentaurScomCacheRegDefs.pl> will generate a source file, which should be
+compiled into Hostboot, that seeds the Secure Boot Centaur SCOM cache sensitive
+register definitions
+
+=cut
diff --git a/src/usr/scom/makefile b/src/usr/scom/makefile
index 8ca16f829..461ad44e6 100644
--- a/src/usr/scom/makefile
+++ b/src/usr/scom/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2017
+# Contributors Listed Below - COPYRIGHT 2011,2018
# [+] International Business Machines Corp.
#
#
@@ -28,8 +28,38 @@ MODULE = scom
#include common ojects between hostboot and runtime hostboot
include scom.mk
-#include unique object modules - currently none
-# OBJS +=
+# Configure virtual paths
+GENDIR = ${ROOTPATH}/obj/genfiles
+VPATH += ${ROOTPATH}/src/import/chips/p9/security/
+VPATH += ${GENDIR}
+
+# Defines for targets/prereqs
+CENTAUR_SCOM_REG_DEF_SCRIPT=genCentaurScomCacheRegDefs.pl
+CENTAUR_SCOM_REG_DEF_BASE=centaurScomCacheRegDefs
+CENTAUR_SCOM_REG_DEF_OBJ=${CENTAUR_SCOM_REG_DEF_BASE}.o
+CENTAUR_SCOM_REG_DEF_SRC=${CENTAUR_SCOM_REG_DEF_BASE}.C
+CENTAUR_SCOM_REG_DEF_CSV=Centaur_Register_List.csv
+
+#include unique object modules
+OBJS += $(if $(CONFIG_SECUREBOOT),centaurScomCache.o,)
+OBJS += $(if $(CONFIG_SECUREBOOT),${CENTAUR_SCOM_REG_DEF_OBJ},)
+OBJS += $(if $(CONFIG_SECUREBOOT),errlud_cache.o,)
+
+# Build rules
+all: GENPASS
+
+GENPASS: ${GENDIR}/${CENTAUR_SCOM_REG_DEF_SRC}
+
+# Bring the Centaur SCOM cache register definition initialization source file
+# up to date by executing the generation script (first dependency), passing
+# it the input .csv file (second dependency) and passing it the output dir
+# (the directory part of the rule target .. namely obj/genfiles)
+${GENDIR}/${CENTAUR_SCOM_REG_DEF_SRC}: \
+ ${CENTAUR_SCOM_REG_DEF_SCRIPT} \
+ ${CENTAUR_SCOM_REG_DEF_CSV}
+ ./$< \
+ --csv=$(word 2,$^) \
+ --output-dir=$(@D)
SUBDIRS += test.d
SUBDIRS += runtime.d
diff --git a/src/usr/scom/plugins/errludP_cache.H b/src/usr/scom/plugins/errludP_cache.H
new file mode 100644
index 000000000..15f5ce747
--- /dev/null
+++ b/src/usr/scom/plugins/errludP_cache.H
@@ -0,0 +1,135 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/plugins/errludP_cache.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,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 */
+
+#ifndef ERRLUDP_CACHE_H
+#define ERRLUDP_CACHE_H
+
+/**
+* @file errludP_cache.H
+*
+* Defines the ErrlUserDetailsParser classes that parse Centaur SCOM register
+* cache mismatch FFDC
+*/
+
+#include "errluserdetails.H"
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+ /**
+ * @class UdParserCentaurCacheMismatch
+ *
+ * @brief Parses UdParserCentaurCacheMismatch user details sections
+ */
+ class UdParserCentaurCacheMismatch : public ERRORLOG::ErrlUserDetailsParser
+ {
+
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ UdParserCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~UdParserCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * @brief Parses user detail data from an error log
+ *
+ * @param[in] i_version Version of the data
+ * @param[in] i_parse ErrlUsrParser object for outputting information
+ * @param[in] i_pBuffer Pointer to buffer containing detail data
+ * @param[in] i_buflen Length of the buffer
+ */
+ virtual void parse(
+ errlver_t i_version,
+ ErrlUsrParser& i_parser,
+ void * i_pBuffer,
+ const uint32_t i_buflen) const
+ {
+ if(i_version < SCOM_UDT_VERSION_1)
+ {
+ i_parser.PrintHeading("SCOM cache FFDC: Unknown version");
+ }
+ else
+ {
+ i_parser.PrintHeading("SCOM cache FFDC");
+
+ const char* fieldName[] =
+ {
+ "Register address",
+ "Unmasked expected value",
+ "Unmasked actual value",
+ "Mask",
+ "Masked expected value",
+ "Masked actual value",
+ };
+
+ const uint64_t* pField =
+ reinterpret_cast<const uint64_t *>(i_pBuffer);
+ for(size_t i=0;
+ i<sizeof(fieldName)/sizeof(fieldName[0]);
+ ++i)
+ {
+ if(i_buflen >= (i+1)*sizeof(*pField) )
+ {
+ i_parser.PrintNumberUint64(
+ fieldName[i],"0x%016llX",
+ ERRORLOG::NTH_UINT64(pField+i));
+ }
+ }
+ }
+ }
+
+ private:
+
+ // Parser isn't compiled with c++11 in all environments, and
+ // therefore "delete" of unused interfaces (like below) is not
+ // supported, nor are functions with move semantics
+
+ // Disable compiler provided default functions
+ UdParserCentaurCacheMismatch(
+ const UdParserCentaurCacheMismatch&);
+
+ UdParserCentaurCacheMismatch & operator=(
+ const UdParserCentaurCacheMismatch&);
+ };
+
+}
+
+}
+
+#endif
+
diff --git a/src/usr/scom/plugins/scomUdParserFactory.H b/src/usr/scom/plugins/scomUdParserFactory.H
index 2763e0f32..adc291882 100644
--- a/src/usr/scom/plugins/scomUdParserFactory.H
+++ b/src/usr/scom/plugins/scomUdParserFactory.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -27,6 +27,7 @@
#include "errludparserfactory.H"
#include "errludP_scom.H"
+#include "errludP_cache.H"
namespace SCOM
{
@@ -37,7 +38,10 @@ namespace SCOM
UserDetailsParserFactory()
{
registerParser<SCOM::UdParserPib>
- (SCOM_UDT_PIB);
+ (SCOM_UDT_PIB);
+ registerParser<
+ ::SECUREBOOT::CENTAUR_SECURITY::UdParserCentaurCacheMismatch>
+ (SCOM_UDT_CENTAUR_CACHE_MISMATCH);
}
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C
index ef9bdf8e6..2dcf4a3c0 100644
--- a/src/usr/scom/scom.C
+++ b/src/usr/scom/scom.C
@@ -50,6 +50,14 @@
#include <targeting/common/utilFilter.H>
#include <targeting/namedtarget.H>
+#include <config.h>
+
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+#endif
// Trace definition
trace_desc_t* g_trac_scom = NULL;
@@ -161,7 +169,6 @@ errlHndl_t scomMemBufPerformOp(DeviceFW::OperationType i_opType,
{
errlHndl_t l_err = NULL;
-
uint64_t l_scomAddr = va_arg(i_args,uint64_t);
l_err = checkIndirectAndDoScom(i_opType,
@@ -219,6 +226,39 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
errlHndl_t l_err = NULL;
do {
+
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+ if( (i_opType == DeviceFW::READ)
+ && (i_target != TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ && SECUREBOOT::enabled()
+ && SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().cacheEnabled()
+ && (i_target->getAttr<TARGETING::ATTR_TYPE>()==TARGETING::TYPE_MEMBUF))
+ {
+ bool skipScom=true;
+ uint64_t cacheData=0;
+ l_err=SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ read(i_target,i_addr,skipScom,cacheData);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, ERR_MRK
+ "checkIndirectAndDoScom: failed in call to ScomCache::read() "
+ "for HUID = 0x%08X, address = 0x%016llX",
+ TARGETING::get_huid(i_target),
+ i_addr);
+ break;
+ }
+
+ if(skipScom)
+ {
+ *reinterpret_cast<uint64_t*>(io_buffer) = cacheData;
+ io_buflen=sizeof(cacheData);
+ break;
+ }
+ }
+#endif
+#endif
+
// Do we need to do the indirect logic or not?
bool l_runIndirectLogic = true;
@@ -329,6 +369,30 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
} while(0);
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+ if( !l_err
+ && (i_opType == DeviceFW::WRITE)
+ && (i_target!=TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ && SECUREBOOT::enabled()
+ && SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().cacheEnabled()
+ && (i_target->getAttr<TARGETING::ATTR_TYPE>()==TARGETING::TYPE_MEMBUF) )
+ {
+ l_err = SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ write(i_target,i_addr,
+ *reinterpret_cast<uint64_t*>(io_buffer));
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, ERR_MRK
+ "checkIndirectAndDoScom: failed in call to ScomCache::write() "
+ "for HUID = 0x%08X, address = 0x%016llX",
+ TARGETING::get_huid(i_target),
+ i_addr);
+ }
+ }
+#endif
+#endif
+
return l_err;
}
OpenPOWER on IntegriCloud