diff options
author | Mike Jones <mjjones@us.ibm.com> | 2011-10-26 14:59:19 -0500 |
---|---|---|
committer | MIKE J. JONES <mjjones@us.ibm.com> | 2011-11-01 12:14:11 -0500 |
commit | 5554e9d53859a91b39b01c8f789fe536e4688ecb (patch) | |
tree | 8f24ea04634c7aed7e34d7ce6a26326c0e954e8d /src | |
parent | 14cd4e689a68a7440309090d0a6f82d25f8b6984 (diff) | |
download | talos-hostboot-5554e9d53859a91b39b01c8f789fe536e4688ecb.tar.gz talos-hostboot-5554e9d53859a91b39b01c8f789fe536e4688ecb.zip |
Initial Deconfigure and GARD support
Change-Id: I8448480627ad478e8e16377027137e6df410053f
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/460
Tested-by: Jenkins Server
Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/hwas/deconfigGard.H | 453 | ||||
-rw-r--r-- | src/include/usr/hwas/hwas_reasoncodes.H | 43 | ||||
-rw-r--r-- | src/lib/sync.C | 2 | ||||
-rw-r--r-- | src/usr/hwas/deconfigGard.C | 692 | ||||
-rw-r--r-- | src/usr/hwas/makefile | 2 | ||||
-rw-r--r-- | src/usr/hwas/test/hwasGardTest.H | 920 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/attribute_types.xml | 13 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/target_types.xml | 12 |
8 files changed, 2135 insertions, 2 deletions
diff --git a/src/include/usr/hwas/deconfigGard.H b/src/include/usr/hwas/deconfigGard.H new file mode 100644 index 000000000..25de080fc --- /dev/null +++ b/src/include/usr/hwas/deconfigGard.H @@ -0,0 +1,453 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/hwas/deconfigGard.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file deconfigGard.H + * + * @brief Defines the DeconfigGard class that provides functions to deconfigure + * and create GARD records for Targets + */ + +#ifndef DECONFIGGARD_H_ +#define DECONFIGGARD_H_ + +#include <vector> +#include <stdint.h> +#include <sys/sync.h> +#include <util/singleton.H> +#include <errl/errlentry.H> +#include <targeting/target.H> +#include <targeting/entitypath.H> + +namespace HWAS +{ + +/** + * @brief Returns a reference to the DeconfigGard singleton. + */ +class DeconfigGard; +DeconfigGard & theDeconfigGard(); + +/** + * @class DeconfigGard + * + * This class defines the singleton that handles Deconfigure and GARD Record + * functionality + */ +class DeconfigGard +{ +public: + + /** + * @enum GardSeverity + * + * Defines the possible severities of a GARD Record + */ + enum GardSeverity + { + GARD_SEVERITY_FATAL = 1, + GARD_SEVERITY_PREDICTIVE = 2, + GARD_SEVERITY_MANUAL = 3, + }; + + /** + * @enum DeconfigCause + * + * Defines the possible causes for the creation of a Deconfigure Record + */ + enum DeconfigCause + { + DECONFIG_CAUSE_GARD_RECORD = 1, // Existence of GARD Record + DECONFIG_CAUSE_FIRMWARE_REQ = 2, // Firmware Request + DECONFIG_CAUSE_DECONFIG_BY_ASSOC = 3, // Deconfigure by Association + }; + + /** + * @struct GardRecord + * + * Defines a GARD Record. + * + * Multiple GARD Records can exist for a specific Target + */ + struct GardRecord + { + uint32_t iv_recordId; + TARGETING::EntityPath iv_targetId; + union + { + char iv_cardMruSn[12]; // TODO is there a SN type? + uint32_t iv_chipMruEcid; // TODO is there an ECID type? + }; + uint32_t iv_errlogPlid; + uint8_t iv_severity; // Value from GardSeverity + uint8_t iv_padding[3]; + uint32_t iv_gardTime; + }; + + typedef std::vector<GardRecord> GardRecords_t; + typedef std::vector<GardRecord>::iterator GardRecordsItr_t; + typedef std::vector<GardRecord>::const_iterator GardRecordsCItr_t; + + /** + * @struct DeconfigureRecord + * + * Defines a Deconfigure Record + * + * Only one Deconfigure Record can exist for a specific Target + */ + struct DeconfigureRecord + { + TARGETING::EntityPath iv_targetId; + uint32_t iv_errlogPlid; + uint8_t iv_cause; // Value from DeconfigCause + uint8_t iv_padding[3]; + uint32_t iv_deconfigureTime; + }; + + typedef std::vector<DeconfigureRecord> DeconfigureRecords_t; + typedef std::vector<DeconfigureRecord>::iterator DeconfigureRecordsItr_t; + typedef std::vector<DeconfigureRecord>::const_iterator DeconfigureRecordsCItr_t; + + /** + * @brief Destructor. + */ + ~DeconfigGard(); + + /** + * @brief Clears GARD Records for replaced Targets. + * + * Called by HWAS as part of initial IPL steps. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t clearGardRecordsForReplacedTargets(); + + /** + * @brief Deconfigures Targets that have GARD Records in preparation to IPL. + * + * Called by HWAS as part of initial IPL steps. + * + * If deconfiguring all such Targets will result in a configuration that is + * unable to IPL then it figures out which subset of Targets to deconfigure + * to give the best chance of IPL (Resource Recovery). + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t deconfigureTargetsFromGardRecordsForIpl(); + + /** + * @brief Deconfigures a Target. + * + * Called by ErrlManager when committing an error log containing a + * Deconfigure request. + * + * This will Deconfigure the Target (set state to non-functional, do any + * Deconfigure actions and create a Deconfigure Record) and Deconfigure + * Targets by association. Any errors deconfiguring targets are committed + * and the function continues. The only errors returned are usage errors. + * + * @param[in] i_target Reference to Target to deconfigure. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t deconfigureTarget(TARGETING::Target & i_target, + errlHndl_t i_pErr); + + /** + * @brief Creates a GARD Record for a Target. + * + * Called by ErrlManager when committing an error log containing a + * GARD Record request. + * + * Called by an administrator to manually create a GARD Record. + * + * Any error creating the GARD Record will be returned to the user. + * + * @param[in] i_target Reference to Target to create GARD Record for. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + * @param[in] i_severity Severity of the GARD Record. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t createGardRecord(const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const GardSeverity i_severity); + + /** + * @brief Gets the specified Deconfigure Records. + * + * Called by an administrator to view Deconfigure Records. There can only be + * one Deconfiguration Record per Target. + * + * If the specified record does not exist then no error is returned. The + * only errors returned are usage errors and errors accessing the + * Deconfigure Records. + * + * @param[in] i_pTargetId Pointer to the Target ID to get the Deconfigure + * Record for. If NULL then all Deconfigure Records + * are retrieved. + * @param[out] o_records Reference to vector of DeconfigureRecords that is + * cleared then filled in with records. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t getDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId, + DeconfigureRecords_t & o_records) const; + + /** + * @brief Clears the specified GARD Records. + * + * Called by an administrator to clear GARD records manually. + * + * If the specified record does not exist then no error is returned. The + * only errors returned are usage errors and errors accessing the GARD + * Records. + * + * @param[in] i_recordId RecordId to clear. If zero then all GARD Records + * are cleared. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t clearGardRecords(const uint32_t i_recordId); + + /** + * @brief Clears all GARD Records for the specified Target. + * + * Called by an administrator to clear GARD records manually. + * + * If no GARD Records exist for the Target then no error is returned. The + * only errors returned are usage errors and errors accessing the GARD + * Records. + * + * @param[in] i_targetId Reference to Target ID to clear GARD Records for. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t clearGardRecords(const TARGETING::EntityPath & i_targetId); + + /** + * @brief Gets the specified GARD Records. + * + * Called by an administrator to view GARD Records. + * + * If the specified record does not exist then no error is returned. The + * only errors returned are usage errors and errors accessing the GARD + * Records. + * + * @param[in] i_recordId RecordId to get. If zero then all GARD Records are + * retrieved. + * @param[out] o_records Reference to vector of GardRecords that is cleared + * then filled in with records. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t getGardRecords(const uint32_t i_recordId, + GardRecords_t & o_records); + + /** + * @brief Gets all GARD Records for the specified Target. + * + * Called by an administrator to view GARD Records. + * + * If no GARD Records exist for the Target then no error is returned. The + * only errors returned are usage errors and errors accessing the GARD + * Records. + * + * @param[in] i_targetId Reference to Target ID to get GARD Records for. + * @param[out] o_records Reference to vector of GardRecords that is cleared + * then filled in with records. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t getGardRecords(const TARGETING::EntityPath & i_targetId, + GardRecords_t & o_records); + +protected: + + /** + * @brief Default constructor + * + * Can only be called by Singleton + */ + DeconfigGard(); + +private: + + // Copy constructor and assignment operator disabled + DeconfigGard(const DeconfigGard & i_right); + DeconfigGard & operator=(const DeconfigGard & i_right); + + /** + * @brief Deconfigures Targets by association. + * + * @param[in] i_target Reference to base Target. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + */ + void _deconfigureByAssoc(TARGETING::Target & i_target, + errlHndl_t i_pErr); + + /** + * @brief Deconfigures a Target. + * + * This will Deconfigure the Target (set state to non-functional, do any + * Deconfigure actions and create a Deconfigure Record). + * + * @param[in] i_target Reference to Target to deconfigure. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + * @param[in] i_cause Deconfigure cause. + */ + void _deconfigureTarget(TARGETING::Target & i_target, + errlHndl_t i_pErr, + const DeconfigCause i_cause); + + /** + * @brief Performs Deconfigure Actions. + * + * @param[in] i_target Reference to Target to perform actions on. + */ + void _doDeconfigureActions(TARGETING::Target & i_target); + + /** + * @brief Creates a Deconfigure Record + * + * @param[in] i_target Reference to Target to create record for. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + * @param[in] i_cause Deconfigure cause. + */ + void _createDeconfigureRecord(const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const DeconfigCause i_cause); + +public: + + /** + * @brief Clears the specified Deconfigure Records. + * + * @note Provided for unit test only. Production code should not be + * clearing Deconfigure Records. + * + * @param[in] i_pTargetId Pointer to the Target ID to clear Deconfigure + * Records for. If NULL then all Deconfigure Records + * are cleared. + */ + void _clearDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId); + +private: + /** + * @brief Gets the specified Deconfigure Records. + * + * @param[in] i_pTargetId Pointer to the Target ID to get the Deconfigure + * Record for. If NULL then all Deconfigure Records + * are retrieved. + * @param[out] o_records Reference to vector of DeconfigureRecords that is + * cleared then filled in with records. + */ + void _getDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId, + DeconfigureRecords_t & o_records) const; + + /** + * @brief Creates a GARD Record for a Target. + * + * @param[in] i_target Reference to Target to create GARD Record for. + * @param[in] i_pErr Pointer to error log that will shortly be committed + * by the caller. + * @param[in] i_severity Severity of the GARD Record. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _createGardRecord(const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const GardSeverity i_severity); + + /** + * @brief Clears the specified GARD Records. + * + * @param[in] i_recordId RecordId to clear. If zero then all GARD Records + * are cleared. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _clearGardRecords(const uint32_t i_recordId); + + /** + * @brief Clears all GARD Records for the specified Target. + * + * @param[in] i_targetId Reference to Target ID to clear GARD Records for. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _clearGardRecords(const TARGETING::EntityPath & i_targetId); + + /** + * @brief Gets the specified GARD Records. + * + * @param[in] i_recordId RecordId to get. If zero then all GARD Records are + * retrieved. + * @param[out] o_records Reference to vector of GardRecords that is cleared + * then filled in with records. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _getGardRecords(const uint32_t i_recordId, + GardRecords_t & o_records); + + /** + * @brief Gets all GARD Records for the specified Target. + * + * + * @param[in] i_targetId Reference to Target ID to get GARD Records for. + * @param[out] o_records Reference to vector of GardRecords that is cleared + * then filled in with records. + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _getGardRecords(const TARGETING::EntityPath & i_targetId, + GardRecords_t & o_records); + + /** + * @brief Ensures that the GARD Record data is setup + * + * @return errlHndl_t. Error log handle. + */ + errlHndl_t _ensureGardRecordDataSetup(); + + // Mutex for thread safety + mutable mutex_t iv_mutex; + + // GARD Record Data + uint32_t iv_nextGardRecordId; // Next GARD Record ID to use + uint32_t iv_maxGardRecords; // Maximum number of GARD Records + GardRecord * iv_pGardRecords; // Pointer to the GARD Records in PNOR + + // The Deconfigure Records + DeconfigureRecords_t iv_deconfigureRecords; +}; + +} + +#endif diff --git a/src/include/usr/hwas/hwas_reasoncodes.H b/src/include/usr/hwas/hwas_reasoncodes.H new file mode 100644 index 000000000..6e2b34858 --- /dev/null +++ b/src/include/usr/hwas/hwas_reasoncodes.H @@ -0,0 +1,43 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/hwas/hwas_reasoncodes.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef HWAS_REASONCODES_H +#define HWAS_REASONCODES_H + +#include <hbotcompid.H> + +namespace HWAS +{ + enum HwasModuleID + { + MOD_DECONFIG_GARD = 0x01, + }; + + enum HwasReasonCode + { + RC_TARGET_NOT_DECONFIGURABLE = HWAS_COMP_ID | 0x01, + RC_TARGET_NOT_GARDABLE = HWAS_COMP_ID | 0x02, + RC_GARD_REPOSITORY_FULL = HWAS_COMP_ID | 0x03, + }; +}; + +#endif diff --git a/src/lib/sync.C b/src/lib/sync.C index 95501d2aa..0b57aa0b7 100644 --- a/src/lib/sync.C +++ b/src/lib/sync.C @@ -97,7 +97,7 @@ void mutex_init(mutex_t * o_mutex) //----------------------------------------------------------------------------- -void mutex_destroy(mutex_t *& i_mutex) +void mutex_destroy(mutex_t * i_mutex) { i_mutex->iv_val = ~0; return; diff --git a/src/usr/hwas/deconfigGard.C b/src/usr/hwas/deconfigGard.C new file mode 100644 index 000000000..e1f42c2c7 --- /dev/null +++ b/src/usr/hwas/deconfigGard.C @@ -0,0 +1,692 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/hwas/deconfigGard.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file deconfigGard.C + * + * @brief Implements the DeconfigGard class + */ + +#include <string.h> +#include <targeting/targetservice.H> +#include <errl/errlmanager.H> +#include <hwas/deconfigGard.H> +#include <hwas/hwas_reasoncodes.H> +#include <pnor/pnorif.H> + +// Trace definition +trace_desc_t* g_trac_deconf = NULL; +#define __COMP_TD__ g_trac_deconf + +// The DeconfigGard code needs to trace a target. The current recommended way is +// to get the Target's PHYS_PATH attribute and do a binary trace. However, the +// size of a TARGETING::EntityPath is 17 bytes. This code will trace only the +// first 16 bytes to avoid a multi-line binary trace. This all seems a little +// convoluted. Is there a better way to trace a Target +#define DG_TRAC_TARGET(string, pPath) \ + TRACFBIN(g_trac_deconf, string, pPath, sizeof(TARGETING::EntityPath) - 1) + +namespace HWAS +{ + +//****************************************************************************** +DeconfigGard & theDeconfigGard() +{ + return Singleton<DeconfigGard>::instance(); +} + +//****************************************************************************** +DeconfigGard::DeconfigGard() +: iv_nextGardRecordId(0), + iv_maxGardRecords(0), + iv_pGardRecords(NULL) +{ + TRAC_INIT_BUFFER(&g_trac_deconf, "DECONF", 4096); + TRAC_INF("DeconfigGard Constructor"); + mutex_init(&iv_mutex); +} + +//****************************************************************************** +DeconfigGard::~DeconfigGard() +{ + TRAC_INF("DeconfigGard Destructor"); + mutex_destroy(&iv_mutex); +} + +//****************************************************************************** +errlHndl_t DeconfigGard::clearGardRecordsForReplacedTargets() +{ + TRAC_INF("****TBD****Usr Request: Clear GARD Records for replaced Targets"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = NULL; + + // TODO + + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::deconfigureTargetsFromGardRecordsForIpl() +{ + TRAC_INF("****TBD****Usr Request: Deconfigure Targets from GARD Records for IPL"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = NULL; + + // TODO + + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::deconfigureTarget(TARGETING::Target & i_target, + errlHndl_t i_pErr) +{ + TRAC_ERR("Usr Request: Deconfigure Target"); + mutex_lock(&iv_mutex); + + // Caller must pass a valid errlHndl_t + assert(i_pErr != NULL); + + // Deconfigure the Target + _deconfigureTarget(i_target, i_pErr, DECONFIG_CAUSE_FIRMWARE_REQ); + + // Deconfigure other Targets by association + _deconfigureByAssoc(i_target, i_pErr); + + mutex_unlock(&iv_mutex); + return NULL; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::createGardRecord(const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const GardSeverity i_severity) +{ + TRAC_ERR("Usr Request: Create GARD Record"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = _createGardRecord(i_target, i_pErr, i_severity); + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::getDeconfigureRecords( + const TARGETING::EntityPath * i_pTargetId, + DeconfigureRecords_t & o_records) const +{ + TRAC_INF("Usr Request: Get Deconfigure Record(s)"); + mutex_lock(&iv_mutex); + _getDeconfigureRecords(i_pTargetId, o_records); + mutex_unlock(&iv_mutex); + return NULL; +} + + +//****************************************************************************** +errlHndl_t DeconfigGard::clearGardRecords(const uint32_t i_recordId) +{ + TRAC_INF("Usr Request: Clear GARD Record(s) by Record ID"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = _clearGardRecords(i_recordId); + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::clearGardRecords( + const TARGETING::EntityPath & i_targetId) +{ + TRAC_INF("Usr Request: Clear GARD Record(s) by Target ID"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = _clearGardRecords(i_targetId); + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::getGardRecords( + const uint32_t i_recordId, + GardRecords_t & o_records) +{ + TRAC_INF("Usr Request: Get GARD Record(s) by Record ID"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = _getGardRecords(i_recordId, o_records); + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::getGardRecords( + const TARGETING::EntityPath & i_targetId, + GardRecords_t & o_records) +{ + TRAC_INF("Usr Request: Get GARD Record(s) by Target ID"); + mutex_lock(&iv_mutex); + errlHndl_t l_pErr = _getGardRecords(i_targetId, o_records); + mutex_unlock(&iv_mutex); + return l_pErr; +} + +//****************************************************************************** +void DeconfigGard::_deconfigureByAssoc(TARGETING::Target & i_target, + errlHndl_t i_pErr) +{ + TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>(); + DG_TRAC_TARGET(ERR_MRK "****TBD****: Deconfiguring by Association for: ", + &l_id); + + // TODO +} + +//****************************************************************************** +void DeconfigGard::_deconfigureTarget(TARGETING::Target & i_target, + errlHndl_t i_pErr, + const DeconfigCause i_cause) +{ + TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>(); + DG_TRAC_TARGET(ERR_MRK "Deconfiguring Target: ", &l_id); + + errlHndl_t l_pErr = NULL; + + if (!i_target.getAttr<TARGETING::ATTR_DECONFIG_GARDABLE>()) + { + // Target is not Deconfigurable. Commit an error + TRAC_ERR("Target not Deconfigurable"); + /*@ + * @errortype + * @moduleid MOD_DECONFIG_GARD + * @reasoncode RC_TARGET_NOT_DECONFIGURABLE + * @devdesc Attempt to deconfigure a target that is not + * deconfigurable + */ + l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + MOD_DECONFIG_GARD, + RC_TARGET_NOT_DECONFIGURABLE); + errlCommit(l_pErr); + } + else + { + // Set the Target state to non-functional. The assumption is that it is + // not possible for another thread (other than deconfigGard) to be + // updating HWAS_STATE concurrently. + TARGETING::HwasState l_state = + i_target.getAttr<TARGETING::ATTR_HWAS_STATE>(); + + if (!l_state.functional) + { + TRAC_ERR("Target HWAS_STATE already non-functional"); + } + else + { + TRAC_ERR("Setting Target HWAS_STATE to non-functional"); + l_state.functional = 0; + i_target.setAttr<TARGETING::ATTR_HWAS_STATE>(l_state); + } + + // Do any necessary Deconfigure Actions + _doDeconfigureActions(i_target); + + // Create a Deconfigure Record + _createDeconfigureRecord(i_target, i_pErr, i_cause); + } +} + +//****************************************************************************** +void DeconfigGard::_doDeconfigureActions(TARGETING::Target & i_target) +{ + // TODO +} + +//****************************************************************************** +void DeconfigGard::_createDeconfigureRecord( + const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const DeconfigCause i_cause) +{ + // Get the Target's ID + TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Look for an existing Deconfigure Record for the Target + DeconfigureRecordsCItr_t l_itr = iv_deconfigureRecords.begin(); + + for (; l_itr != iv_deconfigureRecords.end(); ++l_itr) + { + if ((*l_itr).iv_targetId == l_id) + { + break; + } + } + + if (l_itr != iv_deconfigureRecords.end()) + { + TRAC_ERR("Not creating a Deconfigure Record, one already exists"); + } + else + { + // Create a DeconfigureRecord + TRAC_ERR("Creating a Deconfigure Record"); + + DeconfigureRecord l_record; + l_record.iv_targetId = l_id; + l_record.iv_errlogPlid = 0; // TODO Get PLID from ErrorLog + l_record.iv_cause = i_cause; + l_record.iv_padding[0] = 0; + l_record.iv_padding[1] = 0; + l_record.iv_padding[2] = 0; + l_record.iv_deconfigureTime = 0; // TODO Get epoch time + + iv_deconfigureRecords.push_back(l_record); + } +} + +//****************************************************************************** +void DeconfigGard::_clearDeconfigureRecords( + const TARGETING::EntityPath * i_pTargetId) +{ + if (i_pTargetId == NULL) + { + TRAC_INF("Clearing all %d Deconfigure Records", + iv_deconfigureRecords.size()); + iv_deconfigureRecords.clear(); + } + else + { + // Look for a Deconfigure Record for the specified Target (there can + // only be one record) + bool l_foundRecord = false; + + for (DeconfigureRecordsItr_t l_itr = iv_deconfigureRecords.begin(); + l_itr != iv_deconfigureRecords.end(); ++l_itr) + { + if ((*l_itr).iv_targetId == *i_pTargetId) + { + DG_TRAC_TARGET(INFO_MRK "Clearing Deconfigure Record for: ", + i_pTargetId); + iv_deconfigureRecords.erase(l_itr); + l_foundRecord = true; + break; + } + } + + if (!l_foundRecord) + { + DG_TRAC_TARGET(INFO_MRK "Did not find a Deconfigure Record to clear for: ", + i_pTargetId); + } + } +} + +//****************************************************************************** +void DeconfigGard::_getDeconfigureRecords( + const TARGETING::EntityPath * i_pTargetId, + DeconfigureRecords_t & o_records) const +{ + DeconfigureRecordsCItr_t l_itr = iv_deconfigureRecords.begin(); + o_records.clear(); + + if (i_pTargetId == NULL) + { + TRAC_INF("Getting all %d Deconfigure Records", + iv_deconfigureRecords.size()); + + for (; l_itr != iv_deconfigureRecords.end(); ++l_itr) + { + o_records.push_back(*l_itr); + } + } + else + { + // Look for a Deconfigure Record for the specified Target (there can + // only be one record) + for (; l_itr != iv_deconfigureRecords.end(); ++l_itr) + { + if ((*l_itr).iv_targetId == *i_pTargetId) + { + DG_TRAC_TARGET(INFO_MRK "Getting Deconfigure Record for: ", + i_pTargetId); + o_records.push_back(*l_itr); + break; + } + } + + if (l_itr == iv_deconfigureRecords.end()) + { + DG_TRAC_TARGET(INFO_MRK "Did not find a Deconfigure Record to get for: ", + i_pTargetId); + } + } +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_createGardRecord(const TARGETING::Target & i_target, + errlHndl_t i_pErr, + const GardSeverity i_severity) +{ + errlHndl_t l_pErr = NULL; + + TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>(); + DG_TRAC_TARGET(ERR_MRK "Creating GARD Record for: ", &l_id); + + if (!i_target.getAttr<TARGETING::ATTR_DECONFIG_GARDABLE>()) + { + // Target is not GARDable. Commit an error + TRAC_ERR("Target not GARDable"); + /*@ + * @errortype + * @moduleid MOD_DECONFIG_GARD + * @reasoncode RC_TARGET_NOT_GARDABLE + * @devdesc Attempt to create a GARD Record for a target that is + * not GARDable + */ + l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_DECONFIG_GARD, + RC_TARGET_NOT_GARDABLE); + errlCommit(l_pErr); + } + else + { + l_pErr = _ensureGardRecordDataSetup(); + + if (l_pErr) + { + TRAC_ERR("Error from _ensureGardRecordDataSetup"); + } + else + { + GardRecord * l_pRecord = NULL; + + // Find an empty GARD Record slot + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId == 0) + { + l_pRecord = &(iv_pGardRecords[i]); + break; + } + } + + if (!l_pRecord) + { + TRAC_ERR("GARD Record Repository full"); + /*@ + * @errortype + * @moduleid MOD_DECONFIG_GARD + * @reasoncode RC_GARD_REPOSITORY_FULL + * @devdesc Attempt to create a GARD Record and the GARD + * Repository is full + * @userdata1 Number of GARD Records in repository + */ + l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_DECONFIG_GARD, + RC_GARD_REPOSITORY_FULL, + iv_maxGardRecords); + } + else + { + l_pRecord->iv_recordId = iv_nextGardRecordId++; + l_pRecord->iv_targetId = l_id; + // TODO Setup iv_cardMruSn or iv_chipMruEcid + l_pRecord->iv_errlogPlid = 0; // TODO Get PLID from ErrorLog + l_pRecord->iv_severity = i_severity; + l_pRecord->iv_padding[0] = 0; + l_pRecord->iv_padding[1] = 0; + l_pRecord->iv_padding[2] = 0; + l_pRecord->iv_gardTime = 0; // TODO Get epoch time + } + } + } + + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_clearGardRecords(const uint32_t i_recordId) +{ + errlHndl_t l_pErr = NULL; + + l_pErr = _ensureGardRecordDataSetup(); + + if (l_pErr) + { + TRAC_ERR("Error from _ensureGardRecordDataSetup"); + } + else + { + if (i_recordId == 0) + { + TRAC_INF("Clearing all GARD Records"); + + // Only clear valid GARD Records to avoid excessive PNOR access + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId != 0) + { + memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord)); + } + } + } + else + { + uint32_t i = 0; + for (; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId == i_recordId) + { + TRAC_INF("Clearing GARD Record ID 0x%x", i_recordId); + memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord)); + break; + } + } + + if (i == iv_maxGardRecords) + { + TRAC_INF("No GARD Record ID 0x%x to clear", i_recordId); + } + } + } + + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_clearGardRecords( + const TARGETING::EntityPath & i_targetId) +{ + errlHndl_t l_pErr = NULL; + + l_pErr = _ensureGardRecordDataSetup(); + + if (l_pErr) + { + TRAC_ERR("Error from _ensureGardRecordDataSetup"); + } + else + { + bool l_gardRecordsCleared = false; + + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_targetId == i_targetId) + { + DG_TRAC_TARGET(INFO_MRK "Clearing GARD Record for: ", + &i_targetId); + memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord)); + l_gardRecordsCleared = true; + } + } + + if (!l_gardRecordsCleared) + { + DG_TRAC_TARGET(INFO_MRK "No GARD Records to clear for: ", + &i_targetId); + } + } + + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_getGardRecords(const uint32_t i_recordId, + GardRecords_t & o_records) +{ + errlHndl_t l_pErr = NULL; + o_records.clear(); + + l_pErr = _ensureGardRecordDataSetup(); + + if (l_pErr) + { + TRAC_ERR("Error from _ensureGardRecordDataSetup"); + } + else + { + if (i_recordId == 0) + { + TRAC_INF("Getting all GARD Records"); + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId != 0) + { + TRAC_INF("Getting GARD Record ID 0x%x", + iv_pGardRecords[i].iv_recordId); + o_records.push_back(iv_pGardRecords[i]); + } + } + } + else + { + uint32_t i = 0; + for (; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId == i_recordId) + { + TRAC_INF("Getting GARD Record ID 0x%x", i_recordId); + o_records.push_back(iv_pGardRecords[i]); + break; + } + } + + if (i == iv_maxGardRecords) + { + TRAC_INF("No GARD Record ID 0x%x to get", i_recordId); + } + } + } + + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_getGardRecords( + const TARGETING::EntityPath & i_targetId, + GardRecords_t & o_records) +{ + errlHndl_t l_pErr = NULL; + o_records.clear(); + + l_pErr = _ensureGardRecordDataSetup(); + + if (l_pErr) + { + TRAC_ERR("Error from _ensureGardRecordDataSetup"); + } + else + { + bool l_gardRecordsGot = false; + + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_targetId == i_targetId) + { + DG_TRAC_TARGET(INFO_MRK "Getting GARD Record for: ", + &i_targetId); + o_records.push_back(iv_pGardRecords[i]); + l_gardRecordsGot = true; + } + } + + if (!l_gardRecordsGot) + { + DG_TRAC_TARGET(INFO_MRK "No GARD Records to get for: ", + &i_targetId); + } + } + + return l_pErr; +} + +//****************************************************************************** +errlHndl_t DeconfigGard::_ensureGardRecordDataSetup() +{ + errlHndl_t l_pErr = NULL; + + if (iv_pGardRecords == NULL) + { + PNOR::SectionInfo_t l_section; + + // TODO Update when PNOR for GARD Records available (change HB_DATA) + l_pErr = PNOR::getSectionInfo(PNOR::HB_DATA, PNOR::SIDE_A, l_section); + + if(l_pErr) + { + TRAC_ERR("Error getting GARD Record PNOR section info"); + } + else + { + uint32_t l_numGardRecords = 0; + iv_pGardRecords = reinterpret_cast<GardRecord *>(l_section.vaddr); + iv_maxGardRecords = l_section.size / sizeof(GardRecord); + + // TODO Remove this section when PNOR for GARD Records available + // For now, just use a buffer + iv_pGardRecords = new GardRecord[20]; + memset(iv_pGardRecords, 0, sizeof(GardRecord) * 20); + iv_maxGardRecords = 20; + // TODO Remove this section when PNOR for GARD Records available + + // Figure out the next GARD Record ID to use + for (uint32_t i = 0; i < iv_maxGardRecords; i++) + { + if (iv_pGardRecords[i].iv_recordId > iv_nextGardRecordId) + { + iv_nextGardRecordId = iv_pGardRecords[i].iv_recordId; + } + + if (iv_pGardRecords[i].iv_recordId != 0) + { + l_numGardRecords++; + } + } + + iv_nextGardRecordId++; + + TRAC_INF("GARD Record data setup. MaxRecords: %d. NextID: %d. NumRecords: %d", + iv_maxGardRecords, iv_nextGardRecordId, l_numGardRecords); + } + } + + return l_pErr; +} + +} diff --git a/src/usr/hwas/makefile b/src/usr/hwas/makefile index 2542f0c39..f752aa88c 100644 --- a/src/usr/hwas/makefile +++ b/src/usr/hwas/makefile @@ -29,7 +29,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp MODULE = hwas -OBJS = hwas.o testHWP.o +OBJS = hwas.o deconfigGard.o testHWP.o SUBDIRS=test.d diff --git a/src/usr/hwas/test/hwasGardTest.H b/src/usr/hwas/test/hwasGardTest.H new file mode 100644 index 000000000..dda0de693 --- /dev/null +++ b/src/usr/hwas/test/hwasGardTest.H @@ -0,0 +1,920 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/hwas/test/hwasGardTest.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef _HWASGARDTEST_H +#define _HWASGARDTEST_H + +/** + * @file hwasGardTest.H + * + * @brief Unit tests for HWAS Deconfigure and GARD functionality + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// CXXTEST +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <targeting/targetservice.H> +#include <hwas/deconfigGard.H> +#include <hwas/hwas_reasoncodes.H> + +class HwasGardTest: public CxxTest::TestSuite +{ +public: + + /** + * @brief Test getting all Deconfigure Records + */ + void testDeconfigure1() + { + TS_TRACE(INFO_MRK "testDeconfigure1: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::DeconfigureRecords_t l_records; + + // Get all Deconfigure Records + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(NULL, l_records); + + if (l_pErr) + { + errlCommit(l_pErr); + TS_FAIL("testDeconfigure1: Error from getDeconfigureRecords"); + } + else + { + TS_TRACE(INFO_MRK "testDeconfigure1: Success. %d records", + l_records.size()); + } + } + + /** + * @brief Test getting a Deconfigure Record for a specific Target + */ + void testDeconfigure2() + { + TS_TRACE(INFO_MRK "testDeconfigure2: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::DeconfigureRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Get any Deconfigure Record for the chip + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + errlCommit(l_pErr); + TS_FAIL("testDeconfigure2: Error from getDeconfigureRecords"); + } + else + { + if (l_records.size() > 1) + { + TS_FAIL("testDeconfigure2: More than 1 record (%d) for chip", + l_records.size()); + } + else + { + TS_TRACE(INFO_MRK "testDeconfigure2: Success. %d records", + l_records.size()); + } + } + } + + /** + * @brief Test Deconfiguring a Target, getting the Deconfigure Record and + * clearing the Deconfigure Record + */ + void testDeconfigure3() + { + TS_TRACE(INFO_MRK "testDeconfigure3: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::DeconfigureRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the deconfigureTarget function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get any existing Deconfigure Record for the chip + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testDeconfigure3: Chip has existing Deconfigure Record, skipping test"); + break; + } + + // Get the original HWAS_STATE of the chip + TARGETING::HwasState l_origState = + l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + // Deconfigure the chip + l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget, + l_pNewErr); + + if (l_pErr) + { + TS_FAIL("testDeconfigure3: Error from deconfigureTarget"); + break; + } + + // Get the new HWAS_STATE of the chip + TARGETING::HwasState l_state = + l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + if (l_state.functional) + { + TS_FAIL("testDeconfigure3: Chip functional after deconfigure"); + // intentionally continue + } + + // Get the Deconfigure Record for the chip + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords (2)"); + break; + } + + if (l_records.size() != 1) + { + TS_FAIL("testDeconfigure3: %d records for chip, expected 1", + l_records.size()); + break; + } + + // Reset the HWAS_STATE of the chip + l_pTarget->setAttr<TARGETING::ATTR_HWAS_STATE>(l_origState); + + // Clear the Deconfigure Record + HWAS::theDeconfigGard()._clearDeconfigureRecords(&l_id); + + // Get the Deconfigure Record for the chip + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords (3)"); + break; + } + + if (l_records.size() != 0) + { + TS_FAIL("testDeconfigure3: %d records for chip, expected 0", + l_records.size()); + break; + } + + TS_TRACE(INFO_MRK "testDeconfigure3: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } + + /** + * @brief Test Deconfiguring a Target multiple times + */ + void testDeconfigure4() + { + TS_TRACE(INFO_MRK "testDeconfigure4: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::DeconfigureRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the deconfigureTarget function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get any existing Deconfigure Record for the chip + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + TS_FAIL("testDeconfigure4: Error from getDeconfigureRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testDeconfigure4: Chip has existing Deconfigure Record, skipping test"); + break; + } + + // Get the current HWAS_STATE of the chip + TARGETING::HwasState l_origState = + l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + // Deconfigure the chip + l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget, + l_pNewErr); + + if (l_pErr) + { + TS_FAIL("testDeconfigure4: Error from deconfigureTarget"); + break; + } + + // Deconfigure the chip again + l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget, + l_pNewErr); + + if (l_pErr) + { + TS_FAIL("testDeconfigure4: Error from deconfigureTarget (2)"); + break; + } + + // Get the new HWAS_STATE of the chip + TARGETING::HwasState l_state = + l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + if (l_state.functional) + { + TS_FAIL("testDeconfigure4: Chip functional after deconfigure"); + // intentionally continue + } + + // Get the Deconfigure Record for the chip + l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id, + l_records); + + if (l_pErr) + { + TS_FAIL("testDeconfigure4: Error from getDeconfigureRecords (2)"); + break; + } + + // The second Deconfigure should not have created a new record + if (l_records.size() != 1) + { + TS_FAIL("testDeconfigure4: %d records for chip, expected 1", + l_records.size()); + break; + } + + // Reset the HWAS_STATE of the chip + l_pTarget->setAttr<TARGETING::ATTR_HWAS_STATE>(l_origState); + + // Clear the Deconfigure Record + HWAS::theDeconfigGard()._clearDeconfigureRecords(&l_id); + + TS_TRACE(INFO_MRK "testDeconfigure4: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } + + /** + * @brief Test getting all GARD Records + */ + void testGard1() + { + TS_TRACE(INFO_MRK "testGard1: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records); + + if (l_pErr) + { + errlCommit(l_pErr); + TS_FAIL("testGard1: Error from getGardRecords"); + } + else + { + TS_TRACE(INFO_MRK "testGard1: Success. %d records", + l_records.size()); + } + } + + /** + * @brief Test getting GARD Records with a bad record ID). + */ + void testGard2() + { + TS_TRACE(INFO_MRK "testGard2: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + l_pErr = HWAS::theDeconfigGard().getGardRecords(0x12345678, l_records); + + if (l_pErr) + { + errlCommit(l_pErr); + TS_FAIL("testGard2: Error from getGardRecords"); + } + else + { + if (l_records.size()) + { + TS_FAIL("testGard2: %d records found for bad ID", + l_records.size()); + } + else + { + TS_TRACE(INFO_MRK "testGard2: Success"); + } + } + } + + /** + * @brief Test getting GARD Records for a specific target + */ + void testGard3() + { + TS_TRACE(INFO_MRK "testGard3: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + + // Get all GARD Records for the Target + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + errlCommit(l_pErr); + TS_FAIL("testGard3: Error from getGardRecords"); + } + else + { + TS_TRACE(INFO_MRK "testGard3: Success. %d records", + l_records.size()); + } + } + + /** + * @brief Test creating a GARD Record, getting the GARD Record and + * clearing the GARD Record + */ + void testGard4() + { + TS_TRACE(INFO_MRK "testGard4: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the createGardRecord function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get any existing GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard4: Error from getGardRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testGard4: Chip has %d existing Gard Records, skipping test", + l_records.size()); + break; + } + + // Create a GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE); + + if (l_pErr) + { + TS_FAIL("testGard4: Error from createGardRecord"); + break; + } + + // Get the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard4: Error from getGardRecords (2)"); + break; + } + + if (l_records.size() != 1) + { + TS_FAIL("testGard4: %d records for chip, expected 1", + l_records.size()); + break; + } + + if (l_records[0].iv_severity != + HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE) + { + TS_FAIL("testGard4: Record severity %d, expected predictive", + l_records[0].iv_severity); + break; + } + + // Clear the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id); + + if (l_pErr) + { + TS_FAIL("testGard4: Error from clearGardRecords"); + break; + } + + // Get the GARD Records for the chip + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard4: Error from getGardRecords (3)"); + break; + } + + if (l_records.size() != 0) + { + TS_FAIL("testGard4: %d records for chip, expected 0", + l_records.size()); + break; + } + + TS_TRACE(INFO_MRK "testGard4: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } + + /** + * @brief Test creating a GARD Record for a Target multiple times + */ + void testGard5() + { + TS_TRACE(INFO_MRK "testGard5: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the createGardRecord function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get any existing GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from getGardRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testGard5: Chip has %d existing Gard Records, skipping test", + l_records.size()); + break; + } + + // Create a GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from createGardRecord"); + break; + } + + // Create another GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_FATAL); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from createGardRecord (2)"); + break; + } + + // Get the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from getGardRecords (2)"); + break; + } + + if (l_records.size() != 2) + { + TS_FAIL("testGard5: %d records for chip, expected 2", + l_records.size()); + break; + } + + // Clear the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from clearGardRecords"); + break; + } + + // Get the GARD Records for the chip + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard5: Error from getGardRecords (3)"); + break; + } + + if (l_records.size() != 0) + { + TS_FAIL("testGard5: %d records for chip, expected 0", + l_records.size()); + break; + } + + TS_TRACE(INFO_MRK "testGard5: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } + + /** + * @brief Test getting and clearing GARD Records by recordID + */ + void testGard6() + { + TS_TRACE(INFO_MRK "testGard6: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the createGardRecord function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get any existing GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from getGardRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testGard6: Chip has %d existing Gard Records, skipping test", + l_records.size()); + break; + } + + // Create a GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from createGardRecord"); + break; + } + + // Create another GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_FATAL); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from createGardRecord (2)"); + break; + } + + // Get the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from getGardRecords (2)"); + break; + } + + if (l_records.size() != 2) + { + TS_FAIL("testGard6: %d records for chip, expected 2", + l_records.size()); + break; + } + + // Get the first GARD Record for the chip by Record ID + uint32_t l_recordID = l_records[0].iv_recordId; + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_recordID, + l_records); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from getGardRecords (3)"); + break; + } + + if (l_records.size() != 1) + { + TS_FAIL("testGard6: %d records for chip, expected 1", + l_records.size()); + break; + } + + // Clear the first GARD Record for the chip by Record ID + l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_recordID); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from clearGardRecords"); + break; + } + + // Get the GARD Records for the chip + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from getGardRecords (4)"); + break; + } + + if (l_records.size() != 1) + { + TS_FAIL("testGard6: %d records for chip, expected 1 (2)", + l_records.size()); + break; + } + + // Clear the GARD Records for the chip + l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id); + + if (l_pErr) + { + TS_FAIL("testGard6: Error from clearGardRecords"); + break; + } + + TS_TRACE(INFO_MRK "testGard6: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } + + /** + * @brief Test getting and clearing all GARD Records + */ + void testGard7() + { + TS_TRACE(INFO_MRK "testGard7: Started"); + + errlHndl_t l_pErr = NULL; + HWAS::DeconfigGard::GardRecords_t l_records; + + // Get the master processor chip + TARGETING::Target* l_pTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_pTarget); + TARGETING::EntityPath l_id = + l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + // Create an error log to pass to the createGardRecord function, this + // will never be committed. + errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + HWAS::MOD_DECONFIG_GARD, + HWAS::RC_TARGET_NOT_DECONFIGURABLE); + + do + { + // Get all existing GARD Records + l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records); + + if (l_pErr) + { + TS_FAIL("testGard7: Error from getGardRecords"); + break; + } + + if (l_records.size() != 0) + { + TS_TRACE(INFO_MRK "testGard7: %d existing Gard Records, skipping test", + l_records.size()); + break; + } + + // Create a GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE); + + if (l_pErr) + { + TS_FAIL("testGard7: Error from createGardRecord"); + break; + } + + // Create another GARD Record for the chip + l_pErr = HWAS::theDeconfigGard(). + createGardRecord(*l_pTarget, l_pNewErr, + HWAS::DeconfigGard::GARD_SEVERITY_FATAL); + + if (l_pErr) + { + TS_FAIL("testGard7: Error from createGardRecord (2)"); + break; + } + + // Clear all GARD Records + l_pErr = HWAS::theDeconfigGard().clearGardRecords(0); + + if (l_pErr) + { + TS_FAIL("testGard7: Error from clearGardRecords"); + break; + } + + // Get the GARD Records + l_records.clear(); + + l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records); + + if (l_pErr) + { + TS_FAIL("testGard7: Error from getGardRecords (2)"); + break; + } + + if (l_records.size() != 0) + { + TS_FAIL("testGard7: %d records for chip, expected 0", + l_records.size()); + break; + } + + TS_TRACE(INFO_MRK "testGard7: Success"); + } + while (0); + + delete l_pNewErr; + l_pNewErr = NULL; + + if (l_pErr) + { + errlCommit(l_pErr); + } + } +}; + +#endif diff --git a/src/usr/targeting/xmltohb/attribute_types.xml b/src/usr/targeting/xmltohb/attribute_types.xml index 343d791ce..212c69b30 100644 --- a/src/usr/targeting/xmltohb/attribute_types.xml +++ b/src/usr/targeting/xmltohb/attribute_types.xml @@ -844,6 +844,7 @@ </complexType> <persistency>volatile</persistency> <readable/> + <writeable/> </attribute> <attribute> @@ -935,5 +936,17 @@ <readable/> </attribute> +<attribute> + <id>DECONFIG_GARDABLE</id> + <description>If the Target is Deconfigurable and GARDable</description> + <simpleType> + <uint8_t> + <default>0</default> + </uint8_t> + </simpleType> + <persistency>non-volatile</persistency> + <readable/> +</attribute> + </attributes> diff --git a/src/usr/targeting/xmltohb/target_types.xml b/src/usr/targeting/xmltohb/target_types.xml index 2b0cbfe6c..ea371bd9c 100644 --- a/src/usr/targeting/xmltohb/target_types.xml +++ b/src/usr/targeting/xmltohb/target_types.xml @@ -39,6 +39,10 @@ <id>PRIMARY_CAPABILITIES</id> </attribute> <attribute><id>HWAS_STATE</id></attribute> + <attribute> + <id>DECONFIG_GARDABLE</id> + <default>0</default> + </attribute> </targetType> <targetType> @@ -102,6 +106,10 @@ <attribute> <id>FSI_OPTION_FLAGS</id> </attribute> + <attribute> + <id>DECONFIG_GARDABLE</id> + <default>1</default> + </attribute> </targetType> <targetType> @@ -155,6 +163,10 @@ <field><id>reserved</id><value>0</value></field> </default> </attribute> + <attribute> + <id>DECONFIG_GARDABLE</id> + <default>1</default> + </attribute> </targetType> <targetType> |