diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/usr/isteps/istep_reasoncodes.H | 1 | ||||
| -rw-r--r-- | src/include/usr/util/utiltce.H | 13 | ||||
| -rw-r--r-- | src/include/usr/vmmconst.h | 36 | ||||
| -rw-r--r-- | src/usr/isteps/istep21/call_host_runtime_setup.C | 336 | ||||
| -rw-r--r-- | src/usr/runtime/hdatservice.C | 4 | ||||
| -rw-r--r-- | src/usr/secureboot/trusted/trustedboot.C | 2 | ||||
| -rw-r--r-- | src/usr/util/utillidmgr.C | 53 | ||||
| -rw-r--r-- | src/usr/util/utilmclmgr.C | 7 | ||||
| -rw-r--r-- | src/usr/util/utiltcemgr.C | 153 | ||||
| -rw-r--r-- | src/usr/util/utiltcemgr.H | 56 |
10 files changed, 566 insertions, 95 deletions
diff --git a/src/include/usr/isteps/istep_reasoncodes.H b/src/include/usr/isteps/istep_reasoncodes.H index 1b661f17c..9f75bcfe3 100644 --- a/src/include/usr/isteps/istep_reasoncodes.H +++ b/src/include/usr/isteps/istep_reasoncodes.H @@ -63,6 +63,7 @@ namespace ISTEP MOD_SBE_GET_FFDC_HANDLER = 0x1C, MOD_SET_IPL_PARMS = 0x1D, MOD_OCC_XSTOP_HANDLER = 0x1E, + MOD_VERIFY_AND_MOVE_PAYLOAD = 0x1F, }; /** diff --git a/src/include/usr/util/utiltce.H b/src/include/usr/util/utiltce.H index 0aaffacf1..b0aaf48ae 100644 --- a/src/include/usr/util/utiltce.H +++ b/src/include/usr/util/utiltce.H @@ -50,10 +50,11 @@ namespace TCE * Size must be less than (512K * PAGESIZE) or will fail. * Assert if not greater than zero. * - * @param[out] o_startingToken - Starting Entry into the table. - * (This is an offset into the array based on the - * TCE index * PAGESIZE. Each TCE entry maps to - * a pagesize of memory) + * @param[out] o_startingToken - Key to the Starting Entry into the table. + * This is an offset into the array based on the + * TCE Index * PAGESIZE. + * FSP uses the token as a DMA Address. + * Each TCE entry maps to a pagesize of memory. * * Note: First time this is called will cause TCE Table to be created and * the Processors to be setup to point at the TCE Table @@ -97,7 +98,7 @@ errlHndl_t utilDisableTces(void); /******************************************************/ /** - * @brief Responsible for Setting up TCEs for PAYLOAD + * @brief Responsible for Setting up TCEs for PAYLOAD, including HDAT * * @return errlHndl_t - Return Error Handle if failed * @@ -105,7 +106,7 @@ errlHndl_t utilDisableTces(void); errlHndl_t utilSetupPayloadTces(void); /** - * @brief Responsible for closing the TCEs for PAYLOAD + * @brief Responsible for closing the TCEs for PAYLOAD, including HDAT * * @return errlHndl_t - Return Error Handle if failed * diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h index ed773da09..32be069d6 100644 --- a/src/include/usr/vmmconst.h +++ b/src/include/usr/vmmconst.h @@ -206,7 +206,7 @@ enum BlockPriority * Need to add (ATTR_HB_HRMOR_NODAL_BASE * hbinstance_num) to this * address to get the physical address */ -#define VMM_INTERNODE_PRESERVED_MEMORY_ADDR (96 * MEGABYTE) +#define VMM_INTERNODE_PRESERVED_MEMORY_ADDR (120 * MEGABYTE) /** * Test Constants @@ -222,6 +222,31 @@ enum BlockPriority * Physical Memory Constants */ +/** Layout + * 0MB-4MB: reserved/open + * 4MB-87MB: MCL_ADDR, MCL_TMP_ADDR, HDAT_TMP_ADDR + * 88MB-120MB: TCE Table (needs to be 4-byte aligned) + * 120MB: VMM_INTERNODE_PRESERVED_MEMORY_ADDR (see above) + * 128MB-256MB: See HB_HRMOR info above (with HOMERs, OCC, etc) + */ + +/** Two memory locations for MCL processing **/ +// Note: 2 spaces needed so the MCL can be initialized without wiping out PHYP +// Location for the MCL itself to sit in. +#define MCL_ADDR (4*MEGABYTE) +#define MCL_SIZE (16*KILOBYTE) +// Location for PHYP to be loaded into and reused for all Master Container Lids +// Verification is done in a temporary, non-secure area of mainstore memory, +// then relocated to its final, secure location in mainstore. +#define MCL_TMP_ADDR (MCL_ADDR + MCL_SIZE) +#define MCL_TMP_SIZE ( (64 * MEGABYTE) + PAGESIZE ) + +// Location for HDAT to be loaded into via TCEs by FSP +// Verification is done in a temporary, non-secure area of mainstore memory, +// then relocated to its final, secure location in mainstore. +#define HDAT_TMP_ADDR (MCL_TMP_ADDR + MCL_TMP_SIZE) +#define HDAT_TMP_SIZE (16 * MEGABYTE) + /** Physical memory location of the TCE Table */ /** - needs to be aligned on 4MB boundary */ #define TCE_TABLE_ADDR (88*MEGABYTE) @@ -235,15 +260,6 @@ enum BlockPriority #define UNSECURE_MEM_REGION_SIZE_TEST (1*KILOBYTE) -/** Two memory locations for MCL processing **/ -// Note: 2 spaces needed so the MCL can be initialized without wiping out PHYP -// Location for the MCL itself to sit in. -#define MCL_ADDR (20*MEGABYTE) -#define MCL_SIZE (16*KILOBYTE) -// Location for PHYP to be loaded into and reused for all Master Container Lids -// Verification is done in the temp space and then loaded into mainstore memory -#define MCL_TMP_ADDR (MCL_ADDR + MCL_SIZE) -#define MCL_TMP_SIZE ( (64 * MEGABYTE) + PAGESIZE ) /** PreVerifiedLidMgr test space */ #define PREVERLIDMGR_TEST_ADDR (512*MEGABYTE) diff --git a/src/usr/isteps/istep21/call_host_runtime_setup.C b/src/usr/isteps/istep21/call_host_runtime_setup.C index 767f7c422..fbf00c458 100644 --- a/src/usr/isteps/istep21/call_host_runtime_setup.C +++ b/src/usr/isteps/istep21/call_host_runtime_setup.C @@ -38,7 +38,10 @@ #include <targeting/common/util.H> #include <vpd/vpd_if.H> #include <util/utiltce.H> +#include <map> +#include <secureboot/service.H> +#include <sys/mm.h> //SBE interfacing #include <sbeio/sbeioif.H> #include <sys/misc.h> @@ -53,9 +56,307 @@ using namespace ERRORLOG; using namespace ISTEP; using namespace ISTEP_ERROR; +using namespace TARGETING; namespace ISTEP_21 { + +// Verify PAYLOAD and Move PAYLOAD+HDAT from Temporary TCE-related +// memory region to the proper location +errlHndl_t verifyAndMovePayload(void) +{ + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ENTER_MRK"verifyAndMovePayload()" ); + + errlHndl_t l_err = nullptr; + void * payload_tmp_virt_addr = nullptr; + void * payloadBase_virt_addr = nullptr; + void * hdat_tmp_virt_addr = nullptr; + void * hdat_final_virt_addr = nullptr; + + enum Map_FailLocs_t { + NO_MAP_FAIL = 0x0, + PAYLOAD_TMP_MAP_FAIL = 0x1, // payload_tmp_virt_addr + PAYLOAD_BASE_MAP_FAIL = 0x2, // payloadBase_virt_addr + HDAT_TMP_MAP_FAIL = 0x3, // hdat_tmp_virt_addr + HDAT_FINAL_MAP_FAIL = 0x4, // hdat_final_virt_addr + + PAYLOAD_TMP_UNMAP_FAIL = 0x5, // payload_tmp_virt_addr + PAYLOAD_BASE_UNMAP_FAIL = 0x6, // payloadBase_virt_addr + HDAT_TMP_UNMAP_FAIL = 0x7, // hdat_tmp_virt_addr + HDAT_FINAL_UNMAP_FAIL = 0x8, // hdat_final_virt_addr + }; + + Map_FailLocs_t blockMapFail = NO_MAP_FAIL; + + // Make sure these constants are page-aligned, as they are used below for + // mm_block_map: + static_assert((MCL_TMP_ADDR % PAGESIZE) == 0, "verifyAndMovePayload() MCL_TMP_ADDR isn't page-aligned"); + static_assert((MCL_TMP_SIZE % PAGESIZE) == 0, "verifyAndMovePayload() MCL_TMP_SIZE isn't page-aligned"); + static_assert((HDAT_TMP_ADDR % PAGESIZE) == 0, "verifyAndMovePayload() HDAT_TMP_ADDR isn't page-aligned"); + + do{ + + if (!TCE::utilUseTcesForDmas()) + { + // If TCEs were not enabled, no need to verify and move + break; + } + + TARGETING::ATTR_PAYLOAD_KIND_type payload_kind = + TARGETING::PAYLOAD_KIND_NONE; + bool is_phyp = TARGETING::is_phyp_load(&payload_kind); + + // Only Supporting PHYP/POWERVM and SAPPHIRE/OPAL at this time + // @TODO RTC 183831 in case we ever need to support Payload AVPS + if( !(TARGETING::PAYLOAD_KIND_PHYP == payload_kind ) && + !(TARGETING::PAYLOAD_KIND_SAPPHIRE == payload_kind ) ) + { + break; + } + + // Get Temporary Virtual Address To Payload + uint64_t payload_tmp_phys_addr = MCL_TMP_ADDR; + uint64_t payload_size = MCL_TMP_SIZE; + + payload_tmp_virt_addr = mm_block_map( + reinterpret_cast<void*>(payload_tmp_phys_addr), + payload_size); + + // Check for nullptr being returned + if (payload_tmp_virt_addr == nullptr) + { + blockMapFail = PAYLOAD_TMP_MAP_FAIL; + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ERR_MRK"verifyAndMovePayload(): Fail to mm_block_map " + "payload_tmp_virt_addr (loc=0x%X)", + blockMapFail); + break; + } + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,"verifyAndMovePayload() " + "Processing PAYLOAD_KIND = %d (is_phyp=%d): " + "physAddr=0x%.16llX, virtAddr=0x%.16llX", + payload_kind, is_phyp, payload_tmp_phys_addr, payload_tmp_virt_addr ); + + // If in Secure Mode Verify PHYP at Temporary TCE-related Memory Location + if (SECUREBOOT::enabled()) + { + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,"verifyAndMovePayload() " + "Verifying PAYLOAD: physAddr=0x%.16llX, virtAddr=0x%.16llX", + payload_tmp_phys_addr, payload_tmp_virt_addr ); + + l_err = SECUREBOOT::verifyContainer(payload_tmp_virt_addr); + if (l_err) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "verifyAndMovePayload(): failed verifyContainer"); + l_err->collectTrace("ISTEPS_TRACE",256); + SECUREBOOT::handleSecurebootFailure(l_err); + assert(false,"Bug! handleSecurebootFailure shouldn't return!"); + } + } + + // @TODO RTC 168745 - Verify Component ID with ASCII + // @TODO RTC 168745 - Extend PAYLOAD + + // Move PHYP to Final Location + // Get Target Service, and the system target. + TargetService& tS = targetService(); + TARGETING::Target* sys = nullptr; + (void) tS.getTopLevelTarget( sys ); + assert(sys != nullptr, "verifyAndMovePayload() sys target is NULL"); + uint64_t payloadBase = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>(); + + payloadBase = (payloadBase * MEGABYTE) + - PAGESIZE; // Put header before PAYLOAD_BASE + + // @TODO RTC 168745 - Use ContainerHeader to get accurate payload size + payloadBase_virt_addr = mm_block_map( + reinterpret_cast<void*>(payloadBase), + payload_size); + + // Check for nullptr being returned + if (payloadBase_virt_addr == nullptr) + { + blockMapFail = PAYLOAD_BASE_MAP_FAIL; + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ERR_MRK"verifyAndMovePayload(): Fail to mm_block_map " + "payloadBase_virt_addr (loc=0x%X)", + blockMapFail); + break; + } + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "verifyAndMovePayload(): Copy PAYLOAD from 0x%.16llX (va=" + "0x%llX) to PAYLOAD_BASE = 0x%.16llX (va=%llX), size=0x%llX", + payload_tmp_phys_addr, payload_tmp_virt_addr, payloadBase, + payloadBase_virt_addr, payload_size); + + memcpy (payloadBase_virt_addr, + payload_tmp_virt_addr, + payload_size); + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "verifyAndMovePayload(): after PAYLOAD memcpy"); + + // Move HDAT temporarily put into HDAT_TMP_ADDR (HDAT_TMP_SIZE) into + // its proper place + // @TODO RTC 168745 - Update hdatservices calls to return Spira-S offset + // Currently just using this known offset 80MB=0x5000000 used in current + // PHYP images and then adding 1 PAGESIZE since our virtual address starts + // at the secure header of PAYLOAD before PAYLOAD_BASE + size_t hdat_cpy_offset = 0x5001000; + + hdat_tmp_virt_addr = mm_block_map( + reinterpret_cast<void*>(HDAT_TMP_ADDR), + HDAT_TMP_SIZE); + + // Check for nullptr being returned + if (hdat_tmp_virt_addr == nullptr) + { + blockMapFail = HDAT_TMP_MAP_FAIL; + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ERR_MRK"verifyAndMovePayload(): Fail to mm_block_map " + "hdat_tmp_virt_addr (loc=0x%X)", + blockMapFail); + break; + } + + hdat_final_virt_addr = mm_block_map( + reinterpret_cast<void*>(payloadBase + + hdat_cpy_offset), + HDAT_TMP_SIZE); + + // Check for nullptr being returned + if (hdat_final_virt_addr == nullptr) + { + blockMapFail = HDAT_FINAL_MAP_FAIL; + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ERR_MRK"verifyAndMovePayload(): Fail to mm_block_map " + "hdat_final_virt_addr (loc=0x%X)", + blockMapFail); + break; + } + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "verifyAndMovePayload(): Copy HDAT from 0x%.16llX (va=" + "0x%llX) to HDAT_FINAL = 0x%.16llX (va=0x%llX), size=0x%llX", + HDAT_TMP_ADDR, hdat_tmp_virt_addr, payloadBase+hdat_cpy_offset, + hdat_final_virt_addr, + HDAT_TMP_SIZE); + + memcpy(hdat_final_virt_addr, + hdat_tmp_virt_addr, + HDAT_TMP_SIZE); + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "verifyAndMovePayload(): after HDAT memcpy"); + + } while(0); + + // Handle Possible mm_block_map fails here + if (blockMapFail != NO_MAP_FAIL) + { + // Trace done above. Just create error log here. + + /*@ + * @errortype + * @reasoncode RC_MM_MAP_ERR + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_VERIFY_AND_MOVE_PAYLOAD + * @userdata1 Map Fail Location + * @userdata2 <UNUSED> + * @devdesc mm_block_map failed and returned nullptr + * @custdesc A problem occurred during the IPL + * of the system. + */ + errlHndl_t map_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + MOD_VERIFY_AND_MOVE_PAYLOAD, + RC_MM_MAP_ERR, + blockMapFail, + 0x0, + true /*Add HB SW Callout*/); + map_err->collectTrace("ISTEPS_TRACE",256); + + // if l_err already exists just commit this log; otherwise set to l_err + if (l_err == nullptr) + { + l_err = map_err; + map_err = nullptr; + } + else + { + errlCommit(map_err, ISTEP_COMP_ID); + } + } + + // Cleanup/Unmap Memory Blocks + std::map<void*,Map_FailLocs_t> ptrs_to_unmap = + { + { payload_tmp_virt_addr, PAYLOAD_TMP_UNMAP_FAIL }, + { payloadBase_virt_addr, PAYLOAD_BASE_UNMAP_FAIL }, + { hdat_tmp_virt_addr, HDAT_TMP_UNMAP_FAIL }, + { hdat_final_virt_addr, HDAT_FINAL_UNMAP_FAIL }, + }; + + for ( auto ptr : ptrs_to_unmap ) + { + if (ptr.first == nullptr) + { + continue; + } + + int rc = mm_block_unmap(ptr.first); + + if (rc != 0) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + ERR_MRK"verifyAndMovePayload(): Failed to unmap " + "0x%.16llX (loc=0x%X)", + ptr.first, ptr.second); + + /*@ + * @errortype + * @reasoncode RC_MM_UNMAP_ERR + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_VERIFY_AND_MOVE_PAYLOAD + * @userdata1 Map Fail Location + * @userdata2 <UNUSED> + * @devdesc mm_block_unmap failed and returned nullptr + * @custdesc A problem occurred during the IPL + * of the system. + */ + errlHndl_t unmap_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + MOD_VERIFY_AND_MOVE_PAYLOAD, + RC_MM_UNMAP_ERR, + blockMapFail, + 0x0, + true /*Add HB SW Callout*/); + unmap_err->collectTrace("ISTEPS_TRACE",256); + + // if l_err already exists just commit this log; + // otherwise set to l_err + if (l_err == nullptr) + { + l_err = unmap_err; + unmap_err = nullptr; + } + else + { + errlCommit(unmap_err, ISTEP_COMP_ID); + } + } + } + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + EXIT_MRK"verifyAndMovePayload(): l_err rc = 0x%X", + ERRL_GETRC_SAFE(l_err) ); + + return l_err; +} + + void* call_host_runtime_setup (void *io_pArgs) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, @@ -71,7 +372,6 @@ void* call_host_runtime_setup (void *io_pArgs) do { // Close PAYLOAD TCEs - // @TODO RTC 168745 - also close HDAT TCEs if (TCE::utilUseTcesForDmas()) { @@ -83,16 +383,6 @@ void* call_host_runtime_setup (void *io_pArgs) // break from do loop if error occurred break; } - - // Disable all TCEs - l_err = TCE::utilDisableTces(); - if ( l_err ) - { - TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "Failed TCE::utilDisableTces" ); - // break from do loop if error occurred - break; - } } //Need to send System Configuration down to SBE @@ -152,6 +442,7 @@ void* call_host_runtime_setup (void *io_pArgs) } // Tell SBE to Close All Unsecure Memory Regions + // @TODO RTC 168745 - Move to istep 21.3 (closer to shutdown) l_err = SBEIO::closeAllUnsecureMemRegions(); if ( l_err ) { @@ -185,6 +476,14 @@ void* call_host_runtime_setup (void *io_pArgs) break; } + // Verify PAYLOAD and Move PAYLOAD+HDAT from Temporary TCE-related + // memory region to the proper location + l_err = verifyAndMovePayload(); + if(l_err) + { + break; + } + // Map the Host Data into the VMM if applicable l_err = RUNTIME::load_host_data(); if( l_err ) @@ -365,6 +664,19 @@ void* call_host_runtime_setup (void *io_pArgs) } #endif + if (TCE::utilUseTcesForDmas()) + { + // Disable all TCEs + l_err = TCE::utilDisableTces(); + if ( l_err ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Failed TCE::utilDisableTces" ); + // break from do loop if error occurred + break; + } + } + } while(0); if( l_err ) @@ -380,7 +692,7 @@ void* call_host_runtime_setup (void *io_pArgs) } - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_runtime_setup exit" ); return l_StepError.getErrorHandle(); diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index 88d417c38..3212881e8 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -549,7 +549,7 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, size_t& o_dataSize) { errlHndl_t errhdl = NULL; - TRACFCOMP( g_trac_runtime, "RUNTIME::getHostDataSection( i_section=%d, i_instance=%d )", i_section, i_instance ); + TRACFCOMP( g_trac_runtime, ENTER_MRK"getHostDataSection> i_section=%d, i_instance=%d", i_section, i_instance ); do { @@ -921,7 +921,7 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, } } while(0); - TRACFCOMP( g_trac_runtime, "getHostDataSection> o_dataAddr=0x%X, o_dataSize=%d", o_dataAddr, o_dataSize ); + TRACFCOMP( g_trac_runtime, EXIT_MRK"getHostDataSection> o_dataAddr=0x%X, o_dataSize=%d", o_dataAddr, o_dataSize ); return errhdl; } diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index b135d0513..8c9f7fff3 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -1156,6 +1156,8 @@ void tpmVerifyFunctionalTpmExists() HWAS::SRCI_PRIORITY_LOW); err->collectTrace( SECURE_COMP_NAME ); err->collectTrace(TRBOOT_COMP_NAME); + err->collectTrace( I2C_COMP_NAME ); + err->collectTrace( TPMDD_COMP_NAME ); uint32_t errPlid = err->plid(); // HW callout TPMs diff --git a/src/usr/util/utillidmgr.C b/src/usr/util/utillidmgr.C index 7f94c50ed..d69d02d0b 100644 --- a/src/usr/util/utillidmgr.C +++ b/src/usr/util/utillidmgr.C @@ -35,6 +35,7 @@ #include "utilbase.H" #include <initservice/initserviceif.H> #include <sys/mm.h> +#include <util/align.H> #include <config.h> #ifdef CONFIG_SECUREBOOT @@ -112,7 +113,6 @@ errlHndl_t UtilLidMgr::getLidSize(size_t& o_lidSize) //ask the FSP for it. //Send message to FSP asking for info on the current LID. - // allocate message buffer // buffer will be initialized to zero by msg_allocate() if (iv_spBaseServicesEnabled) @@ -353,8 +353,12 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) uint8_t* dataPtr = nullptr; void* copyOffset = nullptr; bool img_in_pnor = false; + bool use_tces = 0; bool tces_allocated = false; uint32_t tceToken = 0; + uint32_t dmaAddr = 0; + void* tceStartAddr = nullptr; + uint64_t tceSize = 0; do{ ////////////////////////////////////////////////// @@ -371,12 +375,34 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) //Image not in PNOR, request from FSP. if(iv_spBaseServicesEnabled) { + use_tces = TCE::utilUseTcesForDmas(); + // If using TCEs, setup TCE Table for FSP to use - if (TCE::utilUseTcesForDmas()) + if (use_tces) { - // Use Preverification Location and Size - errl = TCE::utilAllocateTces(MCL_TMP_ADDR, - MCL_TMP_SIZE, + // Assume caller passed in Virtual Address that was already + // backed to Physical Memory + UTIL_FT("getLid: requesting TCEs for i_dest=0x%.16llX, i_destSize=0x%X (lidId=0x%X)", i_dest, i_destSize, iv_lidId); + + // Need to Allocate TCEs on Page-Aligned Memory + size_t i_dest_remainder = reinterpret_cast<uint64_t>(i_dest) + % PAGESIZE; + + if (i_dest_remainder != 0) + { + tceStartAddr = reinterpret_cast<void*>( + ALIGN_PAGE_DOWN(reinterpret_cast<uint64_t>(i_dest))); + tceSize = i_destSize + i_dest_remainder; + UTIL_DT("getLid: requesting non-page-aligned i_dest (%p): adjusted TCE tceStartAddr = %p, tceSize=0x%X", i_dest, tceStartAddr, tceSize); + } + else + { + tceStartAddr = i_dest; + tceSize = i_destSize; + } + + errl = TCE::utilAllocateTces(mm_virt_to_phys(tceStartAddr), + tceSize, tceToken); if(errl) { @@ -384,6 +410,10 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) break; } tces_allocated = true; + + // Update dmaAddr that FSP needs to use, if necessary + dmaAddr = tceToken + i_dest_remainder; + UTIL_DT("getLid: got back tceToken=0x%.16llX. DMA_Addr=0x%.16llX", tceToken, dmaAddr); } errl = createMsgQueue(); @@ -402,7 +432,7 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) UTILLID_ADD_LID_ID( iv_lidId, l_pMsg->data[0] ); UTILLID_ADD_HEADER_FLAG( 0 , l_pMsg->data[0] ); - UTILLID_ADD_TCE_TOKEN( tceToken , l_pMsg->data[1] ); + UTILLID_ADD_TCE_TOKEN( dmaAddr , l_pMsg->data[1] ); errl = sendMboxMessage( SYNCHRONOUS, l_pMsg ); if(errl) @@ -444,6 +474,13 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) break; } + // In TCE Mode FSP DMAs the entire LID before returning synchronus + // message above with the SEND_TO_HB message type + if (use_tces && (l_pMsg->type == UTILLID::SEND_TO_HB)) + { + UTIL_DT("getLid: Using TCEs and got back UTILLID::SEND_TO_HB: transfer complete"); + break; + } //Now wait for FSP to send the LID page-by-page. do{ @@ -563,7 +600,6 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) } }while(transferred_data < iv_lidSize); - } if(errl) { @@ -576,7 +612,7 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) { // Use Preverification Location and Size auto tce_errl = TCE::utilDeallocateTces(tceToken, - MCL_TMP_SIZE); + tceSize); if(tce_errl) { @@ -592,6 +628,7 @@ errlHndl_t UtilLidMgr::getLid(void* i_dest, size_t i_destSize) { // Set errl to tce_errl errl = tce_errl; + tce_errl = nullptr; } } } diff --git a/src/usr/util/utilmclmgr.C b/src/usr/util/utilmclmgr.C index 66c3b1a29..81e1c8cff 100644 --- a/src/usr/util/utilmclmgr.C +++ b/src/usr/util/utilmclmgr.C @@ -328,7 +328,6 @@ void MasterContainerLidMgr::printCompInfoCache() errlHndl_t MasterContainerLidMgr::processComponents() { errlHndl_t l_errl = nullptr; - for (auto & compInfoPair : iv_compInfoCache) { // Skip the MCL itself as it's already been processed @@ -377,7 +376,11 @@ errlHndl_t MasterContainerLidMgr::processComponent(const ComponentID& i_compId, { // Skip loading, but still process POWERVM (PHYP) component l_skipLoad = true; - UTIL_FT("MasterContainerLidMgr::processComponent skip load but processing POWERVM component"); + + // @TODO RTC 168745 - Handle POWERVM Correctly + // UTIL_FT("MasterContainerLidMgr::processComponent skip load but processing POWERVM component"); + UTIL_FT("MasterContainerLidMgr::processComponent - skip loading and processing of POWERVM component"); + break; } else { diff --git a/src/usr/util/utiltcemgr.C b/src/usr/util/utiltcemgr.C index 01f2bf7e6..2424ee686 100644 --- a/src/usr/util/utiltcemgr.C +++ b/src/usr/util/utiltcemgr.C @@ -54,6 +54,7 @@ TRAC_INIT(&g_trac_tce, UTILTCE_TRACE_NAME, 4*KILOBYTE); // ------------------------ // Macros for unit testing - leave extra trace enabled for now +// @TODO RTC 168745 - Disable TRACUCOMP as the default #define TRACUCOMP(args...) TRACFCOMP(args) //#define TRACUCOMP(args...) @@ -64,13 +65,10 @@ namespace TCE /************************************************************************/ // Defines /************************************************************************/ -// @TODO RTC 168745 Currently hardcoded to 128MB when the original plan was -// to use PNOR payloadInfo.size, but that only was 19MB -#define TCE_PAYLOAD_SIZE (128*MEGABYTE) - // TCE Table Address must be 4MB Aligned #define TCE_TABLE_ADDRESS_ALIGNMENT (4*MEGABYTE) + /************************************************************************/ // External Interface: // NAME: utilAllocateTces @@ -123,22 +121,6 @@ UtilTceMgr& getTceManager(void) return Singleton<UtilTceMgr>::instance(); }; -/***********************************************************************************/ -/* Local function to get PAYLOAD base address and size */ -/***********************************************************************************/ -errlHndl_t getPayloadAddrAndSize(uint64_t& o_addr, size_t& o_size) -{ - errlHndl_t errl = nullptr; - - // Move PAYLOAD to Preverification Location - o_addr = MCL_TMP_ADDR; - o_size = MCL_TMP_SIZE; - - TRACFCOMP( g_trac_tce,EXIT_MRK"getPayloadAddrAndSize(): o_addr=0x%.16llX, o_size=0x%.16llX", o_addr, o_size); - - return errl; -} - errlHndl_t utilSetupPayloadTces(void) { errlHndl_t errl = nullptr; @@ -149,24 +131,24 @@ errlHndl_t utilSetupPayloadTces(void) do{ - TRACFCOMP(g_trac_tce,ENTER_MRK"utilSetupPayloadTces(): get Address and Size"); + TRACFCOMP(g_trac_tce,ENTER_MRK"utilSetupPayloadTces()"); - errl = getPayloadAddrAndSize(addr, size); + // Allocate TCEs for PAYLOAD to Temporary Space + addr = MCL_TMP_ADDR; + size = MCL_TMP_SIZE; + errl = utilAllocateTces(addr, size, token); if (errl) { - TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from getPayloadAddrAndSize()"); + TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from utilAllocateTces() for PAYLOAD using addr=0x%.16llX, size=0x%llX", addr, size); break; } - - errl = utilAllocateTces(addr, size, token); - if (errl) + else { - TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from utilAllocateTces() using addr=0x%.16llX, size=0x%llX", addr, size); - break; + TRACUCOMP(g_trac_tce,"utilSetupPayloadTces(): utilAllocateTces() for PAYLOAD: addr=0x%.16llX, size=0x%llX, token=0x%X", addr, size, token); } - // Set attribute to tell FSP that Payload has been setup at the start of the TCE Table - // Get Target Service and the system target to set TCE_START_TOKEN_FOR_PAYLOAD + // Set attribute to tell FSP what the PAYLOAD token is + // Get Target Service and the system target to set attributes TARGETING::TargetService& tS = TARGETING::targetService(); TARGETING::Target* sys = nullptr; (void) tS.getTopLevelTarget( sys ); @@ -174,9 +156,34 @@ errlHndl_t utilSetupPayloadTces(void) sys->setAttr<TARGETING::ATTR_TCE_START_TOKEN_FOR_PAYLOAD>(token); + // Save for internal use since we can't trust FSP won't change the attribute + Singleton<UtilTceMgr>::instance().setToken(UtilTceMgr::PAYLOAD_TOKEN, + token); + + // Allocate TCEs for HDAT + addr = HDAT_TMP_ADDR; + size = HDAT_TMP_SIZE; + errl = utilAllocateTces(addr, size, token); + if (errl) + { + TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from utilAllocateTces() for HDAT using addr=0x%.16llX, size=0x%llX", HDAT_TMP_ADDR, HDAT_TMP_SIZE); + break; + } + else + { + TRACUCOMP(g_trac_tce,"utilSetupPayloadTces(): utilAllocateTces() for HDAT: addr=0x%.16llX, size=0x%llX, token=0x%X", addr, size, token); + } + + // Set attribute to tell FSP what the HDAT token is + sys->setAttr<TARGETING::ATTR_TCE_START_TOKEN_FOR_HDAT>(token); + + // Save for internal use since we can't trust FSP won't change the attribute + Singleton<UtilTceMgr>::instance().setToken(UtilTceMgr::HDAT_TOKEN, + token); + } while(0); - TRACFCOMP(g_trac_tce,EXIT_MRK"utilSetupPayloadTces(): Address=0x%.16llX, size=0x%X, token=0x%.8X, errl_rc=0x%X", addr, size, token, ERRL_GETRC_SAFE(errl)); + TRACFCOMP(g_trac_tce,EXIT_MRK"utilSetupPayloadTces(): errl_rc=0x%X", ERRL_GETRC_SAFE(errl)); return errl; } @@ -185,31 +192,26 @@ errlHndl_t utilClosePayloadTces(void) { errlHndl_t errl = nullptr; - uint64_t addr=0x0; size_t size=0x0; uint32_t token=0x0; do{ - TRACFCOMP(g_trac_tce,ENTER_MRK"utilClosePayloadTces(): get Address and Size"); + TRACFCOMP(g_trac_tce,ENTER_MRK"utilClosePayloadTces()"); - // Get Payload Address and Size - errl = getPayloadAddrAndSize(addr, size); + // size is a constant for PAYLOAD + size = MCL_TMP_SIZE; + token = Singleton<UtilTceMgr>::instance().getToken(UtilTceMgr::PAYLOAD_TOKEN); + errl = utilDeallocateTces(token, size); if (errl) { - TRACFCOMP(g_trac_tce,"utilClosePayloadTces(): ERROR back from getPayloadAddrAndSize()"); + TRACFCOMP(g_trac_tce,"utilClosePayloadTces(): ERROR back from utilDeallocateTces() using token=0x%.8X, size=0x%llX", token, size); break; } - // Get Starting Payload Token - // Get Target Service and the system target to set TCE_START_TOKEN_FOR_PAYLOAD - TARGETING::TargetService& tS = TARGETING::targetService(); - TARGETING::Target* sys = nullptr; - (void) tS.getTopLevelTarget( sys ); - assert(sys, "utilSetupPayloadTces() system target is NULL"); - - token = sys->getAttr<TARGETING::ATTR_TCE_START_TOKEN_FOR_PAYLOAD>(); - + // size is a constant for HDAT + size = HDAT_TMP_SIZE; + token = Singleton<UtilTceMgr>::instance().getToken(UtilTceMgr::HDAT_TOKEN); errl = utilDeallocateTces(token, size); if (errl) { @@ -217,9 +219,10 @@ errlHndl_t utilClosePayloadTces(void) break; } + } while(0); - TRACFCOMP(g_trac_tce,EXIT_MRK"utilClosePayloadTces(): token=0x%.8X, size=0x%X, errl_rc=0x%X", token, size, ERRL_GETRC_SAFE(errl)); + TRACFCOMP(g_trac_tce,EXIT_MRK"utilClosePayloadTces(): errl_rc=0x%X", ERRL_GETRC_SAFE(errl)); return errl; } @@ -238,6 +241,8 @@ UtilTceMgr::UtilTceMgr(const uint64_t i_tableAddr, const size_t i_tableSize) ,iv_tceTablePhysAddr(i_tableAddr) ,iv_tceEntryCount(0) ,iv_tceTableSize(i_tableSize) + ,iv_payloadToken(INVALID_TOKEN_VALUE) + ,iv_hdatToken(INVALID_TOKEN_VALUE) { // Table Address must be 4MB Aligned and default input is TCE_TABLE_ADDR static_assert( TCE_TABLE_ADDR % TCE_TABLE_ADDRESS_ALIGNMENT == 0,"TCE Table must align on 4 MB boundary"); @@ -767,9 +772,12 @@ errlHndl_t UtilTceMgr::allocateTces(const uint64_t i_startingAddress, TRACDCOMP(g_trac_tce,INFO_MRK"UtilTceMgr::allocateTces: TCE Entry/Token[%d] (hex) = %llX", index, tablePtr[index]); } - iv_allocatedAddrs[startingIndex].start_addr = i_startingAddress; - iv_allocatedAddrs[startingIndex].size = i_size; - o_startingToken = startingIndex; + // Save And Return Information about Allocated TCEs + // Key to this map is the token, which is a DMA address that = + // (Starting Index in TCE Table) * PAGESIZE + o_startingToken = startingIndex*PAGESIZE; + iv_allocatedAddrs[o_startingToken].start_addr = i_startingAddress; + iv_allocatedAddrs[o_startingToken].size = i_size; TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: SUCCESSFUL: addr = 0x%.16llX, size = 0x%llX, starting entry=0x%X",i_startingAddress, i_size, startingIndex); } @@ -802,7 +810,7 @@ errlHndl_t UtilTceMgr::allocateTces(const uint64_t i_startingAddress, } }while(0); - TRACFCOMP(g_trac_tce, EXIT_MRK"UtilTceMgr::allocateTces: END: addr = 0x%.16llX and size = 0x%X, numTcesNeeded=0x%X", i_startingAddress, i_size, numTcesNeeded); + TRACFCOMP(g_trac_tce, EXIT_MRK"UtilTceMgr::allocateTces: END: addr = 0x%.16llX and size = 0x%X, numTcesNeeded=0x%X. returning o_startingToken=0x%.8X", i_startingAddress, i_size, numTcesNeeded, o_startingToken); printIvMap(); //Debug return errl; @@ -830,6 +838,9 @@ errlHndl_t UtilTceMgr::deallocateTces(const uint32_t i_startingToken, do { + // Assert if i_startingToken is not aligned on PAGESIZE + assert((i_startingToken % PAGESIZE) == 0, "UtilTceMgr::deallocateTces: i_startingToken (0x%.8X) is not page aligned", i_startingToken); + // Assert if i_size is not greater than zero assert(i_size > 0, "UtilTceMgr::deallocateTces: i_size = %d, not greater than zero", i_size); @@ -847,7 +858,7 @@ errlHndl_t UtilTceMgr::deallocateTces(const uint32_t i_startingToken, } else { - startingIndex = map_itr->first; + startingIndex = (map_itr->first) / PAGESIZE; startingAddress = map_itr->second.start_addr; } TRACUCOMP(g_trac_tce,"UtilTceMgr::deallocateTces: numTcesNeeded=0x%X, startingAddress = 0x%X", numTcesNeeded, startingAddress); @@ -1258,6 +1269,45 @@ errlHndl_t UtilTceMgr::unmapPsiHostBridge(void *& io_psihb_ptr) const return errl; } +/**************************************************************************/ +// +// NAME: getToken: +// Returns one of two internally stored tokens +// +/**************************************************************************/ + +uint32_t UtilTceMgr::getToken(const tokenLabels i_tokenLabel) +{ + assert((i_tokenLabel==UtilTceMgr::PAYLOAD_TOKEN)||(i_tokenLabel==UtilTceMgr::HDAT_TOKEN),"UtilTceMgr::getToken bad input parm: 0x%X", i_tokenLabel); + + return (i_tokenLabel==UtilTceMgr::PAYLOAD_TOKEN) + ? iv_payloadToken : iv_hdatToken; + +} + +/**************************************************************************/ +// +// NAME: setToken: +// Sets one of two internally stored tokens +// +/**************************************************************************/ +void UtilTceMgr::setToken(const tokenLabels i_tokenLabel, + const uint32_t i_tokenValue) +{ + assert((i_tokenLabel==UtilTceMgr::PAYLOAD_TOKEN)||(i_tokenLabel==UtilTceMgr::HDAT_TOKEN),"UtilTceMgr::setToken bad input parm: 0x%X", i_tokenLabel); + + if (i_tokenLabel==UtilTceMgr::PAYLOAD_TOKEN) + { + iv_payloadToken = i_tokenValue; + } + else + { + iv_hdatToken = i_tokenValue; + } + + return; +} + /******************************************************/ /* Miscellaneous Functions */ @@ -1290,6 +1340,7 @@ errlHndl_t utilEnableTcesWithoutTceTable(void) { errlHndl_t errl = nullptr; + // @TODO RTC 168745 - Update to use Singleton UtilTceMgr // Create local UtilTceMgr with default TCE table address but with a size // of zero so that all entries are invalid // NOTE: memory at TCE Table Address is initialized to 0 as part of IPL and diff --git a/src/usr/util/utiltcemgr.H b/src/usr/util/utiltcemgr.H index a4689235c..aabf99d5a 100644 --- a/src/usr/util/utiltcemgr.H +++ b/src/usr/util/utiltcemgr.H @@ -120,8 +120,12 @@ class UtilTceMgr /** size of the Tce Table */ size_t iv_tceTableSize; + /** Tokens for PAYLOAD and HDAT entries in the TCE Table */ + uint32_t iv_payloadToken; + uint32_t iv_hdatToken; + /* Cache of starting addresses of allocated TCEs and their - * tokens (starting entry in the TCE Table) and size + * tokens ((starting entry in the TCE Table) * PAGESIZE) and size * Indexed by token - the position of the first entry of the TCE Table * Returns the starting address and size of the memory allocated by the * entries in the TCE Table @@ -146,6 +150,12 @@ class UtilTceMgr PHBSECURE_TCE_ENABLE = 0x2000000000000000, }; + /** Values related to tokens */ + enum tokenValues : uint32_t + { + INVALID_TOKEN_VALUE = 0xFFFFFFFF, + }; + /** * @brief Responsible for initalizing the TCE Table and mapping the * TCE Table into memory @@ -240,9 +250,11 @@ class UtilTceMgr * Size must be less than (512K * PAGESIZE) or will fail * Assert if not greater than zero * @param[out] o_startingToken - Starting Entry into the table. - * (This is an offset into the array based on - * the TCE index * PAGESIZE. Each TCE entry - * maps to a pagesize of memory) + * @param[out] o_startingToken - Key to the Starting Entry into the table. + * This is an offset into the array based on the + * TCE Index * PAGESIZE. + * FSP uses the token as a DMA Address. + * Each TCE entry maps to a pagesize of memory. * * Note: First time this is called will cause TCE table to be created and * the Processors to be setup to point at the TCE table @@ -287,6 +299,42 @@ class UtilTceMgr */ errlHndl_t initTceInHdw(); + + /** Values related to tokens */ + enum tokenLabels + { + PAYLOAD_TOKEN = 0x0, + HDAT_TOKEN = 0x1, + }; + + /** + * @brief Returns one of two internally stored tokens + * + * @param[in] i_tokenLabel - Specifies which token to return + * Assert if neither PAYLOAD_TOKEN nor + * HDAT_TOKEN + * + * @return uint32_t - Return specified token + * + */ + uint32_t getToken(tokenLabels i_tokenLabel); + + /** + * @brief Sets one of two internally stored tokens + * + * @param[in] i_tokenLabel - Specifies which token to set + * Assert if neither PAYLOAD_TOKEN nor + * HDAT_TOKEN + * + * @param[in] i_tokenValue - Value to be set + * + * @return uint32_t - Set specified token + * + */ + void setToken(tokenLabels i_tokenLabel, + uint32_t i_tokenValue); + + }; // class UtilTceMgr /** |

