diff options
author | Adam Muhle <armuhle@us.ibm.com> | 2012-09-21 11:20:22 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-12-04 09:22:32 -0600 |
commit | 4204cd1310954b3c4d49554d0d19c71f485c588c (patch) | |
tree | 5918c3e7bc4707eff62666c85bb9c1e3cb5e53ea /src/usr/ibscom | |
parent | 55ba79e454fc989c561ee5f58435bf610f01dead (diff) | |
download | talos-hostboot-4204cd1310954b3c4d49554d0d19c71f485c588c.tar.gz talos-hostboot-4204cd1310954b3c4d49554d0d19c71f485c588c.zip |
IBSCOM Good Path base support
This drop contains only the base IBSCOM good path support
Future Tasks will cover error path, improved test cases,
enabling IBSCOM, etc.
Change-Id: I8405de9c6c46b7c035b664713e5820268863210d
RTC: 50369
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2337
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/ibscom')
-rw-r--r-- | src/usr/ibscom/ibscom.C | 398 | ||||
-rw-r--r-- | src/usr/ibscom/ibscom.H | 75 | ||||
-rw-r--r-- | src/usr/ibscom/makefile | 30 | ||||
-rw-r--r-- | src/usr/ibscom/test/ibscomtest.H | 174 | ||||
-rw-r--r-- | src/usr/ibscom/test/makefile | 28 |
5 files changed, 705 insertions, 0 deletions
diff --git a/src/usr/ibscom/ibscom.C b/src/usr/ibscom/ibscom.C new file mode 100644 index 000000000..bdde8f4fb --- /dev/null +++ b/src/usr/ibscom/ibscom.C @@ -0,0 +1,398 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ibscom/ibscom.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <sys/mmio.h> +#include <sys/task.h> +#include <sys/sync.h> +#include <sys/misc.h> +#include <string.h> +#include <devicefw/driverif.H> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/common/targetservice.H> +#include <ibscom/ibscomreasoncodes.H> +#include "ibscom.H" +#include <assert.h> +#include <limits.h> + +// Trace definition +trace_desc_t* g_trac_ibscom = NULL; +TRAC_INIT(&g_trac_ibscom, "IBSCOM", KILOBYTE); + +using namespace ERRORLOG; +using namespace TARGETING; + +namespace IBSCOM +{ + + +// Register XSCcom access functions to DD framework +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::IBSCOM, + 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 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); + 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); + break; + } + + + } while(0); + + return l_err; +} + +/** + * @brief Get the virtual address of the input target + * for an inband scom access. + * + * Logic: + * If never inband scom to this chip: + * Call mmio_dev_map() to get virtual addr for this slave proc + * Save virtual addr used to this chip's attribute + * Else + * Use virtual address stored in this chip's attributes. + * End if + * + * @param[in] i_target inband scom target + * @param[out] o_virtAddr Target's virtual address + * + * @return errlHndl_t + */ +errlHndl_t getTargetVirtualAddress(Target* i_target, + uint64_t*& o_virtAddr) +{ + errlHndl_t l_err = NULL; + o_virtAddr = NULL; + IBScomBase_t l_IBScomBaseAddr = 0; + + do + { + // Get the virtual addr value of the chip from attribute + o_virtAddr = reinterpret_cast<uint64_t*> + (i_target->getAttr<ATTR_IBSCOM_VIRTUAL_ADDR>()); + + // If the virtual address equals NULL(default) then this is the + // first IBSCOM to this target so we need to allocate + // the virtual address and save it in the xscom address attribute. + if (o_virtAddr == NULL) + { + + TRACDCOMP(g_trac_ibscom, INFO_MRK + "getTargetVirtualAddress: Need to compute virtual address for Centaur"); + + //Get MMIO Offset from parent MCS attribute. + + uint64_t mcsUnit = 0; + + //Get the parent MCS + Target* parentMCS = NULL; + + PredicateCTM l_mcs(CLASS_UNIT, + TYPE_MCS, + MODEL_NA); + + TargetHandleList mcs_list; + targetService(). + getAssociated(mcs_list, + i_target, + TargetService::PARENT_BY_AFFINITY, + TargetService::ALL, + &l_mcs); + + if( mcs_list.size() != 1 ) + { + TRACFCOMP(g_trac_ibscom, ERR_MRK + "getTargetVirtualAddress: mcs_list size is zero"); + /*@ + * @errortype + * @moduleid IBSCOM_GET_TARG_VIRT_ADDR + * @reasoncode IBSCOM_INVALID_CONFIG + * @userdata1[0:31] HUID of Centaur Target + * @userdata2 Not Used + * @devdesc System configuration does not have a Parent MCS + * for the current centaur. + */ + l_err = + new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + IBSCOM_GET_TARG_VIRT_ADDR, + IBSCOM_INVALID_CONFIG, + TWO_UINT32_TO_UINT64( + get_huid(i_target), + 0), + 0); + + break; + } + parentMCS = *(mcs_list.begin()); + + l_IBScomBaseAddr = + parentMCS->getAttr<ATTR_IBSCOM_MCS_BASE_ADDR>(); + + TRACFCOMP(g_trac_ibscom, INFO_MRK + "getTargetVirtualAddress: From Attribute query l_IBScomBaseAddr=0x%llX, i_target=0x%.8x", + l_IBScomBaseAddr, + i_target->getAttr<ATTR_HUID>()); + + //TODO: Remove this workaround when cen_set_inband_addr procedure + // is delivered + /* -- Start Workaround -> Remove with RTC: 52898 -- */ + + //Since the cen_set_inband_addr procedure has not been delivered, + // setting the bar on demand here so inband scoms will work + const uint64_t barAddrs[] = { + 0x02011802, /* MC0.MCS0.LEFT.LEFT.MCFGPRQ */ + 0x02011882, /* MC0.MCS1.LEFT.LEFT.MCFGPRQ */ + 0x02011902, /* MC1.MCS0.LEFT.LEFT.MCFGPRQ */ + 0x02011982, /* MC1.MCS1.LEFT.LEFT.MCFGPRQ */ + 0x02011C02, /* MC2.MCS0.LEFT.LEFT.MCFGPRQ */ + 0x02011C82, /* MC2.MCS1.LEFT.LEFT.MCFGPRQ */ + 0x02011D02, /* MC3.MCS0.LEFT.LEFT.MCFGPRQ */ + 0x02011D82, /* MC3.MCS1.LEFT.LEFT.MCFGPRQ */ + }; + + //Get the parent processor + Target* parentProcChip = NULL; + + PredicateCTM l_proc(CLASS_CHIP, + TYPE_PROC, + MODEL_NA); + + TargetHandleList proc_list; + targetService(). + getAssociated(proc_list, + i_target, + TargetService::PARENT_BY_AFFINITY, + TargetService::ALL, + &l_proc); + + if( proc_list.size() != 1 ) + { + //Since this code is temporary, just assert + TRACFCOMP(g_trac_ibscom, ERR_MRK + "getTargetVirtualAddress: mcs_list size is zero"); + crit_assert(0); + } + parentProcChip = *(proc_list.begin()); + + mcsUnit = + parentMCS->getAttr<ATTR_CHIP_UNIT>(); + + TRACDCOMP(g_trac_ibscom, INFO_MRK + "getTargetVirtualAddress: Setting IBSCOM Bar : barAddr=0x%X, l_IBScomBaseAddr=0x%llX", + barAddrs[mcsUnit], l_IBScomBaseAddr ); + + size_t op_size = sizeof(uint64_t); + l_err = deviceOp( DeviceFW::WRITE, + parentProcChip, + &l_IBScomBaseAddr, + op_size, + DEVICE_SCOM_ADDRESS(barAddrs[mcsUnit]) ); + + if( l_err ) + { + TRACFCOMP(g_trac_ibscom, ERR_MRK + "getTargetVirtualAddress: Error programming IBSCOM Bar : barAddr=0x%X, l_IBScomBaseAddr=0x%llX", + barAddrs[mcsUnit], l_IBScomBaseAddr ); + break; + } + /* -- END Workaround -> Remove with RTC: 52898 -- */ + + // Map target's virtual address + //NOTE: mmio_dev_map only supports 32 GB Allocation. Technically, + //hostboot IBSCOM MMIO allocated 64GB, but the SCOM address space + //is small enough that 32 GB is sufficient. + o_virtAddr = static_cast<uint64_t*> + (mmio_dev_map(reinterpret_cast<void*>(l_IBScomBaseAddr), + THIRTYTWO_GB)); + + // Save the virtual address attribute. + i_target->setAttr<ATTR_IBSCOM_VIRTUAL_ADDR> + (reinterpret_cast<uint64_t>(o_virtAddr)); + } + + } while (0); + + TRACDCOMP(g_trac_ibscom, EXIT_MRK + "getTargetVirtualAddress: o_Virtual Base Address = 0x%llX", + o_virtAddr); + + + return l_err; +} + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType, + Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) +{ + errlHndl_t l_err = NULL; + uint64_t l_addr = va_arg(i_args,uint64_t); + + do + { + TRACDCOMP(g_trac_ibscom, INFO_MRK + ">>ibscomPerformOp: Perform op to SCOM Address 0x%X", + l_addr); + + // inband scom operation sanity check + l_err = ibscomOpSanityCheck(i_opType, i_target, io_buffer, + io_buflen, l_addr); + if (l_err) + { + break; + } + // Set to buffer len to 0 until successfully access + io_buflen = 0; + + // Get the target chip's virtual address + uint64_t* l_virtAddr = NULL; + l_err = getTargetVirtualAddress(i_target, l_virtAddr); + + if (l_err) + { + break; + } + + // The dereferencing should handle Cache inhibited internally + // Use local variable and memcpy to avoid unaligned memory access + uint64_t l_data = 0; + + if (i_opType == DeviceFW::READ) + { + //TODO: Check that address isn't greater than allocated 32GB range + // RTC: 47212 + l_data = l_virtAddr[l_addr]; + + memcpy(io_buffer, &l_data, sizeof(l_data)); + TRACDCOMP(g_trac_ibscom, + "ibscomPerformOp: Read data: %.16llx", + l_data); + + } + else + { + TRACDCOMP(g_trac_ibscom, + "ibscomPerformOp: Write data: %.16llx", + l_data); + memcpy(&l_data, io_buffer, sizeof(l_data)); + l_virtAddr[l_addr] = l_data; + } + + // Check for error or done + //TODO - check for errors RTC: 47212 + //assume successful for now + io_buflen = sizeof(uint64_t); + + TRACDCOMP(g_trac_ibscom, + "ibscomPerformOp: OpType 0x%.16llX, SCOM Address 0x%llX, Virtual Address 0x%llX", + static_cast<uint64_t>(i_opType), + l_addr, + &(l_virtAddr[l_addr])); + + } while (0); + + return l_err; +} + +} // end namespace diff --git a/src/usr/ibscom/ibscom.H b/src/usr/ibscom/ibscom.H new file mode 100644 index 000000000..7bb17b9ad --- /dev/null +++ b/src/usr/ibscom/ibscom.H @@ -0,0 +1,75 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ibscom/ibscom.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __IBSCOM_H +#define __IBSCOM_H + +/** @file ibscom.H + * @brief Provides the interfaces to perform IBSCOM + */ + +#include <stdint.h> + +/** + * @brief Type definition for IBSCOM address + */ +typedef uint64_t IBScomBase_t; + +namespace IBSCOM +{ + +const size_t IBSCOM_BUFFER_SIZE = 8; // 8 bytes + +/** + * @brief Performs an inband scom access operation + * This function performs an inband scom access operation. It follows a + * pre-defined prototype functions in order to be registered with the + * device-driver framework. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target inband scom target + * @param[in] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in] io_buflen Input: size of io_buffer (in bytes) + * Output: + * Read: Size of output data + * Write: Size of data written + * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there's only one argument, + * which is the MMIO inband scom 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); + + + +}; + + +#endif diff --git a/src/usr/ibscom/makefile b/src/usr/ibscom/makefile new file mode 100644 index 000000000..1ece9f652 --- /dev/null +++ b/src/usr/ibscom/makefile @@ -0,0 +1,30 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ibscom/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2012 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../.. +MODULE = ibscom + +OBJS = ibscom.o + +SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/ibscom/test/ibscomtest.H b/src/usr/ibscom/test/ibscomtest.H new file mode 100644 index 000000000..189f78049 --- /dev/null +++ b/src/usr/ibscom/test/ibscomtest.H @@ -0,0 +1,174 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ibscom/test/ibscomtest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __IBSCOMTEST_H +#define __IBSCOMTEST_H + +/** + * @file ibscomtest.H + * + * @brief Test case for inband scom code +*/ + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/userif.H> +#include <ibscom/ibscomreasoncodes.H> +#include <devicefw/driverif.H> + +extern trace_desc_t* g_trac_ibscom; + +using namespace TARGETING; + + +class IBscomTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief inband scom test #1 + * Write value and read back to verify + */ + void test_IBscom(void) + { + + //TODO Enable and improve test cases RTC: 52900 + return; + + uint64_t fails = 0; + uint64_t total = 0; + errlHndl_t l_err = NULL; + + TARGETING::Target* l_testTarget = NULL; + + // Target: Find a Centaur on the Master processor + TARGETING::Target* l_procTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_procTarget); + assert(l_procTarget != NULL); + + TARGETING::PredicateCTM l_cent(TARGETING::CLASS_CHIP, + TARGETING::TYPE_MEMBUF, + TARGETING::MODEL_NA); + TARGETING::PredicatePostfixExpr cent_query; + cent_query.push(&l_cent); + + + TARGETING::TargetHandleList centaur_list; + TARGETING::targetService(). + getAssociated(centaur_list, + l_procTarget, + TARGETING::TargetService::CHILD_BY_AFFINITY, + TARGETING::TargetService::ALL, + ¢_query); + + if( centaur_list.size() < 1 ) + { + TS_FAIL( "test_IBscom> ERROR : Unable to find a Centaur chip" ); + return; + } + l_testTarget = *(centaur_list.begin()); + + uint64_t addr = 0x03010E03; + uint64_t orig_data = 0; + uint64_t data = 0x12345678FEEDB0B0; + size_t op_size = sizeof(uint64_t); + + //Save of initial register content + l_err = deviceRead( l_testTarget, + &orig_data, + op_size, + DEVICE_SCOM_ADDRESS(addr) ); + if( l_err ) + { + TRACFCOMP(g_trac_ibscom, + "IBscomTest::test_IBscom> Orig Read: Error from device : addr=0x%X, RC=%X", + addr, l_err->reasonCode() ); + TS_FAIL( "test_IBscom1> ERROR : Unexpected error log from read1" ); + fails++; + errlCommit(l_err,IBSCOM_COMP_ID); + } + + l_err = deviceOp( DeviceFW::WRITE, + l_testTarget, + &data, + op_size, + DEVICE_IBSCOM_ADDRESS(addr) ); + if( l_err ) + { + TRACFCOMP(g_trac_ibscom, + "IBscomTest::test_IBscom> Write: Error from device : addr=0x%X, RC=%X", + addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_IBscom> ERROR : Error log from write1" ); + fails++; + errlCommit(l_err,IBSCOM_COMP_ID); + } + + total++; + + l_err = deviceOp( DeviceFW::READ, + l_testTarget, + &data, + op_size, + DEVICE_IBSCOM_ADDRESS(addr) ); + if( l_err ) + { + TRACFCOMP(g_trac_ibscom, + "IBscomTest::test_IBscom> Read: Error from device : addr=0x%X, RC=%X", + addr, l_err->reasonCode() ); + TS_FAIL( "test_IBscom> ERROR : Error log from read2" ); + fails++; + errlCommit(l_err,IBSCOM_COMP_ID); + } + + total++; + + //Restore original data. + l_err = deviceWrite( l_testTarget, + &orig_data, + op_size, + DEVICE_SCOM_ADDRESS(addr) ); + + if( l_err ) + { + TRACFCOMP(g_trac_ibscom, + "IBscomTest::test_IBscom> Write Orig Data: Error from device : addr=0x%X, RC=%X", + addr, l_err->reasonCode() ); + TS_FAIL( "test_IBscom> ERROR : Error log from write2" ); + fails++; + errlCommit(l_err,IBSCOM_COMP_ID); + } + + + TS_TRACE("test_IBscom runs successfully!"); + TRACFCOMP(g_trac_ibscom, + "IBscomTest::test_IBscom> %d/%d fails", + fails, total ); + + return; + } + + + +}; + +#endif diff --git a/src/usr/ibscom/test/makefile b/src/usr/ibscom/test/makefile new file mode 100644 index 000000000..1a21fa2d3 --- /dev/null +++ b/src/usr/ibscom/test/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ibscom/test/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2012 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../../.. + +MODULE = testibscom +TESTS = *.H + +include ${ROOTPATH}/config.mk |