diff options
Diffstat (limited to 'src/usr/diag')
-rw-r--r-- | src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C | 519 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.H | 39 |
2 files changed, 502 insertions, 56 deletions
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C index c9ea58493..6ee25b70c 100644 --- a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C +++ b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C @@ -27,7 +27,13 @@ // Framework includes #include <iipCaptureData.h> +#include <iipSystem.h> +#include <prdfDramRepairUsrData.H> #include <prdfErrlUtil.H> +#include <prdfGlobal.H> +#include <prdfMemMark.H> +#include <UtilHash.H> +#include <utilmem.H> // Platform includes #include <prdfPlatServices.H> @@ -45,62 +51,6 @@ namespace MemCaptureData //------------------------------------------------------------------------------ -template<> -void addEccData<TYPE_MCA>( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & io_sc ) -{ - PRDF_ASSERT( TYPE_MCA == i_chip->getType() ); - - CaptureData & cd = io_sc.service_data->GetCaptureData(); - McaDataBundle * db = getMcaDataBundle( i_chip ); - - // Add CE table to capture data. - db->iv_ceTable.addCapData( cd ); - - // Add UE table to capture data. - db->iv_ueTable.addCapData( cd ); -} - -template<> -void addEccData<TYPE_MCBIST>( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & io_sc ) -{ - PRDF_ASSERT( TYPE_MCBIST == i_chip->getType() ); - - // Add data for each connected MCA. - ExtensibleChipList list = getConnected( i_chip, TYPE_MCA ); - for ( auto & mcaChip : list ) { addEccData<TYPE_MCA>(mcaChip, io_sc); } -} - -template<> -void addEccData<TYPE_MBA>( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & io_sc ) -{ - PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); - -/* TODO: RTC 157888 - CaptureData & cd = io_sc.service_data->GetCaptureData(); - CenMbaDataBundle * db = getMbaDataBundle( i_chip ); - - // Add UE table to capture data. - db->iv_ueTable.addCapData( i_chip, cd ); - - // Add CE table to capture data. - db->iv_ceTable.addCapData( cd ); - - // Add RCE table to capture data. - db->iv_rceTable.addCapData( cd ); - - // Add DRAM repairs data from hardware. - captureDramRepairsData( i_chip->getTrgt(), cd ); - - // Add DRAM repairs data from VPD. - captureDramRepairsVpd( i_chip->getTrgt(), cd ); -*/ -} - -//------------------------------------------------------------------------------ - void addExtMemMruData( const MemoryMru & i_memMru, errlHndl_t io_errl ) { #define PRDF_FUNC "[addExtMemMruData] " @@ -186,6 +136,463 @@ void addExtMemMruData( const MemoryMru & i_memMru, errlHndl_t io_errl ) //------------------------------------------------------------------------------ +template<> +void captureDramRepairsData<TYPE_MCA>( TARGETING::TargetHandle_t i_trgt, + CaptureData & io_cd ) +{ + #define PRDF_FUNC "[captureDramRepairsData<TYPE_MCA>] " + + int32_t rc = SUCCESS; + DramRepairUsrData mcaData; + mcaData.header.isSpareDram = false; + + ExtensibleChip * mcaChip = (ExtensibleChip *)systemPtr->GetChip( i_trgt ); + std::vector<MemRank> masterRanks; + + do + { + getMasterRanks<TYPE_MCA>( i_trgt, masterRanks ); + if( masterRanks.empty() ) + { + PRDF_ERR( PRDF_FUNC "Master Rank list size is 0"); + break; + } + + // Iterate all ranks to get DRAM repair data + for ( auto & rank : masterRanks ) + { + // Get chip/symbol marks + MemMark cm, sm; + rc = MarkStore::readChipMark<TYPE_MCA>( mcaChip, rank, cm ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "readChipMark<TYPE_MCA>(0x%08x,0x%02x) " + "failed", mcaChip->getHuid(), rank.getKey() ); + continue; + } + + rc = MarkStore::readSymbolMark<TYPE_MCA>( mcaChip, rank, sm ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "readSymbolMark<TYPE_MCA>(0x%08x,0x%02x) " + "failed", mcaChip->getHuid(), rank.getKey() ); + continue; + } + + if ( cm.isValid() && sm.isValid() ) + { + // Add data + DramRepairRankData rankData = { rank.getMaster(), + cm.getSymbol().getSymbol(), + sm.getSymbol().getSymbol() }; + mcaData.rankDataList.push_back(rankData); + } + } + // If MCA had some DRAM repair data, add header information + if( mcaData.rankDataList.size() > 0 ) + { + mcaData.header.rankCount = mcaData.rankDataList.size(); + mcaData.header.isX4Dram = isDramWidthX4( i_trgt ); + UtilMem dramStream; + dramStream << mcaData; + + // TODO RTC 179854 + #ifndef PPC + // Fix endianness issues with non PPC machines. + // This is a workaround. Though UtilMem takes care of endianness, + // It seems with capture data its not working + const size_t sz_word = sizeof(uint32_t); + + // Align data with 32 bit boundary + for (uint32_t i = 0; i < ( dramStream.size()%sz_word ); i++) + { + uint8_t dummy = 0; + dramStream << dummy; + } + for ( uint32_t i = 0; i < ( dramStream.size()/sz_word); i++ ) + { + ((uint32_t*)dramStream.base())[i] = + htonl(((uint32_t*)dramStream.base())[i]); + } + #endif + + // Allocate space for the capture data. + BitString dramRepairData ( ( dramStream.size() )*8, + (CPU_WORD *) dramStream.base() ); + io_cd.Add( i_trgt, Util::hashString("DRAM_REPAIRS_DATA"), + dramRepairData ); + } + }while(0); + + if( FAIL == rc ) + PRDF_ERR( PRDF_FUNC "Failed for MCA 0x%08X", getHuid( i_trgt ) ); + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +void captureDramRepairsData<TYPE_MBA>( TARGETING::TargetHandle_t i_trgt, + CaptureData & io_cd ) +{ + #define PRDF_FUNC "[CenMbaCaptureData::captureDramRepairsData] " + /* TODO RTC 178911 + using namespace fapi; // for spare config + + int32_t rc = SUCCESS; + DramRepairMbaData mbaData; + + mbaData.header.isSpareDram = false; + std::vector<CenRank> masterRanks; + + do + { + rc = getMasterRanks( i_mbaTrgt, masterRanks ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "getMasterRanks() failed" ); + break; + } + if( masterRanks.empty() ) + { + PRDF_ERR( PRDF_FUNC "Master Rank list size is 0"); + break;; + } + uint8_t spareConfig = ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE; + // check for spare DRAM. Port does not matter. + // Also this configuration is same for all ranks on MBA. + rc = getDimmSpareConfig( i_mbaTrgt, masterRanks[0], 0, spareConfig ); + if( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "getDimmSpareConfig() failed" ); + break; + } + + if( ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE != spareConfig ) + mbaData.header.isSpareDram = true; + + // Iterate all ranks to get DRAM repair data + for ( std::vector<CenRank>::iterator it = masterRanks.begin(); + it != masterRanks.end(); it++ ) + { + // Get chip/symbol marks + CenMark mark; + rc = mssGetMarkStore( i_mbaTrgt, *it, mark ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "mssGetMarkStore() Failed"); + continue; + } + + // Get DRAM spares + CenSymbol sp0, sp1, ecc; + rc = mssGetSteerMux( i_mbaTrgt, *it, sp0, sp1, ecc ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "mssGetSteerMux() failed"); + continue; + } + + // Add data + DramRepairRankData rankData = { (*it).getMaster(), + mark.getCM().getSymbol(), + mark.getSM().getSymbol(), + sp0.getSymbol(), + sp1.getSymbol(), + ecc.getSymbol() }; + if ( rankData.valid() ) + { + mbaData.rankDataList.push_back(rankData); + } + } + // If MBA had some DRAM repair data, add header information + if( mbaData.rankDataList.size() > 0 ) + { + mbaData.header.rankCount = mbaData.rankDataList.size(); + mbaData.header.isX4Dram = isDramWidthX4( i_mbaTrgt ); + UtilMem dramStream; + dramStream << mbaData; + + #ifndef PPC + // Fix endianness issues with non PPC machines. + // This is a workaround. Though UtilMem takes care of endianness, + // It seems with capture data its not working + const size_t sz_word = sizeof(uint32_t); + + // Align data with 32 bit boundary + for (uint32_t i = 0; i < ( dramStream.size()%sz_word ); i++) + { + uint8_t dummy = 0; + dramStream << dummy; + } + for ( uint32_t i = 0; i < ( dramStream.size()/sz_word); i++ ) + { + ((uint32_t*)dramStream.base())[i] = + htonl(((uint32_t*)dramStream.base())[i]); + } + #endif + + // Allocate space for the capture data. + BitString dramRepairData ( ( dramStream.size() )*8, + (CPU_WORD *) dramStream.base() ); + io_cd.Add( i_mbaTrgt, Util::hashString("DRAM_REPAIRS_DATA"), + dramRepairData ); + } + }while(0); + + if( FAIL == rc ) + PRDF_ERR( PRDF_FUNC "Failed for MBA 0x%08X", getHuid( i_mbaTrgt ) );*/ + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +void captureDramRepairsVpd<TYPE_MCA>(TargetHandle_t i_trgt, CaptureData & io_cd) +{ + #define PRDF_FUNC "[captureDramRepairsVpd] " + + // Get the maximum capture data size. + static const size_t sz_rank = sizeof(uint8_t); + static const size_t sz_entry = MCA_DIMMS_PER_RANK * DQ_BITMAP::BITMAP_SIZE; + static const size_t sz_word = sizeof(CPU_WORD); + + do + { + std::vector<MemRank> masterRanks; + getMasterRanks<TYPE_MCA>( i_trgt, masterRanks ); + if( masterRanks.empty() ) + { + PRDF_ERR( PRDF_FUNC "Master Rank list size is 0"); + break; + } + + // Get the maximum capture data size. + size_t sz_maxData = masterRanks.size() * (sz_rank + sz_entry); + + // Adjust the size for endianness. + sz_maxData = ((sz_maxData + sz_word-1) / sz_word) * sz_word; + + // Initialize to 0. + uint8_t capData[sz_maxData]; + memset( capData, 0x00, sz_maxData ); + + // Iterate all ranks to get VPD data + uint32_t idx = 0; + for ( auto & rank : masterRanks ) + { + MemDqBitmap<DIMMS_PER_RANK::MCA> bitmap; + + if ( SUCCESS != getBadDqBitmap<DIMMS_PER_RANK::MCA>(i_trgt, rank, + bitmap) ) + { + PRDF_ERR( PRDF_FUNC "getBadDqBitmap() failed: MCA=0x%08x" + " rank=0x%02x", getHuid(i_trgt), rank.getKey() ); + continue; // skip this rank + } + + if ( bitmap.badDqs() ) // make sure the data is non-zero + { + // Add the rank, then the entry data. + capData[idx] = rank.getMaster(); + idx += sz_rank; + memcpy(&capData[idx], bitmap.getData(), sz_entry); + idx += sz_entry; + } + } + + if( 0 == idx ) break; // Nothing to capture + + // Fix endianness issues with non PPC machines. + size_t sz_capData = idx; + sz_capData = ((sz_capData + sz_word-1) / sz_word) * sz_word; + for ( uint32_t i = 0; i < (sz_capData/sz_word); i++ ) + ((CPU_WORD*)capData)[i] = htonl(((CPU_WORD*)capData)[i]); + + // Add data to capture data. + BitString bs ( sz_capData*8, (CPU_WORD *) &capData ); + io_cd.Add( i_trgt, Util::hashString("DRAM_REPAIRS_VPD"), bs ); + + }while(0); + + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +void captureDramRepairsVpd<TYPE_MBA>(TargetHandle_t i_trgt, CaptureData & io_cd) +{ + #define PRDF_FUNC "[captureDramRepairsVpd] " + + // Get the maximum capture data size. + /* TODO RTC 178911 + static const size_t sz_rank = sizeof(uint8_t); + static const size_t sz_entry = MBA_DIMMS_PER_RANK * DIMM_DQ_RANK_BITMAP_SIZE; + static const size_t sz_word = sizeof(CPU_WORD); + int32_t rc = SUCCESS; + + do + { + std::vector<CenRank> masterRanks; + rc = getMasterRanks( i_mbaTrgt, masterRanks ); + if ( SUCCESS != rc ) + { + PRDF_ERR( PRDF_FUNC "getMasterRanks() failed" ); + break; + } + + if( masterRanks.empty() ) + { + PRDF_ERR( PRDF_FUNC "Master Rank list size is 0"); + break; + } + + // Get the maximum capture data size. + size_t sz_maxData = masterRanks.size() * (sz_rank + sz_entry); + + // Adjust the size for endianness. + sz_maxData = ((sz_maxData + sz_word-1) / sz_word) * sz_word; + + // Initialize to 0. + uint8_t capData[sz_maxData]; + memset( capData, 0x00, sz_maxData ); + + // Iterate all ranks to get VPD data + uint32_t idx = 0; + for ( std::vector<CenRank>::iterator it = masterRanks.begin(); + it != masterRanks.end(); it++ ) + { + CenDqBitmap bitmap; + uint8_t rank = it->getMaster(); + + if ( SUCCESS != getBadDqBitmap(i_mbaTrgt, *it, bitmap, true) ) + { + PRDF_ERR( PRDF_FUNC "getBadDqBitmap() failed: MBA=0x%08x" + " rank=%d", getHuid(i_mbaTrgt), rank ); + continue; // skip this rank + } + + if ( bitmap.badDqs() ) // make sure the data is non-zero + { + // Add the rank, then the entry data. + capData[idx] = rank; idx += sz_rank; + memcpy(&capData[idx], bitmap.getData(), sz_entry); + idx += sz_entry; + } + } + + if( 0 == idx ) break; // Nothing to capture + + // Fix endianness issues with non PPC machines. + size_t sz_capData = idx; + sz_capData = ((sz_capData + sz_word-1) / sz_word) * sz_word; + for ( uint32_t i = 0; i < (sz_capData/sz_word); i++ ) + ((CPU_WORD*)capData)[i] = htonl(((CPU_WORD*)capData)[i]); + + // Add data to capture data. + BitString bs ( sz_capData*8, (CPU_WORD *) &capData ); + io_cd.Add( i_mbaTrgt, Util::hashString("DRAM_REPAIRS_VPD"), bs ); + + }while(0); + + if( FAIL == rc ) + PRDF_ERR( PRDF_FUNC "Failed for MBA 0x%08X", getHuid( i_mbaTrgt ) );*/ + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +void addEccData<TYPE_MCA>( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ) +{ + PRDF_ASSERT( TYPE_MCA == i_chip->getType() ); + + CaptureData & cd = io_sc.service_data->GetCaptureData(); + McaDataBundle * db = getMcaDataBundle( i_chip ); + + TargetHandle_t trgt = i_chip->GetChipHandle(); + + // Add DRAM repairs data from hardware. + captureDramRepairsData<TYPE_MCA>( trgt, cd ); + + // Add DRAM repairs data from VPD. + captureDramRepairsVpd<TYPE_MCA>( trgt, cd ); + + // Add CE table to capture data. + db->iv_ceTable.addCapData( cd ); + + // Add UE table to capture data. + db->iv_ueTable.addCapData( cd ); +} + +template<> +void addEccData<TYPE_MCBIST>( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ) +{ + PRDF_ASSERT( TYPE_MCBIST == i_chip->getType() ); + + // Add data for each connected MCA. + ExtensibleChipList list = getConnected( i_chip, TYPE_MCA ); + for ( auto & mcaChip : list ) { addEccData<TYPE_MCA>(mcaChip, io_sc); } +} + +template<> +void addEccData<TYPE_MBA>( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ) +{ + PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); + +/* TODO: RTC 157888 + CaptureData & cd = io_sc.service_data->GetCaptureData(); + CenMbaDataBundle * db = getMbaDataBundle( i_chip ); + + // Add UE table to capture data. + db->iv_ueTable.addCapData( i_chip, cd ); + + // Add CE table to capture data. + db->iv_ceTable.addCapData( cd ); + + // Add RCE table to capture data. + db->iv_rceTable.addCapData( cd ); + + // Add DRAM repairs data from hardware. + captureDramRepairsData( i_chip->getTrgt(), cd ); + + // Add DRAM repairs data from VPD. + captureDramRepairsVpd( i_chip->getTrgt(), cd ); +*/ +} + +//------------------------------------------------------------------------------ + +template<TARGETING::TYPE T> +void addEccData( TargetHandle_t i_trgt, errlHndl_t io_errl ) +{ + CaptureData cd; + + // Add DRAM repairs data from hardware. + captureDramRepairsData<T>( i_trgt, cd ); + + // Add DRAM repairs data from VPD. + captureDramRepairsVpd<T>( i_trgt, cd ); + + ErrDataService::AddCapData( cd, io_errl ); +} + +// To resolve template linker errors. +template +void addEccData<TYPE_MCA>( TargetHandle_t i_trgt, errlHndl_t io_errl ); +template +void addEccData<TYPE_MBA>( TargetHandle_t i_trgt, errlHndl_t io_errl ); + +//------------------------------------------------------------------------------ + } //end namespace MemCaptureData } // end namespace PRDF diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.H b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.H index 4f2e2e6ff..029665aa7 100644 --- a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.H +++ b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.H @@ -44,6 +44,19 @@ template<TARGETING::TYPE T> void addEccData( ExtensibleChip * i_chip, STEP_CODE_DATA_STRUCT & io_sc ); /** + * @brief Adds Memory ECC FFDC to an error log. + * @note This is intended to be used in non-normal analysis paths that do not + * 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 relevant during its intended uses. + * @param i_trgt An MBA or MCA target + * @param o_errl Error log. + */ +template<TARGETING::TYPE T> +void addEccData( TARGETING::TargetHandle_t i_trgt, errlHndl_t io_errl ); + +/** * @brief Adds a new user data section to the error log containing a MemoryMru * plus extended data for extra FFDC. * @param i_memMru The memory mru @@ -51,6 +64,32 @@ void addEccData( ExtensibleChip * i_chip, STEP_CODE_DATA_STRUCT & io_sc ); */ void addExtMemMruData( const MemoryMru & i_memMru, errlHndl_t io_errl ); +/** + * @brief Queries hardware for all DRAM repairs data (chip/symbol marks, DRAM + * spare, etc.) for the given MBA or MCA and adds it to the capture data. + * @param i_trgt An MBA or MCA target. + * @param io_cd Capture data struct. + * @note This function will be used to capture DRAM repair data into the + * capture data struct. Other functions can call this function and + * update the error log. + */ +template<TARGETING::TYPE T> +void captureDramRepairsData( TARGETING::TargetHandle_t i_trgt, + CaptureData & io_cd ); + +/** + * @brief Queries the Bad DQ attributes for the content of the DRAM repairs VPD + * and adds it to the capture data. + * @param i_trgt An MBA or MCA target. + * @param io_cd Capture data struct. + * @note This function will be used to capture DRAM repair data into the + * capture data struct. Other functions can call this function and + * update the error log. + */ +template<TARGETING::TYPE T> +void captureDramRepairsVpd( TARGETING::TargetHandle_t i_trgt, + CaptureData & io_cd ); + } // end namespace MemCaptureData } // end namespace PRDF |