summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/scom/centaurScomCache.H391
-rw-r--r--src/include/usr/scom/scomreasoncodes.H16
-rwxr-xr-xsrc/usr/errl/plugins/errluserdetails.H52
-rw-r--r--src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C15
-rw-r--r--src/usr/isteps/istep14/call_proc_exit_cache_contained.C24
-rw-r--r--src/usr/isteps/istep14/call_proc_setup_bars.C15
-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
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/attribute_types_hb.xml13
-rw-r--r--src/usr/targeting/common/xmltohb/target_types_hb.xml1
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/xmltohb.pl4
17 files changed, 2221 insertions, 11 deletions
diff --git a/src/include/usr/scom/centaurScomCache.H b/src/include/usr/scom/centaurScomCache.H
new file mode 100644
index 000000000..013976384
--- /dev/null
+++ b/src/include/usr/scom/centaurScomCache.H
@@ -0,0 +1,391 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/scom/centaurScomCache.H $ */
+/* */
+/* 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 */
+
+#ifndef __CENTAURSCOMCACHE_H
+#define __CENTAURSCOMCACHE_H
+
+/**
+ * @file src/include/usr/scom/centaurScomCache.H
+ *
+ * @brief Interface for the Secure Boot Centaur SCOM cache
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+
+extern trace_desc_t* g_trac_scom;
+
+// These defines allow standard logging of error information in traces
+#define TRACE_ERR_FMT "Error info: PLID=0x%08X, EID=0x%08X, Reason=0x%04X. "
+#define TRACE_ERR_ARGS(pError) \
+ ERRL_GETPLID_SAFE(pError), ERRL_GETEID_SAFE(pError), ERRL_GETRC_SAFE(pError)
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+/**
+ * @brief Structure which provides Centaur SCOM cache register definitions
+ */
+struct ScomRegDef
+{
+ // Address of the SCOM register
+ // Must not be 0
+ uint64_t addr;
+
+ // NOTE: only one of isWandReg or isWorReg can be set in a given record at a
+ // time
+
+ // Indicates whether a write to this register bitwise ANDs the requested
+ // write value into a different base register. 0b1=yes, 0b0=no
+ uint8_t isWandReg : 1;
+
+ // Indicates whether a write to this register bitwise ORs the requested
+ // write value into a different base register. 0b1=yes, 0b0=no
+ uint8_t isWorReg : 1;
+
+ // If isWandReg or isWorReg is 0b1, indicates the base register to perform
+ // the WAND or WOR operation on (which must not be 0).
+ // N/A (set to 0) otherwise
+ uint64_t baseAddr;
+
+ // If isWandReg or isWorReg is 0b1, indicates a different index into the
+ // register definition vector where the base address register is located.
+ // Otherwise, indicates this record's position in the register definition
+ // vector. This index allows base register record and per-Centaur register
+ // lookup with O(1) algorithmic complexity.
+ // Must be -1 prior to init, 0..size-1 afterwards
+ ssize_t baseIndex;
+
+ // The expected hardware initialization value
+ // Default = 0
+ // N/A (set to 0) if isWandReg or isWorReg bit set to 0b1
+ uint64_t expectedHwInitValue;
+
+ // A mask indicating which bits of the register to consider when
+ // comparing values read from hardware vs. the cache. If a bit
+ // is set, the bits at the same position should be compared.
+ // Default = all bits 0b1 = compare whole register.
+ // Must not be 0 when neither isWandReg nor isWorReg bit is set.
+ // N/A (set to 0) if isWandReg or isWorReg bit set to 0b1
+ uint64_t mask;
+
+ /**
+ * @brief Returns whether this register has an associated base register
+ *
+ * @retval bool Boolean indicating whether register has an associated base
+ * register that gets changed on write operations
+ * @return true Register has a base register
+ * @return false Register does not have a base register
+ */
+ bool hasBaseAddr() const
+ {
+ return (isWandReg || isWorReg);
+ }
+
+ /**
+ * @brief Enum giving defaults for various record fields
+ */
+ enum DEFAULTS
+ {
+ DEFAULT_IS_WAND_REG=0b0, ///< Not a WAND register
+ DEFAULT_IS_WOR_REG=0b0, ///< Not a WOR register
+ DEFAULT_BASE_ADDR=0x0ULL, ///< No associated base register
+ DEFAULT_BASE_INDEX=-1, ///< Lookup index not populated
+ DEFAULT_EXPECTED_HW_INIT_VALUE=0x0ULL, ///< Expected HW init value of 0
+ DEFAULT_MASK=0xFFFFFFFFFFFFFFFFULL, ///< Compare whole registers
+ };
+
+ /**
+ * @brief Constructor to build a SCOM register definition record
+ *
+ * @param[in] i_addr Register address
+ * @param[in] i_isWandReg Whether register has a base register it bitwise
+ * ANDs into
+ * @param[in] i_isWorReg Whether register has a base register it bitwise
+ * ANDs into
+ * @param[in] i_baseAddr If isWandReg or isWorReg set, the associated base
+ * register
+ * @param[in] i_baseIndex If isWandReg or isWorReg set, the index of the
+ * associated base register in the SCOM register definition vector.
+ * Otherwise, the index of this record in the SCOM register definition
+ * vector. If DEFAULT_BASE_INDEX, the value must be changed before
+ * caching is enabled.
+ * @param[in] i_expectedHwInitValue The expected hardware initialization
+ * value for the register
+ * @param[in] i_mask A mask indicating which bits to analyze when a
+ * register's cache value is compared to the value read from hardware.
+ *
+ * @note: See ScomRegDef field documentation above for additional
+ * restrictions.
+ */
+ ScomRegDef(
+ uint64_t i_addr,
+ int i_isWandReg=DEFAULT_IS_WAND_REG,
+ int i_isWorReg=DEFAULT_IS_WOR_REG,
+ uint64_t i_baseAddr=DEFAULT_BASE_ADDR,
+ ssize_t i_baseIndex=DEFAULT_BASE_INDEX,
+ uint64_t i_expectedHwInitValue=DEFAULT_EXPECTED_HW_INIT_VALUE,
+ uint64_t i_mask=DEFAULT_MASK)
+ : addr(i_addr),
+ isWandReg(i_isWandReg),
+ isWorReg(i_isWorReg),
+ baseAddr(i_baseAddr),
+ baseIndex(i_baseIndex),
+ expectedHwInitValue(i_expectedHwInitValue),
+ mask(i_mask)
+ {
+ }
+};
+
+// Alias for the SCOM register definition vector type
+typedef std::vector<ScomRegDef> ScomRegDefs;
+
+/**
+ * @brief Class which coordinates tracking read and write access to any Centaur
+ * SCOM register deemed to be security sensitive
+ */
+class ScomCache
+{
+ public:
+
+ /**
+ * @brief Initializes all Centaurs' SCOM register cache
+ *
+ * @par Detailed Description:
+ * Builds a SCOM register cache seeded with expected hardware
+ * initialization values for each security sensitive register, and
+ * clones it to every Centaur
+ */
+ void init() const;
+
+ /**
+ * @brief Globally enables caching of read/write SCOM requests for every
+ * functional Centaur
+ */
+ void enableCache();
+
+ /**
+ * @brief Globally disables caching of read/write SCOM requests for every
+ * functional Centaur
+ */
+ void disableCache();
+
+ /**
+ * @brief Returns whether Centaur SCOM register caching is enabled for
+ * all functional Centaurs
+ *
+ * @retval boolean Indicating whether Centaur SCOM register cache is
+ * enabled for all functional Centuars or not
+ */
+ bool cacheEnabled() const;
+
+ /**
+ * @brief Delete all Centaurs' SCOM register cache
+ */
+ void destroy() const;
+
+ /**
+ * @brief If caching enabled and register is sensitive, writes the
+ * requested value to the given Membuf's cache
+ *
+ * @param[in] i_Membuf Membuf target to write. If the request happens
+ * -not- to be a Centaur or caching is disabled, it's a no-op. Returns
+ * error if target is nullptr.
+ * @param[in] i_addr Register address
+ * @param[in] i_value Register value
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log
+ */
+ errlHndl_t write(
+ TARGETING::Target* i_pMembuf,
+ uint64_t i_addr,
+ uint64_t i_value) const;
+
+ /**
+ * @brief If caching enabled and register is sensitive, reads the
+ * requested register from the given Membuf's cache. If the
+ * register was returned, the call indicates a cache hit, else a miss
+ *
+ * @param[in] i_pMembuf Membuf target to read. If the request happens
+ * -not- to be a Centaur, or caching is disabled, it's a no-op.
+ * Returns error if target is nullptr.
+ * @param[in] i_addr SCOM register address to read
+ * @param[out] o_cacheHit Whether the cache held the requested register
+ * value
+ * @param[out] o_value Register value that was read; only valid if
+ * o_cacheHit is true
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log; all outputs
+ * invalid
+ */
+ errlHndl_t read(
+ TARGETING::Target* i_pMembuf,
+ uint64_t i_addr,
+ bool& o_cacheHit,
+ uint64_t& o_value) const;
+
+ /**
+ * @brief Verifies, node-wide, that every security sensitive Centaur SCOM
+ * register's cached value matches (as directed by the compare mask)
+ * the value actually read from the hardware.
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log
+ */
+ errlHndl_t verify() const;
+
+ /**
+ * @brief Dumps, node-wide, the cached values of every security sensitive
+ * Centaur SCOM register to the trace
+ */
+ void dump() const;
+
+ /**
+ * @brief Returns the Centaur SCOM cache singleton
+ *
+ * @retval ScomCache& Reference to the Centaur SCOM cache singleton
+ */
+ static ScomCache& getInstance();
+
+ /**
+ * Delete Copy Constructor
+ */
+ ScomCache(const ScomCache&) = delete;
+
+ /**
+ * Delete Copy Assignment
+ */
+ ScomCache& operator= (const ScomCache&) = delete;
+
+ /**
+ * Delete Move Constructor
+ */
+ ScomCache (ScomCache&&) = delete;
+
+ /**
+ * Delete Move Assignment
+ */
+ ScomCache& operator = (ScomCache&&) = delete;
+
+ protected:
+
+ /**
+ * @brief Centaur SCOM cache constructor
+ */
+ ScomCache();
+
+ /**
+ * @brief Centaur SCOM cache destructor
+ */
+ ~ScomCache();
+
+ private: // APIs
+
+ /**
+ * @brief Helper function to retrieve a Centaur's SCOM cache
+ *
+ * @param[in] i_pCentaur Centaur target. Must not be nullptr and must be a
+ * Centaur, but this is not strictly enforced.
+ * @retval std::vector<uint64_t>* Pointer to the SCOM cache
+ */
+ std::vector<uint64_t>* _getCachePtr(
+ TARGETING::Target* i_pCentaur) const
+ {
+ return reinterpret_cast<std::vector<uint64_t>*>(
+ i_pCentaur->getAttr<TARGETING::ATTR_CENTAUR_REGISTER_CACHE_PTR>());
+ }
+
+ /**
+ * @brief Helper function to store a Centaur's SCOM cache
+ *
+ * @param[in] i_pCentaur Centaur target. Must not be nullptr and must be a
+ * Centaur, but this is not strictly enforced.
+ * @param[in] i_pCache Pointer to the SCOM cache
+ */
+ void _setCachePtr(
+ TARGETING::Target* i_pCentaur,
+ const std::vector<uint64_t>* i_pCache) const
+ {
+ i_pCentaur->setAttr<TARGETING::ATTR_CENTAUR_REGISTER_CACHE_PTR>(
+ reinterpret_cast<uint64_t>(
+ const_cast<std::vector<uint64_t>*>(i_pCache)));
+ }
+
+ /**
+ * @brief Generated function to initialize the SCOM register definitions
+ *
+ * @return ScomRegDefs* Pointer to the SCOM register definitions. Memory
+ * transfer occurs and caller responsible for deleting the vector later.
+ *
+ * @note: Generated source @ obj/genfiles/centaurScomCacheRegDefs.C
+ */
+ ScomRegDefs* _initScomRegDefs() const;
+
+ /**
+ * @brief Checks for duplicate SCOM register definition records (any with
+ * duplicate addresses) and asserts if that condition is found
+ */
+ void _enforceScomRegDefUniqueness() const;
+
+ /**
+ * @brief Ensures the SCOM register definition records are formatted
+ * properly. Asserts on any violation.
+ */
+ void _validateScomRegDefs() const;
+
+ /**
+ * @brief Performs a performance fixup that allows register lookup for an
+ * individual Centaur that runs in O(log n) algoritmic complexity
+ */
+ void _optimizeScomRegDefs();
+
+ private: // Instance vars
+
+ ///< Pointer to vector of SCOM register definitions
+ ScomRegDefs* iv_pScomRegDefs;
+
+ ///< Whether the node-wide Centaur SCOM cache is active
+ bool iv_cacheEnabled;
+};
+
+} // end CENTAUR_SECURITY namespace
+
+} // end SECUREBOOT namespace
+
+#endif
+
diff --git a/src/include/usr/scom/scomreasoncodes.H b/src/include/usr/scom/scomreasoncodes.H
index c4db021c8..4f6c73187 100644
--- a/src/include/usr/scom/scomreasoncodes.H
+++ b/src/include/usr/scom/scomreasoncodes.H
@@ -42,6 +42,9 @@ namespace SCOM
SCOM_TRANSLATE_CENTAUR = 0x08,
SCOM_RT_SEND_SCOM_TO_HYP = 0x09,
SCOM_OP_SANITY_CHECK = 0x0A,
+ SCOM_VERIFY_CENTAUR_CACHE = 0x0B,
+ SCOM_WRITE_CENTAUR_CACHE = 0x0C,
+ SCOM_READ_CENTAUR_CACHE = 0x0D,
};
enum scomReasonCode
@@ -69,11 +72,22 @@ namespace SCOM
SCOM_RUNTIME_HYP_ERR = SCOM_COMP_ID | 0x15,
SCOM_INVALID_DATA_BUFFER = SCOM_COMP_ID | 0x16,
SCOM_INVALID_OP_TYPE = SCOM_COMP_ID | 0x17,
+ SCOM_BAD_CACHE_VERIFY_SEQ = SCOM_COMP_ID | 0x18,
+ SCOM_CACHE_VERIFY_FAILURE = SCOM_COMP_ID | 0x19,
+ SCOM_SENSITIVE_REG_READ_FAIL = SCOM_COMP_ID | 0x1A,
+ SCOM_BAD_TARGET = SCOM_COMP_ID | 0x1B,
+ SCOM_CACHE_SEQ_ERROR = SCOM_COMP_ID | 0x1C,
};
enum UserDetailsTypes
{
- SCOM_UDT_PIB = 0x1
+ SCOM_UDT_PIB = 0x01,
+ SCOM_UDT_CENTAUR_CACHE_MISMATCH = 0x02,
+ };
+
+ enum UserDetailsVersions
+ {
+ SCOM_UDT_VERSION_1 = 0x01,
};
};
diff --git a/src/usr/errl/plugins/errluserdetails.H b/src/usr/errl/plugins/errluserdetails.H
index 8cc3421b2..917dcf266 100755
--- a/src/usr/errl/plugins/errluserdetails.H
+++ b/src/usr/errl/plugins/errluserdetails.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* 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. */
@@ -37,6 +39,54 @@ namespace ERRORLOG
{
/**
+ * @brief Returns the uint64_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint64 Pointer to a uint64_t in network byte order
+ *
+ * @return uint64_t The uint64_t at the pointed to location in host byte order
+ */
+inline uint64_t NTH_UINT64(const void* i_pUint64)
+{
+ return (ntohll(*(reinterpret_cast<const uint64_t*>(i_pUint64))));
+}
+
+/**
+ * @brief Returns the uint32_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint32 Pointer to a uint32_t in network byte order
+ *
+ * @return uint32_t The uint32_t at the pointed to location in host byte order
+ */
+inline uint32_t NTH_UINT32(const void* i_pUint32)
+{
+ return (ntohl(*(reinterpret_cast<const uint32_t*>(i_pUint32))));
+}
+
+/**
+ * @brief Returns the uint16_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint16 Pointer to a uint16_t in network byte order
+ *
+ * @return uint16_t The uint16_t at the pointed to location in host byte order
+ */
+inline uint16_t NTH_UINT16(const void* i_pUint16)
+{
+ return (ntohs(*(reinterpret_cast<const uint16_t*>(i_pUint16))));
+}
+
+/**
+ * @brief Returns the uint8_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint8 Pointer to a uint8_t in network byte order
+ *
+ * @return uint8_t The uint8_t at the pointed to location in host byte order
+ */
+inline uint8_t NTH_UINT8(const void* i_pUint8)
+{
+ return (*(reinterpret_cast<const uint8_t*>(i_pUint8)));
+}
+
+/**
*
* @class ErrlUserDetailsParser
*
diff --git a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
index 6aba97bc5..f0828b072 100644
--- a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
+++ b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
@@ -102,6 +102,11 @@
#include "../../secureboot/common/errlud_secure.H"
#include <sbe/sbe_update.H>
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+
// end includes for post sbe secureboot steps
const uint64_t MS_TO_WAIT_FIRST = 2500; //(2.5 s)
@@ -817,6 +822,16 @@ void* call_proc_cen_ref_clk_enable(void *io_pArgs )
validateSecuritySettings();
+#ifdef CONFIG_SECUREBOOT
+ if(SECUREBOOT::enabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache& centaurCache =
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance();
+ centaurCache.init();
+ centaurCache.enableCache();
+ }
+#endif
+
TARGETING::TargetHandleList functionalProcChipList;
getAllChips(functionalProcChipList, TYPE_PROC, true);
diff --git a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
index f018c452b..46ed22845 100644
--- a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
+++ b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
@@ -51,6 +51,11 @@
#include <util/misc.H>
#include <hwas/common/hwas.H>
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+
using namespace ISTEP;
using namespace ISTEP_ERROR;
using namespace ERRORLOG;
@@ -69,6 +74,24 @@ void* call_proc_exit_cache_contained (void *io_pArgs)
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"call_proc_exit_cache_contained entry" );
+ errlHndl_t l_errl = nullptr;
+
+#ifdef CONFIG_SECUREBOOT
+ if(SECUREBOOT::enabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache& centaurCache =
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance();
+
+ l_errl = centaurCache.verify();
+ if(l_errl)
+ {
+ l_stepError.addErrorDetails(l_errl);
+ errlCommit(l_errl, HWPF_COMP_ID );
+ }
+
+ centaurCache.destroy();
+ }
+#endif
// @@@@@ CUSTOM BLOCK: @@@@@
// figure out what targets we need
@@ -87,7 +110,6 @@ void* call_proc_exit_cache_contained (void *io_pArgs)
//Check that minimum hardware requirement is meet.
//If not, log error and do not proceed
bool l_bootable;
- errlHndl_t l_errl = nullptr;
l_errl = HWAS::checkMinimumHardware(l_sys, &l_bootable);
if (!l_bootable && !l_errl)
{
diff --git a/src/usr/isteps/istep14/call_proc_setup_bars.C b/src/usr/isteps/istep14/call_proc_setup_bars.C
index e42ba9a07..08d1708d3 100644
--- a/src/usr/isteps/istep14/call_proc_setup_bars.C
+++ b/src/usr/isteps/istep14/call_proc_setup_bars.C
@@ -22,6 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+#include <config.h>
#include <errl/errlentry.H>
#include <isteps/hwpisteperror.H>
#include <initservice/isteps_trace.H>
@@ -48,6 +49,10 @@
#include <attribute_ids.H>
+#ifdef CONFIG_SECUREBOOT
+#include <scom/centaurScomCache.H>
+#endif
+
using namespace ISTEP_ERROR;
using namespace ERRORLOG;
@@ -188,6 +193,7 @@ void* call_proc_setup_bars (void *io_pArgs)
} // end if !l_errl
+#ifdef CONFIG_SECUREBOOT
// Assuming no errors, secure any Centaurs
if ( l_stepError.isNull() )
{
@@ -247,7 +253,16 @@ void* call_proc_setup_bars (void *io_pArgs)
}
}
}
+
+ if(SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ cacheEnabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ disableCache();
+ }
+
}
+#endif
if ( l_errl )
{
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;
}
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index 972c2f01e..e1cebe965 100755
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -1128,4 +1128,17 @@
<writeable/>
</attribute>
+<attribute>
+ <id>CENTAUR_REGISTER_CACHE_PTR</id>
+ <description>
+ Pointer to Secure Boot Centaur SCOM register cache
+ </description>
+ <simpleType>
+ <uint64_t></uint64_t>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
index 5f43f0a7a..46c145c75 100644
--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
@@ -186,6 +186,7 @@
<attribute>
<id>HBRT_HYP_ID</id>
</attribute>
+ <attribute><id>CENTAUR_REGISTER_CACHE_PTR</id></attribute>
</targetTypeExtension>
<targetTypeExtension>
diff --git a/src/usr/targeting/common/xmltohb/xmltohb.pl b/src/usr/targeting/common/xmltohb/xmltohb.pl
index 8d8ac765b..78b28e227 100755
--- a/src/usr/targeting/common/xmltohb/xmltohb.pl
+++ b/src/usr/targeting/common/xmltohb/xmltohb.pl
@@ -4366,8 +4366,8 @@ sub getAttributeIdEnumeration {
# attribute_types_hb.xml or attributes_types_fsp.
else
{
- croak("Error: AttributeId $attribute->{id} "
- . "defined multiple times");
+ croak("Error: AttributeId $attribute->{id} "
+ . "defined multiple times");
}
}
else
OpenPOWER on IntegriCloud