diff options
-rw-r--r-- | src/include/usr/ibscom/ibscomif.H | 46 | ||||
-rw-r--r-- | src/include/usr/scom/scomif.H | 20 | ||||
-rw-r--r-- | src/include/usr/scom/scomreasoncodes.H | 3 | ||||
-rw-r--r-- | src/makefile | 1 | ||||
-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 | ||||
-rw-r--r-- | src/usr/scom/preopchecks.C | 150 | ||||
-rw-r--r-- | src/usr/scom/scom.mk | 1 | ||||
-rw-r--r-- | src/usr/xscom/runtime/rt_xscom.C | 101 | ||||
-rw-r--r-- | src/usr/xscom/xscom.C | 83 |
14 files changed, 578 insertions, 384 deletions
diff --git a/src/include/usr/ibscom/ibscomif.H b/src/include/usr/ibscom/ibscomif.H index f539caf90..41e9f0cdd 100644 --- a/src/include/usr/ibscom/ibscomif.H +++ b/src/include/usr/ibscom/ibscomif.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* 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. */ @@ -26,6 +28,7 @@ #include <stdint.h> #include <builtins.h> #include <errl/errlentry.H> +#include <devicefw/driverif.H> namespace IBSCOM { @@ -40,6 +43,45 @@ namespace IBSCOM */ void enableInbandScoms( bool i_disable = IBSCOM_ENABLE ); -} +/** + * @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 ); + +#ifndef __HOSTBOOT_RUNTIME +/** + * @brief Perform ibscom + * + * @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[in] i_errDataPath generate SUE error + * + * @return error log on fail + */ +errlHndl_t doIBScom(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + uint64_t i_addr, + bool i_errDataPath); +#endif +} // end namespace IBSCOM #endif diff --git a/src/include/usr/scom/scomif.H b/src/include/usr/scom/scomif.H index da7227735..d86bd6358 100644 --- a/src/include/usr/scom/scomif.H +++ b/src/include/usr/scom/scomif.H @@ -25,6 +25,8 @@ #ifndef __SCOMIF_H #define __SCOMIF_H +#include <devicefw/driverif.H> + namespace SCOM { @@ -43,6 +45,24 @@ errlHndl_t scomTranslate(TARGETING::Target * &i_target, bool & o_needsWakeup, uint64_t i_opMode = 0); +/** + * @brief Common routine that verifies input parameters for *scom accesses. + * + * @param[in] i_opType Operation type, see driverif.H + * @param[in] i_target 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 scomOpSanityCheck(const DeviceFW::OperationType i_opType, + const TARGETING::Target* i_target, + const void* i_buffer, + const size_t i_buflen, + const uint64_t i_addr, + const size_t i_minbufsize); + #ifndef __HOSTBOOT_RUNTIME /** * @brief Enable scoms to all cores for multicast workaround diff --git a/src/include/usr/scom/scomreasoncodes.H b/src/include/usr/scom/scomreasoncodes.H index b6fb9816b..c4db021c8 100644 --- a/src/include/usr/scom/scomreasoncodes.H +++ b/src/include/usr/scom/scomreasoncodes.H @@ -41,6 +41,7 @@ namespace SCOM SCOM_HANDLE_SPECIAL_WAKEUP = 0x07, SCOM_TRANSLATE_CENTAUR = 0x08, SCOM_RT_SEND_SCOM_TO_HYP = 0x09, + SCOM_OP_SANITY_CHECK = 0x0A, }; enum scomReasonCode @@ -66,6 +67,8 @@ namespace SCOM SCOM_SPCWKUP_COUNT_ERR = SCOM_COMP_ID | 0x13, SCOM_CEN_TRANS_INVALID_TYPE = SCOM_COMP_ID | 0x14, SCOM_RUNTIME_HYP_ERR = SCOM_COMP_ID | 0x15, + SCOM_INVALID_DATA_BUFFER = SCOM_COMP_ID | 0x16, + SCOM_INVALID_OP_TYPE = SCOM_COMP_ID | 0x17, }; enum UserDetailsTypes diff --git a/src/makefile b/src/makefile index 4a718dd6f..83fe2511c 100644 --- a/src/makefile +++ b/src/makefile @@ -275,6 +275,7 @@ RUNTIME_MODULES += targeting_rt RUNTIME_MODULES += util_rt RUNTIME_MODULES += devicefw_rt RUNTIME_MODULES += xscom_rt +RUNTIME_MODULES += ibscom_rt RUNTIME_MODULES += scom_rt RUNTIME_MODULES += vpd_rt RUNTIME_MODULES += i2c_rt 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 + diff --git a/src/usr/scom/preopchecks.C b/src/usr/scom/preopchecks.C new file mode 100644 index 000000000..f5bc9f4a5 --- /dev/null +++ b/src/usr/scom/preopchecks.C @@ -0,0 +1,150 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/preopchecks.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <scom/scomreasoncodes.H> +#include <scom/scomif.H> + +// Trace definition +extern trace_desc_t* g_trac_scom; + +namespace SCOM +{ + +/** + * @brief Common routine that verifies input parameters for *scom accesses. + * + * @param[in] i_opType Operation type, see driverif.H + * @param[in] i_target 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 scomOpSanityCheck(const DeviceFW::OperationType i_opType, + const TARGETING::Target* i_target, + const void* i_buffer, + const size_t i_buflen, + const uint64_t i_addr, + const size_t i_minbufsize) +{ + errlHndl_t l_err = NULL; + TRACDCOMP(g_trac_scom, INFO_MRK + ">>scomOpSanityCheck: Entering Function"); + + do + { + // Verify address is not over 32-bits long + if(0 != (i_addr & 0xFFFFFFFF00000000)) + { + TRACFCOMP(g_trac_scom, ERR_MRK + "scomOpSanityCheck: Impossible address. i_addr=0x%.16X", + i_addr); + + /*@ + * @errortype + * @moduleid SCOM_OP_SANITY_CHECK + * @reasoncode SCOM_INVALID_ADDR + * @userdata1 Scom address + * @userdata2 Scom target + * @devdesc The provided address is over 32 bits long + * which makes it invalid. + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_OP_SANITY_CHECK, + SCOM_INVALID_ADDR, + i_addr, + get_huid(i_target)); + l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + break; + } + + // Verify data buffer + if ( (i_buflen < i_minbufsize) || + (i_buffer == NULL) ) + { + TRACFCOMP(g_trac_scom, ERR_MRK + "scomOpSanityCheck: Invalid buffer. i_buflen=0x%X", + i_buflen); + /*@ + * @errortype + * @moduleid SCOM_OP_SANITY_CHECK + * @reasoncode SCOM_INVALID_DATA_BUFFER + * @userdata1[0:31] Buffer size + * @userdata1[32:63] Minimum allowed buffer size + * @userdata2 Scom address + * @devdesc Buffer size is less than allowed + * or NULL data buffer + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_OP_SANITY_CHECK, + SCOM_INVALID_DATA_BUFFER, + TWO_UINT32_TO_UINT64( + i_buflen, + i_minbufsize), + 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_scom, ERR_MRK + "scomOpSanityCheck: Invalid opType. i_opType=0x%X", + i_opType); + /*@ + * @errortype + * @moduleid SCOM_OP_SANITY_CHECK + * @reasoncode SCOM_INVALID_OP_TYPE + * @userdata1 Operation type + * @userdata2 Scom address + * @devdesc Scom invalid operation type + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_OP_SANITY_CHECK, + SCOM_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; +} + +} // end namespace SCOM diff --git a/src/usr/scom/scom.mk b/src/usr/scom/scom.mk index 890b106d7..d382b6176 100644 --- a/src/usr/scom/scom.mk +++ b/src/usr/scom/scom.mk @@ -42,6 +42,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2/ OBJS += scom.o OBJS += scomtrans.o OBJS += errlud_pib.o +OBJS += preopchecks.o OBJS += postopchecks.o OBJS += DmiScomWorkaround.o OBJS += ibscom_retry.o diff --git a/src/usr/xscom/runtime/rt_xscom.C b/src/usr/xscom/runtime/rt_xscom.C index 93e011864..cf7d40052 100644 --- a/src/usr/xscom/runtime/rt_xscom.C +++ b/src/usr/xscom/runtime/rt_xscom.C @@ -28,6 +28,7 @@ #include <errl/errlmanager.H> #include <xscom/xscomreasoncodes.H> #include "../xscom.H" +#include <scom/scomif.H> #include <scom/runtime/rt_scomif.H> // Trace definition @@ -42,7 +43,7 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, TARGETING::TYPE_PROC, xscomPerformOp); -// Direct all scom calls though this interface at runtime +// Also direct fsi scom calls though this interface at runtime DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, DeviceFW::FSISCOM, TARGETING::TYPE_PROC, @@ -53,86 +54,6 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, TARGETING::TYPE_MEMBUF, xscomPerformOp); -DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, - DeviceFW::IBSCOM, - TARGETING::TYPE_MEMBUF, - xscomPerformOp); - -/** - * @brief Internal routine that verifies the validity of input parameters - * for an XSCOM access. - * - * @param[in] i_opType Operation type, see DeviceFW::OperationType - * in driverif.H - * @param[in] i_target XSCom target - * @param[in/out] i_buffer Read: Pointer to output data storage - * Write: Pointer to input data storage - * @param[in/out] i_buflen Input: size of io_buffer (in bytes) - * Output: - * Read: Size of output data - * Write: Size of data written - * @param[in] i_args This is an argument list for DD framework. - * In this function, there's only one argument, - * which is the MMIO XSCom address - * @return errlHndl_t - */ -errlHndl_t xscomOpSanityCheck(const DeviceFW::OperationType i_opType, - const TARGETING::Target* i_target, - const void* i_buffer, - const size_t& i_buflen, - const va_list i_args){ - errlHndl_t l_err = NULL; - - do - { - // Verify data buffer - if ( (i_buflen < XSCOM_BUFFER_SIZE) || - (i_buffer == NULL) ) - { - /*@ - * @errortype - * @moduleid XSCOM_RT_SANITY_CHECK - * @reasoncode XSCOM_INVALID_DATA_BUFFER - * @userdata1 Buffer size - * @userdata2 XSCom address - * @devdesc XSCOM buffer size < 8 bytes or NULL data buff - */ - l_err = - new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - XSCOM_RT_SANITY_CHECK, - XSCOM_INVALID_DATA_BUFFER, - i_buflen, - va_arg(i_args,uint64_t)); - break; - } - - // Verify OP type - if ( (i_opType != DeviceFW::READ) && - (i_opType != DeviceFW::WRITE) ) - { - /*@ - * @errortype - * @moduleid XSCOM_RT_SANITY_CHECK - * @reasoncode XSCOM_INVALID_OP_TYPE - * @userdata1 Operation type - * @userdata2 XSCom address - * @devdesc XSCOM invalid operation type - */ - l_err = - new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - XSCOM_RT_SANITY_CHECK, - XSCOM_INVALID_OP_TYPE, - i_opType, - va_arg(i_args,uint64_t)); - break; - } - - - } while(0); - - return l_err; -} - /** * @brief Complete the xscom op @@ -161,13 +82,19 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType, errlHndl_t l_err = NULL; uint64_t l_addr = va_arg(i_args,uint64_t); - l_err = xscomOpSanityCheck(i_opType, - i_target, - io_buffer, - io_buflen, - i_args); + l_err = SCOM::scomOpSanityCheck(i_opType, + i_target, + io_buffer, + io_buflen, + l_addr, + XSCOM_BUFFER_SIZE); - if (!l_err) + if (l_err) + { + // Trace here - sanity check does not know scom type + TRACFCOMP(g_trac_xscom,"Runtime XScom sanity check failed"); + } + else { l_err = SCOM::sendScomToHyp(i_opType, i_target, l_addr, io_buffer); } diff --git a/src/usr/xscom/xscom.C b/src/usr/xscom/xscom.C index a28897f8b..18594d7cd 100644 --- a/src/usr/xscom/xscom.C +++ b/src/usr/xscom/xscom.C @@ -46,6 +46,7 @@ #include <assert.h> #include <errl/errludlogregister.H> #include <xscom/piberror.H> +#include <scom/scomif.H> #include <arch/pirformat.H> #include <lpc/lpcif.H> #include <sys/mm.h> @@ -113,82 +114,6 @@ HMER waitForHMERStatus() /** - * @brief Internal routine that verifies the validity of input parameters - * for an XSCOM access. - * - * @param[in] i_opType Operation type, see DeviceFW::OperationType - * in driverif.H - * @param[in] i_target XSCom target - * @param[in/out] i_buffer Read: Pointer to output data storage - * Write: Pointer to input data storage - * @param[in/out] i_buflen Input: size of io_buffer (in bytes) - * Output: - * Read: Size of output data - * Write: Size of data written - * @param[in] i_args This is an argument list for DD framework. - * In this function, there's only one argument, - * which is the MMIO XSCom address - * @return errlHndl_t - */ -errlHndl_t xscomOpSanityCheck(const DeviceFW::OperationType i_opType, - const TARGETING::Target* i_target, - const void* i_buffer, - const size_t& i_buflen, - const va_list i_args) -{ - errlHndl_t l_err = NULL; - - do - { - // Verify data buffer - if ( (i_buflen < XSCOM_BUFFER_SIZE) || - (i_buffer == NULL) ) - { - /*@ - * @errortype - * @moduleid XSCOM_SANITY_CHECK - * @reasoncode XSCOM_INVALID_DATA_BUFFER - * @userdata1 Buffer size - * @userdata2 XSCom address - * @devdesc XSCOM buffer size < 8 bytes or NULL data buffer - */ - l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - XSCOM_SANITY_CHECK, - XSCOM_INVALID_DATA_BUFFER, - i_buflen, - va_arg(i_args,uint64_t), - true /*Add HB Software Callout*/); - break; - } - - // Verify OP type - if ( (i_opType != DeviceFW::READ) && - (i_opType != DeviceFW::WRITE) ) - { - /*@ - * @errortype - * @moduleid XSCOM_SANITY_CHECK - * @reasoncode XSCOM_INVALID_OP_TYPE - * @userdata1 Operation type - * @userdata2 XSCom address - * @devdesc XSCOM invalid operation type - */ - l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - XSCOM_SANITY_CHECK, - XSCOM_INVALID_OP_TYPE, - i_opType, - va_arg(i_args,uint64_t), - true /*Add HB Software Callout*/); - break; - } - - - } while(0); - - return l_err; -} - -/** * @brief Get the virtual address of the input target * for an XSCOM access. * @@ -752,10 +677,12 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType, do { // XSCOM operation sanity check - l_err = xscomOpSanityCheck(i_opType, i_target, io_buffer, - io_buflen, i_args); + l_err = SCOM::scomOpSanityCheck(i_opType, i_target, io_buffer, + io_buflen, l_addr, XSCOM_BUFFER_SIZE); if (l_err) { + // Trace here - sanity check does not know scom type + TRACFCOMP(g_trac_xscom,"XScom sanity check failed"); break; } |