diff options
author | Rick Ward <rward15@us.ibm.com> | 2018-04-25 08:52:31 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2018-06-05 14:00:46 -0400 |
commit | b364d7b062bfa33c715364eca9654c878c4f6a62 (patch) | |
tree | cbb6c7dec3bf50b27b8eba2ff499f14ecbc9a00d /src/usr/util/runtime/rt_cmds.C | |
parent | 41f3aa61a7e97de134cffd04ebbbbb286424c3cb (diff) | |
download | talos-hostboot-b364d7b062bfa33c715364eca9654c878c4f6a62.tar.gz talos-hostboot-b364d7b062bfa33c715364eca9654c878c4f6a62.zip |
Centaur Channel Checkstop (runtime)
This story covers when a DMI channel gets checkstopped at runtime
and how to service the subsequent SCOM operations that PRD
requests to diagnose the issue. At runtime, PRD makes all of
its SCOM requests to HBRT which passes them on to PHYP for
in-band access. The checkstop blocks in-band access, so HBRT
must fail-over to messaging the FSP to do FSI accesses.
To reduce the number of SCOM calls to the FSP, HBRT makes
a "multi-SCOM read" call for all the common SCOMs that
PRD will request after a checkstop, and caches the results.
Two new calls (MBOX, generic messaging interface) to the FSP
were added in a previous commit to allow FSI SCOM operations
through the FSP:
- MSG_SINGLE_SCOM_OP
- MSG_MULTI_SCOM_OP
Also, a new map, chnlFailScomList, was added in a previous
commit. chnlFailScomList contains a list of target types
and associated SCOM addresses that PRD is likely want to
read after a checkstop. PRD is responsible for maintaining
the contents.
Change-Id: I829a72067007ac8a61d80caa690d8eedee0f08cc
RTC:189294
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/59197
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr/util/runtime/rt_cmds.C')
-rw-r--r-- | src/usr/util/runtime/rt_cmds.C | 222 |
1 files changed, 221 insertions, 1 deletions
diff --git a/src/usr/util/runtime/rt_cmds.C b/src/usr/util/runtime/rt_cmds.C index e350e42dc..ce7df1daf 100644 --- a/src/usr/util/runtime/rt_cmds.C +++ b/src/usr/util/runtime/rt_cmds.C @@ -43,6 +43,9 @@ #include <isteps/pm/pm_common_ext.H> #include <p9_hcd_memmap_base.H> // for reload_pm_complex #include <p9_stop_data_struct.H> // for reload_pm_complex +#include <scom/runtime/rt_scomif.H> // sendScomOpToFsp, + // sendMultiScomReadToFsp, + // switchToFspScomAccess extern char hbi_ImageId; @@ -994,6 +997,158 @@ void cmd_hbrt_update(char*& o_output) /** + * @brief Mark a target as requiring access to its SCOMs through the FSP + * @param[out] o_output Output display buffer, memory allocated here + * @param[in] i_huid HUID associated with Target to switch access on + */ +void cmd_switchToFspScomAccess( char*& o_output, uint32_t i_huid) +{ + UTIL_FT( "cmd_switchToFspScomAccess> huid=%.8X", i_huid ); + + TARGETING::Target* l_targ{}; + + if(0xFFFFFFFF == i_huid) + { + TARGETING::targetService().getTopLevelTarget(l_targ); + } + else + { + l_targ = getTargetFromHUID(i_huid); + } + + o_output = new char[100]; + if( l_targ == NULL ) + { + sprintf( o_output, "HUID %.8X not found", i_huid ); + return; + } + + FSISCOM::switchToFspScomAccess(l_targ); + + sprintf( o_output, "switchToFspScomAccess executed"); +} + + +/** + * @brief Send a scom operation (read/write) to the FSP + * @param[out] o_output Output display buffer, memory allocated here + * @param[in] i_op Operation: r or w + * @param[in] i_huid HUID associated with Target to get the SCOM from + * @param[in] i_scomAddr Address of SCOM to read or write + * @param[in] io_scomValue Buffer for read SCOM value, or value to write + */ +void cmd_sendScomOpToFSP( char*& o_output, + char i_op, + uint32_t i_huid, + uint64_t i_scomAddr, + uint64_t *io_scomValue ) +{ + UTIL_FT( "cmd_getScomFromFSP> op=%c, huid=%.8X, addr=%.8X, size=%d", + i_op, i_huid, i_scomAddr, *io_scomValue ); + + TARGETING::Target* l_targ{}; + + if(0xFFFFFFFF == i_huid) + { + TARGETING::targetService().getTopLevelTarget(l_targ); + } + else + { + l_targ = getTargetFromHUID(i_huid); + } + + o_output = new char[100]; + if( l_targ == NULL ) + { + sprintf( o_output, "HUID %.8X not found", i_huid ); + return; + } + + DeviceFW::OperationType l_op; + switch (i_op) { + case 'r': + case 'R': + l_op = DeviceFW::READ; + break; + case 'w': + case 'W': + l_op = DeviceFW::WRITE; + break; + default: + sprintf( o_output, "Operation must be r or w: %c", i_op ); + return; + } + + errlHndl_t l_err = nullptr; + l_err = FSISCOM::sendScomOpToFsp(l_op, l_targ, i_scomAddr, + (void *)io_scomValue); + if (l_err) + { + sprintf( o_output, "Error on call to sendScomOpToFsp, rc=%.4X", + ERRL_GETRC_SAFE(l_err) ); + return; + } + + sprintf( o_output, "op=%c, huid=%.16llX, scomAddr=%.16llX, scomValue=%.16llX", + i_op, i_huid, i_scomAddr, *io_scomValue); +} + + +/** + * @brief Send a multi scom read to the FSP + * @param[out] o_output Output display buffer, memory allocated here + * @param[in] i_huid HUID associated with Target to get the SCOMs from + * @param[in] i_scomAddr Addresses of SCOMs to read + * @param[in] o_scomValue Values of read SCOMs + */ +void cmd_sendMultiScomReadToFSP( char* &o_output, + uint32_t i_huid, + std::vector<uint64_t> &i_scomAddr, + std::vector<uint64_t> &o_scomValue ) +{ + UTIL_FT( "cmd_sendMultiScomReadToFSP> huid=%.8X, num_SCOMs=%d," + " num_outSCOMs=%d", + i_huid, i_scomAddr.size(), o_scomValue.size() ); + + TARGETING::Target* l_targ{}; + + if(0xFFFFFFFF == i_huid) + { + TARGETING::targetService().getTopLevelTarget(l_targ); + } + else + { + l_targ = getTargetFromHUID(i_huid); + } + + o_output = new char[500]; + if( l_targ == NULL ) + { + sprintf( o_output, "HUID %.8X not found", i_huid ); + return; + } + + errlHndl_t l_err = nullptr; + l_err = FSISCOM::sendMultiScomReadToFsp( l_targ, i_scomAddr, o_scomValue); + if (l_err) + { + sprintf( o_output, "Error on call to sendMultiScomReadToFsp," + " rc=%.4X", ERRL_GETRC_SAFE(l_err) ); + return; + } + + sprintf( o_output, "num_outSCOMs=%d", o_scomValue.size()); + for (auto scom: o_scomValue) + { + char tmp_str[100]; + + sprintf( tmp_str, ", %.8llX", scom); + strcat( o_output, tmp_str); + } +} + + +/** * @brief Execute an arbitrary command inside Hostboot Runtime * @param[in] Number of arguments (standard C args) * @param[in] Array of argument values (standard C args) @@ -1254,9 +1409,67 @@ int hbrtCommand( int argc, "ERROR: hbrt_update\n" ); } } + else if( !strcmp( argv[0], "switchToFspScomAccess" ) ) + { + if (argc == 2) + { + cmd_switchToFspScomAccess( *l_output, + strtou64(argv[1], NULL, 16)); // huid + } + else + { + *l_output = new char[100]; + sprintf(*l_output, + "ERROR: switchToFspScomAccess <huid>"); + } + } + else if( !strcmp( argv[0], "scomOpToFsp" ) ) + { + if ((argc == 4) || (argc == 5)) + { + uint64_t l_scomValue = 0; + + if (argc == 5) + l_scomValue = strtou64( argv[4], NULL, 16 ); // value + + cmd_sendScomOpToFSP( *l_output, + argv[1][0], // op + strtou64(argv[2], NULL, 16), // huid + strtou64(argv[3], NULL, 16), // addr + &l_scomValue ); + } + else + { + *l_output = new char[100]; + sprintf(*l_output, + "ERROR: scomOpToFsp <op> <huid> <scomAddr> [<scomValue>]"); + } + } + else if( !strcmp( argv[0], "multiScomReadToFsp" ) ) + { + if (argc >= 3) + { + std::vector<uint64_t> l_scomAddrs, l_scomValues; + + for (int i = 2;i < argc;++i) + l_scomAddrs.push_back(strtou64( argv[i], NULL, 16 )); + l_scomValues.reserve(argc - 2); + + cmd_sendMultiScomReadToFSP( *l_output, + strtou64(argv[1], NULL, 16), // huid + l_scomAddrs, + l_scomValues ); + } + else + { + *l_output = new char[100]; + sprintf(*l_output, + "ERROR: multiScomReadToFsp <huid> <scomAddrs>"); + } + } else { - *l_output = new char[50+100*10]; + *l_output = new char[50+100*12]; char l_tmpstr[100]; sprintf( *l_output, "HBRT Commands:\n" ); sprintf( l_tmpstr, "testRunCommand <args...>\n" ); @@ -1283,6 +1496,13 @@ int hbrtCommand( int argc, strcat( *l_output, l_tmpstr ); sprintf( l_tmpstr, "hbrt_update\n"); strcat( *l_output, l_tmpstr ); + sprintf( l_tmpstr, "switchToFspScomAccess <huid>\n"); + strcat( *l_output, l_tmpstr ); + sprintf( l_tmpstr, "scomOpToFsp <op> <huid> <scomAddr> [<scomValue>]\n" + " <op> == r|w\n"); + strcat( *l_output, l_tmpstr ); + sprintf( l_tmpstr, "multiScomReadToFsp <huid> <scomAddrs>\n"); + strcat( *l_output, l_tmpstr ); } if( l_traceOut && (*l_output != NULL) ) |