diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/scom/centaurScomCache.H | 391 | ||||
-rw-r--r-- | src/include/usr/scom/scomreasoncodes.H | 16 | ||||
-rwxr-xr-x | src/usr/errl/plugins/errluserdetails.H | 52 | ||||
-rw-r--r-- | src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C | 15 | ||||
-rw-r--r-- | src/usr/isteps/istep14/call_proc_exit_cache_contained.C | 24 | ||||
-rw-r--r-- | src/usr/isteps/istep14/call_proc_setup_bars.C | 15 | ||||
-rw-r--r-- | src/usr/scom/centaurScomCache.C | 878 | ||||
-rw-r--r-- | src/usr/scom/errlud_cache.C | 81 | ||||
-rw-r--r-- | src/usr/scom/errlud_cache.H | 98 | ||||
-rwxr-xr-x | src/usr/scom/genCentaurScomCacheRegDefs.pl | 399 | ||||
-rw-r--r-- | src/usr/scom/makefile | 36 | ||||
-rw-r--r-- | src/usr/scom/plugins/errludP_cache.H | 135 | ||||
-rw-r--r-- | src/usr/scom/plugins/scomUdParserFactory.H | 8 | ||||
-rw-r--r-- | src/usr/scom/scom.C | 66 | ||||
-rwxr-xr-x | src/usr/targeting/common/xmltohb/attribute_types_hb.xml | 13 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types_hb.xml | 1 | ||||
-rwxr-xr-x | src/usr/targeting/common/xmltohb/xmltohb.pl | 4 |
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 |