From d026d31c923e7756586b64c123632d9d7dad8489 Mon Sep 17 00:00:00 2001 From: Zane Shelley Date: Mon, 2 Apr 2018 20:58:21 -0500 Subject: PRD: enable predictive dynamic memory deallocation Change-Id: I54fc3058c2a62efc36deea89b08b3ea1e08a742f Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/56613 Tested-by: Jenkins Server Reviewed-by: Benjamin J. Weisenbeck Reviewed-by: Brian J. Stegmiller Reviewed-by: Caleb N. Palmer Reviewed-by: Zane C. Shelley Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/56891 CI-Ready: Zane C. Shelley Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: Zane C. Shelley --- src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C | 73 +++++++++++++++++++++----- src/usr/diag/prdf/plat/prdfPlatServices_rt.C | 52 +++++++----------- src/usr/diag/prdf/plat/prdfPlatServices_rt.H | 25 ++++++--- 3 files changed, 98 insertions(+), 52 deletions(-) (limited to 'src/usr/diag/prdf/plat') diff --git a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C index b7c76874c..d50980cfb 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C @@ -410,6 +410,8 @@ int32_t page( ExtensibleChip * i_chip, MemAddr i_addr ) } template int32_t page( ExtensibleChip * i_chip, MemAddr i_addr ); +//------------------------------------------------------------------------------ + template int32_t rank( ExtensibleChip * i_chip, MemRank i_rank ) { @@ -457,6 +459,8 @@ int32_t rank( ExtensibleChip * i_chip, MemRank i_rank ) } template int32_t rank( ExtensibleChip * i_chip, MemRank i_rank ); +//------------------------------------------------------------------------------ + template int32_t port( ExtensibleChip * i_chip ) { @@ -503,17 +507,20 @@ int32_t port( ExtensibleChip * i_chip ) } template int32_t port( ExtensibleChip * i_chip ); +//------------------------------------------------------------------------------ + template -int32_t dimmSlct( TargetHandle_t i_dimm ) +int32_t __getDimmRange( TargetHandle_t i_dimm, + uint64_t & o_ssAddr, uint64_t & o_seAddr ) { - #define PRDF_FUNC "[MemDealloc::dimmSlct] " + #define PRDF_FUNC "[MemDealloc::__getDimmRange] " int32_t o_rc = SUCCESS; + o_ssAddr = o_seAddr = 0; + do { - if ( !isEnabled() ) break; // nothing to do - // Get the MCA, MBA, etc. connected to this DIMM. TargetHandle_t trgt = getConnectedParent( i_dimm, T ); ExtensibleChip * chip = (ExtensibleChip *)systemPtr->GetChip( trgt ); @@ -537,10 +544,8 @@ int32_t dimmSlct( TargetHandle_t i_dimm ) } // Get the system addresses. - uint64_t ssAddr = 0; - uint64_t seAddr = 0; - o_rc = getSystemAddr( chip, startAddr, ssAddr ); - o_rc |= getSystemAddr( chip, endAddr, seAddr ); + o_rc = getSystemAddr( chip, startAddr, o_ssAddr ); + o_rc |= getSystemAddr( chip, endAddr, o_seAddr ); if ( SUCCESS != o_rc ) { PRDF_ERR( PRDF_FUNC "getSystemAddr(0x%08x) failed", @@ -548,6 +553,36 @@ int32_t dimmSlct( TargetHandle_t i_dimm ) break; } + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template +int32_t dimmSlct( TargetHandle_t i_dimm ) +{ + #define PRDF_FUNC "[MemDealloc::dimmSlct] " + + int32_t o_rc = SUCCESS; + + do + { + if ( !isEnabled() ) break; // nothing to do + + // Get the system addresses. + uint64_t ssAddr = 0, seAddr = 0; + o_rc = __getDimmRange( i_dimm, ssAddr, seAddr ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "__getDimmRange(0x%08x) failed", + getHuid(i_dimm) ); + break; + } + // Send the address range to the hypervisor. sendDynMemDeallocRequest( ssAddr, seAddr ); PRDF_TRAC( PRDF_FUNC "DIMM Slct dealloc for Start Addr: 0x%016llx " @@ -560,6 +595,8 @@ int32_t dimmSlct( TargetHandle_t i_dimm ) #undef PRDF_FUNC } +//------------------------------------------------------------------------------ + template bool isDimmPair( TargetHandle_t i_dimm1, TargetHandle_t i_dimm2 ) { @@ -601,11 +638,13 @@ bool compareDimms( TargetHandle_t i_dimm1, TargetHandle_t i_dimm2 ) #undef PRDF_FUNC } +//------------------------------------------------------------------------------ template int32_t dimmList( TargetHandleList & i_dimmList ) { #define PRDF_FUNC "[MemDealloc::dimmList] " + int32_t o_rc = SUCCESS; // Find unique dimm slct. @@ -617,17 +656,27 @@ int32_t dimmList( TargetHandleList & i_dimmList ) for( TargetHandleList::iterator it = i_dimmList.begin(); it != uniqueDimmEndIt; it++ ) { - int32_t l_rc = dimmSlct( *it ); - if( SUCCESS != l_rc ) + // Get the system addresses. + uint64_t ssAddr = 0, seAddr = 0; + if ( SUCCESS != __getDimmRange(*it, ssAddr, seAddr) ) { - PRDF_ERR(PRDF_FUNC "Failed for DIMM 0x:%08X", getHuid( *it ) ); - o_rc |= l_rc; + PRDF_ERR( PRDF_FUNC "__getDimmRange(0x%08x) failed", getHuid(*it) ); + o_rc = FAIL; continue; // Continue to the next DIMM. } + + // Send the address range to the hypervisor. + sendPredDeallocRequest( ssAddr, seAddr ); + PRDF_TRAC( PRDF_FUNC "Predictive dealloc for start addr: 0x%016llx " + "end addr: 0x%016llx", ssAddr, seAddr ); } + return o_rc; + #undef PRDF_FUNC } +//------------------------------------------------------------------------------ + int32_t dimmList( TargetHandleList & i_dimmList ) { #define PRDF_FUNC "[MemDealloc::dimmList] " diff --git a/src/usr/diag/prdf/plat/prdfPlatServices_rt.C b/src/usr/diag/prdf/plat/prdfPlatServices_rt.C index 6e78e3052..6d1528a23 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices_rt.C +++ b/src/usr/diag/prdf/plat/prdfPlatServices_rt.C @@ -63,56 +63,44 @@ namespace PlatServices //## Memory specific functions //############################################################################## -void sendPageGardRequest( uint64_t i_systemAddress ) +void __dyndealloc( uint64_t i_saddr, uint64_t i_eaddr, MemoryError_t i_type ) { - #define PRDF_FUNC "[PlatServices::sendPageGardRequest] " + #define PRDF_FUNC "[PlatServices::__dyndealloc] " do { - if( !g_hostInterfaces || !g_hostInterfaces->memory_error ) + if ( !g_hostInterfaces || !g_hostInterfaces->memory_error ) { - PRDF_ERR(PRDF_FUNC " memory_error() interface is not defined"); + PRDF_ERR( PRDF_FUNC "memory_error() interface is not defined" ); break; } - int32_t rc = g_hostInterfaces->memory_error( i_systemAddress, - i_systemAddress, - MEMORY_ERROR_CE ); - if( SUCCESS != rc ) + int32_t rc = g_hostInterfaces->memory_error( i_saddr, i_eaddr, i_type ); + if ( SUCCESS != rc ) { - PRDF_ERR(PRDF_FUNC " memory_error() failed"); + PRDF_ERR( PRDF_FUNC "memory_error() failed" ); break; } - }while(0); + + } while (0); #undef PRDF_FUNC } -//------------------------------------------------------------------------------ - -void sendDynMemDeallocRequest( uint64_t i_startAddr, uint64_t i_endAddr ) +void sendPageGardRequest( uint64_t i_saddr ) { - #define PRDF_FUNC "[PlatServices::sendDynMemDeallocRequest] " - - do - { - if( !g_hostInterfaces || !g_hostInterfaces->memory_error ) - { - PRDF_ERR(PRDF_FUNC " memory_error() interface is not defined"); - break; - } + // Note that both addresses will be the same for a page gard. + __dyndealloc( i_saddr, i_saddr, MEMORY_ERROR_CE ); +} - int32_t rc = g_hostInterfaces->memory_error( i_startAddr, - i_endAddr, - MEMORY_ERROR_UE ); - if( SUCCESS != rc ) - { - PRDF_ERR(PRDF_FUNC " memory_error() failed"); - break; - } - }while(0); +void sendDynMemDeallocRequest( uint64_t i_saddr, uint64_t i_eaddr ) +{ + __dyndealloc( i_saddr, i_eaddr, MEMORY_ERROR_UE ); +} - #undef PRDF_FUNC +void sendPredDeallocRequest( uint64_t i_saddr, uint64_t i_eaddr ) +{ + __dyndealloc( i_saddr, i_eaddr, MEMORY_ERROR_PREDICTIVE ); } //############################################################################## diff --git a/src/usr/diag/prdf/plat/prdfPlatServices_rt.H b/src/usr/diag/prdf/plat/prdfPlatServices_rt.H index 157e4cb25..17f8be9e1 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices_rt.H +++ b/src/usr/diag/prdf/plat/prdfPlatServices_rt.H @@ -42,18 +42,27 @@ namespace PlatServices //############################################################################## /** - * @brief Communicates a page gard request to the hypervisor. - * @param i_systemAddress Any address in the target page. + * @brief Sends a page gard request to the hypervisor. + * @param i_addr Any address in the target page. */ -void sendPageGardRequest( uint64_t i_systemAddress ); +void sendPageGardRequest( uint64_t i_addr ); /** - * @brief Communicates to the hypervisor a range of address to remove from the - * available memory space. - * @param i_startAddr First address in the range. - * @param i_endAddr Last address in the range. + * @brief Sends a dynamic memory deallocation message to the hypervisor. This + * message is intended for memory UEs, channel/port failures, etc. + * @param i_saddr The first address in the range. + * @param i_eaddr The last address in the range. */ -void sendDynMemDeallocRequest( uint64_t i_startAddr, uint64_t i_endAddr ); +void sendDynMemDeallocRequest( uint64_t i_saddr, uint64_t i_eaddr ); + +/** + * @brief Sends a predictive dynamic memory deallocation message to the + * hypervisor. This message is intended to be send whenever there is a + * predictive callout of any part in the memory subsystem. + * @param i_saddr The first address in the range. + * @param i_eaddr The last address in the range. + */ +void sendPredDeallocRequest( uint64_t i_saddr, uint64_t i_eaddr ); //############################################################################## //## Nimbus/Centaur Maintenance Command wrappers -- cgit v1.2.1