diff options
author | Zane Shelley <zshelle@us.ibm.com> | 2013-08-29 15:33:34 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-09-18 13:55:51 -0500 |
commit | 71f0f9b62fe2369493bd9f323423490a62abb85f (patch) | |
tree | a80d2e2e12a1350f6b56f8b305f98c4587361492 | |
parent | 61bd30cddc44108ea1f1cc72527f2ea52fd3f7e5 (diff) | |
download | talos-hostboot-71f0f9b62fe2369493bd9f323423490a62abb85f.tar.gz talos-hostboot-71f0f9b62fe2369493bd9f323423490a62abb85f.zip |
PRD: Memory UE table support
Change-Id: Ie4209c04c1b9b7da78318b410203768fef836db1
RTC: 81713
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5981
Tested-by: Jenkins Server
Reviewed-by: Christopher T. Phan <cphan@us.ibm.com>
Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Reviewed-by: Zane Shelley <zshelle@us.ibm.com>
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6230
12 files changed, 546 insertions, 112 deletions
diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMba.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMba.C index 1ff6265eb..fe4eb5a71 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMba.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMba.C @@ -87,14 +87,13 @@ int32_t MaintCmdComplete( ExtensibleChip * i_mbaChip, int32_t l_rc = SUCCESS; - TargetHandle_t mbaTarget = i_mbaChip->GetChipHandle(); CenMbaDataBundle * mbadb = getMbaDataBundle( i_mbaChip ); // Tell the TD controller that a maintenance command complete occurred. l_rc = mbadb->iv_tdCtlr.handleCmdCompleteEvent( i_sc ); if ( SUCCESS != l_rc ) { - PRDF_ERR( PRDF_FUNC"Failed: i_mbaChip=0x%08x", getHuid(mbaTarget) ); + PRDF_ERR( PRDF_FUNC"Failed: i_mbaChip=0x%08x", i_mbaChip->GetId() ); CalloutUtil::defaultError( i_sc ); } @@ -103,7 +102,7 @@ int32_t MaintCmdComplete( ExtensibleChip * i_mbaChip, // successful with no errors because the error log will not be // committed. if ( !i_sc.service_data->IsDontCommitErrl() ) - CenMbaCaptureData::addMemEccData( mbaTarget, i_sc ); + CenMbaCaptureData::addMemEccData( i_mbaChip, i_sc ); return PRD_NO_CLEAR_FIR_BITS; // FIR bits are cleared by this plugin diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C index 9a081ea18..371ea99a7 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.C @@ -29,13 +29,15 @@ #include <prdfCenMbaCaptureData.H> // Framwork includes -#include <utilmem.H> -#include <UtilHash.H> -#include <prdfDramRepairUsrData.H> #include <iipServiceDataCollector.h> +#include <prdfDramRepairUsrData.H> +#include <prdfExtensibleChip.H> #include <prdfRasServices.H> +#include <utilmem.H> +#include <UtilHash.H> // Pegasus includes +#include <prdfCenMbaDataBundle.H> #include <prdfCenMarkstore.H> #include <prdfCenDqBitmap.H> @@ -51,36 +53,42 @@ namespace CenMbaCaptureData //------------------------------------------------------------------------------ -void addMemEccData( TargetHandle_t i_mba, errlHndl_t io_errl ) +void addMemEccData( TargetHandle_t i_mbaTrgt, errlHndl_t io_errl ) { CaptureData cd; // Add DRAM repairs data from hardware. - captureDramRepairsData( i_mba, cd ); + captureDramRepairsData( i_mbaTrgt, cd ); // Add DRAM repairs data from VPD. - captureDramRepairsVpd( i_mba, cd ); + captureDramRepairsVpd( i_mbaTrgt, cd ); ErrDataService::AddCapData( cd, io_errl ); } //------------------------------------------------------------------------------ -void addMemEccData( TargetHandle_t i_mba, STEP_CODE_DATA_STRUCT & io_sc ) +void addMemEccData( ExtensibleChip * i_mbaChip, STEP_CODE_DATA_STRUCT & io_sc ) { CaptureData & cd = io_sc.service_data->GetCaptureData(); + CenMbaDataBundle * mbadb = getMbaDataBundle( i_mbaChip ); + TargetHandle_t mbaTarget = i_mbaChip->GetChipHandle(); + + // Add UE table to capture data. + mbadb->iv_ueTable.addCapData( mbaTarget, cd ); + // Add DRAM repairs data from hardware. - captureDramRepairsData( i_mba, cd ); + captureDramRepairsData( mbaTarget, cd ); // Add DRAM repairs data from VPD. - captureDramRepairsVpd( i_mba, cd ); + captureDramRepairsVpd( mbaTarget, cd ); } //------------------------------------------------------------------------------ -void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, - CaptureData & o_cd ) +void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTrgt, + CaptureData & io_cd ) { int32_t rc = SUCCESS; DramRepairMbaData mbaData; @@ -92,7 +100,7 @@ void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, // Get chip/symbol marks CenMark mark; - rc = PlatServices::mssGetMarkStore( i_mbaTarget, rank, mark ); + rc = PlatServices::mssGetMarkStore( i_mbaTrgt, rank, mark ); if ( SUCCESS != rc ) { PRDF_ERR("Failed to get markstore data"); @@ -101,7 +109,7 @@ void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, // Get DRAM spares CenSymbol sp0, sp1, ecc; - rc = PlatServices::mssGetSteerMux( i_mbaTarget, rank, sp0, sp1, ecc ); + rc = PlatServices::mssGetSteerMux( i_mbaTrgt, rank, sp0, sp1, ecc ); if ( SUCCESS != rc ) { PRDF_ERR("Failed to get DRAM steer data"); @@ -125,9 +133,9 @@ void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, { bool isCentaurDimm = true; mbaData.header.rankCount = mbaData.rankDataList.size(); - PlatServices::isMembufOnDimm( i_mbaTarget, isCentaurDimm ); + PlatServices::isMembufOnDimm( i_mbaTrgt, isCentaurDimm ); mbaData.header.isIsDimm = !isCentaurDimm; - mbaData.header.isX4Dram = PlatServices::isDramWidthX4( i_mbaTarget ); + mbaData.header.isX4Dram = PlatServices::isDramWidthX4( i_mbaTrgt ); UtilMem dramStream; dramStream << mbaData; @@ -153,14 +161,14 @@ void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, // Allocate space for the capture data. BIT_STRING_ADDRESS_CLASS dramRepairData ( 0, ( dramStream.size() )*8, (CPU_WORD *) dramStream.base() ); - o_cd.Add( i_mbaTarget, Util::hashString("DRAM_REPAIRS_DATA"), - dramRepairData ); + io_cd.Add( i_mbaTrgt, Util::hashString("DRAM_REPAIRS_DATA"), + dramRepairData ); } } //------------------------------------------------------------------------------ -void captureDramRepairsVpd( TargetHandle_t i_mba, CaptureData & io_cd ) +void captureDramRepairsVpd( TargetHandle_t i_mbaTrgt, CaptureData & io_cd ) { #define PRDF_FUNC "[captureDramRepairsVpd] " @@ -186,10 +194,10 @@ void captureDramRepairsVpd( TargetHandle_t i_mba, CaptureData & io_cd ) CenRank rank ( r ); CenDqBitmap bitmap; - if ( SUCCESS != getBadDqBitmap(i_mba, rank, bitmap, true) ) + if ( SUCCESS != getBadDqBitmap(i_mbaTrgt, rank, bitmap, true) ) { PRDF_ERR( PRDF_FUNC"getBadDqBitmap() failed: MBA=0x%08x rank=%d", - getHuid(i_mba), r ); + getHuid(i_mbaTrgt), r ); continue; // skip this rank } @@ -209,7 +217,7 @@ void captureDramRepairsVpd( TargetHandle_t i_mba, CaptureData & io_cd ) // Add data to capture data. BIT_STRING_ADDRESS_CLASS bs ( 0, sz_capData*8, (CPU_WORD *) &capData ); - io_cd.Add( i_mba, Util::hashString("DRAM_REPAIRS_VPD"), bs ); + io_cd.Add( i_mbaTrgt, Util::hashString("DRAM_REPAIRS_VPD"), bs ); #undef PRDF_FUNC } diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.H index b264ee31c..bc0cdb1a4 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCaptureData.H @@ -36,6 +36,7 @@ namespace PRDF { +class ExtensibleChip; struct STEP_CODE_DATA_STRUCT; namespace CenMbaCaptureData @@ -47,43 +48,42 @@ namespace CenMbaCaptureData * have an SDC (i.e. Restore DRAM Repairs, IPL MNFG CE Isolation). * @note The data will be limited and include things like the DRAM Repairs data * but will not include stuff like the CE/UE tables, because that - * information is not relevent during its intented uses. - * @param i_mba Target MBA. - * @param o_errl Target error log. + * information is not relevant during its intented uses. + * @param i_mbaTrgt An MBA target + * @param o_errl Error log. */ -void addMemEccData( TARGETING::TargetHandle_t i_mba, errlHndl_t io_errl ); +void addMemEccData( TARGETING::TargetHandle_t i_mbaTrgt, errlHndl_t io_errl ); /** * @brief Adds Memory ECC FFDC to an SDC. - * @param i_mba Target MBA. - * @param io_sc Target step code data struct. + * @param i_mbaChip An MBA chip. + * @param io_sc Step code data struct. */ -void addMemEccData( TARGETING::TargetHandle_t i_mba, - STEP_CODE_DATA_STRUCT & io_sc ); +void addMemEccData( ExtensibleChip * i_mbaChip, STEP_CODE_DATA_STRUCT & io_sc ); /** * @brief Queries hardware for all DRAM repairs data (chip/symbol marks, DRAM * spare, etc.) for the given MBA and added it to the capture data. - * @param i_mbaTarget An MBA target. - * @param o_cd Capture data struct. + * @param i_mbaTrgt An MBA target. + * @param io_cd Capture data struct. * @note This function will be used to capture DRAM repair data into * capture data struct. Other functions can call this function and - * update error log + * update error log. */ -void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTarget, - CaptureData & o_cd ); +void captureDramRepairsData( TARGETING::TargetHandle_t i_mbaTrgt, + CaptureData & io_cd ); /** * @brief Queries the Bad DQ attributes for the content of the DRAM repairs VPD * and add it to the capture data. - * @param i_mbaTarget An MBA target. - * @param o_cd Capture data struct. + * @param i_mbaTrgt An MBA target. + * @param io_cd Capture data struct. * @note This function will be used to capture DRAM repair data into * capture data struct. Other functions can call this function and - * update error log + * update error log. */ -void captureDramRepairsVpd( TARGETING::TargetHandle_t i_mba, - CaptureData & o_cd ); +void captureDramRepairsVpd( TARGETING::TargetHandle_t i_mbaTrgt, + CaptureData & io_cd ); } // end namespace MbaCaptureData 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 ecda1af5b..fc6eadafa 100644 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaDataBundle_common.H @@ -36,6 +36,7 @@ // Pegasus includes #include <prdfCenMbaTdCtlr.H> +#include <prdfCenMbaUeTable.H> namespace PRDF { @@ -52,7 +53,8 @@ class CenMbaDataBundleCommon : public DataBundle * @param i_mbaChip The MBA chip. */ explicit CenMbaDataBundleCommon( ExtensibleChip * i_mbaChip ) : - iv_mbaChip(i_mbaChip), iv_membChip(NULL), iv_tdCtlr(i_mbaChip) + iv_mbaChip(i_mbaChip), iv_membChip(NULL), iv_tdCtlr(i_mbaChip), + iv_ueTable() {} /** @@ -88,11 +90,13 @@ class CenMbaDataBundleCommon : public DataBundle ExtensibleChip * iv_mbaChip; ///< This MBA chip private: // instance variables + ExtensibleChip * iv_membChip; ///< The connected MEMBUF chip public: // instance variables - CenMbaTdCtlr iv_tdCtlr; ///< Targeted Diagnostics Controller + CenMbaTdCtlr iv_tdCtlr; ///< Targeted Diagnostics Controller + CenMbaUeTable iv_ueTable; ///< UE table for FFDC }; diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.C new file mode 100755 index 000000000..4c8217157 --- /dev/null +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.C @@ -0,0 +1,125 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.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 <prdfCenMbaUeTable.H> + +#include <algorithm> + +// Framwork includes +#include <iipServiceDataCollector.h> +#include <UtilHash.H> + +using namespace TARGETING; + +namespace PRDF +{ + +using namespace UE_TABLE; + +//------------------------------------------------------------------------------ + +void CenMbaUeTable::addEntry( UE_TABLE::Type i_type, const CenAddr & i_addr ) +{ + // Create the new entry. + UeTableData data ( i_type, i_addr ); + + // First, check if the entry already exists. If so, increment its count and + // move it to the end of the queue. + UeTable::iterator it = std::find( iv_table.begin(), iv_table.end(), data ); + if ( iv_table.end() != it ) + { + // Update the count + data.count = it->count; + if ( MAX_ENTRY_COUNT > data.count ) + data.count++; + + // Remove the old entry + iv_table.erase( it ); + } + + // Pop off the oldest entry if the table is full. + if ( MAX_ENTRIES == iv_table.size() ) + iv_table.pop_front(); + + // Add the new entry to the end of the list. + iv_table.push_back( data ); +} + +//------------------------------------------------------------------------------ + +void CenMbaUeTable::addCapData( TargetHandle_t i_mbaTrgt, + CaptureData & io_cd ) +{ + static const size_t sz_word = sizeof(CPU_WORD); + + // Get the maximum capture data size and adjust the size for endianess. + static const size_t sz_maxData = ((MAX_SIZE+sz_word-1) / sz_word) * sz_word; + + // Initialize to 0. + uint8_t data[sz_maxData]; + memset( data, 0x00, sz_maxData ); + + size_t sz_actData = 0; + + for ( UeTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ ) + { + uint32_t mrnk = it->addr.getRank().getMaster(); // 3-bit + uint32_t srnk = it->addr.getRank().getSlave(); // 3-bit + uint32_t svld = it->addr.getRank().isSlaveValid() ? 1 : 0; // 1-bit + uint32_t bnk = it->addr.getBank(); // 4-bit + uint32_t row = it->addr.getRow(); // 17-bit + uint32_t col = it->addr.getCol(); // 12-bit + + uint8_t row0 = (row & 0x10000) >> 16; + uint8_t row1_8 = (row & 0x0ff00) >> 8; + uint8_t row9_16 = row & 0x000ff; + + uint8_t col0_3 = (col & 0xf00) >> 8; + uint8_t col4_11 = col & 0x0ff; + + data[sz_actData ] = it->count; + data[sz_actData+1] = it->type << 4; // 4 bits to spare. + data[sz_actData+2] = (mrnk << 5) | (srnk << 2) | (svld << 1) | row0; + data[sz_actData+3] = row1_8; + data[sz_actData+4] = row9_16; + data[sz_actData+5] = (bnk << 4) | col0_3; + data[sz_actData+6] = col4_11; + + sz_actData += ENTRY_SIZE; + } + + if ( 0 != sz_actData ) + { + // 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_UE_TABLE"), bs ); + } +} + +} // end namespace PRDF + diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.H new file mode 100755 index 000000000..148b28fcf --- /dev/null +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.H @@ -0,0 +1,121 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaUeTable.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 __prdfCenMbaUeTable_H +#define __prdfCenMbaUeTable_H + +/** @file prdfCenMbaUeTable.H */ + +// Framwork includes +#include <iipCaptureData.h> +#include <prdfParserEnums.H> +#include <prdfPlatServices.H> + +// Pegasus includes +#include <prdfCenAddress.H> + +// Other includes +#include <list> + +namespace PRDF +{ + +/** + * @brief A table of memory UEs. + * @note Only one of these tables will exists per MBA. + * @note So far, this table is used only for FFDC. + */ +class CenMbaUeTable +{ + + private: // constants, enums + + /** @brief Table size limits. */ + enum TableTHs + { + MAX_ENTRY_COUNT = 255, ///< Entry count threshold + }; + + public: // functions + + /** + * @brief Will attempt to add a new entry to the table. + * @note If an entry already exists, the entry's count is incremented and + * moved to the end of the queue. + * @param i_type See enum UE_TABLE::Type. + * @param i_addr The address in which the UE occured. + */ + void addEntry( UE_TABLE::Type i_type, const CenAddr & i_addr ); + + /** + * @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 ); + + private: // structs, typedefs + + /** @brief Individual entries of iv_table. */ + struct UeTableData + { + UE_TABLE::Type type; ///< See enum UE_TABLE::Type + CenAddr addr; ///< The address in which the UE occured + uint8_t count; ///< Number of times the entry is detected + + /** @brief Default constructor. */ + UeTableData() {} + + /** + * @brief Constructor from components. + * @param i_type See enum UE_TABLE::Type. + * @param i_addr The address in which the UE occured. + */ + UeTableData( UE_TABLE::Type i_type, const CenAddr & i_addr ) : + type(i_type), addr(i_addr), count(1) + {} + + /** An entry is equivalent if the type and address match. */ + bool operator==( const UeTableData & i_data ) const + { + return ( this->type == i_data.type && this->addr == i_data.addr ); + } + }; + + typedef std::list<UeTableData> UeTable; + + private: // instance variables + + /** A FIFO that stores the latest memory UE addresses and their types. This + * is not a pure FIFO, because if a new entry matches an existing entry, + * the existing entries count is incremented and it is moved to the end of + * the queue. However, if a new entry does not match an existing entry and + * the table is full, the oldest entry will be removed to make room for + * the new entry. */ + UeTable iv_table; +}; + +} // end namespace PRDF + +#endif // __prdfCenMbaUeTable_H + diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMembuf.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMembuf.C index 32f55e715..85ad9f048 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMembuf.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMembuf.C @@ -406,28 +406,45 @@ int32_t AnalyzeMpe( ExtensibleChip * i_membChip, STEP_CODE_DATA_STRUCT & i_sc, int32_t l_rc = SUCCESS; - TargetHandle_t mbaTrgt = NULL; + ExtensibleChip * mbaChip = NULL; do { CenMembufDataBundle * membdb = getMembufDataBundle( i_membChip ); - ExtensibleChip * mbaChip = membdb->getMbaChip( i_mbaPos ); + mbaChip = membdb->getMbaChip( i_mbaPos ); if ( NULL == mbaChip ) { PRDF_ERR( PRDF_FUNC"getMbaChip() returned NULL" ); l_rc = FAIL; break; } - mbaTrgt = mbaChip->GetChipHandle(); + CenMbaDataBundle * mbadb = getMbaDataBundle( mbaChip ); + TargetHandle_t mbaTrgt = mbaChip->GetChipHandle(); // Add address to UE table. if ( isFetchError ) { - // TODO: RTC 81713 Add fetch address to UE table. + CenReadAddrReg reg = (0 == i_mbaPos) ? READ_MPE_ADDR_0 + : READ_MPE_ADDR_1; + CenAddr addr; + l_rc = getCenReadAddr( i_membChip, reg, addr ); + if ( SUCCESS != l_rc ) + { + PRDF_ERR( PRDF_FUNC"getCenReadAddr() failed" ); + break; + } + mbadb->iv_ueTable.addEntry( UE_TABLE::FETCH_MPE, addr ); } else { - // TODO: RTC 81713 Add maintenance address to UE table. + CenAddr addr; + l_rc = getCenMaintStartAddr( mbaChip, addr ); + if ( SUCCESS != l_rc ) + { + PRDF_ERR( PRDF_FUNC"getCenMaintStartAddr() failed" ); + break; + } + mbadb->iv_ueTable.addEntry( UE_TABLE::SCRUB_MPE, addr ); } // Get the current mark in hardware. @@ -450,7 +467,6 @@ int32_t AnalyzeMpe( ExtensibleChip * i_membChip, STEP_CODE_DATA_STRUCT & i_sc, CalloutUtil::calloutMark( mbaTrgt, rank, mark, i_sc ); // Tell TD controller to handle VCM event. - CenMbaDataBundle * mbadb = getMbaDataBundle( mbaChip ); l_rc = mbadb->iv_tdCtlr.handleTdEvent( i_sc, rank, CenMbaTdCtlrCommon::VCM_EVENT ); if ( SUCCESS != l_rc ) @@ -462,8 +478,8 @@ int32_t AnalyzeMpe( ExtensibleChip * i_membChip, STEP_CODE_DATA_STRUCT & i_sc, } while (0); // Add ECC capture data for FFDC. - if ( NULL != mbaTrgt ) - CenMbaCaptureData::addMemEccData( mbaTrgt, i_sc ); + if ( NULL != mbaChip ) + CenMbaCaptureData::addMemEccData( mbaChip, i_sc ); if ( SUCCESS != l_rc ) { @@ -493,20 +509,18 @@ int32_t AnalyzeFetchNce( ExtensibleChip * i_membChip, int32_t l_rc = SUCCESS; - TargetHandle_t mbaTrgt = NULL; + ExtensibleChip * mbaChip = NULL; do { CenMembufDataBundle * membdb = getMembufDataBundle( i_membChip ); - ExtensibleChip * mbaChip = membdb->getMbaChip( i_mbaPos ); + mbaChip = membdb->getMbaChip( i_mbaPos ); if ( NULL == mbaChip ) { PRDF_ERR( PRDF_FUNC"getMbaChip() returned NULL" ); l_rc = FAIL; break; } - mbaTrgt = mbaChip->GetChipHandle(); - CenReadAddrReg reg = (0 == i_mbaPos) ? READ_NCE_ADDR_0 : READ_NCE_ADDR_1; CenAddr addr; @@ -522,15 +536,15 @@ int32_t AnalyzeFetchNce( ExtensibleChip * i_membChip, // workaround but is it complicated. Need to check with Ken if it // is ok to just callout the rank for DD1.x. - MemoryMru memmru ( mbaTrgt, addr.getRank(), + MemoryMru memmru ( mbaChip->GetChipHandle(), addr.getRank(), MemoryMruData::CALLOUT_RANK ); i_sc.service_data->SetCallout( memmru ); } while (0); // Add ECC capture data for FFDC. - if ( NULL != mbaTrgt ) - CenMbaCaptureData::addMemEccData( mbaTrgt, i_sc ); + if ( NULL != mbaChip ) + CenMbaCaptureData::addMemEccData( mbaChip, i_sc ); if ( SUCCESS != l_rc ) { @@ -560,20 +574,18 @@ int32_t AnalyzeFetchRce( ExtensibleChip * i_membChip, int32_t l_rc = SUCCESS; - TargetHandle_t mbaTrgt = NULL; + ExtensibleChip * mbaChip = NULL; do { CenMembufDataBundle * membdb = getMembufDataBundle( i_membChip ); - ExtensibleChip * mbaChip = membdb->getMbaChip( i_mbaPos ); + mbaChip = membdb->getMbaChip( i_mbaPos ); if ( NULL == mbaChip ) { PRDF_ERR( PRDF_FUNC"getMbaChip() returned NULL" ); l_rc = FAIL; break; } - mbaTrgt = mbaChip->GetChipHandle(); - CenReadAddrReg reg = (0 == i_mbaPos) ? READ_RCE_ADDR_0 : READ_RCE_ADDR_1; CenAddr addr; @@ -592,8 +604,8 @@ int32_t AnalyzeFetchRce( ExtensibleChip * i_membChip, } while (0); // Add ECC capture data for FFDC. - if ( NULL != mbaTrgt ) - CenMbaCaptureData::addMemEccData( mbaTrgt, i_sc ); + if ( NULL != mbaChip ) + CenMbaCaptureData::addMemEccData( mbaChip, i_sc ); if ( SUCCESS != l_rc ) { @@ -623,7 +635,7 @@ int32_t AnalyzeFetchUe( ExtensibleChip * i_membChip, int32_t l_rc = SUCCESS; - TargetHandle_t mbaTrgt = NULL; + ExtensibleChip * mbaChip = NULL; do { @@ -633,15 +645,13 @@ int32_t AnalyzeFetchUe( ExtensibleChip * i_membChip, i_sc.service_data->SetServiceCall(); CenMembufDataBundle * membdb = getMembufDataBundle( i_membChip ); - ExtensibleChip * mbaChip = membdb->getMbaChip( i_mbaPos ); + mbaChip = membdb->getMbaChip( i_mbaPos ); if ( NULL == mbaChip ) { PRDF_ERR( PRDF_FUNC"getMbaChip() returned NULL" ); l_rc = FAIL; break; } - mbaTrgt = mbaChip->GetChipHandle(); - CenReadAddrReg reg = (0 == i_mbaPos) ? READ_UE_ADDR_0 : READ_UE_ADDR_1; CenAddr addr; @@ -652,6 +662,10 @@ int32_t AnalyzeFetchUe( ExtensibleChip * i_membChip, break; } + // Add address to UE table. + CenMbaDataBundle * mbadb = getMbaDataBundle( mbaChip ); + mbadb->iv_ueTable.addEntry( UE_TABLE::FETCH_UE, addr ); + // Callout the rank. MemoryMru memmru ( mbaChip->GetChipHandle(), addr.getRank(), MemoryMruData::CALLOUT_RANK ); @@ -660,8 +674,8 @@ int32_t AnalyzeFetchUe( ExtensibleChip * i_membChip, } while (0); // Add ECC capture data for FFDC. - if ( NULL != mbaTrgt ) - CenMbaCaptureData::addMemEccData( mbaTrgt, i_sc ); + if ( NULL != mbaChip ) + CenMbaCaptureData::addMemEccData( mbaChip, i_sc ); if ( SUCCESS != l_rc ) { diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C index 85b002b2d..21647ccea 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C @@ -33,32 +33,19 @@ #include <prdfDramRepairUsrData.H> #include <prdfMemoryMruData.H> +#include <prdfParserEnums.H> namespace PRDF { + +using namespace PARSER; + #ifdef PRDF_HOSTBOOT_ERRL_PLUGIN namespace HOSTBOOT #else namespace FSP #endif { -//------------------------------------------------------------------------------ -// Constants/structs/enums -//------------------------------------------------------------------------------ - -enum -{ - // This is defined in a file we can't include into the error log parser. - DIMM_DQ_RANK_BITMAP_SIZE = 10, - - // Used for the several functions that parse bad DQ bitmaps. - BITMAP_RANK_SIZE = sizeof(uint8_t), - BITMAP_DATA_SIZE = PORT_SLCT_PER_MBA * DIMM_DQ_RANK_BITMAP_SIZE, - BITMAP_ENTRY_SIZE = BITMAP_RANK_SIZE + BITMAP_DATA_SIZE, - - PARSER_HEADER_SIZE = 25, - PARSER_DATA_SIZE = 50, -}; //------------------------------------------------------------------------------ // Helper functions @@ -80,21 +67,21 @@ void getDramRepairSymbolStr( uint8_t i_value, char * o_str, uint32_t i_strSize ) // Gets the string representation for a single bad DQ bitmap entry. void getBadDqBitmapEntry( uint8_t * i_buffer, char * o_str ) { - UtilMem membuf( i_buffer, BITMAP_ENTRY_SIZE ); + UtilMem membuf( i_buffer, DQ_BITMAP::ENTRY_SIZE ); uint8_t rank; membuf >> rank; - snprintf( o_str, PARSER_DATA_SIZE, "R:%1d", rank ); + snprintf( o_str, DATA_SIZE, "R:%1d", rank ); for ( int32_t p = 0; p < PORT_SLCT_PER_MBA; p++ ) { - char temp[PARSER_DATA_SIZE]; + char temp[DATA_SIZE]; strcat( o_str, " " ); - for ( int32_t b = 0; b < DIMM_DQ_RANK_BITMAP_SIZE; b++ ) + for ( int32_t b = 0; b < DQ_BITMAP::BITMAP_SIZE; b++ ) { uint8_t byte; membuf >> byte; - snprintf( temp, PARSER_DATA_SIZE, "%02x", byte ); + snprintf( temp, DATA_SIZE, "%02x", byte ); strcat( o_str, temp ); } } @@ -114,32 +101,32 @@ bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ) uint8_t cenPos = (mm.s.procPos << 3) | mm.s.cenPos; uint8_t mbaPos = mm.s.mbaPos; - char tmp[PARSER_HEADER_SIZE] = { '\0' }; + char tmp[HEADER_SIZE] = { '\0' }; if ( 1 == mm.s.srankValid ) - snprintf( tmp, PARSER_HEADER_SIZE, "S%d", mm.s.srank ); + snprintf( tmp, HEADER_SIZE, "S%d", mm.s.srank ); - char header[PARSER_HEADER_SIZE]; - snprintf( header, PARSER_HEADER_SIZE, " mba(n%dp%dc%d)%s Rank:M%d%s", + char header[HEADER_SIZE]; + snprintf( header, HEADER_SIZE, " mba(n%dp%dc%d)%s Rank:M%d%s", nodePos, cenPos, mbaPos, (cenPos < 10) ? " " : "", mm.s.mrank, tmp ); - char data[PARSER_DATA_SIZE]; + char data[DATA_SIZE]; switch ( mm.s.symbol ) { case MemoryMruData::CALLOUT_RANK: - snprintf( data, PARSER_DATA_SIZE, "Special: CALLOUT_RANK" ); + snprintf( data, DATA_SIZE, "Special: CALLOUT_RANK" ); break; case MemoryMruData::CALLOUT_RANK_AND_MBA: - snprintf( data, PARSER_DATA_SIZE, "Special: CALLOUT_RANK_AND_MBA" ); + snprintf( data, DATA_SIZE, "Special: CALLOUT_RANK_AND_MBA" ); break; case MemoryMruData::CALLOUT_ALL_MEM: - snprintf( data, PARSER_DATA_SIZE, "Special: CALLOUT_ALL_MEM" ); + snprintf( data, DATA_SIZE, "Special: CALLOUT_ALL_MEM" ); break; default: // TODO: RTC 67358 Symbol, Pins, and Spared will be replaced with // the DRAM Site Location and Wiring Type. - snprintf( data, PARSER_DATA_SIZE, "Symbol: %d Pins: %d Spared: %s", + snprintf( data, DATA_SIZE, "Symbol: %d Pins: %d Spared: %s", mm.s.symbol, mm.s.pins, (1 == mm.s.dramSpared) ? "true" : "false" ); } @@ -155,6 +142,82 @@ bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ) //------------------------------------------------------------------------------ +bool parseMemUeTable( uint8_t * i_buffer, uint32_t i_buflen, + ErrlUsrParser & i_parser ) +{ + using namespace UE_TABLE; + + bool rc = true; + + if ( NULL == i_buffer ) return false; // Something failed in parser. + + const uint32_t entries = i_buflen / ENTRY_SIZE; + + i_parser.PrintNumber( " MEM_UE_TABLE", "%d", entries ); + + const char * hh = " Count Type"; + const char * hd = "Rank Bank Row Column"; + i_parser.PrintString( hh, hd ); + hh = " ----- -------------"; + hd = "---- ---- ------- ------"; + i_parser.PrintString( hh, hd ); + + for ( uint32_t i = 0; i < entries; i++ ) + { + uint32_t idx = i * ENTRY_SIZE; + + uint32_t count = i_buffer[idx ]; // 8-bit + uint32_t type = i_buffer[idx+1] >> 4; // 4-bit + + uint32_t mrnk = (i_buffer[idx+2] >> 5) & 0x7; // 3-bit + uint32_t srnk = (i_buffer[idx+2] >> 2) & 0x7; // 3-bit + uint32_t svld = (i_buffer[idx+2] >> 1) & 0x1; // 1-bit + + uint32_t row0 = i_buffer[idx+2] & 0x1; + uint32_t row1_8 = i_buffer[idx+3]; + uint32_t row9_16 = i_buffer[idx+4]; + uint32_t row = (row0 << 16) | (row1_8 << 8) | row9_16; // 17-bit + + uint32_t bnk = i_buffer[idx+5] >> 4; // 4-bit + + uint32_t col0_3 = i_buffer[idx+5] & 0xf; + uint32_t col4_11 = i_buffer[idx+6]; + uint32_t col = (col0_3 << 8) | col4_11; // 12-bit + + const char * type_str = "UNKNOWN "; // 13 characters + switch ( type ) + { + case SCRUB_MPE: type_str = "SCRUB_MPE "; break; + case FETCH_MPE: type_str = "FETCH_MPE "; break; + case SCRUB_UE: type_str = "SCRUB_UE "; break; + case FETCH_UE: type_str = "FETCH_UE "; break; + } + + char rank_str[DATA_SIZE]; // 4 characters + if ( 1 == svld ) + { + snprintf( rank_str, DATA_SIZE, "m%ds%d", mrnk, srnk ); + } + else + { + snprintf( rank_str, DATA_SIZE, "m%d ", mrnk ); + } + + char header[HEADER_SIZE] = { '\0' }; + snprintf( header, HEADER_SIZE, " 0x%02x %s", count, type_str ); + + char data[DATA_SIZE] = { '\0' }; + snprintf( data, DATA_SIZE, "%s 0x%01x 0x%05x 0x%03x", + rank_str, bnk, row, col ); + + i_parser.PrintString( header, data ); + } + + return rc; +} + +//------------------------------------------------------------------------------ + bool parseDramRepairsData( uint8_t * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ) { @@ -169,7 +232,7 @@ bool parseDramRepairsData( uint8_t * i_buffer, uint32_t i_buflen, uint8_t rankCount = mbaData.header.rankCount; - i_parser.PrintNumber( " DRAM_REPAIRS_DATA", "0x%02x", rankCount ); + i_parser.PrintNumber( " DRAM_REPAIRS_DATA", "%d", rankCount ); // Iterate over all ranks for ( uint8_t rankIdx = 0; rankIdx < rankCount; rankIdx++ ) @@ -230,14 +293,14 @@ bool parseDramRepairsVpd( uint8_t * i_buffer, uint32_t i_buflen, if ( NULL == i_buffer ) return false; // Something failed in parser. - const uint32_t entries = i_buflen / BITMAP_ENTRY_SIZE; + const uint32_t entries = i_buflen / DQ_BITMAP::ENTRY_SIZE; - i_parser.PrintNumber( " DRAM_REPAIRS_VPD", "0x%02x", entries ); + i_parser.PrintNumber( " DRAM_REPAIRS_VPD", "%d", entries ); for ( uint32_t i = 0; i < entries; i++ ) { - char data[PARSER_DATA_SIZE]; - getBadDqBitmapEntry( &i_buffer[i*BITMAP_ENTRY_SIZE], data ); + char data[DATA_SIZE]; + getBadDqBitmapEntry( &i_buffer[i*DQ_BITMAP::ENTRY_SIZE], data ); i_parser.PrintString( "", data ); } @@ -254,14 +317,14 @@ bool parseBadDqBitmap( uint8_t * i_buffer, uint32_t i_buflen, if ( NULL == i_buffer ) return false; // Something failed in parser. - if ( BITMAP_ENTRY_SIZE > i_buflen ) // Data is expected to be one entry. + if ( DQ_BITMAP::ENTRY_SIZE > i_buflen ) // Data is expected to be one entry. { i_parser.PrintString( " BAD_DQ_BITMAP", "" ); i_parser.PrintHexDump(i_buffer, i_buflen); } else { - char data[PARSER_DATA_SIZE]; + char data[DATA_SIZE]; getBadDqBitmapEntry( i_buffer, data ); i_parser.PrintString( " BAD_DQ_BITMAP", data ); diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H index d1a7e5f6e..c2695b10d 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H @@ -21,7 +21,7 @@ /* */ /* IBM_PROLOG_END_TAG */ -/** @file prdfCenLogParse.C +/** @file prdfCenLogParse.H * @brief Error log parsing code specific to the memory subsystem. */ @@ -53,6 +53,15 @@ namespace FSP bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ); /** + * @brief Parses Memory UE table. + * @param i_buffer The data buffer. + * @param i_buflen The buffer length. + * @param i_parser The error log parser. + */ +bool parseMemUeTable( 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). * @param i_buffer The data buffer. diff --git a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C index 9e02af728..78f152789 100644 --- a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C +++ b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C @@ -313,6 +313,10 @@ bool parseCaptureData( void * i_buffer, uint32_t i_buflen, { i_parser.PrintString( sigHeaderString, "No Data Found" ); } + else if ( Util::hashString("MEM_UE_TABLE") == sigId ) + { + parseMemUeTable( 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 new file mode 100644 index 000000000..d720639f8 --- /dev/null +++ b/src/usr/diag/prdf/common/plugins/prdfParserEnums.H @@ -0,0 +1,86 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plugins/prdfParserEnums.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 */ + +/** @file prdfParserEnums.H + * @brief Common enums used for building and parsing capture data. + */ + +#ifndef __prdfParserEnums_H +#define __prdfParserEnums_H + +#include <prdfCenConst.H> + +namespace PRDF +{ + +namespace PARSER +{ + enum + { + // i_parser.PrintString() has two parts: header and data. These are the + // maximum string lengths for one line in the error log. Note that the + // header has a hard stop of one line, however, the data can wrap onto + // multiple lines (not sure of the line limit). + HEADER_SIZE = 25, + DATA_SIZE = 50, + }; + +} // namespace PARSER + +namespace UE_TABLE +{ + enum + { + MAX_ENTRIES = 16, ///< Maximum number of entries allow in table. + ENTRY_SIZE = 7, ///< Number of bytes per entry. + + MAX_SIZE = MAX_ENTRIES * ENTRY_SIZE, ///< Maximum table size. + }; + + /** + * @brief Represents the several different types of UEs stored in the table. + */ + enum Type + { + SCRUB_MPE = 1, ///< Chip mark placed by scrub + FETCH_MPE, ///< Chip mark placed by fetch + SCRUB_UE, ///< Scrub UE + FETCH_UE, ///< Fetch UE + }; + +} // namespace UE_TABLE + +namespace DQ_BITMAP +{ + enum + { + BITMAP_SIZE = 10, // 80-bit bitmap + ENTRY_SIZE = sizeof(uint8_t) + PORT_SLCT_PER_MBA * BITMAP_SIZE, + }; + +} // namespace DQ_BITMAP + +} // end namespace PRDF + +#endif // __prdfParserEnums_H + diff --git a/src/usr/diag/prdf/common/prd_pegasus.mk b/src/usr/diag/prdf/common/prd_pegasus.mk index 026dd7228..055074e1f 100755 --- a/src/usr/diag/prdf/common/prd_pegasus.mk +++ b/src/usr/diag/prdf/common/prd_pegasus.mk @@ -45,11 +45,12 @@ prd_pegasus_specific = \ prdfCenMbaCaptureData.o \ prdfCenMbaTdCtlr.o \ prdfCenMbaTdCtlr_common.o \ + prdfCenMbaThresholds_common.o \ + prdfCenMbaUeTable.o \ + prdfCenMemUtils.o \ prdfCenSymbol.o \ prdfLaneRepair.o \ prdfLineDelete.o \ prdfMemoryMru.o \ prdfPegasusConfigurator.o \ - prdfCenMbaThresholds_common.o \ - prdfCenMemUtils.o \ prdfRegisterData.o |