/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/include/usr/sbeio/sbe_retry_handler.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2017,2018 */ /* [+] 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 */ #ifndef __SBE_RETRY_HANDLER_H #define __SBE_RETRY_HANDLER_H #include #include #include #include namespace SBEIO { class SbeRetryHandler { public: enum SBE_REG_RETURN { FAILED_COLLECTING_REG = 0, // Error returned from HWP SBE_AT_RUNTIME = 1, // SBE is at runtime and booted SBE_NOT_AT_RUNTIME = 2, // SBE has failed to boot PROC_DECONFIG = 3, // Deconfig done on Proc with SBE }; //Possible values of iv_sbeMode enum SBE_MODE_OF_OPERATION { INFORMATIONAL_ONLY = 0, // Get error logs from the SBE HWP's // This will not attempt an SBE restart // On FSP systems if informational mode is set we will TI // On BMC systems we will run extract_rc then bail out ATTEMPT_REBOOT = 1, // Full SBE run, attempt to restart // This will run all the steps and HWP's to attempt // an SBE restart on both sides. }; enum SBE_RESTART_METHOD { START_CBS = 0, // Use p9_start_cbs to restart the SBE HRESET = 1, // Use Hreset to restart the SBE }; /** * @brief Constructor * * @param[in] i_sbeMode Execute the SbeRetryHandler in either * informational mode, attempt to reboot mode, * or action set mode. * (@see sbe_retry_handler.H) */ explicit SbeRetryHandler(SBE_MODE_OF_OPERATION i_sbeMode); /** * @brief Constructor * * @param[in] i_sbeMode Execute the SbeRetryHandler in either * informational mode, attempt to reboot mode, * or action set mode. * (@see sbe_retry_handler.H) * @param[in] i_plid A PLID that is to be propagated down to any * Error Log Entries that may be created */ SbeRetryHandler(SBE_MODE_OF_OPERATION i_sbeMode, uint32_t i_plid); /** * @brief Destructor */ ~SbeRetryHandler(); /**************** Functions to return Class Elements ****************/ inline bool isSbeAtRuntime() { return (iv_currentSBEState == SbeRetryHandler::SBE_REG_RETURN::SBE_AT_RUNTIME); } inline uint32_t getCallerPLID() { return iv_callerErrorLogPLID; } inline uint8_t getSwitchCount() { return iv_switchSidesCount; } inline sbeMsgReg_t getSbeRegister() { return iv_sbeRegister; } inline P9_EXTRACT_SBE_RC::RETURN_ACTION getCurrentAction() { return iv_currentAction; } inline SBE_REG_RETURN getCurrentSBEState() { return iv_currentSBEState; } inline SBE_RESTART_METHOD getSbeRestartMethod() { return iv_sbeRestartMethod; } inline void setSbeRestartMethod(SBE_RESTART_METHOD i_method) { iv_sbeRestartMethod = i_method; } inline SBE_MODE_OF_OPERATION getSBEMode() { return iv_sbeMode; } inline void setSBEMode(SBE_MODE_OF_OPERATION i_sbeMode) { iv_sbeMode = i_sbeMode; } inline bool getUseSDB() { return iv_useSDB; } inline void setUseSDB(bool i_useSDB) { iv_useSDB = i_useSDB; } inline bool getSecureModeDisabled() { return iv_secureModeDisabled; } inline void setSecureModeDisabled(bool i_secureModeDisabled) { iv_secureModeDisabled = i_secureModeDisabled; } inline void setInitialPowerOn(bool i_isInitialPowerOn) { iv_initialPowerOn = i_isInitialPowerOn; } /** * @brief This function is the main entry point for all of the * SBE handler functions. * * @param[in] i_target - current proc target */ void main_sbe_handler( TARGETING::Target * i_target); private: #ifndef __HOSTBOOT_RUNTIME /** * @brief This function will look at the SBE status register and decide * whether to send the SBEIO_DEAD_SBE or SBEIO_HWSV_COLLECT_SBE_RC * along with the TI depending on if the asyncFFDC bit is set in * the status register * * @param[in] i_target - current proc target we are handling fail for * * @return - void */ void handleFspIplTimeFail(TARGETING::Target * i_target); #endif /** * @brief There are 8 scratch registers that the SBE will look at during initialization. After we bring up the slave SBE in istep 8, hostboot will begin to repurpose these registers. If we restart the SBE during runtime with HRESET the SBE will look at these registers which hostboot has repurposed. We do not want the SBE to use this data as it is no longer valid. If the registers are all zero's then the SBE will use data from its image. This will work because hostboot has customized the image with the correct values during the IPL. This function will zero out all of the scratch registers to make sure the SBE uses its own copy of the values it is looking for in these registers. * * @param[in] i_target - Proc we are clearing scratch regs for */ errlHndl_t clearSbeScratchRegisters(TARGETING::Target * i_target); /** * @brief This function will look at what iv_currentAction is set to * and take into account how many times we have tried to boot * and how many times we have switched sides. * Note: no_recovery is only an acceptable answer if we have tried * all possibilities. That means that we must have attempted * two boots on both sides. If we have not hit our max attempts * for both sides then this procedure should change iv_currentAction * to either RESTART_SBE or REIPL_BKP_SEEPROM * * * @return - void */ void bestEffortCheck(); /** * @brief This function handles the SBE timeout and loops * required to start it. * * @param[in] i_target - current proc target * * @return - error, NULL if no error */ errlHndl_t sbe_poll_status_reg(TARGETING::Target * i_target); /** * @brief This function handles getting the SBE FFDC. * * @param[in] i_target - current proc target * * @return - bool for flow control on return to caller, if false, * caller should go on with the processing flow, if true, * caller should interrupt the processing flow and get out * of loop or current iteration */ void sbe_get_ffdc_handler(TARGETING::Target * i_target); /** * @brief This function handles the SBE failed to boot error. * * @param[in] i_target - current proc target * * @return - bool: true if we need to retry * * Note: This will default to calling the 2 param version w/ i_hideLog * set to TRUE */ void sbe_run_extract_rc(TARGETING::Target * i_target); /** * @brief This function deals with the mask needed to switch * boot side on the SBE for a given proc * * @param[in] i_target - current proc target * * @return - error, NULL if no error */ errlHndl_t switch_sbe_sides(TARGETING::Target * i_target); /** * @brief This is the switch case that identifies the action needed * for the RC value in an SBE FFDC package. * * @param[in] i_rc - RC value from SBE FFDC package * * @return - pass(0) or specific returned SBE action */ uint32_t action_for_ffdc_rc( uint32_t i_rc); /** * @brief This function handles the call to the p9_get_sbe_msg_handler. * It will read the sbe msg register (Cfam 2809 or Scom 50009) * and update iv_currentSBEState to reflect the state that * the sbe's msg register is telling us * * @param[in] i_target - current proc target * * @return - return true if reading the message register was a success * return false if there was an error getting the sbe msg register */ bool sbe_run_extract_msg_reg(TARGETING::Target * i_target); /************************** Class Elements **************************/ /* * @brief Bit used to tell if we are in secure debug mode. This means * we are expecting a complete restart so it is safe to perform * some extra operations. */ bool iv_useSDB; /* * @brief Bit used for testing in the lab with systems that have secure * mode disabled. * NOTE: This bit is only used in the lab when running this HWP with cronus. * We offered to have this bit set in FW based on the security settings of the * system HW people told us it would be safer for us to always assume this bit * is off in FW, so we will leave this bit as 0 until the HW devs tell us to use it. */ bool iv_secureModeDisabled; /* * @brief PLID of the caller. 0 if caller does not * provide one. Not to be confused with the * PLID when error log is created in the usage * of this class. */ uint32_t iv_callerErrorLogPLID; /* * @brief Number of times we switch SBE sides. Max is defined by * MAX_SWITCH_SIDE_COUNT */ uint8_t iv_switchSidesCount; /* * @brief The current sbe register */ sbeMsgReg_t iv_sbeRegister; /* * @brief The current SBE return action that has to be taken */ P9_EXTRACT_SBE_RC::RETURN_ACTION iv_currentAction; /* * @brief The current SBE state - booted, failed, or deconfig */ SBE_REG_RETURN iv_currentSBEState; /* * @brief Currently there are 3 options for what the shutdownReturnCode * will be. It can be 0 if there is no return code we wish to * send with shutdown. Then it can also be SBEIO_HWSV_COLLECT_SBE_RC * to notify that HWSV should collect FFDC or it can be SBEIO_DEAD_SBE * to tell HWSV that the SBE is dead. */ uint32_t iv_shutdownReturnCode; /* * @brief This value will keep track of how many times we have attempted * to boot the current side of the SBE's seeprom. In the ctor this * value should be 1, because if the retry handler has been called * that means that we have attempted to boot the current side at * least 1 time. When we switch seeprom sides this value should * drop back to 0. It will be incremeted each time we attempt * to call start_cbs or hreset depending on iv_sbeRestartMethod */ uint8_t iv_currentSideBootAttempts; /* * @brief If the asyncFFDC bit is found to be set on the status register * this indicates to hostboot that the SBE was able to collect * FFDC about what went wrong in its attempt to boot itself * in this case Hostboot will send a FIFO chip op to the SBE * so the SBE will write the FFDC data out to memory where * Hostboot can parse it. Note that after the SBE writes * the data to memory the asyncFFDC bit on the status register * will be off. */ bool iv_ffdcSetAction; /* * @brief The mode of operation that needs to be run through the * SbeRetryHandler. The different modes are specified in the * SBE_MODE_OF_OPERATION enum */ SBE_MODE_OF_OPERATION iv_sbeMode; /* * @brief This instance variable will instruct the main_sbe_handler * loop on what method to use when attempting to restart the * sbe that we have detected an error on. Currently there are * two options to recover an sbe in a bad state. The first option * is to run "start_cbs", this essentially powers down the proc * and starts the boot sequence from the beginning. This is okay * to use when initially trying to poweron slave processor's sbe * but it is not as useful after that as it will blow away any fabric * initialization we have done on the slave proc chip. The other * option is to use HRESET. HRESET will attempt to restart the * sbe on the fly and does not require us to completely restart * the processor. HRESET can be used during runtime to attempt * to recover an sbe while not disrupting the rest of the proc * chips. Both choices are noted in the SBE_RESTART_METHOD enum */ SBE_RESTART_METHOD iv_sbeRestartMethod; /* * @brief If true, this tells the retry_hanlder that the caller has recently * attempted to boot the sbe on processor passed to the ctor. This * tells us that the sbe_status register is not stale and that we * can use the curState value on the status register to determine * if the SBE made it to runtime or not */ bool iv_initialPowerOn; }; // End of class SbeRetryHandler } // End of namespace SBEIO #endif