diff options
Diffstat (limited to 'src/usr/diag/prdf/plat')
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H | 208 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C | 151 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C | 208 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk | 4 |
4 files changed, 571 insertions, 0 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H new file mode 100644 index 000000000..c9cdd23ea --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H @@ -0,0 +1,208 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 prdfMemTdCtlr.H + * @brief A state machine for memory Targeted Diagnostics (TD). + */ + +#ifndef __prdfMemTdCtlr_H +#define __prdfMemTdCtlr_H + +// Framework includes +#include <iipServiceDataCollector.h> + +// Platform includes +#include <prdfMemTdQueue.H> +#include <prdfPlatServices.H> + +namespace PRDF +{ + +/** + * @brief A state machine for memory Targeted Diagnostics (TD). + */ +template <TARGETING::TYPE T, typename D> +class MemTdCtlr +{ + public: + + /** + * @brief Constructor + * + * This contructor will only be called in the MCBIST or MBA data bundle, + * which already checks for a valid type. + * + * @param i_chip An MCBIST or MBA chip. + */ + explicit MemTdCtlr( ExtensibleChip * i_chip ) : + iv_chip( i_chip ) + { + PRDF_ASSERT( T == iv_chip->getTrgtType() ); + } + + /** + * @brief Determines and executes the next course of action after a + * maintenance command complete attention. + * @note Initializes the TD controller, if needed (runtime only). + * @param io_sc The step code data struct. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ); + + #ifdef __HOSTBOOT_RUNTIME + + /** + * @brief Adds a new TD procedure to the queue. + * + * This is only supported during runtime. It is used to process TD requests + * during analysis of attentions other than the command complete attention + * (i.e. memory CEs and UEs). If there isn't a current TD procedure in + * progress, this function will stop background scrubbing and start this new + * procedure. Otherwise, this new procedure is simply added to the queue. + * + * It is possible that some of the other attentions my occur during the IPL + * after Hostboot has been flushed from the cache to system memory. At that + * point we don't have time to complete a TD procedure. Therefore, the + * requests will be ignored. Any chip marks placed during this time will be + * redetected when the runtime TD controller is initialized. + * + * @note Initializes the TD controller, if needed. + * @param io_sc The step code data struct. + * @param i_entry The new TD queue entry. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t handleTdEvent( STEP_CODE_DATA_STRUCT & io_sc, + TdEntry<T> * i_entry ); + + #endif + + private: + + /** + * @brief This is called when there are no more TD procedures to execute. + * + * During Memory Diagnostics, this means the current pattern test command + * has reached the end of memory on the MBA or MCBIST. So this function will + * tell MDIA to move onto the next pattern test command, if needed. + * + * At runtime, this function will restart background scrubbing. + * + * @param io_sc The step code data struct. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t defaultStep( STEP_CODE_DATA_STRUCT & io_sc ); + + /** + * @brief Progresses onto the next step of the state machine. + * + * This function will move onto the next step of the current procedure, if + * one is in progress. Otherwise, it pops the next procedure off of the + * queue, if one exists, and starts that procedure. + * + * @param io_sc The step code data struct. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t nextStep( STEP_CODE_DATA_STRUCT & io_sc ) + { + uint32_t rc = SUCCESS; + + if ( nullptr == iv_curProcedure ) // Nothing currently in progress. + { + if ( iv_queue.empty() ) // No more TD procedures. + { + rc = defaultStep( io_sc ); + } + else + { + // Get the next entry in the queue and move forward. + iv_curProcedure = iv_queue.getNextEntry(); + rc = nextStep( io_sc ); + } + } + else + { + // Do the next step of the current procedure. + bool done = false; + rc = iv_curProcedure->nextStep( io_sc, done ); + if ( SUCCESS != rc ) + { + // Something failed. Clean up the current command and stop. + iv_curProcedure = nullptr; iv_queue.pop(); + } + else if ( done ) + { + // This procedure is done so clean it up and move on. + iv_curProcedure = nullptr; iv_queue.pop(); + rc = nextStep( io_sc ); + } + } + + return rc; + } + + #ifdef __HOSTBOOT_RUNTIME + + /** + * @brief Initializes the TD controller, if needed. + * + * This is only supported during runtime. This is mostly useful at runtime + * to query hardware for any unverified chip marks. Those may occur after + * starting background scrubbing, but before PRD is up and running. We may + * also have unverified chip marks if the HBRT service is stopped and + * restarted (PRD is reinitialize and all previous state machine data is + * lost). + * + * @note Should be called at the beginning of every public function to + * ensure the TD controller is initialized. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t initialize(); + + #endif + + private: // instance variables + + /** An MCBIST or MBA chip associated with this TD controller. */ + ExtensibleChip * const iv_chip; + + /** The TD queue that contains all of the pending TD procedures. */ + TdQueue<T> iv_queue; + + /** The procedure that is currently in progress. */ + TdEntry<T> * iv_curProcedure = nullptr; + + #ifdef __HOSTBOOT_RUNTIME + + /** True if the TD controller has been initialized. False otherwise. */ + bool iv_initialized = false; + + #endif + +}; + +} // end namespace PRDF + +#endif // __prdfMemTdCtlr_H + diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C new file mode 100644 index 000000000..0d0b6d473 --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C @@ -0,0 +1,151 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 prdfMemTdCtlr_ipl.C + * @brief A state machine for memory Targeted Diagnostics (IPL only). + */ + +#include <prdfMemTdCtlr.H> + +// Platform includes +#include <prdfMemExtraSig.H> +#include <prdfP9McbistDataBundle.H> + +using namespace TARGETING; + +namespace PRDF +{ + +using namespace PlatServices; + +//------------------------------------------------------------------------------ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[MemTdCtlr::handleCmdComplete] " + + PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running. + + uint32_t o_rc = SUCCESS; + + TargetHandle_t trgt = iv_chip->getTrgt(); + + do + { + // Inform MDIA the command has completed and PRD is starting analysis. + o_rc = mdiaSendEventMsg( trgt, MDIA::RESET_TIMER ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(RESET_TIMER) failed" ); + break; + } + + if ( nullptr == iv_curProcedure ) + { + // There is nothing currently in progress, which means the command + // either stopped at the end of memory successfully (nothing to do, + // so call nextStep() to initiate defaultStep()) or stopped at the + // end of a rank due to an error (will need to add procedures to the + // queue to handle the errors and finish the pattern test to the end + // of memory). + + // TODO: RTC 157892 Check why the command stopped and take actions + // appropriately. Note that since nothing is happening here at + // the moment, the code will simply assume the command stopped + // at the end of memory with no errors. + + // If the command completed successfully with no error, do not + // commit the error log. This is done to suppress unnecessary + // information error logs. + io_sc.service_data->setDontCommitErrl(); + } + + // Move onto the next step in the state machine. + o_rc = nextStep( io_sc ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "nextStep() failed" ); + break; + } + + } while (0); + + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "Failed on 0x%08x", iv_chip->getHuid() ); + + // Just in case it was a legitimate command complete (error log not + // committed) but something else failed. + io_sc.service_data->clearDontCommitErrl(); + + // Change signature indicating there was an error in analysis. + io_sc.service_data->SetErrorSig( PRDFSIG_CmdComplete_ERROR ); + + // Something definitely failed, so callout 2nd level support. + io_sc.service_data->SetCallout( NextLevelSupport_ENUM, MRU_HIGH ); + io_sc.service_data->setServiceCall(); + + // Tell MDIA to skip further analysis on this target. + uint32_t l_rc = mdiaSendEventMsg( trgt, MDIA::STOP_TESTING ); + if ( SUCCESS != l_rc ) + PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(STOP_TESTING) failed" ); + } + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[MemTdCtlr::defaultStep] " + + uint32_t o_rc = SUCCESS; + + // The command complete message to MDIA must be sent after clearing the + // attention. Otherwise, we may run into a race condition where MDIA may try + // to start the next command before PRD clears the FIR bits. + D db = static_cast<D>(iv_chip->getDataBundle()); + db->iv_sendCmdCompleteMsg = true; + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +// Avoid linker errors with the template. +template class MemTdCtlr<TYPE_MCBIST, McbistDataBundle *>; + +//------------------------------------------------------------------------------ + +} // end namespace PRDF + + diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C new file mode 100644 index 000000000..c1ea99144 --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C @@ -0,0 +1,208 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 prdfMemTdCtlr_rt.C + * @brief A state machine for memory Targeted Diagnostics (runtime only). + */ + +#include <prdfMemTdCtlr.H> + +// Framework includes + +// Platform includes +#include <prdfMemExtraSig.H> +#include <prdfP9McbistDataBundle.H> +#include <prdfPlatServices.H> + +using namespace TARGETING; + +namespace PRDF +{ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[MemTdCtlr::handleCmdComplete] " + + uint32_t o_rc = SUCCESS; + + do + { + // Make sure the TD controller is initialized. + o_rc = initialize(); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "initialize() failed" ); + break; + } + + if ( nullptr == iv_curProcedure ) + { + // Determine why background scrubbing has stopped, add any necessary + // procedures to the queue and move on to the next step in the state + // machine. + + // TODO: RTC 136126 Note that since nothing is happening here at + // the moment, the code will simply assume the command stopped + // without error and background scrubbing will resume. + + // If the command completed successfully with no error, do not + // commit the error log. This is done to suppress unnecessary + // information error logs. + io_sc.service_data->setDontCommitErrl(); + } + + // Move onto the next step in the state machine. + o_rc = nextStep( io_sc ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "nextStep() failed" ); + break; + } + + } while (0); + + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "Failed on 0x%08x", iv_chip->getHuid() ); + + // Just in case it was a legitimate command complete (error log not + // committed) but something else failed. + io_sc.service_data->clearDontCommitErrl(); + + // Change signature indicating there was an error in analysis. + io_sc.service_data->SetErrorSig( PRDFSIG_CmdComplete_ERROR ); + + // Something definitely failed, so callout 2nd level support. + io_sc.service_data->SetCallout( NextLevelSupport_ENUM, MRU_HIGH ); + io_sc.service_data->setServiceCall(); + } + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::handleTdEvent( STEP_CODE_DATA_STRUCT & io_sc, + TdEntry<T> * i_entry ) +{ + #define PRDF_FUNC "[MemTdCtlr::handleTdEvent] " + + uint32_t o_rc = SUCCESS; + + do + { + // Make sure the TD controller is initialized. + o_rc = initialize(); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "initialize() failed" ); + break; + } + + // Add this entry to the queue. + iv_queue.push( i_entry ); + + // Don't interrupt a TD procedure if one is already in progress. + if ( nullptr != iv_curProcedure ) break; + + // Stop background scrubbing. + // TODO: RTC 136126 + + // Move onto the next step in the state machine. + o_rc = nextStep( io_sc ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "nextStep() failed" ); + break; + } + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::initialize() +{ + #define PRDF_FUNC "[MemTdCtlr::initialize] " + + uint32_t o_rc = SUCCESS; + + do + { + if ( iv_initialized ) break; // nothing to do + + // Add any unverified chip marks to the TD queue + // TODO: RTC 136126 + + // At this point, the TD controller is initialized. + iv_initialized = true; + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template <TYPE T, typename D> +uint32_t MemTdCtlr<T,D>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[MemTdCtlr::defaultStep] " + + uint32_t o_rc = SUCCESS; + + do + { + // Restart background scrubbing. + // TODO: RTC 136126 + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +// Avoid linker errors with the template. +template class MemTdCtlr<TYPE_MCBIST, McbistDataBundle *>; + +//------------------------------------------------------------------------------ + +} // end namespace PRDF + + diff --git a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk index 12f54c7af..188b3b14f 100644 --- a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk +++ b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk @@ -46,6 +46,8 @@ prd_rule_plugin += prdfP9Mcbist.o ifneq (${HOSTBOOT_RUNTIME},1) +# plat/mem/ (non-rule plugin related) +prd_obj += prdfMemTdCtlr_ipl.o prd_obj += prdfMemVcm_ipl.o endif @@ -56,6 +58,8 @@ endif ifeq (${HOSTBOOT_RUNTIME},1) +# plat/mem/ (non-rule plugin related) +prd_obj += prdfMemTdCtlr_rt.o prd_obj += prdfMemVcm_rt.o endif |