summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/plat
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/diag/prdf/plat')
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H208
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C151
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C208
-rw-r--r--src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk4
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
OpenPOWER on IntegriCloud