diff options
author | Elizabeth Liner <eliner@us.ibm.com> | 2017-09-27 20:06:33 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-10-10 13:39:38 -0400 |
commit | c381bea9d38f2cc0f41e570dc092ed43602a5509 (patch) | |
tree | ebbe0426682b83eaaf177f6712797dc4a30233f9 /src/usr/sbeio | |
parent | 5173779196d3a3a97872914a3875dc6598c0feca (diff) | |
download | talos-hostboot-c381bea9d38f2cc0f41e570dc092ed43602a5509.tar.gz talos-hostboot-c381bea9d38f2cc0f41e570dc092ed43602a5509.zip |
Moving SBE error and threshold handler to sbeio
Change-Id: I15438b21692f45899efb75afcc1db31f9caece15
RTC:178801
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46843
Reviewed-by: Martin Gloff <mgloff@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Prachi Gupta <pragupta@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/sbeio')
-rw-r--r-- | src/usr/sbeio/makefile | 5 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_extract_rc_handler.C | 1100 |
2 files changed, 1104 insertions, 1 deletions
diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile index 769e198c4..77d151b0f 100644 --- a/src/usr/sbeio/makefile +++ b/src/usr/sbeio/makefile @@ -23,7 +23,7 @@ # # IBM_PROLOG_END_TAG ROOTPATH = ../../.. - +PROCEDURES_PATH = ${ROOTPATH}/src/import/chips/p9/procedures MODULE = sbeio EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include @@ -33,6 +33,8 @@ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/utils/imageProcs EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/ffdc EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/perv +EXTRAINCDIR += ${PROCEDURES_PATH}/hwp/sbe/ + OBJS += sbe_psudd.o OBJS += sbe_utils.o OBJS += sbe_coreStateControl.o @@ -50,6 +52,7 @@ OBJS += sbe_memRegionMgr.o OBJS += sbe_fifo_buffer.o OBJS += sbe_ffdc_package_parser.o OBJS += sbe_attn.o +OBJS += sbe_extract_rc_handler.o VPATH += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/perv/ include ${ROOTPATH}/procedure.rules.mk diff --git a/src/usr/sbeio/sbe_extract_rc_handler.C b/src/usr/sbeio/sbe_extract_rc_handler.C new file mode 100644 index 000000000..35a9cbdae --- /dev/null +++ b/src/usr/sbeio/sbe_extract_rc_handler.C @@ -0,0 +1,1100 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/sbe_extract_rc_handler.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] 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 sbe_extract_rc_handler.C + * + * Handle a SBE extract rc error. We use a switch-case to determine + * what action to take, and a finite state machine to control the + * threshold actions. + */ + +/*****************************************************************************/ +// Includes +/*****************************************************************************/ +#include <stdint.h> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <p9_extract_sbe_rc.H> + +#include <fapi2/target.H> +#include <fapi2/plat_hwp_invoker.H> +#include <initservice/isteps_trace.H> +#include <initservice/initserviceif.H> +#include <errl/errludtarget.H> +#include <sys/time.h> +#include <util/misc.H> +#include <ipmi/ipmiwatchdog.H> + +#include <p9_start_cbs.H> +#include <p9_get_sbe_msg_register.H> +#include <p9_perv_scom_addresses.H> +#include <sbeio/sbe_extract_rc_handler.H> +#include <sbe/sbe_update.H> +#include <sbeio/sbeioif.H> +#include <sbeio/sbe_sp_intf.H> +#include <../../usr/sbeio/sbe_fifodd.H> +#include <../../usr/sbeio/sbe_fifo_buffer.H> +#include <sbeio/sbe_ffdc_parser.H> +#include <sbeio/sbeioreasoncodes.H> + +extern trace_desc_t* g_trac_sbeio; + +#define SBE_TRACF(printf_string,args...) \ + TRACFCOMP(g_trac_sbeio,"sbe_extract_rc_handler.C: " printf_string,##args) +#define SBE_TRACD(printf_string,args...) \ + TRACDCOMP(g_trac_sbeio,"sbe_extract_rc_handler.C: " printf_string,##args) +#define SBE_TRACU(args...) +#define SBE_TRACFBIN(printf_string,args...) \ + TRACFBIN(g_trac_sbeio,"sbe_extract_rc_handler.C: " printf_string,##args) +#define SBE_TRACDBIN(printf_string,args...) \ + TRACDBIN(g_trac_sbeio,"sbe_extract_rc_handler.C: " printf_string,##args) + +using namespace SBEIO; + +/* array and enum must be in sync */ +P9_EXTRACT_SBE_RC::RETURN_ACTION (* sbe_handler_state[])( + TARGETING::Target * i_target, + uint8_t i_prev_error) = + { same_side_retry_state, // SAME_SIDE_RETRY + other_side_state, // OTHER_SIDE + working_exit_state, // WORKING_EXIT + failing_exit_state }; // FAILING_EXIT + +enum STATE_CODES { SAME_SIDE_RETRY, + OTHER_SIDE, + WORKING_EXIT, + FAILING_EXIT }; +struct transition +{ + enum STATE_CODES src_state; + uint8_t ret_code; + enum STATE_CODES dst_state; +}; + +/* transistions from end states aren't needed */ +struct transition state_transitions[] = { + { SAME_SIDE_RETRY, 0, WORKING_EXIT }, + { SAME_SIDE_RETRY, 1, OTHER_SIDE }, + { OTHER_SIDE, 0, WORKING_EXIT }, + { OTHER_SIDE, 1, FAILING_EXIT } +}; + +enum STATE_CODES get_next_state( enum STATE_CODES i_src, uint8_t i_rc ) +{ + return (state_transitions[ i_src*2 + i_rc ]).dst_state; +} + +void sbe_threshold_handler( bool i_procSide, + TARGETING::Target * i_target, + P9_EXTRACT_SBE_RC::RETURN_ACTION i_initialAction, + uint8_t i_previousError ) +{ + // Note: This is set up as a finite state machine since all actions are + // connected and most of them lead to another. + + STATE_CODES cur_state = SAME_SIDE_RETRY; + + // The initial state depends on our inputs + if( i_procSide ) + { + cur_state = OTHER_SIDE; + } + + // Setup the rest of the FSM + P9_EXTRACT_SBE_RC::RETURN_ACTION l_returnedAction; + P9_EXTRACT_SBE_RC::RETURN_ACTION (*state_fcn)(TARGETING::Target * i_target, + uint8_t i_orig_error); + + // Begin FSM + for(;;) + { +#ifdef CONFIG_BMC_IPMI + // This could potentially take awhile, reset watchdog + errlHndl_t l_errl = IPMIWATCHDOG::resetWatchDogTimer(); + if(l_errl) + { + SBE_TRACF("Inside sbe_extract_rc_handler FSM, " + "Resetting watchdog"); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl,ISTEP_COMP_ID); + } +#endif + + state_fcn = sbe_handler_state[cur_state]; + l_returnedAction = state_fcn(i_target, i_initialAction); + + if( cur_state == WORKING_EXIT || cur_state == FAILING_EXIT) + { + break; + } + // If the returned action was 0, the return is a pass: 0, + // Else, the SBE did not start cleanly and we continue + cur_state = get_next_state(cur_state, + !(P9_EXTRACT_SBE_RC::ERROR_RECOVERED == l_returnedAction)); + + } + + return; + +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION same_side_retry_state( + TARGETING::Target * i_target, + uint8_t i_orig_error) +{ + SBE_TRACF("Running p9_start_cbs HWP on processor target %.8X", + TARGETING::get_huid(i_target)); + + // We don't actually need an accurate p9_extract_sbe_rc value if + // we're coming from the state machine, so we send in a pass. + return handle_sbe_restart(i_target,true, + P9_EXTRACT_SBE_RC::ERROR_RECOVERED); +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION other_side_state( + TARGETING::Target * i_target, + uint8_t i_orig_error) +{ + SBE_TRACF("Running p9_start_cbs HWP on processor target %.8X", + TARGETING::get_huid(i_target)); + + errlHndl_t l_errl = NULL; + + // Run HWP, but from the other side. + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + l_errl = switch_sbe_sides(i_target); + if(l_errl) + { + errlCommit(l_errl,ISTEP_COMP_ID); + return P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION; + } + + // We don't actually need an accurate p9_extract_sbe_rc value if + // we're coming from the state machine, so we send in a pass. + P9_EXTRACT_SBE_RC::RETURN_ACTION l_ret = + handle_sbe_restart(i_target, true, + P9_EXTRACT_SBE_RC::ERROR_RECOVERED); + if(i_target->getAttr<TARGETING::ATTR_SBE_IS_STARTED>()) + { + // Information log + /*@ + * @errortype + * @moduleid SBEIO_THRESHOLD_FSM + * @reasoncode SBEIO_BOOTED_UNEXPECTED_SIDE_BKP + * @userdata1 SBE status reg + * @userdata2 HUID + * @devdesc The SBE has booted on an unexpected side + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_THRESHOLD_FSM, + SBEIO_BOOTED_UNEXPECTED_SIDE_BKP, + l_ret, + get_huid(i_target)); + + l_errl->collectTrace( "ISTEPS_TRACE", 256); + + errlCommit(l_errl, ISTEP_COMP_ID); + + } + + return l_ret; +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION working_exit_state( + TARGETING::Target * i_target, + uint8_t i_orig_error) +{ + return P9_EXTRACT_SBE_RC::ERROR_RECOVERED; //pass +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION failing_exit_state( + TARGETING::Target * i_target, + uint8_t i_orig_error) +{ + errlHndl_t l_errl = NULL; + + // Look at original error + // Escalate to REIPL_BKP_SEEPROM (recall fcn) + if( (i_orig_error == P9_EXTRACT_SBE_RC::RESTART_SBE) || + (i_orig_error == P9_EXTRACT_SBE_RC::RESTART_CBS) || + (i_orig_error == P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM) ) + { +#ifdef CONFIG_BMC_IPMI + // This could potentially take awhile, reset watchdog + l_errl = IPMIWATCHDOG::resetWatchDogTimer(); + if(l_errl) + { + SBE_TRACF("Inside sbe_extract_rc_handler FSM, before sbe_handler " + "Resetting watchdog"); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl,ISTEP_COMP_ID); + } +#endif + proc_extract_sbe_handler(i_target, + P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM); + } + // Gard and callout proc, return back to 8.4 + else if(i_orig_error == P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM) + { + // There is no action possible. Gard and Callout the proc + /*@ + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid SBEIO_THRESHOLD_FSM + * @reasoncode SBEIO_NO_RECOVERY_ACTION + * @userdata1 SBE current error + * @userdata2 HUID of proc + * @devdesc There is no recovery action on the SBE. + * We're garding this proc + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SBEIO_THRESHOLD_FSM, + SBEIO_NO_RECOVERY_ACTION, + i_orig_error, + TARGETING::get_huid(i_target)); + l_errl->collectTrace( "ISTEPS_TRACE", 256); + l_errl->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_Predictive ); + errlCommit(l_errl, ISTEP_COMP_ID); + + } + + return P9_EXTRACT_SBE_RC::ERROR_RECOVERED; //pass +} +// end FSM + + +void proc_extract_sbe_handler( TARGETING::Target * i_target, + uint8_t i_current_error) +{ + SBE_TRACF(ENTER_MRK "proc_extract_sbe_handler error: %x", + i_current_error); + + errlHndl_t l_errl = NULL; + + /*@ + * @errortype + * @severity ERRORLOG::ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_EXTRACT_RC_ERROR + * @userdata1 HUID of proc that had the SBE timeout + * @userdata2 SBE failing code + * + * @devdesc SBE did not start, this function is looking at + * the error to determine next course of action + * + * @custdesc The SBE did not start, we will attempt a reboot if possible + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_EXTRACT_RC_ERROR, + TARGETING::get_huid(i_target), + i_current_error); + + l_errl->collectTrace("ISTEPS_TRACE",256); + + // Commit error and continue + errlCommit(l_errl, ISTEP_COMP_ID); + + switch(i_current_error) + { + case P9_EXTRACT_SBE_RC::RESTART_SBE: + case P9_EXTRACT_SBE_RC::RESTART_CBS: + { + // Note: These two are only going to have the same handling until + // we have runtime handling in place. + + SBE_TRACF("Running p9_start_cbs HWP on processor target %.8X", + TARGETING::get_huid(i_target)); + handle_sbe_restart(i_target, false, + P9_EXTRACT_SBE_RC::RESTART_SBE); + break; + } + case P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM: + { + // Log additional error on proc. + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_BOOT_FROM_BKP_SEEPROM + * @userdata1 SBE return code + * @userdata2 HUID current side + * @devdesc Attempting to boot from backup SEEPROM + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_BOOT_FROM_BKP_SEEPROM, + i_current_error, + get_huid(i_target)); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID); + + // Run HWP, but from the other side. + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + l_errl = switch_sbe_sides(i_target); + if(l_errl) + { + errlCommit(l_errl,ISTEP_COMP_ID); + break; + } + + // Run HWP, but from the other side. + // if it passes make a note that we booted from + // an unexpected side + // if it fails, call the threshold handler + SBE_TRACF( "Running p9_start_cbs HWP on processor target %.8X", + TARGETING::get_huid(i_target)); + + handle_sbe_restart(i_target, false, + P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM); + + if(i_target->getAttr<TARGETING::ATTR_SBE_IS_STARTED>()) + { + // Make a note that we booted from an unexpected side + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_BOOTED_UNEXPECTED_SIDE_BKP + * @userdata1 0 + * @userdata2 HUID of working proc + * @devdesc SBE booted from unexpected side. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_BOOTED_UNEXPECTED_SIDE_BKP, + 0,TARGETING::get_huid(i_target)); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID); + } + + break; + } + case P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM: + { + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + l_errl = switch_sbe_sides(i_target); + if(l_errl) + { + errlCommit(l_errl,ISTEP_COMP_ID); + break; + } + + // Run HWP, but from the other side. + // if it passes make a note that we booted from an + // unexpected side + // if it fails, escalate to RE_IPL_SEEPROM and call + // this function again. + SBE_TRACF( "Running p9_start_cbs HWP on processor target %.8X", + TARGETING::get_huid(i_target)); + + handle_sbe_restart(i_target, false, + P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM); + + if(i_target->getAttr<TARGETING::ATTR_SBE_IS_STARTED>()) + { + // Make a note that we booted from an unexpected side + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_BOOTED_UNEXPECTED_SIDE_UPD + * @userdata1 0 + * @userdata2 HUID of proc + * @devdesc SBE booted from unexpected side. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_BOOTED_UNEXPECTED_SIDE_UPD, + 0,TARGETING::get_huid(i_target)); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID); + } + + break; + } + case P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION: + { + // There is no action possible. Gard and Callout the proc + /*@ + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_NO_RECOVERY_ACTION + * @userdata1 SBE current error + * @userdata2 HUID of proc + * @devdesc There is no recovery action on the SBE. + * We're garding this proc + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_NO_RECOVERY_ACTION, + P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION, + TARGETING::get_huid(i_target)); + l_errl->collectTrace( "ISTEPS_TRACE", 256); + l_errl->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_NULL ); + errlCommit(l_errl, ISTEP_COMP_ID); + + break; + } + default: + { + //Error out, unexpected enum value returned. + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @reasoncode SBEIO_INCORRECT_FCN_CALL + * @userdata1 SBE current error + * @userdata2 HUID of proc + * @devdesc This function was called incorrectly or + * there is a new enum that is not handled yet. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_INCORRECT_FCN_CALL, + i_current_error, + TARGETING::get_huid(i_target)); + l_errl->collectTrace( "ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID); + + break; + } + } + + SBE_TRACF(EXIT_MRK "proc_extract_sbe_handler"); + + return; +} + +SBE_REG_RETURN check_sbe_reg(TARGETING::Target * i_target) +{ + SBE_TRACF(ENTER_MRK "check_sbe_reg"); + + errlHndl_t l_errl = nullptr; + SBE_REG_RETURN l_ret = SBE_REG_RETURN::SBE_FAILED_TO_BOOT; + + do + { + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + sbeMsgReg_t l_sbeReg; + + l_errl = sbe_timeout_handler(&l_sbeReg,i_target,&l_ret); + + if((!l_errl) && (l_sbeReg.currState != SBE_STATE_RUNTIME)) + { + // See if async FFDC bit is set in SBE register + if(l_sbeReg.asyncFFDC) + { + bool l_flowCtrl = sbe_get_ffdc_handler(i_target); + + if(l_flowCtrl) + { + break; + } + } + + // Handle that SBE failed to boot in the allowed time + sbe_boot_fail_handler(i_target,l_sbeReg); + } + else if (l_errl) + { + SBE_TRACF("ERROR: call check_sbe_reg, PLID=0x%x", l_errl->plid() ); + + // capture the target data in the elog + ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog( l_errl ); + + // Commit error log + errlCommit( l_errl, HWPF_COMP_ID ); + } + // No error and still functional + else if(i_target->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + // Set attribute indicating that SBE is started + i_target->setAttr<TARGETING::ATTR_SBE_IS_STARTED>(1); + + SBE_TRACF("SUCCESS: check_sbe_reg completed okay for proc 0x%.8X", + TARGETING::get_huid(i_target)); + } + //@TODO-RTC:100963 - this should match the logic in + //call_proc_check_slave_sbe_seeprom.C + } while(0); + + return l_ret; + +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION handle_sbe_reg_value( + TARGETING::Target * i_target, + SBE_REG_RETURN i_sbe_reg, + P9_EXTRACT_SBE_RC::RETURN_ACTION i_current_sbe_error, + bool i_fromStateMachine) +{ + errlHndl_t l_errl = NULL; + + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + switch(i_sbe_reg) + { + case SBE_REG_RETURN::FUNCTION_ERROR: + { + // There has been a failure getting the SBE register + // We cannot continue any further, return failure. + return P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION; + } + case SBE_REG_RETURN::SBE_AT_RUNTIME: + { + // The SBE has successfully booted at runtime + return P9_EXTRACT_SBE_RC::ERROR_RECOVERED; + } + case SBE_REG_RETURN::SBE_FAILED_TO_BOOT: + { + if((!i_fromStateMachine) && + (i_current_sbe_error == P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM)) + { +#ifdef CONFIG_BMC_IPMI + // This could potentially take awhile, reset watchdog + l_errl = IPMIWATCHDOG::resetWatchDogTimer(); + if(l_errl) + { + SBE_TRACF("Inside handle_sbe_reg_value before sbe_handler " + "Resetting watchdog"); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl,ISTEP_COMP_ID); + } +#endif + // If we were trying to reipl and hit the error, we need + // to start with a new seeprom before hitting the threshold + proc_extract_sbe_handler(i_target, + P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM); + return P9_EXTRACT_SBE_RC::ERROR_RECOVERED; + } + + // Get SBE extract rc + P9_EXTRACT_SBE_RC::RETURN_ACTION l_rcAction = + P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM; + FAPI_INVOKE_HWP(l_errl, p9_extract_sbe_rc, + l_fapi2_proc_target, l_rcAction); + + if(l_errl) + { + SBE_TRACF("ERROR : p9_extract_sbe_rc HWP returning errorlog " + "PLID-0x%x", l_errl->plid()); + + // capture the target data in the elog + ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl); + + // Commit error log + errlCommit( l_errl, HWPF_COMP_ID ); + } + + if(i_fromStateMachine) + { + return l_rcAction; + } + + uint8_t l_prevError = (i_target)->getAttr< + TARGETING::ATTR_PREVIOUS_SBE_ERROR>(); + (i_target)->setAttr<TARGETING::ATTR_PREVIOUS_SBE_ERROR>( + l_rcAction); + + if(i_current_sbe_error == P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM) + { + // Call sbe_threshold handler on the opposite side + sbe_threshold_handler(false, i_target, l_rcAction, l_prevError); + } + else + { + // Call sbe_threshold handler on the same side + sbe_threshold_handler(true, i_target, l_rcAction, l_prevError); + } + return P9_EXTRACT_SBE_RC::ERROR_RECOVERED; + } + default: + { + // This should never happened + // error out, unexpected enum value returned. + //return P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION; + /*@ + * @errortype ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_HANDLE_SBE_REG_VALUE + * @reasoncode SBEIO_INCORRECT_FCN_CALL + * @userdata1 HUID of target + * @userdata2 check_sbe_reg return value + * @devdesc This function was called incorrectly or + * there is a new enum that is not handled yet. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_HANDLE_SBE_REG_VALUE, + SBEIO_INCORRECT_FCN_CALL, + get_huid(i_target),i_sbe_reg); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID); + return P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION; + } + } +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION handle_sbe_restart( + TARGETING::Target * i_target, + bool i_fromStateMachine, + P9_EXTRACT_SBE_RC::RETURN_ACTION i_current_condition) +{ + errlHndl_t l_errl = NULL; + + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target (i_target); + + FAPI_INVOKE_HWP(l_errl, p9_start_cbs, l_fapi2_proc_target, true); + if(l_errl) + { + SBE_TRACF("ERROR: call p9_start_cbs, " + "PLID=0x%x", l_errl->plid() ); + l_errl->collectTrace( "ISTEPS_TRACE", 256); + + errlCommit(l_errl, ISTEP_COMP_ID); + } + + SBE_REG_RETURN l_checkSBE = check_sbe_reg(i_target); + return handle_sbe_reg_value(i_target, l_checkSBE, + i_current_condition, i_fromStateMachine); +} + +errlHndl_t sbe_timeout_handler(sbeMsgReg_t * o_sbeReg, + TARGETING::Target * i_target, + SBE_REG_RETURN * o_returnAction) +{ + errlHndl_t l_errl = NULL; + + (*o_returnAction) = SBE_FAILED_TO_BOOT; + + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + // Each slave sbe gets 60s to respond with the fact that it's + // booted and at runtime (stable state) + uint64_t SBE_TIMEOUT_NSEC = 60*NS_PER_SEC; //60 sec + // Bump this up really high for simics, things are slow there + if( Util::isSimicsRunning() ) + { + SBE_TIMEOUT_NSEC *= 10; + } + const uint64_t SBE_NUM_LOOPS = 100; + const uint64_t SBE_WAIT_SLEEP = (SBE_TIMEOUT_NSEC/SBE_NUM_LOOPS); + + SBE_TRACF("Running p9_get_sbe_msg_register HWP on proc target %.8X", + TARGETING::get_huid(i_target)); + + for( uint64_t l_loops = 0; l_loops < SBE_NUM_LOOPS; l_loops++ ) + { + (*o_sbeReg).reg = 0; + FAPI_INVOKE_HWP(l_errl, p9_get_sbe_msg_register, + l_fapi2_proc_target, (*o_sbeReg)); + if (l_errl) + { + SBE_TRACF("ERROR : call p9_get_sbe_msg_register, PLID=0x%x, " + "on loop %d", + l_errl->plid(), + l_loops ); + (*o_returnAction) = SBE_REG_RETURN::FUNCTION_ERROR; + break; + } + else if ((*o_sbeReg).currState == SBE_STATE_RUNTIME) + { + SBE_TRACF("SBE 0x%.8X booted and at runtime, o_sbeReg=0x%.8X, " + "on loop %d", + TARGETING::get_huid(i_target), (*o_sbeReg).reg, + l_loops); + (*o_returnAction) = SBE_REG_RETURN::SBE_AT_RUNTIME; + break; + } + else if ((*o_sbeReg).asyncFFDC) + { + SBE_TRACF("SBE 0x%.8X has async FFDC bit set, o_sbeReg=0x%.8X", + TARGETING::get_huid(i_target), (*o_sbeReg).reg); + // Async FFDC is indicator that SBE is failing to boot, and if + // in DUMP state, that SBE is done dumping, so leave loop + break; + } + else + { + if( !(l_loops % 10) ) + { + SBE_TRACF("%d> SBE 0x%.8X NOT booted yet, o_sbeReg=0x%.8X", + l_loops, TARGETING::get_huid(i_target), + (*o_sbeReg).reg); + } + l_loops++; + nanosleep(0,SBE_WAIT_SLEEP); + } + } + + if ((*o_sbeReg).currState != SBE_STATE_RUNTIME) + { + // Switch to using FSI SCOM + TARGETING::ScomSwitches l_switches = + i_target->getAttr<TARGETING::ATTR_SCOM_SWITCHES>(); + TARGETING::ScomSwitches l_switches_before = l_switches; + + // Turn off SBE SCOM and turn on FSI SCOM. + l_switches.useFsiScom = 1; + l_switches.useSbeScom = 0; + + SBE_TRACF("sbe_timeout_handler: changing SCOM switches from 0x%.2X " + "to 0x%.2X for proc 0x%.8X", + l_switches_before, + l_switches, + TARGETING::get_huid(i_target)); + i_target->setAttr<TARGETING::ATTR_SCOM_SWITCHES>(l_switches); + } + + return l_errl; +} + +P9_EXTRACT_SBE_RC::RETURN_ACTION action_for_ffdc_rc(uint32_t i_rc) +{ + P9_EXTRACT_SBE_RC::RETURN_ACTION l_action; + + switch(i_rc) + { + case fapi2::RC_EXTRACT_SBE_RC_RUNNING: + case fapi2::RC_EXTRACT_SBE_RC_NEVER_STARTED: + case fapi2::RC_EXTRACT_SBE_RC_PROGRAM_INTERRUPT: + case fapi2::RC_EXTRACT_SBE_RC_ADDR_NOT_RECOGNIZED: + case fapi2::RC_EXTRACT_SBE_RC_PIBMEM_ECC_ERR_INSECURE_MODE: + case fapi2::RC_EXTRACT_SBE_RC_FI2CM_BIT_RATE_ERR: + case fapi2::RC_EXTRACT_SBE_RC_PIBMEM_ECC_ERR: + + l_action = P9_EXTRACT_SBE_RC::RESTART_SBE; + + break; + + case fapi2::RC_EXTRACT_SBE_RC_MAGIC_NUMBER_MISMATCH: + case fapi2::RC_EXTRACT_SBE_RC_FI2C_ECC_ERR_INSECURE_MODE: + case fapi2::RC_EXTRACT_SBE_RC_FI2C_ECC_ERR: + + l_action = P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM; + + break; + + case fapi2::RC_EXTRACT_SBE_RC_FI2C_ERROR: + case fapi2::RC_EXTRACT_SBE_RC_FI2C_TIMEOUT: + case fapi2::RC_EXTRACT_SBE_RC_UNKNOWN_ERROR: + + l_action = P9_EXTRACT_SBE_RC::REIPL_BKP_SEEPROM; + + break; + + case fapi2::RC_EXTRACT_SBE_RC_OTP_TIMEOUT: + case fapi2::RC_EXTRACT_SBE_RC_OTP_PIB_ERR: + case fapi2::RC_EXTRACT_SBE_RC_PIBMEM_PIB_ERR: + case fapi2::RC_EXTRACT_SBE_RC_FI2C_SPRM_CFG_ERR: + case fapi2::RC_EXTRACT_SBE_RC_FI2C_PIB_ERR: + + l_action = P9_EXTRACT_SBE_RC::RESTART_CBS; + + break; + + case fapi2::RC_EXTRACT_SBE_RC_OTP_ECC_ERR_INSECURE_MODE: + case fapi2::RC_EXTRACT_SBE_RC_BRANCH_TO_SEEPROM_FAIL: + case fapi2::RC_EXTRACT_SBE_RC_UNEXPECTED_OTPROM_HALT: + case fapi2::RC_EXTRACT_SBE_RC_OTP_ECC_ERR: + default: + + l_action = P9_EXTRACT_SBE_RC::NO_RECOVERY_ACTION; + + break; + } + + return l_action; +} + +bool sbe_get_ffdc_handler(TARGETING::Target * i_target) +{ + bool l_flowCtrl = false; + errlHndl_t l_errl = nullptr; + uint32_t l_responseSize = SbeFifoRespBuffer::MSG_BUFFER_SIZE; + uint32_t *l_pFifoResponse = + reinterpret_cast<uint32_t *>(malloc(l_responseSize)); + + l_errl = getFifoSBEFFDC(i_target, + l_pFifoResponse, + l_responseSize); + + // Check if there was an error log created + if(l_errl) + { + // Trace but otherwise silently ignore error + SBE_TRACF("sbe_get_ffdc_handler: ignoring error PLID=0x%x from " + "get SBE FFDC FIFO request to proc 0x%.8X", + l_errl->plid(), + TARGETING::get_huid(i_target)); + delete l_errl; + l_errl = nullptr; + } + else + { + // Parse the FFDC package(s) in the response + SbeFFDCParser * l_ffdc_parser = + new SbeFFDCParser(); + l_ffdc_parser->parseFFDCData(reinterpret_cast<void *>(l_pFifoResponse)); + + uint8_t l_pkgs = l_ffdc_parser->getTotalPackages(); + P9_EXTRACT_SBE_RC::RETURN_ACTION l_action; + + // If there are FFDC packages, make a log for FFDC from SBE + if(l_pkgs > 0) + { + /*@ + * @errortype + * @moduleid SBEIO_GET_FFDC_HANDLER + * @reasoncode SBEIO_RETURNED_FFDC + * @userdata1 Processor Target + * @userdata2 Number of FFDC packages + * @devdesc FFDC returned by SBE after failing to reach runtime + * @custdesc FFDC associated with boot device failing to boot + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_GET_FFDC_HANDLER, + SBEIO_RETURNED_FFDC, + TARGETING::get_huid(i_target), + l_pkgs); + + // Also log the failing proc as FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl); + } + + // Process each FFDC package + for(auto i=0; i<l_pkgs; i++) + { + // Add each package to the log + l_errl->addFFDC( SBEIO_COMP_ID, + l_ffdc_parser->getFFDCPackage(i), + l_ffdc_parser->getPackageLength(i), + 0, + SBEIO_UDT_PARAMETERS, + false ); + + // Get the RC from the FFDC package + uint32_t l_rc = l_ffdc_parser->getPackageRC(i); + + // Determine an action for the RC + l_action = action_for_ffdc_rc(l_rc); + + // Handle that action + proc_extract_sbe_handler(i_target, + l_action); + } + + // If there are FFDC packages, commit the log + if(l_pkgs > 0) + { + l_errl->collectTrace( SBEIO_COMP_NAME, KILOBYTE/4); + l_errl->collectTrace( "ISTEPS_TRACE", KILOBYTE/4); + + errlCommit(l_errl, ISTEP_COMP_ID); + } + + delete l_ffdc_parser; + l_ffdc_parser = nullptr; + + l_flowCtrl = true; + } + + free(l_pFifoResponse); + l_pFifoResponse = nullptr; + + return l_flowCtrl; +} + +void sbe_boot_fail_handler(TARGETING::Target * i_target, + sbeMsgReg_t i_sbeReg) +{ + errlHndl_t l_errl = nullptr; + + SBE_TRACF("SBE 0x%.8X never started, sbeReg=0x%.8X", + TARGETING::get_huid(i_target),i_sbeReg.reg ); + /*@ + * @errortype + * @reasoncode SBEIO_SLAVE_TIMEOUT + * @severity ERRORLOG::ERRL_SEV_INFORMATIONAL + * @moduleid SBEIO_EXTRACT_RC_HANDLER + * @userdata1 HUID of proc which had SBE timeout + * @userdata2 SBE MSG Register + * + * @devdesc Slave SBE did not get to ready state within + * allotted time + * + * @custdesc A processor in the system has failed to initialize + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + SBEIO_EXTRACT_RC_HANDLER, + SBEIO_SLAVE_TIMEOUT, + TARGETING::get_huid(i_target), + i_sbeReg.reg); + + l_errl->collectTrace( "ISTEPS_TRACE", KILOBYTE/4); + + // Commit error and continue, this is not terminating since + // we can still at least boot with master proc + errlCommit(l_errl,ISTEP_COMP_ID); + + // Setup for the HWP + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_fapi2ProcTarget( + const_cast<TARGETING::Target*> (i_target)); + P9_EXTRACT_SBE_RC::RETURN_ACTION l_rcAction = + P9_EXTRACT_SBE_RC::REIPL_UPD_SEEPROM; + FAPI_INVOKE_HWP(l_errl, p9_extract_sbe_rc, + l_fapi2ProcTarget, l_rcAction); + + if(l_errl) + { + SBE_TRACF("ERROR : sbe_boot_fail_handler : " + "p9_extract_sbe_rc HWP returning errorlog " + "PLID=0x%x",l_errl->plid()); + + // capture the target data in the elog + ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog( l_errl ); + + // Commit error log + errlCommit( l_errl, HWPF_COMP_ID ); + + } + else if(l_rcAction != P9_EXTRACT_SBE_RC::ERROR_RECOVERED) + { + + if(INITSERVICE::spBaseServicesEnabled()) + { + // When we are on an FSP machine, we want to fail out of + // hostboot and give control back to the FSP. They have + // better diagnostics for this type of error. + INITSERVICE::doShutdownWithError(SBEIO_HWSV_COLLECT_SBE_RC, + TARGETING::get_huid(i_target)); + } + + // Save the current rc error + (i_target)->setAttr<TARGETING::ATTR_PREVIOUS_SBE_ERROR>(l_rcAction); +#ifdef CONFIG_BMC_IPMI + // This could potentially take awhile, reset watchdog + l_errl = IPMIWATCHDOG::resetWatchDogTimer(); + if(l_errl) + { + SBE_TRACF("sbe_boot_fail_handler " + "Resetting watchdog before sbe_handler"); + l_errl->collectTrace("ISTEPS_TRACE",KILOBYTE/4); + errlCommit(l_errl,ISTEP_COMP_ID); + } +#endif + proc_extract_sbe_handler( i_target, + l_rcAction); + } + + return; +} + +errlHndl_t switch_sbe_sides(TARGETING::Target * i_target) +{ + errlHndl_t l_errl = NULL; + fapi2::buffer<uint32_t> l_read_reg; + const uint32_t l_sbeBootSelectMask = SBE::SBE_BOOT_SELECT_MASK >> 32; + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + l_fapi2_proc_target(i_target); + + // Read version from MVPD for target proc + SBE::mvpdSbKeyword_t l_mvpdSbKeyword; + l_errl = getSetMVPDVersion(i_target, + SBE::MVPDOP_READ, + l_mvpdSbKeyword); + if(l_errl) + { + SBE_TRACF("Failure to getSetMVPDVersion"); + return l_errl; + } + + fapi2::ReturnCode l_fapi_rc = fapi2::getCfamRegister( + l_fapi2_proc_target, PERV_SB_CS_FSI, + l_read_reg); + if(!l_fapi_rc.isRC(0)) + { + l_errl = fapi2::rcToErrl(l_fapi_rc); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + l_errl->collectTrace(FAPI_TRACE_NAME,384); + + SBE_TRACF("Failure to getCfamRegister"); + return l_errl; + } + + // Determine boot side from flags in MVPD + bool l_bootSide0 = (SBE::isIplFromReIplRequest()) + ? (SBE::REIPL_SEEPROM_0_VALUE == (l_mvpdSbKeyword.flags + & SBE::REIPL_SEEPROM_MASK)) + : (SBE::SEEPROM_0_PERMANENT_VALUE == (l_mvpdSbKeyword.flags + & SBE::PERMANENT_FLAG_MASK)); + if(l_bootSide0) + { + // Set Boot Side 0 by clearing bit for side 1 + l_read_reg &= ~l_sbeBootSelectMask; + } + else + { + // Set Boot Side 1 by setting bit for side 1 + l_read_reg |= l_sbeBootSelectMask; + } + + l_fapi_rc = fapi2::putCfamRegister(l_fapi2_proc_target, + PERV_SB_CS_FSI, l_read_reg); + if(!l_fapi_rc.isRC(0)) + { + l_errl = fapi2::rcToErrl(l_fapi_rc); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + l_errl->collectTrace(FAPI_TRACE_NAME,384); + + SBE_TRACF("Failure to putCfamRegister"); + return l_errl; + } + + return l_errl; +} + + |