From ef42b9f0d4600b9ab3a54e81936b09534eec3b55 Mon Sep 17 00:00:00 2001 From: Stephen Cprek Date: Mon, 15 May 2017 14:57:33 -0500 Subject: [PATCH] Provide ability to clear an HDAT memory region and clear HB resv mem Clear all HDAT HB reserved memory sections before hostboot populates This is done to ensure that nothing in this section is written by the FSP or some other process Change-Id: I70f4fabc2f9bebab0fe3f170d4676183a4bc638b RTC: 156485 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40514 Tested-by: Jenkins Server Reviewed-by: Nicholas E. Bofferding Reviewed-by: Marshall J. Wilks Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins Reviewed-by: William G. Hoffa --- src/include/usr/runtime/runtime.H | 12 +- src/usr/runtime/hdatservice.C | 199 ++++++++++++++++++++++----- src/usr/runtime/hdatservice.H | 24 +++- src/usr/runtime/populate_hbruntime.C | 7 + 4 files changed, 202 insertions(+), 40 deletions(-) diff --git a/src/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H index c16c1e298b8..e4b4b412156 100644 --- a/src/include/usr/runtime/runtime.H +++ b/src/include/usr/runtime/runtime.H @@ -30,6 +30,7 @@ #include #include #include +#include "../../../src/usr/runtime/hdatstructs.H" namespace RUNTIME { @@ -163,9 +164,18 @@ enum SectionId errlHndl_t get_host_data_section( SectionId i_section, uint64_t i_instance, uint64_t& o_dataAddr, - size_t& o_dataSize ); + size_t& o_dataSize); const size_t DATA_SIZE_UNKNOWN = 0xFFFFFFFFFFFFFFFF; +/** + * @brief Clear section of host data memory one instance at a time. + * + * @param[in] i_section Chunk of data to clear + * + * @return errlHndl_t nullptr on success, pointer to error log on failure + */ +errlHndl_t clear_host_data_section(const RUNTIME::SectionId i_section); + /** * @brief Get the number of instances in a given section. * diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index 82aef463024..cd4e31916ad 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -546,7 +546,7 @@ errlHndl_t hdatService::loadHostData(void) errlHndl_t hdatService::getHostDataSection( SectionId i_section, uint64_t i_instance, uint64_t& o_dataAddr, - size_t& o_dataSize ) + size_t& o_dataSize) { errlHndl_t errhdl = NULL; TRACFCOMP( g_trac_runtime, "RUNTIME::getHostDataSection( i_section=%d, i_instance=%d )", i_section, i_instance ); @@ -670,40 +670,15 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, } else if (RUNTIME::RESERVED_MEM == i_section) { - // Find the right tuple and verify it makes sense - errhdl = getAndCheckTuple(i_section, tuple); - if( errhdl ) { break; } - TRACUCOMP(g_trac_runtime, "MDT_DATA tuple=%p", tuple); - - uint64_t base_addr; - errhdl = getSpiraTupleVA(tuple, base_addr); + hdatMsReservedMemArrayHeader_t* reservedMemArrayHeader = nullptr; + errhdl = getResvMemArrHdr(reservedMemArrayHeader); if( errhdl ) { break; } - hdatHDIF_t* mdt_header = - reinterpret_cast(base_addr); - TRACUCOMP( g_trac_runtime, "mdt_header=%p", mdt_header ); - - // Check the headers and version info - errhdl = check_header( mdt_header, - MDT_HEADER ); - if( errhdl ) { break; } - - hdatHDIFDataHdr_t* mdt_data_header = - reinterpret_cast - (mdt_header->hdatDataPtrOffset + base_addr); - - errhdl = verify_hdat_address(mdt_data_header, - mdt_header->hdatDataPtrCnt * sizeof(hdatHDIFDataHdr_t) ); - if( errhdl ) { break; } - - uint64_t resvMemHdatAddr = mdt_data_header[MDT_RESERVED_HB_MEM_SECTION].hdatOffset + base_addr; - - hdatMsReservedMemArrayHeader_t* reservedMemArrayHeader = - reinterpret_cast(resvMemHdatAddr); - - if( i_instance >= reservedMemArrayHeader->arrayEntryCount ) + uint64_t l_arrCount = reservedMemArrayHeader->arrayEntryCount; + if( i_instance >= l_arrCount ) { - TRACFCOMP( g_trac_runtime, "Instance %d exceeds max reserved mem entry count %d", i_instance, reservedMemArrayHeader->arrayEntryCount ); + TRACFCOMP( g_trac_runtime, "Instance %d exceeds max reserved mem entry count %d", + i_instance, l_arrCount); /*@ * @errortype * @moduleid RUNTIME::MOD_HDATSERVICE_GETHOSTDATASECTION @@ -719,16 +694,19 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, RUNTIME::MOD_HDATSERVICE_GETHOSTDATASECTION, RUNTIME::RC_INVALID_RHB_INSTANCE, i_instance, - reservedMemArrayHeader->arrayEntryCount, + l_arrCount, true /*Add HB Software Callout*/); errhdl->collectTrace(RUNTIME_COMP_NAME,KILOBYTE); break; } - o_dataAddr = reinterpret_cast( - resvMemHdatAddr + reservedMemArrayHeader->offsetToArray + (i_instance * sizeof(hdatMsVpdRhbAddrRange_t))); //Array Header addr - o_dataSize = sizeof(hdatMsVpdRhbAddrRange_t); + o_dataAddr = reinterpret_cast( + reinterpret_cast(reservedMemArrayHeader) + + reservedMemArrayHeader->offsetToArray + + (i_instance * reservedMemArrayHeader->entrySize)); + //Array Header size + o_dataSize = reservedMemArrayHeader->entrySize; } // HB Runtime Data else if ( (RUNTIME::HBRT == i_section) || @@ -1370,7 +1348,6 @@ errlHndl_t hdatService::getInstanceCount(const SectionId i_section, uint64_t& o_count) { errlHndl_t errhdl = nullptr; - hdat5Tuple_t* tuple = nullptr; o_count = 0; do { @@ -1379,6 +1356,8 @@ errlHndl_t hdatService::getInstanceCount(const SectionId i_section, switch(i_section) { case RUNTIME::PCRD: + { + hdat5Tuple_t* tuple = nullptr; errhdl = getAndCheckTuple(i_section, tuple); if( errhdl ) { @@ -1386,6 +1365,18 @@ errlHndl_t hdatService::getInstanceCount(const SectionId i_section, } o_count = tuple->hdatActualCnt; break; + } + case RUNTIME::RESERVED_MEM: + { + hdatMsReservedMemArrayHeader_t* reservedMemArrayHeader = nullptr; + errhdl = getResvMemArrHdr(reservedMemArrayHeader); + if( errhdl ) + { + break; + } + o_count = reservedMemArrayHeader->arrayEntryCount; + break; + } default: TRACFCOMP( g_trac_runtime, ERR_MRK"getInstanceCount> section %d has no concept of instances", i_section ); @@ -1515,6 +1506,133 @@ errlHndl_t hdatService::getAndCheckTuple(const SectionId i_section, return errhdl; } +errlHndl_t hdatService::clearHostDataSection(const RUNTIME::SectionId i_section) +{ + TRACFCOMP(g_trac_runtime, ENTER_MRK"clearHostDataSection> section = %d", + i_section); + + errlHndl_t l_elog = nullptr; + + do { + + //Always force a load (mapping) + l_elog = loadHostData(); + if(l_elog) + { + break; + } + + // Setup the SPIRA pointers + l_elog = findSpira(); + if(l_elog) + { + break; + } + + uint64_t l_count = 0; + l_elog = getInstanceCount(i_section, l_count); + if(l_elog) + { + break; + } + + // Clear each instance of a host data section + for (uint64_t instance = 0; instance < l_count; ++instance) + { + // Call getHostDataSection with clear flag set + uint64_t l_hostDataAddr = 0; + uint64_t l_hostDataSize = 0; + l_elog = getHostDataSection(i_section, + instance, + l_hostDataAddr, + l_hostDataSize); + if(l_elog) + { + break; + } + + assert(l_hostDataAddr>0, "Clear address 0x%X is <= 0", l_hostDataAddr); + assert(l_hostDataSize>0, "Clear size 0x%X is <= 0", l_hostDataSize); + + // Sections differ in how they should be "cleared" or invalidated + switch (i_section) + { + case RUNTIME::RESERVED_MEM: + { + // Set Reserved Memory Type to Invalid + memset(reinterpret_cast(l_hostDataAddr), + HDAT::RHB_TYPE_INVALID, + sizeof(HDAT::hdatMsVpdRhbAddrRangeType)); + // Clear rest of entries in range with zero + memset(reinterpret_cast(l_hostDataAddr + + sizeof(HDAT::hdatMsVpdRhbAddrRangeType)), + 0, + l_hostDataSize - sizeof(HDAT::hdatMsVpdRhbAddrRangeType)); + break; + } + default: + { + // Clear entire range with zero + memset(reinterpret_cast(l_hostDataAddr), + 0, + l_hostDataSize); + break; + } + } + } + // If for loop broke with error + if(l_elog) + { + break; + } + + } while(0); + + return l_elog; +} + +errlHndl_t hdatService::getResvMemArrHdr(hdatMsReservedMemArrayHeader_t*& + o_resvMemArrHdr) +{ + errlHndl_t errhdl = nullptr; + hdat5Tuple_t* tuple = nullptr; + uint64_t base_addr = 0; + + do { + // Find the right tuple and verify it makes sense + errhdl = getAndCheckTuple(RUNTIME::RESERVED_MEM, tuple); + if( errhdl ) { break; } + TRACUCOMP(g_trac_runtime, "getNumResvMemEntries: MDT_DATA tuple=%p", tuple); + + errhdl = getSpiraTupleVA(tuple, base_addr); + if( errhdl ) { break; } + + hdatHDIF_t* mdt_header = + reinterpret_cast(base_addr); + TRACUCOMP( g_trac_runtime, "getNumResvMemEntries: mdt_header=%p", mdt_header ); + + // Check the headers and version info + errhdl = check_header( mdt_header, + MDT_HEADER ); + if( errhdl ) { break; } + + hdatHDIFDataHdr_t* mdt_data_header = + reinterpret_cast + (mdt_header->hdatDataPtrOffset + base_addr); + + errhdl = verify_hdat_address(mdt_data_header, + mdt_header->hdatDataPtrCnt * sizeof(hdatHDIFDataHdr_t) ); + if( errhdl ) { break; } + + uint64_t resvMemHdatAddr = mdt_data_header[MDT_RESERVED_HB_MEM_SECTION].hdatOffset + base_addr; + + o_resvMemArrHdr = reinterpret_cast(resvMemHdatAddr); + assert(o_resvMemArrHdr != nullptr, "Reserved Memory Array Header is a nullptr"); + } while (0); + + return errhdl; +} + /******************** Public Methods ********************/ @@ -1535,7 +1653,7 @@ errlHndl_t load_host_data( void ) errlHndl_t get_host_data_section( SectionId i_section, uint64_t i_instance, uint64_t& o_dataAddr, - size_t& o_dataSize ) + size_t& o_dataSize) { return Singleton::instance(). getHostDataSection(i_section,i_instance, o_dataAddr, o_dataSize); @@ -1574,6 +1692,11 @@ errlHndl_t get_instance_count(const SectionId i_section, o_count); } +errlHndl_t clear_host_data_section(const RUNTIME::SectionId i_section) +{ + return Singleton::instance().clearHostDataSection(i_section); +} + }; void hdatMsVpdRhbAddrRange_t::set(const HDAT::hdatMsVpdRhbAddrRangeType i_type, diff --git a/src/usr/runtime/hdatservice.H b/src/usr/runtime/hdatservice.H index d72c6319275..6a49fd4261e 100644 --- a/src/usr/runtime/hdatservice.H +++ b/src/usr/runtime/hdatservice.H @@ -96,7 +96,19 @@ namespace RUNTIME errlHndl_t getHostDataSection( SectionId i_section, uint64_t i_instance, uint64_t& o_dataAddr, - size_t& o_dataSize ); + size_t& o_dataSize); + + /** + * @brief Clear or invalidate a particular section of the host data + * memory. + * NOTE: Section must be supported by getInstanceCount to + * actually clear. + * + * @param[in] i_section Chunk of data to clear + * + * @return errlHndl_t NULL on success; errlog otherwise + */ + errlHndl_t clearHostDataSection(const RUNTIME::SectionId i_section); /** * @brief See documentation for get_instance_count in runtime.H @@ -249,6 +261,16 @@ namespace RUNTIME errlHndl_t getAndCheckTuple(const SectionId i_section, hdat5Tuple_t*& o_tuple); + /** + * @brief Get pointer to reserved memory array header + * + * @param[out] o_resvMemArrHdr Pointer, by reference, to the array header + * + * @return errlHndl_t Returns nullptr on success; otherwise errlog + */ + errlHndl_t getResvMemArrHdr(hdatMsReservedMemArrayHeader_t*& + o_resvMemArrHdr); + /******************************************** * VARIABLES ********************************************/ diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 7a80a3eab02..4bbd1ab09ea 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -521,6 +521,13 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId) // Wipe out our cache of the NACA/SPIRA pointers RUNTIME::rediscover_hdat(); + // Wipe out all HB reserved memory sections + l_elog = RUNTIME::clear_host_data_section(RUNTIME::RESERVED_MEM); + if(l_elog) + { + break; + } + uint64_t l_topMemAddr = 0x0; uint64_t l_vAddr = 0x0;