diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2018-09-06 13:31:35 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-11-09 09:30:00 -0600 |
commit | 40039bb5fddf5efd1b01429ef011b68be999dce3 (patch) | |
tree | d509be93e473fc292bd51658b377954785d1117a /src/usr/scom | |
parent | fffa79ecb0c701ee029eae8ffb33483701e4c117 (diff) | |
download | talos-hostboot-40039bb5fddf5efd1b01429ef011b68be999dce3.tar.gz talos-hostboot-40039bb5fddf5efd1b01429ef011b68be999dce3.zip |
Extend multicast workaround and add tests
- Add support for multicast OR op type
- Add xscom and scom multicast tests
- Avoid false fails by not setting multicast bit in bad address tests
Change-Id: I32ea5b1b68a1a2f0d92c2b82b5ab1b932ddb54af
RTC:198114
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/65778
Tested-by: Jenkins Server <pfd-jenkins+hostboot@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>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/scom')
-rw-r--r-- | src/usr/scom/scom.C | 257 | ||||
-rw-r--r-- | src/usr/scom/test/scomtest.H | 26 |
2 files changed, 189 insertions, 94 deletions
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C index 2dcf4a3c0..1a4ba857f 100644 --- a/src/usr/scom/scom.C +++ b/src/usr/scom/scom.C @@ -362,7 +362,7 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, SCOM_INVALID_FORM, i_addr, get_huid(i_target), - true /*Add HB Software Callout*/); + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } @@ -786,7 +786,7 @@ errlHndl_t doForm1IndirectScom(DeviceFW::OperationType i_opType, SCOM_FORM_1_READ_REQUEST, i_addr, i_opType, - true /*Add HB SW Callout*/); + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } @@ -811,7 +811,7 @@ errlHndl_t doForm1IndirectScom(DeviceFW::OperationType i_opType, SCOM_FORM_1_INVALID_DATA, i_addr, l_io_buffer, - true /*Add HB SW Callout*/); + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } @@ -1269,12 +1269,16 @@ errlHndl_t doMulticastWorkaround( DeviceFW::OperationType i_opType, errlHndl_t l_err = nullptr; uint64_t* l_summaryReg = reinterpret_cast<uint64_t*>(io_buffer); - constexpr uint64_t IS_MULTICAST = 0x40000000; - constexpr uint64_t MULTICAST_GROUP = 0x07000000; - constexpr uint64_t IS_PCBSLAVE = 0x000F0000; - constexpr uint64_t CHIPLET_BYTE = 0xFF000000; - constexpr uint64_t MULTICAST_OP = 0x38000000; + // Some masks for parsing the address + constexpr uint64_t IS_MULTICAST = 0x40000000; + constexpr uint64_t MULTICAST_GROUP = 0x07000000; + constexpr uint64_t GROUP_ZERO = 0x00000000; + constexpr uint64_t GROUP_ONE = 0x01000000; + constexpr uint64_t IS_PCBSLAVE = 0x000F0000; + constexpr uint64_t CHIPLET_BYTE = 0xFF000000; + constexpr uint64_t MULTICAST_OP = 0x38000000; constexpr uint64_t MULTICAST_OP_BITWISE = 0x10000000; + constexpr uint64_t MULTICAST_OP_OR = 0x00000000; #ifndef __HOSTBOOT_RUNTIME // Some P9-specific chiplet values to make things more efficient @@ -1286,108 +1290,177 @@ errlHndl_t doMulticastWorkaround( DeviceFW::OperationType i_opType, constexpr uint64_t P9_LAST_EC = 0x3F; #endif - // Skip calls to the SENTINEL since we don't have the - // ability to find its children - if( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL - == i_target ) - { - o_didWorkaround = false; - return nullptr; - } + o_didWorkaround = false; - // Only perform this workaround for: - // - reads - // - multicast registers - // - scom is not part of pcb slave - // - multicast read option XXX 'bit-wise' - // - multicast group0 'all functional chiplets' - if( !((DeviceFW::READ == i_opType) - && ((IS_MULTICAST & i_addr) == IS_MULTICAST) - && ((IS_PCBSLAVE & i_addr) != IS_PCBSLAVE) - && ((MULTICAST_OP & i_addr) == MULTICAST_OP_BITWISE) - && ((MULTICAST_GROUP & i_addr) == 0)) ) + do { - o_didWorkaround = false; - return nullptr; - } - TRACFCOMP( g_trac_scom, "doMulticastWorkaround on %.8X for %.8X", TARGETING::get_huid(i_target), i_addr ); - // Loop around every functional pervasive target - TARGETING::TargetHandleList l_chiplets; - TARGETING::getChildChiplets( l_chiplets, - i_target, - TARGETING::TYPE_PERV, - true ); - for( auto l_chiplet : l_chiplets ) - { - uint64_t l_data = 0; - uint64_t l_addr = (i_addr & ~CHIPLET_BYTE); - uint64_t l_unit = l_chiplet->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + // Skip calls to the SENTINEL since we don't have the + // ability to find its children + if( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL == i_target ) + { + break; + } -#ifndef __HOSTBOOT_RUNTIME - // filter out some chiplets that aren't running yet - if( !g_useSlaveCores - && (((l_unit >= P9_FIRST_EQ) && (l_unit <= P9_LAST_EQ)) - || ((l_unit >= P9_FIRST_EC) && (l_unit <= P9_LAST_EC)) - ) - ) + bool l_opIsBitwise = false; + bool l_opIsOr = false; + bool l_groupIsZero = false; + bool l_groupIsOne = false; + + // Only perform this workaround for: + // - reads + // - multicast registers + // - scom is not part of pcb slave + if( (DeviceFW::READ == i_opType) + && ((IS_MULTICAST & i_addr) == IS_MULTICAST) + && ((IS_PCBSLAVE & i_addr) != IS_PCBSLAVE) ) { - // Only access the master ec/eq - static const TARGETING::Target* l_masterCore = - TARGETING::getMasterCore(); - uint64_t l_ecNum = - l_masterCore->getAttr<TARGETING::ATTR_CHIP_UNIT>(); - bool l_fused = TARGETING::is_fused_mode(); - if( !((l_unit == l_ecNum) //master - || (l_fused && (l_unit == l_ecNum+1))) ) //fused-pair + l_opIsBitwise = ((MULTICAST_OP & i_addr) == MULTICAST_OP_BITWISE); + l_opIsOr = ((MULTICAST_OP & i_addr) == MULTICAST_OP_OR); + l_groupIsZero = ((MULTICAST_GROUP & i_addr) == GROUP_ZERO); + l_groupIsOne = ((MULTICAST_GROUP & i_addr) == GROUP_ONE); + + // - multicast read option XXX 'bit-wise' + // - multicast read option XXX 'or' + // - multicast group0 'all functional chiplets' + // - multicast group1 'all functional cores' + if( (l_opIsBitwise || l_opIsOr) && + (l_groupIsZero || l_groupIsOne) ) { - continue; + TRACFCOMP( g_trac_scom, "doMulticastWorkaround on %.8X for %.8X", TARGETING::get_huid(i_target), i_addr ); } - auto l_eqNum = 0x10 + l_ecNum/4; - if( l_unit == l_eqNum ) + // Not a supported multicast op + else { - continue; + TRACFCOMP(g_trac_scom, "doMulticastWorkaround Multicast op has unsupported group 0x%X",(MULTICAST_OP & i_addr)); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_DO_MULTICAST_WORKAROUND + * @reasoncode SCOM::SCOM_UNSUPPORTED_MULTICAST_OP + * @userdata1 Address + * @userdata1 Target huid + * @devdesc Unsupported multicast op + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_DO_MULTICAST_WORKAROUND, + SCOM_UNSUPPORTED_MULTICAST_OP, + i_addr, + get_huid(i_target), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + break; } } - if( !g_useMemChiplets - && ((l_unit >= P9_FIRST_MC) && (l_unit <= P9_LAST_MC)) ) + // Common path when not a multicast op + else { - // Only access the mem chiplets if we're not in async mode - // because we don't start clocks until later on in that case - auto l_syncMode = - i_target->getAttr<TARGETING::ATTR_MC_SYNC_MODE>(); - if( l_syncMode == TARGETING::MC_SYNC_MODE_NOT_IN_SYNC ) - { - continue; - } + break; } -#endif - l_addr |= (l_unit << 24); - io_buflen = sizeof(uint64_t); - l_err = deviceOp(i_opType, - i_target, - &l_data, - io_buflen, - DEVICE_XSCOM_ADDRESS_NO_ERROR(l_addr)); - // just ignore any errors, we expect they will happen - if( l_err ) + TARGETING::TargetHandleList l_chiplets; + if( l_groupIsZero ) { - delete l_err; - l_err = nullptr; + // Get every functional pervasive target + TARGETING::getChildChiplets( l_chiplets, + i_target, + TARGETING::TYPE_PERV, + true ); } - // if any bits are set, set this unit's bit in summary reg - // note: this is good enough for the use-case we have now - // but a better implementation would be to actually - // check the select regs as well so we know which bit(s) - // are the trigger - else if( l_data & 0x8000000000000000 ) + else if( l_groupIsOne ) { - *l_summaryReg |= (0x8000000000000000 >> l_unit); + // Get every functional core target + TARGETING::getChildChiplets( l_chiplets, + i_target, + TARGETING::TYPE_CORE, + true ); } - } - o_didWorkaround = true; + // Loop through the chiplets, perform the xscom reads, combine results + for( auto l_chiplet : l_chiplets ) + { + uint64_t l_data = 0; + uint64_t l_addr = (i_addr & ~CHIPLET_BYTE); + // Use CHIPLET_ID for unit, is equal to CHIP_UNIT for TYPE_PERV + uint64_t l_unit = l_chiplet->getAttr<TARGETING::ATTR_CHIPLET_ID>(); + +#ifndef __HOSTBOOT_RUNTIME + // filter out some chiplets that aren't running yet + if( !g_useSlaveCores + && (((l_unit >= P9_FIRST_EQ) && (l_unit <= P9_LAST_EQ)) + || ((l_unit >= P9_FIRST_EC) && (l_unit <= P9_LAST_EC)) + ) + ) + { + // Only access the master ec/eq + static const TARGETING::Target* l_masterCore = + TARGETING::getMasterCore(); + uint64_t l_ecNum = + l_masterCore->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + bool l_fused = TARGETING::is_fused_mode(); + if( !((l_unit == l_ecNum) //master + || (l_fused && (l_unit == l_ecNum+1))) ) //fused-pair + { + continue; + } + auto l_eqNum = 0x10 + l_ecNum/4; + if( l_unit == l_eqNum ) + { + continue; + } + } + if( !g_useMemChiplets + && ((l_unit >= P9_FIRST_MC) && (l_unit <= P9_LAST_MC)) ) + { + // Only access the mem chiplets if we're not in async mode + // because we don't start clocks until later on in that case + auto l_syncMode = + i_target->getAttr<TARGETING::ATTR_MC_SYNC_MODE>(); + if( l_syncMode == TARGETING::MC_SYNC_MODE_NOT_IN_SYNC ) + { + continue; + } + } +#endif + + l_addr |= (l_unit << 24); + io_buflen = sizeof(uint64_t); + l_err = deviceOp(i_opType, + i_target, + &l_data, + io_buflen, + DEVICE_XSCOM_ADDRESS_NO_ERROR(l_addr)); + // just ignore any errors, we expect they will happen + if( l_err ) + { + delete l_err; + l_err = nullptr; + continue; + } + + if( l_opIsBitwise ) + { + // if any bits are set, set this unit's bit in summary reg + // note: this is good enough for the use-case we have now + // but a better implementation would be to actually + // check the select regs as well so we know which bit(s) + // are the trigger + if( l_data & 0x8000000000000000 ) + { + *l_summaryReg |= (0x8000000000000000 >> l_unit); + } + } + else if( l_opIsOr ) + { + *l_summaryReg |= l_data; + } + } + + o_didWorkaround = true; + + } while (0); + return l_err; } diff --git a/src/usr/scom/test/scomtest.H b/src/usr/scom/test/scomtest.H index 6a64b37b5..6da3d9f9e 100644 --- a/src/usr/scom/test/scomtest.H +++ b/src/usr/scom/test/scomtest.H @@ -1621,9 +1621,19 @@ public: TARGETING::Target* target; uint64_t addr; uint64_t data; + bool write; + bool read; } test_data[] = { - { scom_targets[PROC1], 0x02010803, 0x1234567887654321}, // addr: CXA FIR Mask Register - { scom_targets[PROC1], 0x02011083, 0x1122334455667788}, // addr: PBI CQ FIR Mask Register + { scom_targets[PROC1], 0x02010803, 0x1234567887654321, 1, 1}, // addr: CXA FIR Mask Register + { scom_targets[PROC1], 0x02011083, 0x1122334455667788, 1, 1}, // addr: PBI CQ FIR Mask Register + { scom_targets[PROC1], 0x20010A89, 0x1000000000000000, 1, 0}, // addr: Scratch reg 3 + { scom_targets[PROC1], 0x20110A89, 0x0200000000000000, 1, 0}, // addr: Scratch reg 3 + { scom_targets[PROC1], 0x20210A89, 0x0030000000000000, 1, 0}, // addr: Scratch reg 3 + { scom_targets[PROC1], 0x20310A89, 0x0004000000000000, 1, 0}, // addr: Scratch reg 3 + { scom_targets[PROC1], 0x10040018, 0x1000000000000000, 1, 0}, // addr: Local checkstop chipletID 0x10 + { scom_targets[PROC1], 0x20040018, 0x1000000000000000, 1, 0}, // addr: Local checkstop chipletID 0x20 + { scom_targets[PROC1], 0x41010a89, 0x1234000000000000, 0, 1}, // addr: Scratch reg 3 multicast read (OR type) + { scom_targets[PROC1], 0x50040018, 0x0000800080000000, 0, 1}, // addr: Local checkstop multicast read (BITWISE type) }; const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]); @@ -1641,6 +1651,12 @@ public: continue; } + //only run if write is specified + if(test_data[x].write == false) + { + continue; + } + op_size = sizeof(uint64_t); total++; @@ -1667,6 +1683,12 @@ public: continue; } + //only run if read is specified + if(test_data[x].read == false) + { + continue; + } + op_size = sizeof(uint64_t); total++; |