From 37dbb4a827b19ba0634b38542c294106e3d70b25 Mon Sep 17 00:00:00 2001 From: sachin gupta Date: Fri, 4 Oct 2013 04:54:51 -0500 Subject: PRD: RCE table support Change-Id: I156d3cfc05b36d52fc647382134a0daa58501aa7 RTC: 87541 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/6486 Tested-by: Jenkins Server Reviewed-by: Prem Shanker Jha Reviewed-by: Christopher T. Phan Reviewed-by: A. Patrick Williams III Reviewed-by: Zane Shelley Squashed: I6e3bf7ff73d4161eb266d4a542dab4b061c48f62 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/7084 --- .../prdf/common/mnfgtools/prdfMfgThresholds.lst | 1 + .../diag/prdf/common/plat/pegasus/prdfCenConst.H | 6 +- .../common/plat/pegasus/prdfCenMbaCaptureData.C | 3 + .../plat/pegasus/prdfCenMbaDataBundle_common.H | 2 + .../prdf/common/plat/pegasus/prdfCenMbaRceTable.C | 128 +++++++++++++++++++++ .../prdf/common/plat/pegasus/prdfCenMbaRceTable.H | 95 +++++++++++++++ .../plat/pegasus/prdfCenMbaThresholds_common.C | 20 ++++ .../plat/pegasus/prdfCenMbaThresholds_common.H | 5 + src/usr/diag/prdf/common/plat/prdfLineDelete.H | 3 + src/usr/diag/prdf/common/plugins/prdfCenLogParse.C | 89 ++++++++++++++ src/usr/diag/prdf/common/plugins/prdfCenLogParse.H | 9 ++ .../diag/prdf/common/plugins/prdfLogParse_common.C | 4 + src/usr/diag/prdf/common/plugins/prdfParserEnums.H | 11 +- src/usr/diag/prdf/common/prd_pegasus.mk | 1 + 14 files changed, 373 insertions(+), 4 deletions(-) create mode 100644 src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.C create mode 100644 src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.H (limited to 'src/usr/diag/prdf/common') diff --git a/src/usr/diag/prdf/common/mnfgtools/prdfMfgThresholds.lst b/src/usr/diag/prdf/common/mnfgtools/prdfMfgThresholds.lst index 2b64ee1ed..6e232513d 100755 --- a/src/usr/diag/prdf/common/mnfgtools/prdfMfgThresholds.lst +++ b/src/usr/diag/prdf/common/mnfgtools/prdfMfgThresholds.lst @@ -19,3 +19,4 @@ P8CHIP_OFFNODE_BUS_CES 1 # P8 Centaur Mba thresholds CEN_MBA_RT_SOFT_CE_TH_ALGO 2 CEN_MBA_IPL_SOFT_CE_TH_ALGO 2 +CEN_MBA_RT_RCE_PER_RANK 2 diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenConst.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenConst.H index 133a852ab..4dcbcc0f6 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenConst.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenConst.H @@ -21,8 +21,8 @@ /* */ /* IBM_PROLOG_END_TAG */ -#ifndef PRDF_CEN_MBA_CONST_H -#define PRDF_CEN_MBA_CONST_H +#ifndef PRDF_CEN_CONST_H +#define PRDF_CEN_CONST_H /** * @file prdfCenConst.H @@ -61,5 +61,5 @@ enum } // end namespace PRDF -#endif // PRDF_CEN_MBA_CAPTURE_DATA_H +#endif // PRDF_CEN_CONST_H diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C index d74c5da03..f0d3c6bd3 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C @@ -163,6 +163,9 @@ void addMemEccData( ExtensibleChip * i_mbaChip, STEP_CODE_DATA_STRUCT & io_sc ) // Add CE table to capture data. mbadb->iv_ceTable.addCapData( mbaTarget, cd ); + // Add RCE table to capture data. + mbadb->iv_rceTable.addCapData( mbaTarget, cd ); + // Add DRAM repairs data from hardware. captureDramRepairsData( mbaTarget, cd ); diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H index aa40507f1..7c5e6cf93 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H @@ -38,6 +38,7 @@ #include #include #include +#include namespace PRDF { @@ -99,6 +100,7 @@ class CenMbaDataBundleCommon : public DataBundle CenMbaTdCtlr iv_tdCtlr; ///< Targeted Diagnostics Controller CenMbaUeTable iv_ueTable; ///< UE table for FFDC CenMbaCeTable iv_ceTable; ///< CE table for FFDC + CenMbaRceTable iv_rceTable; ///< RCE table for FFDC }; diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.C new file mode 100644 index 000000000..a53c7f178 --- /dev/null +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.C @@ -0,0 +1,128 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 */ + +#include + +// Framwork includes +#include +#include +#include + +// Pegasus includes +#include +#include + +using namespace TARGETING; + +namespace PRDF +{ + +using namespace RCE_TABLE; +using namespace LineDelete; + +//------------------------------------------------------------------------------ + +bool CenMbaRceTable::addEntry( const CenRank & i_rank , + STEP_CODE_DATA_STRUCT & i_sc, uint8_t i_count ) +{ + bool o_doTps = false; + + RceTable::iterator it = iv_table.find( i_rank ); + if( iv_table.end() == it) + { + // TODO via RTC 89386 + // PrdfCacheCETable implementation is not quite efficient. Need to + // find better way. + PrdfCacheCETable entry( getRceThreshold() ); + // Insert the element and get the iterator + it = iv_table.insert( std::make_pair( i_rank, entry)).first; + } + for( uint32_t i = 0; i < i_count; i++ ) + { + // Insert all entries even if threshold is crossed + // for better FFDC. + o_doTps |= it->second.addAddress(0 , i_sc ); + } + + return o_doTps; +} + +//------------------------------------------------------------------------------ + +void CenMbaRceTable::flushEntry( const CenRank & i_rank ) +{ + RceTable::iterator it = iv_table.find( i_rank ); + if( iv_table.end() != it) + it->second.flushTable(); +} +//------------------------------------------------------------------------------ + +void CenMbaRceTable::addCapData( TargetHandle_t i_mbaTrgt, CaptureData & io_cd ) +{ + static const size_t sz_word = sizeof(CPU_WORD); + static const size_t sz_entryCnt = sizeof( uint8_t ); // entry count + + // Get the maximum capture data size and adjust the size for endianess. + const size_t sz_maxData = ((( iv_table.size() * ENTRY_SIZE + sz_entryCnt )+ + sz_word-1) / sz_word) * sz_word; + + // Initialize to 0. + uint8_t data[sz_maxData]; + memset( data, 0x00, sz_maxData ); + + // reserve first index for total entries + size_t sz_actData = sz_entryCnt; + + for ( RceTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ ) + { + // skip if there is no RCE count + if( 0 == it->second.getTotalCount() ) + { + continue; + } + uint32_t mrnk = it->first.getMaster(); // 3-bit + uint32_t srnk = it->first.getSlave(); // 3-bit + uint32_t svld = it->first.isSlaveValid() ? 1 : 0; // 1-bit + + data[sz_actData] = (mrnk << 5) | (srnk << 2) | (svld << 1); + uint32_t count = it->second.getTotalCount(); + data[sz_actData + 1] = ( count > 255 ) ? 255 : count; + sz_actData += ENTRY_SIZE; + } + + if ( 1 != sz_actData ) + { + data[0] = sz_actData / ENTRY_SIZE; + // Fix endianess issues with non PPC machines. + sz_actData = ((sz_actData + sz_word-1) / sz_word) * sz_word; + for ( uint32_t i = 0; i < (sz_actData/sz_word); i++ ) + ((CPU_WORD*)data)[i] = htonl(((CPU_WORD*)data)[i]); + + // Add data to capture data. + BIT_STRING_ADDRESS_CLASS bs ( 0, sz_actData*8, (CPU_WORD *) &data ); + io_cd.Add( i_mbaTrgt, Util::hashString("MEM_RCE_TABLE"), bs ); + } +} + +} // end namespace PRDF + diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.H new file mode 100644 index 000000000..88aae6df0 --- /dev/null +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.H @@ -0,0 +1,95 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaRceTable.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 __prdfCenMbaRceTable_H +#define __prdfCenMbaRceTable_H + +/** @file prdfCenMbaRceTable.H */ + +// Framwork includes +#include +#include +#include +// Other includes +#include + +namespace PRDF +{ +class CenRank; + +/** + * @brief A table of memory RCEs. + * @note Only one of these tables will exist per MBA. + * @note Will be used to determine when to do a TPS procedure for Targeted + * Diagnostics at runtime. Will be used for FFDC only during Hostboot. + */ +class CenMbaRceTable +{ + + public: // functions + + /** + * @brief Will attempt to add a new entry to the table. + * + * If an entry already exists, the entry's count is incremented. Otherwise, + * a new entry is created. Will return TRUE if the RCE triggers TPS + * conditions: + * + * @param i_rank rank. + * @param i_sc The step code data struct. + * @param i_count RCE count. + * @return TRUE if TPS is required, FALSE otherwise. + */ + bool addEntry( const CenRank & i_rank, + STEP_CODE_DATA_STRUCT & i_sc, uint8_t i_count = 1 ); + + /** + * @brief Flush entry covered by a rank. + * @param i_rank The target rank. + */ + void flushEntry( const CenRank & i_rank ); + + /** + * @brief Gathers all table data to be stored in capture data. + * @param i_mbaTrgt An MBA target. + * @param io_cd Capture data struct. + */ + void addCapData( TARGETING::TargetHandle_t i_mbaTrgt, CaptureData & io_cd ); + + /** Default Constructor */ + CenMbaRceTable():iv_table(){} + + private: // structs, typedefs + + typedef std::map RceTable; + + private: // instance variables + + /** A storage container for memory RCE errors. */ + RceTable iv_table; +}; + +} // end namespace PRDF + +#endif // __prdfCenMbaRceTable_H + diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.C index 0d8157a26..b17347150 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.C @@ -42,6 +42,26 @@ namespace PRDF using namespace PlatServices; +// MNFG RCE threshold +static uint32_t MBA_RCE_NON_MNFG_TH = 8; + +//----------------------------------------------------------------------------- + +ThresholdResolution::ThresholdPolicy getRceThreshold() +{ + uint32_t th = MBA_RCE_NON_MNFG_TH; + if ( mfgMode() ) + { + th = MfgThresholdMgr::getInstance()-> + getThreshold( PRDF_CEN_MBA_RT_RCE_PER_RANK ); + + if( th > MBA_RCE_NON_MNFG_TH ) th = MBA_RCE_NON_MNFG_TH; + } + return ThresholdResolution::ThresholdPolicy( th, + ThresholdResolution::ONE_DAY); +} + +//----------------------------------------------------------------------------- int32_t getMnfgMemCeTh( ExtensibleChip * i_mbaChip, const CenRank & i_rank, uint16_t & o_cePerDram, uint16_t & o_cePerHalfRank, uint16_t & o_cePerDimm ) diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.H index 4084ec614..32f6423d8 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaThresholds_common.H @@ -51,6 +51,11 @@ int32_t getMnfgMemCeTh( ExtensibleChip * i_mbaChip, const CenRank & i_rank, uint16_t & o_cePerDram, uint16_t & o_cePerHalfRank, uint16_t & o_cePerDimm ); +/** + * @brief Returns RCE threshold policy. + */ +ThresholdResolution::ThresholdPolicy getRceThreshold(); + } // end namespace PRDF #endif /* __PRDF_CEN_MBA_COMMON_THRESHOLDS_H */ diff --git a/src/usr/diag/prdf/common/plat/prdfLineDelete.H b/src/usr/diag/prdf/common/plat/prdfLineDelete.H index fb0150cac..889125e1d 100755 --- a/src/usr/diag/prdf/common/plat/prdfLineDelete.H +++ b/src/usr/diag/prdf/common/plat/prdfLineDelete.H @@ -90,6 +90,9 @@ namespace LineDelete { public: + /** Default constructor */ + PrdfCacheCETable() {} + /** * @brief Constructor from ThresholdPolicy struct. * @param i_thPolicy A pointer to a ThresholdPolicy struct. diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C index 7c02ceeac..6d73f6ab6 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C @@ -302,6 +302,95 @@ bool parseMemCeTable( uint8_t * i_buffer, uint32_t i_buflen, //------------------------------------------------------------------------------ +void getRceEntry( uint8_t * i_buffer , char * o_entry ) +{ + + uint32_t mrnk = (i_buffer[0] >> 5) & 0x7; // 3-bit + uint32_t srnk = (i_buffer[0] >> 2) & 0x7; // 3-bit + uint32_t svld = (i_buffer[0] >> 1) & 0x1; // 1-bit + uint32_t count = i_buffer[1]; // 8-bit + + // This Function should return string in this format + // "Rank Count ". + if ( 1 == svld ) + { + snprintf( o_entry, DATA_SIZE, "m%ds%d", mrnk, srnk ); + } + else + { + snprintf( o_entry, DATA_SIZE, "m%d ", mrnk ); + } + + // Reserve some extra space for format + // 5 chars for "Count", 1 blank before count , one after count + char countStr[8] = { '\0' }; + snprintf( countStr, 8, " %d ", count ); + + strcat( o_entry, countStr ); +} + +//------------------------------------------------------------------------------ + +bool parseMemRceTable( uint8_t * i_buffer, uint32_t i_buflen, + ErrlUsrParser & i_parser ) +{ + using namespace RCE_TABLE; + + bool rc = true; + + // Check if something failed in parser. + if ( ( NULL == i_buffer ) || ( 0 == i_buflen) ) return false; + + const uint32_t entries = i_buffer[0]; + uint32_t idx = 1; + i_parser.PrintNumber( " MEM_RCE_TABLE", "%d", entries ); + + // To conserve space in error log output, have two entries in header + // and 4 in Description. + const uint32_t entryNumHdr = 2; + const uint32_t entryNumDesc = 4; + const char * hh = " Rank Count Rank Count"; + const char * hd = "Rank Count Rank Count Rank Count Rank Count"; + + i_parser.PrintString( hh, hd ); + hh = " ---- ----- ---- -----"; + hd = "---- ----- ---- ----- ---- ----- ---- -----"; + i_parser.PrintString( hh, hd ); + + uint32_t count = 0; + + while( count < entries ) + { + // Get Header + char header[HEADER_SIZE] = { '\0' }; + strcat( header, " "); + for( uint32_t i = 0; i < entryNumHdr && count < entries; + i++, count++, idx += ENTRY_SIZE ) + { + char data[12] = { '\0' }; + getRceEntry( i_buffer+idx, data ); + strcat( header, data ); + } + + // Get Description + char desc[DATA_SIZE] = { '\0' }; + for( uint32_t i = 0; i < entryNumDesc && count < entries; + i++, count++, idx += ENTRY_SIZE ) + { + if( count >= entries ) break; + + char data[12] = { '\0' }; + getRceEntry( i_buffer+idx, data ); + strcat( desc, data ); + } + i_parser.PrintString( header, desc ); + } + + return rc; +} + +//------------------------------------------------------------------------------ + bool parseDramRepairsData( uint8_t * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ) { diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H index 8a7c49391..c1bd89108 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H @@ -70,6 +70,15 @@ bool parseMemUeTable( uint8_t * i_buffer, uint32_t i_buflen, bool parseMemCeTable( uint8_t * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ); +/** + * @brief Parses Memory RCE table. + * @param i_buffer The data buffer. + * @param i_buflen The buffer length. + * @param i_parser The error log parser. + */ +bool parseMemRceTable( uint8_t * i_buffer, uint32_t i_buflen, + ErrlUsrParser & i_parser ); + /** * @brief Parses DRAM Repairs data (actual chip/symbol marks and DRAM repairs in * hardware). diff --git a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C index 71c693cb7..ea32141eb 100644 --- a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C +++ b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C @@ -321,6 +321,10 @@ bool parseCaptureData( void * i_buffer, uint32_t i_buflen, { parseMemCeTable( sigData, sigDataSize, i_parser ); } + else if ( Util::hashString("MEM_RCE_TABLE") == sigId ) + { + parseMemRceTable( sigData, sigDataSize, i_parser ); + } else if ( Util::hashString("DRAM_REPAIRS_DATA") == sigId ) { parseDramRepairsData( sigData, sigDataSize, i_parser ); diff --git a/src/usr/diag/prdf/common/plugins/prdfParserEnums.H b/src/usr/diag/prdf/common/plugins/prdfParserEnums.H index 4d40e287b..b049d0e5b 100644 --- a/src/usr/diag/prdf/common/plugins/prdfParserEnums.H +++ b/src/usr/diag/prdf/common/plugins/prdfParserEnums.H @@ -80,7 +80,16 @@ namespace CE_TABLE MAX_SIZE = MAX_ENTRIES * ENTRY_SIZE, ///< Maximum table size. }; -} // namespace UE_TABLE +} // namespace CE_TABLE + +namespace RCE_TABLE +{ + enum + { + ENTRY_SIZE = 2, ///< Number of bytes per entry. + }; + +} // namespace RCE_TABLE namespace DQ_BITMAP { diff --git a/src/usr/diag/prdf/common/prd_pegasus.mk b/src/usr/diag/prdf/common/prd_pegasus.mk index 5d7577c59..b74cad004 100755 --- a/src/usr/diag/prdf/common/prd_pegasus.mk +++ b/src/usr/diag/prdf/common/prd_pegasus.mk @@ -45,6 +45,7 @@ prd_pegasus_specific = \ prdfCenDqBitmap.o \ prdfCenMbaCaptureData.o \ prdfCenMbaCeTable.o \ + prdfCenMbaRceTable.o \ prdfCenMbaTdCtlr.o \ prdfCenMbaTdCtlr_common.o \ prdfCenMbaThresholds_common.o \ -- cgit v1.2.1