diff options
author | CamVan Nguyen <ctnguyen@us.ibm.com> | 2012-09-13 13:58:53 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-10-03 10:54:01 -0500 |
commit | 34fcc1f815552f0ffd84686d6f97ab47f5bd4f73 (patch) | |
tree | 0c94f04d5d5823d3c3c330dec12b34ff3ba932f7 /src/usr | |
parent | 2b8b3515924605e86d6bccdb5b64d9155963ec83 (diff) | |
download | talos-hostboot-34fcc1f815552f0ffd84686d6f97ab47f5bd4f73.tar.gz talos-hostboot-34fcc1f815552f0ffd84686d6f97ab47f5bd4f73.zip |
Added proc_thread_control hwp and enable calling of it to activate threads
Change-Id: I92f5542d93e41cb90da81603761387e5194fc3d9
RTC: 42817
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1734
Tested-by: Jenkins Server
Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Reviewed-by: Van H. Lee <vanlee@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
6 files changed, 951 insertions, 110 deletions
diff --git a/src/usr/hwpf/hwp/thread_activate/makefile b/src/usr/hwpf/hwp/thread_activate/makefile index e76e6cb94..d911d28f6 100644 --- a/src/usr/hwpf/hwp/thread_activate/makefile +++ b/src/usr/hwpf/hwp/thread_activate/makefile @@ -40,15 +40,18 @@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/thread_activate ## NOTE: add a new EXTRAINCDIR when you add a new HWP ## EXAMPLE: ## EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/thread_activate/<HWP_dir> +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/thread_activate/proc_thread_control ## NOTE: add new object files when you add a new HWP -OBJS = thread_activate.o +OBJS = thread_activate.o \ + proc_thread_control.o ## NOTE: add a new directory onto the vpaths when you add a new HWP ## EXAMPLE: # VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/thread_activate/<HWP_dir> +VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/thread_activate/proc_thread_control include ${ROOTPATH}/config.mk diff --git a/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.C b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.C new file mode 100644 index 000000000..c760dd1ef --- /dev/null +++ b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.C @@ -0,0 +1,728 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: proc_thread_control.C,v 1.18 2012/09/26 15:14:36 karm Exp $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2012 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! TITLE : proc_thread_control +// *! DESCRIPTION : Core Thread start/stop/step/query/activate operations +// *! Use to start (start or sreset) thread instruction execution, +// *! stop instruction execution, or single instruction step. +// *! Activate is used to put a POR state thread in the proper +// *! state to enable ram prior to starting. +// *! Also used to query the state of a thread. +// *! OWNER NAME : Lance Karm Email: karm@us.ibm.com +// *! BACKUP NAME : Sebastien Lafontant Email: slafont@us.ibm.com +//------------------------------------------------------------------------------ +#include <fapi.H> +#include "proc_thread_control.H" + +extern "C" +{ + //-------------------------------------------------------------------------- + // Function definitions + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // function: proc_thread_control: utility subroutine to control thread state + // parameters: i_target => core target + // i_thread => thread (0..7) + // i_command => + // PTC_CMD_SRESET => initiate sreset thread command + // PTC_CMD_START => initiate start thread command + // PTC_CMD_STOP => initiate stop thread command + // PTC_CMD_STEP => initiate step thread command + // PTC_CMD_QUERY => query and return thread state + // return data in o_ras_status + // i_warncheck => convert pre/post checks errors to warnings + // i_activate => initiate activate thread command + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // function-specific fail codes (see function definitions), + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control(const fapi::Target& i_target, + const uint8_t i_thread, const uint8_t i_command, + const bool i_warncheck, ecmdDataBufferBase& o_ras_status, + uint64_t& o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + FAPI_INF("proc_thread_control : Start"); + + do + { + rc_ecmd |= o_ras_status.setBitLength(64); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + + if (i_command == PTC_CMD_SRESET) + { + rc = proc_thread_control_sreset(i_target, i_thread, i_warncheck, + o_ras_status, o_state); + break; + } + if (i_command == PTC_CMD_START) + { + rc = proc_thread_control_start(i_target, i_thread, i_warncheck, + o_ras_status, o_state); + break; + } + if (i_command == PTC_CMD_STOP) + { + rc = proc_thread_control_stop(i_target, i_thread, i_warncheck, + o_ras_status, o_state); + break; + } + if (i_command == PTC_CMD_STEP) + { + rc = proc_thread_control_step(i_target, i_thread, i_warncheck, + o_ras_status, o_state); + break; + } + if (i_command == PTC_CMD_ACTIVATE) + { + rc = proc_thread_control_activate(i_target, i_thread, + o_ras_status, o_state); + break; + } + if (i_command == PTC_CMD_QUERY) + { + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control: ERROR calling proc_thread_control_query for thread %d", i_thread); + break; + } + break; + } + + FAPI_ERR("proc_thread_control: ERROR - invalid command issued to proc_thread_control"); + FAPI_SET_HWP_ERROR(rc, RC_PROC_THREAD_CONTROL_INV_COMMAND); + + } + while(0); + return rc; + } // proc_thread_control + + //-------------------------------------------------------------------------- + // function: proc_thread_control_sreset: utility subroutine to sreset + // a thread + // parameters: i_target => core target + // i_thread => thread (0..7) + // i_warncheck => convert check errors to warnings + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // RC_PROC_THREAD_CONTROL_SRESET_FAIL if sreset command failed, + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_sreset(const fapi::Target& i_target, + const uint8_t i_thread, const bool i_warncheck, + ecmdDataBufferBase& o_ras_status, uint64_t& o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + ecmdDataBufferBase scomData(64); + + uint32_t directControlAddr = EX_PERV_TCTL0_DIRECT_0x10013000 + + (i_thread << 4); + + do + { + FAPI_DBG("proc_thread_control_sreset : Initiating sreset command to core PC logic for thread %d", i_thread); + + // Setup & Initiate SReset Command + rc_ecmd |= scomData.flushTo0(); + rc_ecmd |= scomData.setBit(PTC_DIR_CTL_SP_SRESET); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_sreset: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, directControlAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_sreset: fapiPutScom error when issuing sp_sreset to thread %d", i_thread); + break; + } + + // Post-conditions check + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_sreset: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (!(o_state & THREAD_STATE_INSTCOMP)) + { + if (i_warncheck) + { + FAPI_INF("proc_thread_control_sreset: WARNING: Thread SReset issued, but no instructions have completed. SReset might have failed"); + break; + } + else + { + FAPI_ERR("proc_thread_control_sreset: ERROR: Thread SReset issued, but no instructions have completed. SReset might have failed for thread %d", i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_SRESET_FAIL); + break; + } + } + + FAPI_INF("proc_thread_control_sreset : sreset command issued for thread %d", i_thread); + break; + } + while (0); + return rc; + } // proc_thread_control_sreset + + //-------------------------------------------------------------------------- + // function: proc_thread_control_start: utility subroutine to start a thread + // parameters: i_target => core target + // i_thread => thread (0..7) + // i_warncheck => convert check errors to warnings + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // RC_PROC_THREAD_CONTROL_START_PRE_NOMAINT if maintenance bit + // was not set before start was issued + // RC_PROC_THREAD_CONTROL_START_FAIL if start command failed, + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_start(const fapi::Target& i_target, + const uint8_t i_thread, const bool i_warncheck, + ecmdDataBufferBase& o_ras_status, uint64_t& o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + ecmdDataBufferBase scomData(64); + + uint32_t directControlAddr = EX_PERV_TCTL0_DIRECT_0x10013000 + + (i_thread << 4); + + do + { + FAPI_DBG("proc_thread_control_start : Initiating start command to core PC logic for thread %d", i_thread); + + // Check Preconditions: look for Core Maintenance Mode + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_start: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (!(o_state & THREAD_STATE_MAINT)) + { + if (i_warncheck) + { + FAPI_INF("proc_thread_control_start: WARNING: Aborting Start Command for Thread %d - Maintenance bit is not on", i_thread); + break; + } + else + { + FAPI_ERR("proc_thread_control_start: Start Precondition Check failed: RAS Status Maintenance bit is not on for thread %d", i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_START_PRE_NOMAINT); + break; + } + } + + // Issue Start Command + rc_ecmd |= scomData.flushTo0(); + rc_ecmd |= scomData.setBit(PTC_DIR_CTL_SP_START); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_start: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, directControlAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_start: fapiPutScom error when issuing sp_start to thread %d", i_thread); + break; + } + + // Check Postconditions (for warning/debug) + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_start: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (!(o_state & THREAD_STATE_INSTCOMP)) + { + if (i_warncheck) + { + FAPI_INF("proc_thread_control_start: WARNING: Thread Start issued, but no instructions have completed. Start might have failed"); + break; + } + else + { + FAPI_ERR("proc_thread_control_start: ERROR: Thread Start issued, but no instructions have completed. Start might have failed for thread %d", i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_START_FAIL); + break; + } + } + + FAPI_INF("proc_thread_control_start : Start command issued for thread %d", i_thread); + break; + } + while (0); + return rc; + } // proc_thread_control_start + + //-------------------------------------------------------------------------- + // function: proc_thread_control_stop: utility subroutine to stop a thread + // parameters: i_target => core target + // i_thread => thread (0..7) + // i_warncheck => convert check errors to warnings + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // RC_PROC_THREAD_CONTROL_STOP_FAIL if stop command failed, + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_stop(const fapi::Target& i_target, + const uint8_t i_thread, const bool i_warncheck, + ecmdDataBufferBase& o_ras_status, uint64_t& o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + ecmdDataBufferBase scomData(64); + + uint32_t directControlAddr = EX_PERV_TCTL0_DIRECT_0x10013000 + + (i_thread << 4); + + do + { + FAPI_DBG("proc_thread_control_stop : Initiating stop command to core PC logic for thread %d", i_thread); + + rc_ecmd |= scomData.flushTo0(); + rc_ecmd |= scomData.setBit(PTC_DIR_CTL_SP_STOP); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_stop: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + + // Issue Stop + rc = fapiPutScom(i_target, directControlAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_stop: fapiPutScom error when issuing sp_stop to thread %d", i_thread); + break; + } + + // Post-condition check + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_stop: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (o_state & THREAD_STATE_CHKSTOP) + { + FAPI_INF("proc_thread_control_stop: WARNING: RAS Status register indicated checkstop after Thread Stop command was issued"); + break; + } + if (!(o_state & THREAD_STATE_MAINT)) + { + if (i_warncheck) + { + FAPI_INF("proc_thread_control_stop: WARNING: Thread Stop failed: RAS Status Maintenance bit is not on"); + break; + } + else + { + FAPI_ERR("proc_thread_control_stop: Thread Stop failed: RAS Status Maintenance bit is not on for thread %d", i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_STOP_FAIL); + break; + } + } + + FAPI_INF("proc_thread_control_stop : stop command successful for thread %d", i_thread); + break; + } + while(0); + return rc; + } // proc_thread_control_stop + + //-------------------------------------------------------------------------- + // function: proc_thread_control_step: utility subroutine to single- + // instruction step a thread + // parameters: i_target => core target + // i_thread => thread (0..7) + // i_warncheck => convert check errors to warnings + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // RC_PROC_THREAD_CONTROL_STEP_PRE_NOMAINT if maintenance bit + // was not set before step was issued + // RC_PROC_THREAD_CONTROL_STEP_FAIL if step command failed, + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_step(const fapi::Target& i_target, + const uint8_t i_thread, const bool i_warncheck, + ecmdDataBufferBase& o_ras_status, uint64_t& o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + ecmdDataBufferBase scomData(64); + + uint32_t directControlAddr = EX_PERV_TCTL0_DIRECT_0x10013000 + + (i_thread << 4); + uint32_t rasModeAddr = EX_PERV_TCTL0_R_MODE_0x10013001 + + (i_thread << 4); + + do + { + FAPI_DBG("proc_thread_control_step: Initiating step command to core PC logic for thread %d", i_thread); + + // Check Preconditions + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_step: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (!(o_state & THREAD_STATE_MAINT)) + { + FAPI_ERR("proc_thread_control_step: Step Precondition failed: RAS Status Maintenance bit is not on for thread %d", i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_STEP_PRE_NOMAINT); + break; + } + + // Set Single Mode + ecmdDataBufferBase rasModeSave; + rc = fapiGetScom(i_target, rasModeAddr, rasModeSave); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_step: fapiPutScom error when reading ras_mode register for thread %d", i_thread); + break; + } + scomData = rasModeSave; + rc_ecmd |= scomData.setBit(PTC_RAS_MODE_SINGLE); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_step: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, rasModeAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_step: fapiPutScom error when single step mode in ras_mode register for thread %d", i_thread); + break; + } + + // Issue Step Command + rc_ecmd |= scomData.flushTo0(); + rc_ecmd |= scomData.setBit(PTC_DIR_CTL_SP_STEP); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_step: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, directControlAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_step: fapiPutScom error when issuing sp_step to thread %d", i_thread); + break; + } + + // Poll for step complete + uint8_t stepCompletePollCount = 0; + bool step_complete = false; + do + { + rc = proc_thread_control_query(i_target, i_thread, + o_ras_status, o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_start: ERROR checking RAS_STATUS bits for thread %d", i_thread); + break; + } + if (o_state & THREAD_STATE_INSTCOMP) + { + step_complete = true; + break; + } + stepCompletePollCount++; + if (stepCompletePollCount > PTC_STEP_COMP_POLL_LIMIT) { + if (i_warncheck) + { + FAPI_INF("proc_thread_control_step: WARNING: Thread Step failed: RAS Status Group/Inst Complete bit is not on after %d poll attempts. WARNING: RAS_MODE bit %d still in single instruction mode! Thread %d", PTC_STEP_COMP_POLL_LIMIT, PTC_RAS_MODE_SINGLE, i_thread); + break; + } + else + { + FAPI_ERR("proc_thread_control_step: Thread Step failed: RAS Status Group/Inst Complete bit is not on after %d poll attempts. WARNING: RAS_MODE bit %d still in single instruction mode! Thread %d", PTC_STEP_COMP_POLL_LIMIT, PTC_RAS_MODE_SINGLE, i_thread); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_STEP_FAIL); + break; + } + } + } + while(1); + + // break if error detected in polling + if (!rc.ok()) + { + break; + } + + // Restore RasMode register (Exit Single Mode) + if (step_complete) + { + FAPI_DBG("proc_thread_control_step : Instruction step complete. Clearing single inst mode."); + rc = fapiPutScom(i_target, rasModeAddr, rasModeSave); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_step: fapiPutScom error when restoring ras_mode register for thread %d", i_thread); + break; + } + + FAPI_INF("proc_thread_control_step : step command successful for thread %d", i_thread); + } + break; + } + while(0); + return rc; + } // proc_thread_control_step + + //-------------------------------------------------------------------------- + // function: proc_thread_control_activate: utility subroutine to activate + // a thread in POR state to enable ramming + // parameters: i_target => core target + // i_thread => thread (0..7) + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // RC_PROC_THREAD_CONTROL_ACTIVATE_FAIL if activate command failed, + // else error + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_activate(const fapi::Target& i_target, + const uint8_t i_thread, ecmdDataBufferBase& o_ras_status, uint64_t& + o_state) + { + fapi::ReturnCode rc; + uint32_t rc_ecmd = 0; + + ecmdDataBufferBase scomData(64); + o_ras_status.setBitLength(64); + + do + { + FAPI_DBG("proc_thread_control_activate : Initiating activate thread command to core PC logic for thread %d", i_thread); + uint8_t thd_activate_bit = PTC_RAM_THREAD_ACTIVE_T0 + i_thread; + rc = fapiGetScom(i_target, EX_PERV_THREAD_ACTIVE_0x1001310E, + scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_activate: fapiGetScom error when reading THREAD_ACTIVE register for thread %d", i_thread); + break; + } + if (scomData.isBitSet(thd_activate_bit)) + { + FAPI_INF("proc_thread_control_activate: Thread %d activate bit already set. No action required.", i_thread); + break; + } + rc_ecmd |= scomData.setBit(thd_activate_bit); + if (rc_ecmd) + { + FAPI_ERR("proc_thread_control_activate: Error setting up data buffer"); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, EX_PERV_THREAD_ACTIVE_0x1001310E, + scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_activate: fapiPutScom error writing to THREAD_ACTIVE register when activating thread %d for RAM", i_thread); + break; + } + rc = fapiGetScom(i_target, EX_PERV_THREAD_ACTIVE_0x1001310E, + scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_activate: fapiGetScom error when reading THREAD_ACTIVE register for thread %d", i_thread); + break; + } + if (scomData.isBitClear(thd_activate_bit)) + { + FAPI_ERR("proc_thread_control_activate: Activate Thread failed: Thread Active bit is still off."); + FAPI_SET_HWP_ERROR(rc, + RC_PROC_THREAD_CONTROL_ACTIVATE_FAIL); + break; + } + + // Always return RAS_STATUS and state + rc = proc_thread_control_query(i_target, i_thread, o_ras_status, + o_state); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_activate: error calling proc_thread_control_query for thread %d", i_thread); + break; + } + + FAPI_INF("proc_thread_control_activate : activate command successful for thread %d.", i_thread); + break; + } + while(0); + return rc; + } // proc_thread_control_activate + + //-------------------------------------------------------------------------- + // function: proc_thread_control_query: utility subroutine to check + // various thread status bits + // parameters: i_target => core target + // i_thread => thread (0..7) + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + // returns: FAPI_RC_SUCCESS if operation was successful, + // else SCOM read failure + //-------------------------------------------------------------------------- + fapi::ReturnCode proc_thread_control_query(const fapi::Target& + i_target, const uint8_t i_thread, ecmdDataBufferBase& o_ras_status, + uint64_t& o_state) + { + fapi::ReturnCode rc; + ecmdDataBufferBase scomData; + + uint32_t rasStatAddr = EX_PERV_TCTL0_R_STAT_0x10013002 + + (i_thread << 4); + o_ras_status.setBitLength(64); // this also clears the buffer + + do + { + o_state = 0; + rc = fapiGetScom(i_target, rasStatAddr, scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_query: fapiGetScom error when reading TCTL_R_STAT register for thread %d", i_thread); + break; + } + o_ras_status = scomData; + + if (o_ras_status.isBitSet(PTC_RAS_STAT_CHKSTOP)) + { + o_state |= THREAD_STATE_CHKSTOP; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_MAINT)) + { + o_state |= THREAD_STATE_MAINT; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_INST_COMP)) + { + o_state |= THREAD_STATE_INSTCOMP; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_THD_POR)) + { + o_state |= THREAD_STATE_POR; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_ENABLED)) + { + o_state |= THREAD_STATE_ENABLED; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_RUN_BIT)) + { + o_state |= THREAD_STATE_RUNNING; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_THD_QUIESCED)) + { + o_state |= THREAD_STATE_QUIESCED; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_THD_STARTING)) + { + o_state |= THREAD_STATE_STARTING; + } + if (o_ras_status.isBitSet(PTC_RAS_STAT_THD_STOPPING)) + { + o_state |= THREAD_STATE_STOPPING; + } + + uint8_t thd_ram_active_bit = PTC_RAM_THREAD_ACTIVE_T0 + i_thread; + rc = fapiGetScom(i_target, EX_PERV_THREAD_ACTIVE_0x1001310E, + scomData); + if (!rc.ok()) + { + FAPI_ERR("proc_thread_control_query: fapiGetScom error when reading THREAD_ACTIVE register for thread %d", i_thread); + break; + } + if (scomData.isBitSet(thd_ram_active_bit)) + { + o_state |= THREAD_STATE_RAM_ACTIVE; + } + + } + while (0); + return rc; + } // proc_thread_control_query +} // extern "C" diff --git a/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.H b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.H new file mode 100644 index 000000000..5fd8044a8 --- /dev/null +++ b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.H @@ -0,0 +1,114 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: proc_thread_control.H,v 1.8 2012/09/10 17:34:27 karm Exp $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2012 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! TITLE : proc_thread_control +// *! DESCRIPTION : Core Thread start/stop/step/query/activate operations +// *! Use to start (start or sreset) thread instruction execution, +// *! stop instruction execution, or single instruction step. +// *! Also used to query the state of a thread. +// *! OWNER NAME : Lance Karm Email: karm@us.ibm.com +// *! BACKUP NAME : Sebastien Lafontant Email: slafont@us.ibm.com +//------------------------------------------------------------------------------ + + +#ifndef _PROC_THREAD_CONTROL_H_ +#define _PROC_THREAD_CONTROL_H_ + +#include <fapi.H> +#include "p8_scom_addresses.H" + +typedef fapi::ReturnCode +(*proc_thread_control_FP_t)(const fapi::Target&, + const uint8_t, + const uint8_t, + const bool, + ecmdDataBufferBase&, + uint64_t&); + + +// ProcThreadControl input commands +const uint8_t PTC_CMD_SRESET = 0; +const uint8_t PTC_CMD_STEP = 1; +const uint8_t PTC_CMD_START = 2; +const uint8_t PTC_CMD_STOP = 3; +const uint8_t PTC_CMD_ACTIVATE = 4; +const uint8_t PTC_CMD_QUERY = 5; + +// ProcThreadContrl Thread Control and State bit definitions +const uint8_t PTC_DIR_CTL_SP_SRESET = 60; +const uint8_t PTC_DIR_CTL_SP_STEP = 61; +const uint8_t PTC_DIR_CTL_SP_START = 62; +const uint8_t PTC_DIR_CTL_SP_STOP = 63; +const uint8_t PTC_RAM_THREAD_ACTIVE_T0 = 8; +const uint8_t PTC_RAS_MODE_SINGLE = 50; + +const uint8_t PTC_RAS_STAT_CHKSTOP = 2; +const uint8_t PTC_RAS_STAT_INST_COMP = 12; +const uint8_t PTC_RAS_STAT_THD_POR = 20; +const uint8_t PTC_RAS_STAT_MAINT = 21; +const uint8_t PTC_RAS_STAT_ENABLED = 48; +const uint8_t PTC_RAS_STAT_THD_QUIESCED = 49; +const uint8_t PTC_RAS_STAT_THD_STARTING = 50; +const uint8_t PTC_RAS_STAT_RUN_BIT = 51; +const uint8_t PTC_RAS_STAT_THD_STOPPING = 52; + +const uint8_t PTC_STEP_COMP_POLL_LIMIT = 10; + +// o_state thread state return bit enums +const uint64_t THREAD_STATE_RUNNING = 0x8000000000000000ULL; +const uint64_t THREAD_STATE_QUIESCED = 0x4000000000000000ULL; +const uint64_t THREAD_STATE_STARTING = 0x2000000000000000ULL; +const uint64_t THREAD_STATE_STOPPING = 0x1000000000000000ULL; +const uint64_t THREAD_STATE_POR = 0x0800000000000000ULL; +const uint64_t THREAD_STATE_ENABLED = 0x0400000000000000ULL; +const uint64_t THREAD_STATE_RAM_ACTIVE = 0x0200000000000000ULL; +const uint64_t THREAD_STATE_MAINT = 0x0100000000000000ULL; +const uint64_t THREAD_STATE_CHKSTOP = 0x0080000000000000ULL; +const uint64_t THREAD_STATE_INSTCOMP = 0x0040000000000000ULL; + + +extern "C" +{ + fapi::ReturnCode proc_thread_control(const fapi::Target&, const uint8_t, + const uint8_t, const bool, ecmdDataBufferBase&, uint64_t&); + + fapi::ReturnCode proc_thread_control_sreset(const fapi::Target&, + const uint8_t, const bool, ecmdDataBufferBase&, uint64_t&); + fapi::ReturnCode proc_thread_control_start(const fapi::Target&, + const uint8_t, const bool, ecmdDataBufferBase&, uint64_t&); + fapi::ReturnCode proc_thread_control_stop(const fapi::Target&, + const uint8_t, const bool, ecmdDataBufferBase&, uint64_t&); + fapi::ReturnCode proc_thread_control_step(const fapi::Target&, + const uint8_t, const bool, ecmdDataBufferBase&, uint64_t&); + fapi::ReturnCode proc_thread_control_activate(const fapi::Target&, + const uint8_t, ecmdDataBufferBase&, uint64_t&); + fapi::ReturnCode proc_thread_control_query(const fapi::Target&, + const uint8_t, ecmdDataBufferBase&, uint64_t&); +} + +#endif // _PROC_THREAD_CONTROL_H_ diff --git a/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.xml b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.xml new file mode 100644 index 000000000..299f99b76 --- /dev/null +++ b/src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.xml @@ -0,0 +1,66 @@ +<!-- IBM_PROLOG_BEGIN_TAG --> +<!-- This is an automatically generated prolog. --> +<!-- --> +<!-- $Source: src/usr/hwpf/hwp/thread_activate/proc_thread_control/proc_thread_control.xml $ --> +<!-- --> +<!-- IBM CONFIDENTIAL --> +<!-- --> +<!-- COPYRIGHT International Business Machines Corp. 2012 --> +<!-- --> +<!-- 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 otherwise --> +<!-- divested of its trade secrets, irrespective of what has been --> +<!-- deposited with the U.S. Copyright Office. --> +<!-- --> +<!-- Origin: 30 --> +<!-- --> +<!-- IBM_PROLOG_END_TAG --> +<!-- $Id: proc_thread_control.xml,v 1.6 2012/07/25 18:29:09 karm Exp $ --> +<!-- Error definitions for proc_thread_control procedure --> +<hwpErrors> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_INV_COMMAND</rc> + <description>Invalid command issued to proc_thread_control procedure</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_SRESET_FAIL</rc> + <description>Sreset command failed: RAS STAT instruction completed bit was not set after sreset command.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_START_PRE_NOMAINT</rc> + <description>Start command precondition not met: RAS STAT Maintenance bit is not set.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_START_FAIL</rc> + <description>Sreset command failed: RAS STAT instruction completed bit was not set after start command.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_STOP_FAIL</rc> + <description>Stop command issued to core PC, but RAS STAT maintenance bit is not set.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_STEP_PRE_NOMAINT</rc> + <description>Step command precondition not met: RAS STAT Maintenance bit is not set.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_STEP_FAIL</rc> + <description>Step command issued to core PC, but RAS STAT run bit is still set.</description> + </hwpError> + <!-- ********************************************************************* --> + <hwpError> + <rc>RC_PROC_THREAD_CONTROL_ACTIVATE_FAIL</rc> + <description>Activate command issued to core PC, but THREAD ACTIVE bit was not set.</description> + </hwpError> +</hwpErrors> diff --git a/src/usr/hwpf/hwp/thread_activate/thread_activate.C b/src/usr/hwpf/hwp/thread_activate/thread_activate.C index cce1589ac..20a345e47 100644 --- a/src/usr/hwpf/hwp/thread_activate/thread_activate.C +++ b/src/usr/hwpf/hwp/thread_activate/thread_activate.C @@ -41,6 +41,8 @@ #include <devicefw/userif.H> #include <sys/misc.h> +#include <proc_thread_control.H> + // targeting support #include <targeting/common/commontargeting.H> #include <targeting/common/utilFilter.H> @@ -158,36 +160,44 @@ void activate_threads( errlHndl_t& io_rtaskRetErrl ) // send a magic instruction for PHYP Simics to work... MAGIC_INSTRUCTION(MAGIC_SIMICS_CORESTATESAVE); - //@todo - call the real proc_thread_control HWP (RTC:42816) -#if 0 // parameters: i_target => core target // i_thread => thread (0..7) - // i_sreset => initiate sreset thread command - // i_start => initiate start thread command - // i_stop => initiate stop thread command - // i_step => initiate step thread command - // i_activate => initiate activate thread command - // i_query => query and return thread state - // return data in o_thread_state - // o_thread_state => output: thread state - uint8_t l_threadState = false; + // i_command => + // PTC_CMD_SRESET => initiate sreset thread command + // PTC_CMD_START => initiate start thread command + // PTC_CMD_STOP => initiate stop thread command + // PTC_CMD_STEP => initiate step thread command + // PTC_CMD_QUERY => query and return thread state + // return data in o_ras_status + // i_warncheck => convert pre/post checks errors to warnings + // o_ras_status => output: complete RAS status register + // o_state => output: thread state info + // see proc_thread_control.H + // for bit enumerations: + // THREAD_STATE_* + ecmdDataBufferBase l_ras_status; + uint64_t l_thread_state; FAPI_INVOKE_HWP( l_errl, proc_thread_control, - l_fapiCore, //i_target - thread, //i_thread - true, //i_sreset - false, //i_start - false, //i_stop - false, //i_step - false, //i_activate - false, //i_query - l_threadState ); //o_thread_state - if ( l_errl ) + l_fapiCore, //i_target + thread, //i_thread + PTC_CMD_SRESET, //i_command + false, //i_warncheck + l_ras_status, //o_ras_status + l_thread_state); //o_state + + if ( l_errl != NULL ) { TRACFCOMP( g_fapiImpTd, - "ERROR: 0x%.8X : proc_thread_control HWP( cpu %d, thread %d )", + "ERROR: 0x%.8X : proc_thread_control HWP( cpu %d, thread %d, " + "ras status 0x%.16X, thread state 0x%.16X )", l_errl->reasonCode(), l_masterCoreID, - thread ); + thread, + l_ras_status.getDoubleWord(0), + l_thread_state ); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + // if 1 thread fails it is unlikely that other threads will work // so we'll just jump out now break; @@ -195,94 +205,13 @@ void activate_threads( errlHndl_t& io_rtaskRetErrl ) else { TRACFCOMP( g_fapiTd, - "SUCCESS: 0x%.8X : proc_thread_control HWP( cpu %d, thread %d )", - l_errl->reasonCode(), - l_masterCoreID, - thread ); - } -#else - //@todo - Temp version, just do the scoms manually (RTC:42816) - size_t scom_size = sizeof(uint64_t); - uint32_t directControlAddr = 0x10013000 + (thread << 4); - uint32_t rasStatAddr = 0x10013002 + (thread << 4); - - // Check the initial state - uint64_t statreg = 0; - l_errl = deviceRead( l_masterCore, - &statreg, - scom_size, - DEVICE_SCOM_ADDRESS(rasStatAddr) ); - if( l_errl ) { break; } - - // Make sure the thread is in maintenance mode - if( !(statreg & 0x0000040000000000) ) //21:PTC_RAS_STAT_MAINT - { - TRACFCOMP( g_fapiImpTd, - "ERROR: Thread c%d t%d is in the wrong state : Status=%.16X", - l_masterCoreID, - thread, - statreg ); - /*@ - * @errortype - * @moduleid fapi::MOD_THREAD_ACTIVATE - * @reasoncode fapi::RC_THREAD_IN_WRONG_STATE - * @userdata1 Thread RAS Status Scom Addr - * @userdata2 Thread RAS Status Data - * @devdesc activate_threads> Thread start attempted on - * thread that is not in maintenance mode - */ - l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - fapi::MOD_THREAD_ACTIVATE, - fapi::RC_THREAD_IN_WRONG_STATE, - rasStatAddr, - statreg); - l_errl->collectTrace(FAPI_TRACE_NAME,256); - l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); - break; - - } - - // Start the thread - uint64_t ctlreg = 0x0000000000000008; //60:PTC_DIR_CTL_SP_SRESET - l_errl = deviceWrite( l_masterCore, - &ctlreg, - scom_size, - DEVICE_SCOM_ADDRESS(directControlAddr) ); - if( l_errl ) { break; } - - // Make sure we really started - l_errl = deviceRead( l_masterCore, - &statreg, - scom_size, - DEVICE_SCOM_ADDRESS(rasStatAddr) ); - if( l_errl ) { break; } - - if( !(statreg & 0x0008000000000000) ) //12:PTC_RAS_STAT_INST_COMP - { - TRACFCOMP( g_fapiImpTd, - "ERROR: Thread c%d t%d did not start : Status=%.16X", + "SUCCESS: proc_thread_control HWP( cpu %d, thread %d, " + "ras status 0x%.16X,thread state 0x%.16X )", l_masterCoreID, thread, - statreg ); - /*@ - * @errortype - * @moduleid fapi::MOD_THREAD_ACTIVATE - * @reasoncode fapi::RC_THREAD_DID_NOT_START - * @userdata1 Thread RAS Status Scom Addr - * @userdata2 Thread RAS Status Data - * @devdesc activate_threads> Thread did not start - */ - l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - fapi::MOD_THREAD_ACTIVATE, - fapi::RC_THREAD_DID_NOT_START, - rasStatAddr, - statreg); - l_errl->collectTrace(FAPI_TRACE_NAME,256); - l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); - break; - + l_ras_status.getDoubleWord(0), + l_thread_state ); } -#endif TRACFCOMP( g_fapiTd, "SUCCESS: Thread c%d t%d started", diff --git a/src/usr/hwpf/makefile b/src/usr/hwpf/makefile index a80bfb541..e0d71a709 100644 --- a/src/usr/hwpf/makefile +++ b/src/usr/hwpf/makefile @@ -47,7 +47,8 @@ HWP_ERROR_XML_FILES = hwp/fapiHwpErrorInfo.xml \ hwp/nest_chiplets/proc_chiplet_scominit/proc_chiplet_scominit_errors.xml \ hwp/nest_chiplets/proc_a_x_pci_dmi_pll_setup_errors.xml \ hwp/core_activate/proc_prep_master_winkle/proc_prep_master_winkle_errors.xml \ - hwp/core_activate/proc_stop_deadman_timer/proc_stop_deadman_timer_errors.xml + hwp/core_activate/proc_stop_deadman_timer/proc_stop_deadman_timer_errors.xml \ + hwp/thread_activate/proc_thread_control/proc_thread_control.xml ## these get generated into obj/genfiles/AttributeIds.H |