diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2018-03-23 10:49:35 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-04-02 13:44:41 -0400 |
commit | b51298075aee402dbcef485088cfa71a6ca61725 (patch) | |
tree | 21bd59df20830b108f6b3f6dd835915c28691ec7 /src/usr/ibscom | |
parent | 55f0053bc34e10d118e383f782b7be5cb14f59d2 (diff) | |
download | talos-hostboot-b51298075aee402dbcef485088cfa71a6ca61725.tar.gz talos-hostboot-b51298075aee402dbcef485088cfa71a6ca61725.zip |
Add ibscom runtime support
- Add ibscom runtime files
- Make ibscom multicast workaround common
- Call from ibscom rt_ibscom
- Make scom sanity check common
- Call from xscom rt_xscom ibscom rt_ibscom
RTC:190144
Change-Id: Ia52feac596ff6b6c8fb9f0db4493f35e4ee837af
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/56215
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>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Martin Gloff <mgloff@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/ibscom')
-rw-r--r-- | src/usr/ibscom/ibscom.C | 221 | ||||
-rw-r--r-- | src/usr/ibscom/ibscom.mk | 27 | ||||
-rw-r--r-- | src/usr/ibscom/ibscom_multicast.C | 149 | ||||
-rw-r--r-- | src/usr/ibscom/makefile | 8 | ||||
-rw-r--r-- | src/usr/ibscom/runtime/makefile | 38 | ||||
-rw-r--r-- | src/usr/ibscom/runtime/rt_ibscom.C | 114 |
6 files changed, 340 insertions, 217 deletions
diff --git a/src/usr/ibscom/ibscom.C b/src/usr/ibscom/ibscom.C index 8d0671072..fd1918e34 100644 --- a/src/usr/ibscom/ibscom.C +++ b/src/usr/ibscom/ibscom.C @@ -45,6 +45,7 @@ #include <errl/errludtarget.H> #include <xscom/piberror.H> #include <diag/attn/attn.H> +#include <scom/scomif.H> #include <ibscom/ibscomif.H> #include <targeting/common/utilFilter.H> #include <arch/memorymap.H> @@ -74,112 +75,6 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, TYPE_MEMBUF, ibscomPerformOp); -/** - * @brief Internal routine that verifies the validity of input parameters - * for an inband scom access. - * - * @param[in] i_opType Operation type, see DeviceFW::OperationType - * in driverif.H - * @param[in] i_target inband scom target - * @param[in] i_buffer Read: Pointer to output data storage - * Write: Pointer to input data storage - * @param[in] i_buflen Input: size of io_buffer (in bytes) - * @param[in] i_addr Address being accessed (Used for FFDC) - * @return errlHndl_t - */ -errlHndl_t ibscomOpSanityCheck(const DeviceFW::OperationType i_opType, - const Target* i_target, - const void* i_buffer, - const size_t& i_buflen, - const uint64_t i_addr) -{ - errlHndl_t l_err = NULL; - TRACDCOMP(g_trac_ibscom, INFO_MRK - ">>ibscomOpSanityCheck: Entering Function"); - - do - { - // Verify address is somewhat valid (not over 32-bits long) - if(0 != (i_addr & 0xFFFFFFFF00000000)) - { - TRACFCOMP(g_trac_ibscom, ERR_MRK"ibscomOpSanityCheck: Impossible address. i_addr=0x%.16X", - i_buflen); - /*@ - * @errortype - * @moduleid IBSCOM_SANITY_CHECK - * @reasoncode IBSCOM_INVALID_ADDRESS - * @userdata1 Inband Scom address - * @userdata2 <none> - * @devdesc The provided address is over 32 bits long - * which makes it invalid. - */ - l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, - IBSCOM_SANITY_CHECK, - IBSCOM_INVALID_ADDRESS, - i_addr, - 0); - l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); - break; - } - - // Verify data buffer - if ( (i_buflen < IBSCOM_BUFFER_SIZE) || - (i_buffer == NULL) ) - { - TRACFCOMP(g_trac_ibscom, ERR_MRK - "ibscomOpSanityCheck: Invalid buffer. i_buflen=0x%X", - i_buflen); - /*@ - * @errortype - * @moduleid IBSCOM_SANITY_CHECK - * @reasoncode IBSCOM_INVALID_DATA_BUFFER - * @userdata1 Buffer size - * @userdata2 Inband Scom address - * @devdesc Inband buffer size < 8 bytes or NULL - * data buffer - */ - l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, - IBSCOM_SANITY_CHECK, - IBSCOM_INVALID_DATA_BUFFER, - i_buflen, - i_addr); - l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); - break; - } - - // Verify OP type - if ( (i_opType != DeviceFW::READ) && - (i_opType != DeviceFW::WRITE) ) - { - TRACFCOMP(g_trac_ibscom, ERR_MRK - "ibscomOpSanityCheck: Invalid opType. i_opType=0x%X", - i_opType); - /*@ - * @errortype - * @moduleid IBSCOM_SANITY_CHECK - * @reasoncode IBSCOM_INVALID_OP_TYPE - * @userdata1 Operation type - * @userdata2 inband scom address - * @devdesc inband scom invalid operation type - */ - l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, - IBSCOM_SANITY_CHECK, - IBSCOM_INVALID_OP_TYPE, - i_opType, - i_addr); - l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); - break; - } - - - } while(0); - - return l_err; -} - /** * @brief Return the parent DMI target for the input membuf target @@ -520,10 +415,12 @@ errlHndl_t doIBScom(DeviceFW::OperationType i_opType, i_addr); // inband scom operation sanity check - l_err = ibscomOpSanityCheck(i_opType, i_target, io_buffer, - io_buflen, i_addr); + l_err = SCOM::scomOpSanityCheck(i_opType, i_target, io_buffer, + io_buflen, i_addr, IBSCOM_BUFFER_SIZE); if (l_err) { + // Trace here - sanity check does not know scom type + TRACFCOMP(g_trac_ibscom,"IBScom sanity check failed"); break; } // Set to buffer len to 0 until successfully access @@ -955,114 +852,6 @@ errlHndl_t doIBScom(DeviceFW::OperationType i_opType, return l_err; } -/** - * @brief Multicast this ibscom address - * - * @param[in] i_opType read/write - * @param[in] i_target target membuf - * @param[inout] io_buffer return data - * @param[inout] io_buflen return data length - * @param[in] i_addr inband scom address - * @param[out] o_didWorkaround return indicator - * - * @return error log on fail - */ -errlHndl_t doIBScomMulticast( DeviceFW::OperationType i_opType, - Target* i_target, - void* io_buffer, - size_t& io_buflen, - uint64_t i_addr, - bool& o_didWorkaround ) -{ - errlHndl_t l_err = nullptr; - uint64_t* l_summaryReg = reinterpret_cast<uint64_t*>(io_buffer); - - // Chiplet byte info masks - constexpr uint64_t IS_MULTICAST = 0x40000000; - constexpr uint64_t MULTICAST_GROUP = 0x07000000; - constexpr uint64_t MULTICAST_OP = 0x38000000; - constexpr uint64_t MULTICAST_OP_BITWISE = 0x10000000; - constexpr uint64_t CHIPLET_BYTE = 0xFF000000; - - // Valid groups - constexpr uint64_t GROUP_0 = 0x00000000; - constexpr uint64_t GROUP_3 = 0x03000000; - - uint64_t l_group = MULTICAST_GROUP & i_addr; - - // Only perform this workaround for: - // - reads - // - multicast registers - // - multicast read option 'bit-wise' - // - multicast group 0 or 3 - if( !((DeviceFW::READ == i_opType) - && ((IS_MULTICAST & i_addr) == IS_MULTICAST) - && ((MULTICAST_OP & i_addr) == MULTICAST_OP_BITWISE) - && ((GROUP_0 == l_group) || (GROUP_3 == l_group)) ) ) - { - o_didWorkaround = false; - return nullptr; - } - - TRACFCOMP( g_trac_ibscom, "doIBScomMulticast on %.8X for %.8X", TARGETING::get_huid(i_target), i_addr ); - - // Chiplet numbers - constexpr uint64_t CHIPLET_PRV = 1; - constexpr uint64_t CHIPLET_NST = 2; - constexpr uint64_t CHIPLET_MEM = 3; - - // Start chiplet depends on group, end chiplet is always MEM - // - Multicast group 0: PRV NST MEM, chiplets 1 2 3 - // - Multicast group 3: NST MEM, chiplets 2 3 - uint64_t l_start_chplt = 0; - uint64_t l_end_chplt = CHIPLET_MEM; - if( GROUP_0 == l_group ) - { - l_start_chplt = CHIPLET_PRV; - } - else // Must be group 3 - { - l_start_chplt = CHIPLET_NST; - } - - // Do the ibscom for each chiplet and return the combined value - for( uint64_t l_chplt = l_start_chplt; l_chplt <= l_end_chplt; l_chplt++ ) - { - // Remove the chiplet byte info from the address - uint64_t l_addr = (i_addr & ~CHIPLET_BYTE); - uint64_t l_data = 0; - - // Add the chiplet to the address - l_addr |= (l_chplt << 24); - io_buflen = sizeof(uint64_t); - - l_err = doIBScom(i_opType, - i_target, - &l_data, - io_buflen, - l_addr, - false); - if( l_err ) - { - break; - } - // If any bits are set, set this unit's bit in summary reg - // note: just check the first bit, - // 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_chplt); - } - - } - - o_didWorkaround = true; - - return l_err; -} /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/src/usr/ibscom/ibscom.mk b/src/usr/ibscom/ibscom.mk new file mode 100644 index 000000000..ac8802ca7 --- /dev/null +++ b/src/usr/ibscom/ibscom.mk @@ -0,0 +1,27 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ibscom/ibscom.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2012,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 + +OBJS += ibscom_multicast.o + diff --git a/src/usr/ibscom/ibscom_multicast.C b/src/usr/ibscom/ibscom_multicast.C new file mode 100644 index 000000000..fb2513d12 --- /dev/null +++ b/src/usr/ibscom/ibscom_multicast.C @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ibscom/ibscom_multicast.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +#include <ibscom/ibscomif.H> +#include <trace/interface.H> +#include <errl/errlmanager.H> +#include <scom/runtime/rt_scomif.H> + +// Trace definition +extern trace_desc_t* g_trac_ibscom; + +namespace IBSCOM +{ + +/** + * @brief Multicast this ibscom address + * + * @param[in] i_opType read/write + * @param[in] i_target target membuf + * @param[inout] io_buffer return data + * @param[inout] io_buflen return data length + * @param[in] i_addr inband scom address + * @param[out] o_didWorkaround return indicator + * + * @return error log on fail + */ +errlHndl_t doIBScomMulticast( DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + uint64_t i_addr, + bool& o_didWorkaround ) +{ + errlHndl_t l_err = nullptr; + uint64_t* l_summaryReg = reinterpret_cast<uint64_t*>(io_buffer); + + // Chiplet byte info masks + constexpr uint64_t IS_MULTICAST = 0x40000000; + constexpr uint64_t MULTICAST_GROUP = 0x07000000; + constexpr uint64_t MULTICAST_OP = 0x38000000; + constexpr uint64_t MULTICAST_OP_BITWISE = 0x10000000; + constexpr uint64_t CHIPLET_BYTE = 0xFF000000; + + // Valid groups + constexpr uint64_t GROUP_0 = 0x00000000; + constexpr uint64_t GROUP_3 = 0x03000000; + + uint64_t l_group = MULTICAST_GROUP & i_addr; + + // Only perform this workaround for: + // - reads + // - multicast registers + // - multicast read option 'bit-wise' + // - multicast group 0 or 3 + if( !((DeviceFW::READ == i_opType) + && ((IS_MULTICAST & i_addr) == IS_MULTICAST) + && ((MULTICAST_OP & i_addr) == MULTICAST_OP_BITWISE) + && ((GROUP_0 == l_group) || (GROUP_3 == l_group)) ) ) + { + o_didWorkaround = false; + return nullptr; + } + + TRACFCOMP( g_trac_ibscom, "doIBScomMulticast on %.8X for %.8X", TARGETING::get_huid(i_target), i_addr ); + + // Chiplet numbers + constexpr uint64_t CHIPLET_PRV = 1; + constexpr uint64_t CHIPLET_NST = 2; + constexpr uint64_t CHIPLET_MEM = 3; + + // Start chiplet depends on group, end chiplet is always MEM + // - Multicast group 0: PRV NST MEM, chiplets 1 2 3 + // - Multicast group 3: NST MEM, chiplets 2 3 + uint64_t l_start_chplt = 0; + uint64_t l_end_chplt = CHIPLET_MEM; + if( GROUP_0 == l_group ) + { + l_start_chplt = CHIPLET_PRV; + } + else // Must be group 3 + { + l_start_chplt = CHIPLET_NST; + } + + // Do the ibscom for each chiplet and return the combined value + for( uint64_t l_chplt = l_start_chplt; l_chplt <= l_end_chplt; l_chplt++ ) + { + // Remove the chiplet byte info from the address + uint64_t l_addr = (i_addr & ~CHIPLET_BYTE); + uint64_t l_data = 0; + + // Add the chiplet to the address + l_addr |= (l_chplt << 24); + io_buflen = sizeof(uint64_t); + +#ifdef __HOSTBOOT_RUNTIME + l_err = SCOM::sendScomToHyp(i_opType, i_target, l_addr, &l_data); +#else + l_err = doIBScom(i_opType, + i_target, + &l_data, + io_buflen, + l_addr, + false); +#endif + if( l_err ) + { + break; + } + // If any bits are set, set this unit's bit in summary reg + // note: just check the first bit, + // 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_chplt); + } + + } + + o_didWorkaround = true; + + return l_err; +} + +} // end namespace IBSCOM diff --git a/src/usr/ibscom/makefile b/src/usr/ibscom/makefile index 8e34154e0..69403562f 100644 --- a/src/usr/ibscom/makefile +++ b/src/usr/ibscom/makefile @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2012,2014 +# Contributors Listed Below - COPYRIGHT 2012,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. @@ -23,8 +25,12 @@ ROOTPATH = ../../.. MODULE = ibscom +#include common ojects between hostboot and runtime hostboot +include ibscom.mk + OBJS += ibscom.o SUBDIRS += test.d +SUBDIRS += runtime.d include ${ROOTPATH}/config.mk diff --git a/src/usr/ibscom/runtime/makefile b/src/usr/ibscom/runtime/makefile new file mode 100644 index 000000000..ba45c1b5e --- /dev/null +++ b/src/usr/ibscom/runtime/makefile @@ -0,0 +1,38 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ibscom/runtime/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,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 +HOSTBOOT_RUNTIME = 1 +ROOTPATH = ../../../.. +MODULE = ibscom_rt + +#include common ojects between hostboot and runtime hostboot +include ../ibscom.mk + +#include unique object modules +OBJS += rt_ibscom.o + +#SUBDIRS += test.d + +VPATH += .. +include $(ROOTPATH)/config.mk diff --git a/src/usr/ibscom/runtime/rt_ibscom.C b/src/usr/ibscom/runtime/rt_ibscom.C new file mode 100644 index 000000000..d731f1acc --- /dev/null +++ b/src/usr/ibscom/runtime/rt_ibscom.C @@ -0,0 +1,114 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ibscom/runtime/rt_ibscom.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,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 */ +#include <devicefw/driverif.H> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <ibscom/ibscomreasoncodes.H> +#include "../ibscom.H" +#include <scom/scomif.H> +#include <scom/runtime/rt_scomif.H> +#include <ibscom/ibscomif.H> + +// Trace definition +trace_desc_t* g_trac_ibscom = NULL; +TRAC_INIT(&g_trac_ibscom, "IBSCOM", 2*KILOBYTE, TRACE::BUFFER_SLOW); + +namespace IBSCOM +{ + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::IBSCOM, + TARGETING::TYPE_MEMBUF, + ibscomPerformOp); + + +/** + * @brief Complete the ibscom op + * + * @param[in] i_opType Operation type, see driverif.H + * @param[in] i_target IBSCom target + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes) + * Output: Read: Size of output data + * Write: Size of data written + * @param[in] i_accessType Access type + * @param[in] i_args This is an argument list for DD framework. + * In this function, there's only one argument, + * which is the MMIO IBSCom address + * @return errlHndl_t + */ +errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) +{ + TRACDCOMP(g_trac_ibscom,ENTER_MRK"ibscomPerformOp"); + errlHndl_t l_err = NULL; + uint64_t l_addr = va_arg(i_args,uint64_t); + + do + { + l_err = SCOM::scomOpSanityCheck(i_opType, + i_target, + io_buffer, + io_buflen, + l_addr, + IBSCOM_BUFFER_SIZE); + if( l_err ) + { + // Trace here - sanity check does not know scom type + TRACFCOMP(g_trac_ibscom,"Runtime IBScom sanity check failed"); + break; + } + + // Multicast is not handled correctly by inband scom + // Call workaround to complete manually + bool l_didWorkaround = false; + l_err = doIBScomMulticast(i_opType, + i_target, + io_buffer, + io_buflen, + l_addr, + l_didWorkaround); + if( l_err || l_didWorkaround ) + { + break; + } + + l_err = SCOM::sendScomToHyp(i_opType, i_target, l_addr, io_buffer); + + } while(0); + + TRACDCOMP(g_trac_ibscom,EXIT_MRK"ibscomPerformOp"); + + return l_err; +} + +}; // end namespace IBSCOM + |