From 44d0f070400aabde3a06eb7b836923577a117cc0 Mon Sep 17 00:00:00 2001 From: Roland Veloz Date: Mon, 4 Dec 2017 17:37:05 -0600 Subject: Handles FSP reset-reload in HBRT messages For every instance where a firmware_request is made, it is possible to get an error if the FSP is doing a reset/reload. Now, if an error returned from the firmware_request call indicates that the FSP is doing a reset/reload, the firmware_request call will be made again. Also refactored the code. Consolidated the calls to firmware_request to another file to facilitate the adding/updating of messages. Change-Id: I5be440927ab255c55b40a0a0ed26f786d31a9317 RTC:182606 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/50505 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Reviewed-by: Daniel M. Crowell --- src/usr/errl/runtime/makefile | 2 +- src/usr/errl/runtime/rt_errlmanager.C | 84 ++-- src/usr/isteps/pm/runtime/rt_pm.C | 139 +++--- .../isteps/pm/runtime/test/firmwareRequestTest.H | 11 +- src/usr/isteps/tod/runtime/makefile | 4 +- src/usr/isteps/tod/runtime/rt_todintf.C | 465 ++++++++------------- src/usr/testcore/rtloader/loader.H | 11 +- src/usr/util/runtime/makefile | 1 + src/usr/util/runtime/rt_fwnotify.C | 380 ++++++++--------- src/usr/util/runtime/rt_fwreq_helper.C | 455 ++++++++++++++++++++ src/usr/vpd/runtime/makefile | 2 +- src/usr/vpd/runtime/rt_vpd.C | 198 ++++----- 12 files changed, 1018 insertions(+), 734 deletions(-) create mode 100644 src/usr/util/runtime/rt_fwreq_helper.C (limited to 'src/usr') diff --git a/src/usr/errl/runtime/makefile b/src/usr/errl/runtime/makefile index ec449ea5d..d4d097dfe 100644 --- a/src/usr/errl/runtime/makefile +++ b/src/usr/errl/runtime/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2015 +# Contributors Listed Below - COPYRIGHT 2013,2017 # [+] International Business Machines Corp. # # diff --git a/src/usr/errl/runtime/rt_errlmanager.C b/src/usr/errl/runtime/rt_errlmanager.C index cea88de64..4361a691d 100644 --- a/src/usr/errl/runtime/rt_errlmanager.C +++ b/src/usr/errl/runtime/rt_errlmanager.C @@ -31,7 +31,8 @@ #include #include #include -#include +#include // g_hostInterfaces +#include // firmware_request_helper #include #include #include @@ -89,7 +90,8 @@ ErrlManager::ErrlManager() : } else { - TRACFCOMP( g_trac_errl, "Error log being created before TARGETING is ready..." ); + TRACFCOMP( g_trac_errl, "Error log being created before " + "TARGETING is ready..." ); } if(sys) { @@ -116,7 +118,8 @@ ErrlManager::ErrlManager() : spfn.baseServices)) { iv_isSpBaseServices = false; - TRACFCOMP( g_trac_errl, INFO_MRK"no baseServices, setting up to save to pnor" ); + TRACFCOMP( g_trac_errl, INFO_MRK"no baseServices, setting " + "up to save to pnor" ); setupPnorInfo(); } else @@ -146,6 +149,10 @@ ErrlManager::~ErrlManager() /////////////////////////////////////////////////////////////////////////////// void ErrlManager::sendMboxMsg ( errlHndl_t& io_err ) { + // Put the handle to the firmware_request request struct + // out here so it is easier to free later + hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr; + do { if (!iv_isSpBaseServices) @@ -155,8 +162,8 @@ void ErrlManager::sendMboxMsg ( errlHndl_t& io_err ) bool l_savedToPnor = saveErrLogToPnor(io_err); if (!l_savedToPnor) { - TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor didn't save 0x%X", - io_err->eid()); + TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor " + "didn't save 0x%X", io_err->eid()); } } @@ -186,8 +193,8 @@ void ErrlManager::sendMboxMsg ( errlHndl_t& io_err ) if(rc) { - TRACFCOMP(g_trac_errl, ERR_MRK - "Failed sending error log to FSP via " + TRACFCOMP(g_trac_errl, + ERR_MRK"Failed sending error log to FSP via " "sendErrorLog. rc: %d. plid: 0x%08x", rc, io_err->plid() ); @@ -197,43 +204,53 @@ void ErrlManager::sendMboxMsg ( errlHndl_t& io_err ) } else if (g_hostInterfaces->firmware_request) { - // Get an accurate size of memory actually - // needed to transport the data - size_t l_req_fw_msg_size = - hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(hostInterfaces::hbrt_fw_msg::error_log) + - l_msgSize; - - // Create the firmware_request structure - // to carry the error log data + // Get an accurate size of memory needed to transport + // the data for the firmware_request request struct + uint64_t l_req_fw_msg_size = + hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(hostInterfaces::hbrt_fw_msg::error_log) + + l_msgSize - + sizeof(hostInterfaces::hbrt_fw_msg::error_log.i_data); + + // Create the firmware_request request struct to send data hostInterfaces::hbrt_fw_msg *l_req_fw_msg = (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); - memset(l_req_fw_msg, 0, l_req_fw_msg_size); - // Populate the firmware_request structure with given data + // Populate the firmware_request request struct with given data l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_TYPE_ERROR_LOG; l_req_fw_msg->error_log.i_plid = io_err->plid(); l_req_fw_msg->error_log.i_errlSize = l_msgSize; io_err->flatten (&(l_req_fw_msg->error_log.i_data), l_msgSize); + // Trace out firmware request info + TRACFCOMP(g_trac_errl, + INFO_MRK"Error log firmware request info: " + "io_type:%d, plid: 0x%08x, errlSize:%d", + l_req_fw_msg->io_type, + l_req_fw_msg->error_log.i_plid, + l_req_fw_msg->error_log.i_errlSize); + + TRACFBIN(g_trac_errl, "Error log firmware request data: ", + &(l_req_fw_msg->error_log.i_data), + l_req_fw_msg->error_log.i_errlSize); + + // Create the firmware_request response struct to receive data hostInterfaces::hbrt_fw_msg l_resp_fw_msg; uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); - size_t rc = g_hostInterfaces-> - firmware_request(l_req_fw_msg_size, l_req_fw_msg, - &l_resp_fw_msg_size, &l_resp_fw_msg); + memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); - if(rc) - { - TRACFCOMP(g_trac_errl, ERR_MRK - "Failed sending error log to FSP " - "via firmware_request. rc: %d. plid: 0x%08x", - rc, - io_err->plid() ); - } - free(l_req_fw_msg); + // Make the firmware_request call + errlHndl_t l_err = firmware_request_helper(l_req_fw_msg_size, + l_req_fw_msg, + &l_resp_fw_msg_size, + &l_resp_fw_msg); + + // Should not get an error log, but if it happens, + // just delete it. + delete l_err, l_err = nullptr; } else { @@ -258,6 +275,10 @@ void ErrlManager::sendMboxMsg ( errlHndl_t& io_err ) } while (0); + // Release the firmware_request request struct + free(l_req_fw_msg); + l_req_fw_msg = nullptr; + TRACFCOMP( g_trac_errl, EXIT_MRK"sendToHypervisor()" ); return; } @@ -341,7 +362,8 @@ bool rt_processCallout(errlHndl_t &io_errl, if (!l_err) { - errlHndl_t errl = HWAS::theDeconfigGard().platCreateGardRecord(pTarget, + errlHndl_t errl = HWAS::theDeconfigGard().platCreateGardRecord + (pTarget, io_errl->eid(), pCalloutUD->gardErrorType); if (errl) diff --git a/src/usr/isteps/pm/runtime/rt_pm.C b/src/usr/isteps/pm/runtime/rt_pm.C index 33d2014d1..ecddab2a2 100644 --- a/src/usr/isteps/pm/runtime/rt_pm.C +++ b/src/usr/isteps/pm/runtime/rt_pm.C @@ -28,16 +28,19 @@ #include #include #include + #include #include #include #include -#include +#include // g_hostInterfaces +#include // firmware_request_helper #include #include + #include // targeting support @@ -49,6 +52,7 @@ using namespace TARGETING; using namespace RUNTIME; +using namespace ERRORLOG; namespace ISTEPS_TRACE { @@ -342,6 +346,7 @@ namespace RTPM "/firmware_request interface not linked"); /*@ * @errortype + * @severity ERRL_SEV_INFORMATIONAL * @moduleid MOD_PM_RT_HCODE_UPDATE * @reasoncode RC_PM_RT_INTERFACE_ERR * @userdata1[0:31] Target HUID @@ -350,14 +355,13 @@ namespace RTPM * @devdesc HCODE scom update runtime * interface not linked. */ - l_err= new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_INFORMATIONAL, - MOD_PM_RT_HCODE_UPDATE, - RC_PM_RT_INTERFACE_ERR, - TWO_UINT32_TO_UINT64( - TARGETING::get_huid(i_target), - i_section), - i_rel_scom_addr); + l_err= new ErrlEntry(ERRL_SEV_INFORMATIONAL, + MOD_PM_RT_HCODE_UPDATE, + RC_PM_RT_INTERFACE_ERR, + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(i_target), + i_section), + i_rel_scom_addr); break; } @@ -411,32 +415,37 @@ namespace RTPM TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"hcode_update: " "HCODE scom update failed. " - "rc 0x%X target 0x%llX chipId 0x%llX section 0x%X " - "operation 0x%X scomAddr 0x%llX scomData 0x%llX", + "rc: 0x%X, target: 0x%llX, chipId: 0x%llX, " + "section: 0x%X, operation: 0x%X, scomAddr: 0x%llX, " + "scomData: 0x%llX", rc, get_huid(i_target), l_chipId, i_section, i_operation, l_scomAddr, i_scom_data); - // convert rc to error log /*@ * @errortype + * @severity ERRL_SEV_INFORMATIONAL * @moduleid MOD_PM_RT_HCODE_UPDATE * @reasoncode RC_PM_RT_HCODE_UPDATE_ERR * @userdata1 Hypervisor return code * @userdata2 SCOM address * @devdesc HCODE SCOM update error */ - l_err=new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_INFORMATIONAL, - MOD_PM_RT_HCODE_UPDATE, - RC_PM_RT_HCODE_UPDATE_ERR, - rc, - l_scomAddr); + l_err = new ErrlEntry( ERRL_SEV_INFORMATIONAL, + MOD_PM_RT_HCODE_UPDATE, + RC_PM_RT_HCODE_UPDATE_ERR, + rc, + l_scomAddr); break; } } else if (g_hostInterfaces->firmware_request != nullptr) { + // Create the firmware_request request struct to send data hostInterfaces::hbrt_fw_msg l_req_fw_msg; + uint64_t l_req_fw_msg_size = sizeof(l_req_fw_msg); + memset(&l_req_fw_msg, 0, l_req_fw_msg_size); + + // Populate the firmware_request request struct with given data l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE; l_req_fw_msg.req_hcode_update.i_chipId = l_chipId; @@ -445,82 +454,35 @@ namespace RTPM l_req_fw_msg.req_hcode_update.i_scomAddr = l_scomAddr; l_req_fw_msg.req_hcode_update.i_scomData = i_scom_data; + // Trace out firmware request info + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + INFO_MRK"HCODE update firmware request info: " + "io_type:%d, chipId:0x%llX, section:0x%X, " + "operation:0x%X, scomAddr:0x%llX, scomData:0x%llX", + l_req_fw_msg.io_type, + l_req_fw_msg.req_hcode_update.i_chipId, + l_req_fw_msg.req_hcode_update.i_section, + l_req_fw_msg.req_hcode_update.i_operation, + l_req_fw_msg.req_hcode_update.i_scomAddr, + l_req_fw_msg.req_hcode_update.i_scomData); + + // Create the firmware_request response struct to receive data hostInterfaces::hbrt_fw_msg l_resp_fw_msg; uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); - rc = g_hostInterfaces->firmware_request(sizeof(l_req_fw_msg), - &l_req_fw_msg, &l_resp_fw_msg_size, &l_resp_fw_msg); - if(rc) - { - TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, - ERR_MRK"firmware request: " - "firmware request for hcode scom update failed. " - "rc 0x%X target 0x%llX chipId 0x%llX section 0x%X " - "operation 0x%X scomAddr 0x%llX scomData 0x%llX", - rc, get_huid(i_target), l_chipId, i_section, - i_operation, l_scomAddr, i_scom_data); + memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); - // convert rc to error log - /*@ - * @errortype - * @moduleid MOD_PM_RT_FIRMWARE_REQUEST - * @reasoncode RC_PM_RT_HCODE_UPDATE_ERR - * @userdata1[0:31] Firmware Request return code - * @userdata1[32:63] SCOM address - * @userdata2[0:31] Generic response code - if it exists - * @userdata2[32:63] Firmware Response type - * @devdesc Firmware Request for - * HCODE SCOM update error - */ - // - // Pack the generic response code if the response - // is of type "RESP_GENERIC" - // else just send the response type alone - uint64_t l_userData2 = 0; - if (l_resp_fw_msg_size >= - hostInterfaces::HBRT_FW_MSG_BASE_SIZE) - { - // just assign the response type for now - l_userData2 = l_resp_fw_msg.io_type; - - // Pack the response code if it is available - if ((l_resp_fw_msg_size >= - (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(l_resp_fw_msg.resp_generic))) && - hostInterfaces::HBRT_FW_MSG_TYPE_RESP_GENERIC == - l_resp_fw_msg.io_type) - { - l_userData2 = TWO_UINT32_TO_UINT64 - (l_resp_fw_msg.resp_generic.o_status, - l_resp_fw_msg.io_type); - } - } - - l_err=new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_INFORMATIONAL, - MOD_PM_RT_FIRMWARE_REQUEST, - RC_PM_RT_HCODE_UPDATE_ERR, - TWO_UINT32_TO_UINT64(rc, l_scomAddr), - l_userData2); - - if (l_resp_fw_msg_size > 0) - { - l_err->addFFDC( ISTEP_COMP_ID, - &l_resp_fw_msg, - l_resp_fw_msg_size, - 0, 0, false ); - } - - if (sizeof(l_req_fw_msg) > 0) - { - l_err->addFFDC( ISTEP_COMP_ID, - &l_req_fw_msg, - sizeof(l_req_fw_msg), - 0, 0, false ); - } + // Make the firmware_request call + l_err = firmware_request_helper(l_req_fw_msg_size, + &l_req_fw_msg, + &l_resp_fw_msg_size, + &l_resp_fw_msg); + if (l_err) + { + // If error, break out of encompassing while loop break; } - } + } // END else if (g_hostInterfaces->firmware_request != nullptr) // Disable special wakeup l_err = handleSpecialWakeup(i_target,false); @@ -572,3 +534,4 @@ namespace RTPM registerPm g_registerPm; }; + diff --git a/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H b/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H index 01085dbae..2e2abe25e 100644 --- a/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H +++ b/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H @@ -187,7 +187,8 @@ class FirmwareRequestTest : public CxxTest::TestSuite hostInterfaces::hbrt_fw_msg l_req_fw_msg; l_req_fw_msg.generic_msg.initialize(); - if (l_req_fw_msg.generic_msg.magic != GFMM_MAGIC_NUMBER) + if (l_req_fw_msg.generic_msg.magic != + GenericFspMboxMessage_t::MAGIC_NUMBER) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "magic was not properly initialized"); @@ -200,7 +201,8 @@ class FirmwareRequestTest : public CxxTest::TestSuite "dataSize was not properly initialized"); } - if (l_req_fw_msg.generic_msg.structVer != GFMM_VERSION) + if (l_req_fw_msg.generic_msg.structVer != + GenericFspMboxMessage_t::STRUCT_VERSION_LATEST) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "structVer was not properly initialized"); @@ -220,8 +222,9 @@ class FirmwareRequestTest : public CxxTest::TestSuite l_req_fw_msg.generic_msg.seqnum = 0x300; l_req_fw_msg.generic_msg.msgq = 0x400; l_req_fw_msg.generic_msg.msgType = 0x500; - l_req_fw_msg.generic_msg.__req = GFMM_REQUEST; - l_req_fw_msg.generic_msg.__onlyError = GFMM_ERROR_ONLY; + l_req_fw_msg.generic_msg.__req = GenericFspMboxMessage_t::REQUEST; + l_req_fw_msg.generic_msg.__onlyError = + GenericFspMboxMessage_t::ERROR_ONLY; uint32_t l_plid = 0x600; uint32_t l_huid = 0x700; l_req_fw_msg.generic_msg.data = diff --git a/src/usr/isteps/tod/runtime/makefile b/src/usr/isteps/tod/runtime/makefile index 5c65fd3ff..2d7946358 100644 --- a/src/usr/isteps/tod/runtime/makefile +++ b/src/usr/isteps/tod/runtime/makefile @@ -30,7 +30,9 @@ ROOTPATH = ../../../../.. MODULE = tod_rt EXTRAINCDIR += ${ROOTPATH}/src/usr/isteps/tod -EXTRAINCDIR += ${ROOTPATH}/src/include/usr/isteps/ +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/isteps +EXTRAINCDIR += ${ROOTPATH}/src/usr/errl +#EXTRAINCDIR += ${ROOTPATH}/src/include/usr/util OBJS += rt_todintf.o diff --git a/src/usr/isteps/tod/runtime/rt_todintf.C b/src/usr/isteps/tod/runtime/rt_todintf.C index c79419604..180049d18 100644 --- a/src/usr/isteps/tod/runtime/rt_todintf.C +++ b/src/usr/isteps/tod/runtime/rt_todintf.C @@ -28,8 +28,13 @@ #include // GETHUID #include // getMaxProcsOnSystem -#include // g_hostInterfaces -#include // TOD_RT_TOPOLOGY_RESET_BACKUP, etc +#include // g_hostInterfaces +#include // firmware_request_helper +#include // TOD_RT_TOPOLOGY_RESET_BACKUP, etc +#include // errlCommit + + +using namespace ERRORLOG; namespace TOD { @@ -51,38 +56,42 @@ errlHndl_t resetBackupTopology( TOD_ENTER("resetBackupTopology"); errlHndl_t l_err = nullptr; - // Put the handle to the firmware request out here - // so it is easier to free later + // Put the handle to the firmware_request request struct + // out here so it is easier to free later hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr; + hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr; do { if ((nullptr == g_hostInterfaces) || (nullptr == g_hostInterfaces->firmware_request)) { + TOD_ERR("resetBackupTopology: " + "Hypervisor firmware_request interface not linked"); + /*@ * @errortype - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid TOD::TOD_RT_TOPOLOGY_RESET_BACKUP - * @reasoncode TOD::TOD_RT_NULL_FIRMWARE_REQUEST_PTR + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid TOD_RT_TOPOLOGY_RESET_BACKUP + * @reasoncode TOD_RT_NULL_FIRMWARE_REQUEST_PTR + * @userdata1 None + * @userdata2 None * @devdesc Host interfaces are not initialized - * @custdesc An internal error occurred. This will force the - * Time of Day function to run with complete - * redundancy. + * @custdesc An internal error occurred. This will + * force the Time of Day function to run + * with complete redundancy. */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - TOD::TOD_RT_TOPOLOGY_RESET_BACKUP, - TOD::TOD_RT_NULL_FIRMWARE_REQUEST_PTR, + l_err = new ErrlEntry( ERRL_SEV_UNRECOVERABLE, + TOD_RT_TOPOLOGY_RESET_BACKUP, + TOD_RT_NULL_FIRMWARE_REQUEST_PTR, 0, 0, true); break; } - // First, I'll present the format of the data - // to help with the understanding of the code that follows // The format of the data to be sent, according to the document // "Handle PRD Request for resetting backup TOD topology" is as follows + // All data members below are 4 bytes long (32 bits) // Ordinal ID - 0xFFFFFFFF means no OSC to be avoided // HUID of the node - This field should be considered only if Ordinal // ID is NOT set to 0xFFFFFFFF otherwise it is set @@ -90,82 +99,89 @@ errlHndl_t resetBackupTopology( // HUID of the first processor // HUID of the second processor, etc + // Check if we get conflicting data, if so send a Trace out + if ((0xFFFFFFFF == i_oscPos) && (nullptr != i_procOscTgt)) + { + TOD_ERR("Conflicting input data, input oscillator position " + "(i_oscPos) has value 0xFFFFFFFF, meaning no oscillator " + "to be avoided but input oscillator target (i_procOscTgt) " + "has a valid value" ); + } + else if ((0xFFFFFFFF != i_oscPos) && (nullptr == i_procOscTgt)) + { + TOD_ERR("Conflicting input data, input oscillator position " + "(i_oscPos) has value 0x%X, meaning avoid oscillator " + "but input oscillator target (i_procOscTgt) " + "has a NULL value", i_oscPos); + } // Flag to determine if the OSC data will be added to the data bool l_addOscData = (0xFFFFFFFF != i_oscPos) && (nullptr != i_procOscTgt); - // Calculate the size of the data that is being added to the - // generic struct - size_t l_data_size = 0; + // Default the request data size to the size of the + // GenericFspMboxMessage_t minus the size of the + // GenericFspMboxMessage_t's data. The size of the + // GenericFspMboxMessage_t's data will be added later + uint32_t l_req_data_size = sizeof(GenericFspMboxMessage_t) - + sizeof(GenericFspMboxMessage_t::data); - // Add to the size iff there is data needing to be passed + // Add to the request data size iff there is data needing to be passed if (i_badChipList.size() > 0) { // if the bad chip list has any items then increase size to // accommodate for an ordinal ID and a HUID, regardless if // they have relevant data or not, because they are expected // before the HUID list. - l_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)) + - (i_badChipList.size() * sizeof(uint32_t)); + l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)) + + (i_badChipList.size() * sizeof(uint32_t)); } else if (l_addOscData) { // if there is a valid OSC then accommodate for an ordinal ID // and HUID of node, but don't need space for HUID list because, // if we are here, the list is empty - l_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)); + l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)); } - // Update the data size with the size of the generic msg struct - if (l_data_size < sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data)) - { - // If the current size of the data is less than the size of the - // data within the generic message (GenericFspMboxMessage_t.data), - // then default the data size to just the generic message because - // the size of the data to be passed in - // GenericFspMboxMessage_t.dataSize has be at the minimum - the - // size of the generic message (sizeof(GenericFspMboxMessage_t)). - l_data_size = sizeof(hostInterfaces::hbrt_fw_msg::generic_msg); - } - else + // The request data size must be at a minimum the size of the + // FSP generic message (sizeof(GenericFspMboxMessage_t)) + if (l_req_data_size < sizeof(GenericFspMboxMessage_t)) { - // If the current size of the data is greater than the size of the - // data within the generic message (GenericFspMboxMessage_t.data), - // then add the size of the generic message minus the size of - // generic message's data. - l_data_size += sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) - - sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data); + l_req_data_size = sizeof(GenericFspMboxMessage_t); } - // At last. Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg - // which means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to - // the previous calculated data size - size_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - l_data_size; + // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which + // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to + // the previous calculated request data size + uint64_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + l_req_data_size; - // Create the firmware request structure to carry the TOD data - l_req_fw_msg =(hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); + // Create the firmware_request request struct to send data + l_req_fw_msg = + (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); - // Set the data for the request - l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + // Initialize the firmware_request request struct l_req_fw_msg->generic_msg.initialize(); - l_req_fw_msg->generic_msg.dataSize = l_data_size; + + // Populate the firmware_request request struct with given data + l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg->generic_msg.dataSize = l_req_data_size; l_req_fw_msg->generic_msg.msgq = MBOX::FSP_TOD_MSGQ; l_req_fw_msg->generic_msg.msgType = (false == i_informPhyp ? - GFMM_MSG_TOD_BACKUP_RESET: - GFMM_MSG_TOD_BACKUP_RESET_INFORM_PHYP); - l_req_fw_msg->generic_msg.__req = GFMM_REQUEST; - l_req_fw_msg->generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; + GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET: + GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET_INFORM_PHYP); + l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST; // A convenient way to populate the data - uint32_t* l_dataPtr = (uint32_t*)&(l_req_fw_msg->generic_msg.data); + uint32_t* l_dataPtr = + reinterpret_cast(&(l_req_fw_msg->generic_msg.data)); if (i_badChipList.size() > 0) { // set the ordinal ID l_dataPtr[MSG_OSC_ORDINAL_ID_LOC] = i_oscPos; - // attach the HUIDs from bad chip list to end of structure + // attach the HUIDs from bad chip list to end of struct size_t i = MSG_OSC_HUIDS_LOC; for (auto l_target : i_badChipList) { @@ -194,120 +210,59 @@ errlHndl_t resetBackupTopology( { /*@ * @errortype - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid TOD::TOD_RT_TOPOLOGY_RESET_BACKUP - * @reasoncode TOD::TOD_INVALID_TARGET - * @devdesc No parent for processor osc target - * @custdesc An internal error occurred. This will force - * the Time of Day function to run with complete - * redundancy. + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid TOD_RT_TOPOLOGY_RESET_BACKUP + * @reasoncode TOD_INVALID_TARGET + * @userdata1 The number of parents found osc target + * @userdata2 None + * @devdesc No/Multiple parent(s) found for + * processor osc target + * @custdesc An internal error occurred. This will + * force the Time of Day function to run + * with complete redundancy. */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - TOD::TOD_RT_TOPOLOGY_RESET_BACKUP, - TOD::TOD_INVALID_TARGET, - 0, 0, true); + l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + TOD_RT_TOPOLOGY_RESET_BACKUP, + TOD_INVALID_TARGET, + l_list.size(), 0, true); break; } } - // No data is returning from the call, just capture any errors - hostInterfaces::hbrt_fw_msg l_resp_fw_msg; - size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); - - // Clear the response structure - memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); - - // Send the data via a firmware request - size_t rc = g_hostInterfaces->firmware_request( - l_req_fw_msg_size, l_req_fw_msg, - &l_resp_fw_msg_size, &l_resp_fw_msg); + // Create the firmware_request response struct to receive data + // NOTE: For messages to the FSP the response size must match + // the request size + uint64_t l_resp_fw_msg_size = l_req_fw_msg_size; + l_resp_fw_msg = + (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size); + memset(l_resp_fw_msg, 0, l_resp_fw_msg_size); - // Error log id - uint32_t l_errPlid(0); + // Trace out the request structure + TRACFBIN(ISTEPS_TRACE::g_trac_isteps_trace, + INFO_MRK"TOD::Sending firmware_request", + l_req_fw_msg, + l_req_fw_msg_size); - // Create a useful structure to get to the PLID - // The PLID is expected to be in the first 4 bytes of the data - // if it exists - struct hbrtFspRespData_t - { - uint32_t plid; - uint32_t otherData; - } PACKED ; - - hbrtFspRespData_t *l_hbrtFspRespData = - (hbrtFspRespData_t*)&(l_resp_fw_msg.generic_msg.data); - - // Capture the error log ID if any - // The return code (rc) may return OK, but there still may be an issue - // with the HWSV code on the FSP. - if ((hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP - == l_resp_fw_msg.io_type) && - (GFMM_ERROR_ONLY == l_resp_fw_msg.generic_msg.__onlyError) && - (0 != l_hbrtFspRespData->plid) ) - { - l_errPlid = l_hbrtFspRespData->plid; - } + // Make the firmware_request call + l_err = firmware_request_helper(l_req_fw_msg_size, + l_req_fw_msg, + &l_resp_fw_msg_size, + l_resp_fw_msg); - // Gather up the error data and create an error log out of it - if (rc || l_errPlid) + if (l_err) { - /*@ - * @errortype - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid TOD::TOD_RT_TOPOLOGY_RESET_BACKUP - * @reasoncode TOD::TOD_RT_TOPOLOGY_RESET_BACKUP_ERR - * @userdata1[0..31] Hypervisor return code - * @userdata1[32:63] HWSV error log id (if any) - * @userdata2[0:31] MBOX message type - * @userdata2[32:63] TOD message type - * @devdesc TOD reset backup topology failed - * @custdesc An internal error occurred. This will force - * the Time of Day function to run with complete - * redundancy. - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - TOD::TOD_RT_TOPOLOGY_RESET_BACKUP, - TOD::TOD_RT_TOPOLOGY_RESET_BACKUP_ERR, - TWO_UINT32_TO_UINT64(rc, l_errPlid), - TWO_UINT32_TO_UINT64( - l_req_fw_msg->generic_msg.msgq, - l_req_fw_msg->generic_msg.msgType), - true); - - l_err->addFFDC( ISTEP_COMP_ID, - &l_resp_fw_msg, - l_resp_fw_msg_size, - 0, 0, false ); - - if (sizeof(l_req_fw_msg) > 0) - { - l_err->addFFDC( ISTEP_COMP_ID, - l_req_fw_msg, - sizeof(l_req_fw_msg), - 0, 0, false ); - } - - l_err->collectTrace( "TOD", 256); - - if (l_errPlid) - { - l_err->plid(l_errPlid); - } - break; } - } - while (0); + } while (0); - // The firmware request message is no longer needed - free the data + // Release the firmware messages free(l_req_fw_msg); + free(l_resp_fw_msg); + l_req_fw_msg = l_resp_fw_msg = nullptr; TOD_EXIT("resetBackupTopology"); return l_err; - } // end resetBackupTopology @@ -319,170 +274,100 @@ errlHndl_t readTodProcDataFromFile(TodChipDataContainer& o_todChipData) TOD_ENTER("readTodProcDataFromFile"); errlHndl_t l_err = nullptr; - // Put the handle to the firmware response out here + // Put the handle to the firmware messages out here // so it is easier to free later + hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr; hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr; + // clear the out data, regardless of the code to follow + o_todChipData.clear(); + do { - // clear the out data, regardless of the code to follow - o_todChipData.clear(); - if ((nullptr == g_hostInterfaces) || (nullptr == g_hostInterfaces->firmware_request)) { + TOD_ERR("readTodProcDataFromFile: " + "Hypervisor firmware_request interface not linked"); + /*@ * @errortype - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid TOD::TOD_RT_TOPOLOGY_DATA - * @reasoncode TOD::TOD_RT_NULL_FIRMWARE_REQUEST_PTR + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid TOD_RT_TOPOLOGY_DATA + * @reasoncode TOD_RT_NULL_FIRMWARE_REQUEST_PTR * @devdesc Host interfaces are not initialized - * @custdesc An internal error occurred. This will force the - * Time of Day function to run with complete - * redundancy. + * @custdesc An internal error occurred. This will + * force the Time of Day function to run + * with complete redundancy. */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - TOD::TOD_RT_TOPOLOGY_DATA, - TOD::TOD_RT_NULL_FIRMWARE_REQUEST_PTR, + l_err = new ErrlEntry( ERRL_SEV_UNRECOVERABLE, + TOD_RT_TOPOLOGY_DATA, + TOD_RT_NULL_FIRMWARE_REQUEST_PTR, 0, 0, true); break; } - // Create the firmware request structure. No data is being - // passed via this structure so this step may be moot. - // Maybe just passing size of 0 and a null pointer would be better? - hostInterfaces::hbrt_fw_msg l_req_fw_msg; - size_t l_req_fw_msg_size = sizeof(l_req_fw_msg); - - // Set the data for the request - l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; - l_req_fw_msg.generic_msg.initialize(); - l_req_fw_msg.generic_msg.msgq = MBOX::FSP_TOD_MSGQ; - l_req_fw_msg.generic_msg.msgType = GFMM_MSG_TOD_TOPOLOGY_DATA; - l_req_fw_msg.generic_msg.__req = GFMM_REQUEST; - l_req_fw_msg.generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; - - // Calculate the size of the response - the number - // of TodChipData items that will be returned. + // Default the response data size to the size of the + // GenericFspMboxMessage_t minus the size of the + // GenericFspMboxMessage_t's data. The size of the + // GenericFspMboxMessage_t's data will be added later + uint32_t l_resp_data_size = sizeof(GenericFspMboxMessage_t) - + sizeof(GenericFspMboxMessage_t::data); + + // Get the number of TodChipData items that will be returned. uint32_t l_nTodChips = TodSvcUtil::getMaxProcsOnSystem(); - // Calculate the size of the data that is being added to the - // generic struct - size_t l_data_size = (l_nTodChips * sizeof(TodChipData)); + // Add to the response data size iff there is data needing to be passed + l_resp_data_size += (l_nTodChips * sizeof(TodChipData)); - // Update the data size with the size of the generic msg struct - if (l_data_size < sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data)) - { - // If the current size of the data is less than the size of the - // data within the generic message (GenericFspMboxMessage_t.data), - // then default the data size to just the generic message because - // the size of the data to be passed in - // GenericFspMboxMessage_t.dataSize has be at the minimum - the - // size of the generic message (sizeof(GenericFspMboxMessage_t)). - l_data_size = sizeof(hostInterfaces::hbrt_fw_msg::generic_msg); - } - else + // The response data size must be at a minimum the size of the + // FSP generic message (sizeof(GenericFspMboxMessage_t)) + if (l_resp_data_size < sizeof(GenericFspMboxMessage_t)) { - // If the current size of the data is greater than the size of the - // data within the generic message (GenericFspMboxMessage_t.data), - // then add the size of the generic message minus the size of - // generic message's data. - l_data_size += sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) - - sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data); + l_resp_data_size = sizeof(GenericFspMboxMessage_t); } - // At last. Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg - // which means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to - // the previous calculated data size - size_t l_resp_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - l_data_size; + // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which + // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to + // the previous calculated response data size + uint64_t l_resp_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + l_resp_data_size; - // Create the firmware response structure to return the data + // Create the firmware_request response struct to receive data l_resp_fw_msg = (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size); - - // Clear the response structure memset(l_resp_fw_msg, 0, l_resp_fw_msg_size); - // Send the data via a firmware request - size_t rc = g_hostInterfaces->firmware_request( - l_req_fw_msg_size, &l_req_fw_msg, - &l_resp_fw_msg_size, l_resp_fw_msg); + // Create the firmware_request request struct to send data + uint64_t l_req_fw_msg_size = l_resp_fw_msg_size; + l_req_fw_msg = + (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); - // Error log id - uint32_t l_errPlid(0); - - // Create a useful structure to get to the PLID - // The PLID is expected to be in the first 4 bytes of the data - struct hbrtFspRespData_t - { - uint32_t plid; - uint32_t otherData; - } PACKED ; - - hbrtFspRespData_t *l_hbrtFspRespData = - (hbrtFspRespData_t*)&(l_resp_fw_msg->generic_msg.data); - - // Capture the error log ID if any - // The return code (rc) may return OK, but there still may be an issue - // with the HWSV code on the FSP. - if ((hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP - == l_resp_fw_msg->io_type) && - (GFMM_ERROR_ONLY == l_resp_fw_msg->generic_msg.__onlyError) && - (0 != l_hbrtFspRespData->plid) ) - { - l_errPlid = l_hbrtFspRespData->plid; - } + // Initialize the firmware_request request struct + l_req_fw_msg->generic_msg.initialize(); - // Gather up the error data and create an error log out of it - if (rc || l_errPlid) + // Populate the firmware_request request struct with given data + l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg->generic_msg.msgq = MBOX::FSP_TOD_MSGQ; + l_req_fw_msg->generic_msg.msgType = + GenericFspMboxMessage_t::MSG_TOD_TOPOLOGY_DATA; + l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST; + + // Trace out the request structure + TRACFBIN(ISTEPS_TRACE::g_trac_isteps_trace, + INFO_MRK"TOD::Sending firmware_request", + l_req_fw_msg, + l_req_fw_msg_size); + + // Make the firmware_request call + l_err = firmware_request_helper(l_req_fw_msg_size, + l_req_fw_msg, + &l_resp_fw_msg_size, + l_resp_fw_msg); + + if (l_err) { - /*@ - * @errortype - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid TOD::TOD_RT_TOPOLOGY_DATA - * @reasoncode TOD::TOD_RT_TOPOLOGY_DATA_ERR - * @userdata1[0..31] Hypervisor return code - * @userdata1[32:63] HWSV error log id (if any) - * @userdata2[0:31] MBOX message type - * @userdata2[32:63] TOD message type - * @devdesc TOD read proc data failed - * @custdesc An internal error occurred. This will force - * the Time of Day function to run with complete - * redundancy. - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - TOD::TOD_RT_TOPOLOGY_DATA, - TOD::TOD_RT_TOPOLOGY_DATA_ERR, - TWO_UINT32_TO_UINT64(rc, l_errPlid), - TWO_UINT32_TO_UINT64( - l_req_fw_msg.generic_msg.msgq, - l_req_fw_msg.generic_msg.msgType), - true); - - if (l_resp_fw_msg_size > 0) - { - l_err->addFFDC( ISTEP_COMP_ID, - l_resp_fw_msg, - l_resp_fw_msg_size, - 0, 0, false ); - } - - l_err->addFFDC( ISTEP_COMP_ID, - &l_req_fw_msg, - sizeof(l_req_fw_msg), - 0, 0, false ); - - l_err->collectTrace( "TOD", 256); - - if (l_errPlid) - { - l_err->plid(l_errPlid); - } - break; } @@ -500,15 +385,17 @@ errlHndl_t readTodProcDataFromFile(TodChipDataContainer& o_todChipData) } while (0); - // Free the memory associated with the response + // Release the firmware messages + free(l_req_fw_msg); free(l_resp_fw_msg); + l_req_fw_msg = l_resp_fw_msg = nullptr; TOD_EXIT("readTodProcDataFromFile"); return l_err; } // end readTodProcDataFromFile // This code was ported over from the FIPS code - -// /esw/fips910/Builds/b1005a_1742.910/ +// fips910/Builds/b1005a_1742.910/ // src/hwsv/server/services/todservice/hwsvTodSvc.C // It was decided that a port of the code is not needed but to hold onto // the code since the majority of it has been ported. diff --git a/src/usr/testcore/rtloader/loader.H b/src/usr/testcore/rtloader/loader.H index 973afd158..d80b93cb6 100644 --- a/src/usr/testcore/rtloader/loader.H +++ b/src/usr/testcore/rtloader/loader.H @@ -833,6 +833,12 @@ class RuntimeLoaderTest : public CxxTest::TestSuite break; } + if (i_reqLen != *o_respLen) + { + retVal = -EINVAL; + break; + } + uint32_t* l_data = (uint32_t*) &(l_req_fw_msg->generic_msg.data); TRACFCOMP(g_trac_hbrt, @@ -868,9 +874,10 @@ class RuntimeLoaderTest : public CxxTest::TestSuite l_resp_fw_msg->generic_msg.seqnum = 0x30; l_resp_fw_msg->generic_msg.msgq = 0x40; l_resp_fw_msg->generic_msg.msgType = 0x50; - l_resp_fw_msg->generic_msg.__req = GFMM_RESPONSE; + l_resp_fw_msg->generic_msg.__req = + GenericFspMboxMessage_t::RESPONSE; l_resp_fw_msg->generic_msg.__onlyError = - GFMM_NOT_ERROR_ONLY; + GenericFspMboxMessage_t::NOT_ERROR_ONLY; l_resp_data.plid = 0x60; l_resp_data.huid = 0x70; memcpy(&(l_resp_fw_msg->generic_msg.data), diff --git a/src/usr/util/runtime/makefile b/src/usr/util/runtime/makefile index ff5509e5e..b926c9209 100644 --- a/src/usr/util/runtime/makefile +++ b/src/usr/util/runtime/makefile @@ -53,6 +53,7 @@ OBJS += utilrsvdmem.o OBJS += utilxipimage.o OBJS += utilcommonattr.o OBJS += rt_fwnotify.o +OBJS += rt_fwreq_helper.o SUBDIRS += test.d diff --git a/src/usr/util/runtime/rt_fwnotify.C b/src/usr/util/runtime/rt_fwnotify.C index 9441519ab..fd6037512 100644 --- a/src/usr/util/runtime/rt_fwnotify.C +++ b/src/usr/util/runtime/rt_fwnotify.C @@ -22,35 +22,14 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/util/runtime/rt_fwnotify.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ #include // SbeRetryHandler -#include // firmware_notify +#include // firmware_request_helper +#include // g_hostInterfaces #include // MOD_RT_FIRMWARE_NOTIFY, etc #include // ErrlEntry #include // errlCommit +#include // TWO_UINT32_TO_UINT64 #include // TargetHandle_t, getTargetFromHuid using namespace TARGETING; @@ -59,36 +38,39 @@ using namespace ERRORLOG; using namespace MBOX; using namespace SBEIO; -trace_desc_t* g_trac_hwsv = nullptr; -TRAC_INIT(&g_trac_hwsv, "HWSV_TRACE", 4*KILOBYTE); +// Trace definition +extern trace_desc_t* g_trac_runtime; /** - * @brief The lower and upper bounds for the sequence ID. - **/ -const uint16_t GFMM_SEQ_ID_MIN = 0x0000; -const uint16_t GFMM_SEQ_ID_MAX = 0x7FFF; + * @brief The lower and upper bounds for the sequence ID. + **/ +const uint16_t SEQ_ID_MIN = 0x0000; +const uint16_t SEQ_ID_MAX = 0x7FFF; /** - * @brief Set the sequence ID to the minimum value - **/ -uint16_t SeqId_t::GFMM_SEQ_ID = GFMM_SEQ_ID_MIN; + * @brief Set the sequence ID to the minimum value + **/ +uint16_t SeqId_t::SEQ_ID = SEQ_ID_MIN; /** - * @brief Gets the next sequence ID. - * @return The next sequence ID value within it's lower and upper bound + * @brief Gets the next sequence ID. + * @return The next sequence ID value within its lower and upper bound + * @note This code is thread safe, no need for a mutex around this because + * HBRT never runs in multi-thread. + * **/ uint16_t SeqId_t::getNextSeqId() { - if (SeqId_t::GFMM_SEQ_ID < GFMM_SEQ_ID_MAX) + if (SeqId_t::SEQ_ID < SEQ_ID_MAX) { - ++SeqId_t::GFMM_SEQ_ID; + ++SeqId_t::SEQ_ID; } else { - SeqId_t::GFMM_SEQ_ID = GFMM_SEQ_ID_MIN; + SeqId_t::SEQ_ID = SEQ_ID_MIN; } - return SeqId_t::GFMM_SEQ_ID; + return SeqId_t::SEQ_ID; } /** @@ -97,7 +79,7 @@ uint16_t SeqId_t::getNextSeqId() **/ uint16_t SeqId_t::getCurrentSeqId() { - return SeqId_t::GFMM_SEQ_ID; + return SeqId_t::SEQ_ID; } /** @@ -108,34 +90,34 @@ uint16_t SeqId_t::getCurrentSeqId() **/ void sbeAttemptRecovery(uint64_t i_data) { + // Create a useful struct to get to the data + // The data is expected to be a plid (in the first 4 bytes) + // followed by a HUID (in the last 4 bytes). + HbrtFspData_t *l_hbrtFspData = reinterpret_cast(&i_data); + + TRACFCOMP(g_trac_runtime, ENTER_MRK"sbeAttemptRecovery: plid:0x%X, " + "HUID:0x%X", l_hbrtFspData->plid, l_hbrtFspData->userData); + errlHndl_t l_err = nullptr; do { - // Create a useful structure to get to the data - // The data is expected to be a plid (in the first 4 bytes) - // followed by a HUID (in the last 4 bytes). - struct sbeErrorData_t - { - uint32_t plid; - uint32_t huid; - } PACKED ; - - sbeErrorData_t *l_sbeErrorDataReq = (sbeErrorData_t*)(&i_data); - // Extract the target from the given HUID TargetHandle_t l_target = - Target::getTargetFromHuid(l_sbeErrorDataReq->huid); + Target::getTargetFromHuid(l_hbrtFspData->userData); // If HUID invalid, log error and quit if (nullptr == l_target) { - TRACFCOMP( g_trac_hwsv, "firmware_notify: No target assoicated " - "with HUID:0x%.8X", l_sbeErrorDataReq->huid); + TRACFCOMP(g_trac_runtime, ERR_MRK"sbeAttemptRecovery: " + "No target associated with HUID:0x%.8X", + l_hbrtFspData->userData); + /*@ - * @errortype ERRL_SEV_PREDICTIVE - * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY - * @reasoncode RUNTIME::RC_SBE_RT_INVALID_HUID + * @errortype + * @severity ERRL_SEV_PREDICTIVE + * @moduleid MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RC_SBE_RT_INVALID_HUID * @userdata1 HUID of target * @userdata2 HWSV error log id (plid) * @devdesc SBE error recovery attempt failed @@ -143,8 +125,8 @@ void sbeAttemptRecovery(uint64_t i_data) l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, MOD_RT_FIRMWARE_NOTIFY, RC_SBE_RT_INVALID_HUID, - l_sbeErrorDataReq->huid, - l_sbeErrorDataReq->plid, + l_hbrtFspData->userData, + l_hbrtFspData->plid, true); break; } @@ -163,13 +145,14 @@ void sbeAttemptRecovery(uint64_t i_data) if (nullptr == g_hostInterfaces || nullptr == g_hostInterfaces->firmware_request) { - TRACFCOMP( g_trac_hwsv, "firmware_notify: Hypervisor " - "firmware_request interface not linked"); + TRACFCOMP(g_trac_runtime, ERR_MRK"sbeAttemptRecovery: " + "Hypervisor firmware_request interface not linked"); /*@ - * @errortype ERRL_SEV_PREDICTIVE - * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY - * @reasoncode RUNTIME::RC_FW_REQUEST_RT_NULL_PTR + * @errortype + * @severity ERRL_SEV_PREDICTIVE + * @moduleid MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RC_FW_REQUEST_RT_NULL_PTR * @userdata1 HUID of target * @userdata2 HWSV error log id (plid) * @devdesc SBE error recovery attempt failed @@ -177,105 +160,60 @@ void sbeAttemptRecovery(uint64_t i_data) l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, MOD_RT_FIRMWARE_NOTIFY, RC_FW_REQUEST_RT_NULL_PTR, - l_sbeErrorDataReq->huid, - l_sbeErrorDataReq->plid, + l_hbrtFspData->userData, + l_hbrtFspData->plid, true); - break; } - // Create the firmware_request request structure to send data + // Create the firmware_request request struct to send data hostInterfaces::hbrt_fw_msg l_req_fw_msg; - memset(&l_req_fw_msg, 0, sizeof(l_req_fw_msg)); + uint64_t l_req_fw_msg_size = sizeof(l_req_fw_msg); - // Set the data for the request - l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + // Initialize the firmware_request request struct l_req_fw_msg.generic_msg.initialize(); - l_req_fw_msg.generic_msg.msgq = GFMM_MSG_SBE_ERROR; - l_req_fw_msg.generic_msg.__req = GFMM_REQUEST; - l_req_fw_msg.generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; + + // Populate the firmware_request request struct with given data + l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg.generic_msg.msgq = GenericFspMboxMessage_t::MSG_SBE_ERROR; + l_req_fw_msg.generic_msg.__req = GenericFspMboxMessage_t::REQUEST; l_req_fw_msg.generic_msg.data = i_data; + // Set msgType based on recovery success or failure if (l_recoverySuccessful) { - l_req_fw_msg.generic_msg.msgType= GFMM_MSG_SBE_RECOVERY_SUCCESS; + l_req_fw_msg.generic_msg.msgType = + GenericFspMboxMessage_t::MSG_SBE_RECOVERY_SUCCESS; } else { - l_req_fw_msg.generic_msg.msgType = GFMM_MSG_SBE_RECOVERY_FAILED; + l_req_fw_msg.generic_msg.msgType = + GenericFspMboxMessage_t::MSG_SBE_RECOVERY_FAILED; } - // Create the firmware_request response structure to receive data + // Create the firmware_request response struct to receive data + // NOTE: For messages to the FSP the response size must match + // the request size + // No need to check for expected response size > request + // size because they use the same base structure hostInterfaces::hbrt_fw_msg l_resp_fw_msg; - size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); - size_t rc = g_hostInterfaces->firmware_request(sizeof(l_req_fw_msg), - &l_req_fw_msg, - &l_resp_fw_msg_size, - &l_resp_fw_msg); - - // Error log id - uint32_t l_errPlid(0); + // Trace out the request structure + TRACFBIN( g_trac_runtime, INFO_MRK"Sending firmware_request", + &l_req_fw_msg, + l_req_fw_msg_size); - sbeErrorData_t *l_sbeErrorDataResp = - (sbeErrorData_t*)&(l_resp_fw_msg.generic_msg.data); + // Make the firmware_request call + l_err = firmware_request_helper(l_req_fw_msg_size, + &l_req_fw_msg, + &l_resp_fw_msg_size, + &l_resp_fw_msg); - // Capture the error log ID if any - // The return code (rc) may return OK, but there still may be an issue - // with the HWSV code on the FSP. - if ((hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP - == l_resp_fw_msg.io_type) && - (GFMM_ERROR_ONLY == l_resp_fw_msg.generic_msg.__onlyError) && - (0 != l_sbeErrorDataResp->plid) ) + if (l_err) { - l_errPlid = l_sbeErrorDataResp->plid; - } - - // Gather up the error data and create an error log out of it - if (rc || l_errPlid) - { - /*@ - * @errortype ERRL_SEV_PREDICTIVE - * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY - * @reasoncode RUNTIME::RC_SBE_RT_RECOVERY_ERR - * @userdata1[0:31] Firmware Request return code - * @userdata1[32:63] HWSV error log id (plid) - * @userdata2[0:31] MBOX message type - * @userdata2[32:63] Message Tyepe - * @devdesc SBE error recovery attempt failed - */ - l_err = new ERRORLOG::ErrlEntry( - ERRL_SEV_PREDICTIVE, - MOD_RT_FIRMWARE_NOTIFY, - RC_SBE_RT_RECOVERY_ERR, - TWO_UINT32_TO_UINT64(rc, l_errPlid), - TWO_UINT32_TO_UINT64( - l_resp_fw_msg.generic_msg.msgq, - l_resp_fw_msg.generic_msg.msgType), - true); - - l_err->addFFDC( RUNTIME_COMP_ID, - &l_resp_fw_msg, - l_resp_fw_msg_size, - 0, 0, false ); - - if (sizeof(l_req_fw_msg) > 0) - { - l_err->addFFDC( RUNTIME_COMP_ID, - &l_req_fw_msg, - sizeof(l_req_fw_msg), - 0, 0, false ); - } - - l_err->collectTrace( "SBE", 256); - - if (l_errPlid) - { - l_err->plid(l_errPlid); - } - break; } } while(0); @@ -285,84 +223,146 @@ void sbeAttemptRecovery(uint64_t i_data) //Commit the error if it exists errlCommit(l_err, RUNTIME_COMP_ID); } + + TRACFCOMP(g_trac_runtime, EXIT_MRK"sbeAttemptRecovery"); } /** - * @brief Receive an async notification from firmware - * @param[in] i_len length of notification data - * @param[in] i_data notification data - * @platform FSP, OpenPOWER + * @see src/include/runtime/interface.h for definition of call + * */ void firmware_notify( uint64_t i_len, void *i_data ) { + TRACFCOMP(g_trac_runtime, ENTER_MRK"firmware_notify: " + "i_len:%d", i_len ); + + TRACFBIN(g_trac_runtime, "firmware_notify: i_data", i_data, i_len); + errlHndl_t l_err = nullptr; + // Flag to detect an invlaid/unknown/not used message + bool l_badMessage = false; + + // Capture the unique message data associated with errant message + uint64_t l_userData1(0), l_userData2(0); + do { // make sure the length of the data is not less than the - // structure we are expecting to receive - if (i_len < sizeof(GenericFspMboxMessage_t)) + // data necessary to determine type of message + if (i_len < hostInterfaces::HBRT_FW_MSG_BASE_SIZE) { - TRACFCOMP( g_trac_hwsv, - "firmware_notify: Received a non GenericFspMboxMessage " - "data stream" ); + l_badMessage = true; - /*@ - * @errortype - * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY - * @reasoncode RUNTIME::RC_FW_NOTIFY_RT_INVALID_MSG - * @userdata1 Unused - * @userdata2 Unused - * @devdesc Error with Firmware Notify request - */ - l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, - MOD_RT_FIRMWARE_NOTIFY, - RC_FW_NOTIFY_RT_INVALID_MSG, - 0, 0, true); - break; - } + TRACFCOMP(g_trac_runtime, ERR_MRK"firmware_notify: " + "Received a non hostInterfaces::hbrt_fw_msg data stream" ); - // Cast the data to the structure we wish to parse - GenericFspMboxMessage_t* genericMsg = - static_cast(i_data); + break; + } - // Do function based on message type (msgType) - switch(genericMsg->msgType) + // Cast the data to an hbrt_fw_msg to extract the input type + hostInterfaces::hbrt_fw_msg* l_hbrt_fw_msg = + static_cast(i_data); + switch (l_hbrt_fw_msg->io_type) { - case GFMM_MSG_SBE_ERROR: sbeAttemptRecovery(genericMsg->data); - break; + + case hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ: + { + + // Extract the message type + switch(l_hbrt_fw_msg->generic_msg.msgType) + { + + case GenericFspMboxMessage_t::MSG_SBE_ERROR: + sbeAttemptRecovery(l_hbrt_fw_msg->generic_msg.data); + + break; + + default: + { + l_badMessage = true; + + TRACFCOMP(g_trac_runtime, ERR_MRK"firmware_notify: " + "Unknown FSP message type:0x%.8X, " + "message queue id:0x%.8X, seqNum:%d ", + l_hbrt_fw_msg->generic_msg.msgq, + l_hbrt_fw_msg->generic_msg.msgType, + l_hbrt_fw_msg->generic_msg.seqnum); + + // Pack user data 1 with message input type and + // firmware request message sequence number + l_userData1 = TWO_UINT32_TO_UINT64( + l_hbrt_fw_msg->io_type, + l_hbrt_fw_msg->generic_msg.seqnum); + + // Pack user data 2 with message queue and message type + l_userData2 = TWO_UINT32_TO_UINT64( + l_hbrt_fw_msg->generic_msg.msgq, + l_hbrt_fw_msg->generic_msg.msgType); + } + + break; // END default + + } // END switch(l_genericMsg->msgType) + } // END case HBRT_FW_MSG_HBRT_FSP_REQ: + + break; default: { - TRACFCOMP( g_trac_hwsv, "firmware_notify: Unknown " - "message type:0x%.8X, message queue id:0x%.8X ", - genericMsg->msgq, genericMsg->msgType); - - /*@ - * @errortype - * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY - * @reasoncode RUNTIME::RC_FW_NOTIFY_RT_INVALID_MSG_TYPE - * @userdata1 Message Queue ID - * @userdata2 Message Type - * @devdesc Error with Firmware Notify request - */ - l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, - MOD_RT_FIRMWARE_NOTIFY, - RC_FW_NOTIFY_RT_INVALID_MSG_TYPE, - genericMsg->msgq, - genericMsg->msgType, - true); - } + l_badMessage = true; + + TRACFCOMP(g_trac_runtime, ERR_MRK"firmware_notify: " + "Unknown firmware request input type:0x%.8X ", + l_hbrt_fw_msg->io_type); + + l_userData1 = l_hbrt_fw_msg->io_type; + } // END default + break; - }; + + }; // END switch (l_hbrt_fw_msg->io_type) } while(0); + if (l_badMessage) + { + /*@ + * @errortype + * @severity ERRL_SEV_PREDICTIVE + * @moduleid MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RC_FW_NOTIFY_RT_INVALID_MSG + * @userdata1[0:31] Firmware Request type + * @userdata1[32:63] Sequence number (FSP msg) + * @userdata2[0:31] MBOX message type (FSP msg) + * @userdata2[32:63] Message Type (FSP msg) + * @devdesc Error with Firmware Notify request + */ + l_err = new ErrlEntry(ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_FW_NOTIFY_RT_INVALID_MSG, + l_userData1, + l_userData2, + true); + + if (i_len > 0) + { + l_err->addFFDC(RUNTIME_COMP_ID, + i_data, + i_len, + 0, 0, false ); + } + + l_err->collectTrace( "FW_REQ", 256); + } + if (l_err) { //Commit the error if it exists errlCommit(l_err, RUNTIME_COMP_ID); } + + TRACFCOMP(g_trac_runtime, EXIT_MRK"firmware_notify"); }; struct registerFwNotify diff --git a/src/usr/util/runtime/rt_fwreq_helper.C b/src/usr/util/runtime/rt_fwreq_helper.C new file mode 100644 index 000000000..16c9de777 --- /dev/null +++ b/src/usr/util/runtime/rt_fwreq_helper.C @@ -0,0 +1,455 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/util/runtime/rt_fwreq_helper.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include +#include // hostInterfaces +#include // MOD_RT_FIRMWARE_REQUEST, etc +#include // errlCommit + +using namespace ERRORLOG; +using namespace RUNTIME; +using namespace TRACE; + +// Trace definition +trace_desc_t *g_trac_runtime = nullptr; +TRAC_INIT(&g_trac_runtime, RUNTIME_COMP_NAME, KILOBYTE); + + +/*****************************************************************************/ +// firmware_request_helper +/*****************************************************************************/ +errlHndl_t firmware_request_helper(uint64_t i_reqLen, void *i_req, + uint64_t* o_respLen, void *o_resp) +{ + errlHndl_t l_err = nullptr; + + // Cast incoming parameters to useful structs + hostInterfaces::hbrt_fw_msg *l_req_fw_msg = + reinterpret_cast(i_req); + hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = + reinterpret_cast(o_resp); + + // Capture the Reset/Reload error log if it happens + bool l_isResetReloadErr = false; + + // Retry the firmware_request call if the call is made while the + // FSP is doing a reset/reload. + // If there is a reset/reload error create an error log and try again. + // If subsequent calls cause an error, commit the reset/reload error, + // and return the latest error back to the user. + // If there is an initial error that IS NOT a reset/reload error + // then break out of the retry loop and return error to user. + // If no error (a successful call) then delete any previous error + // (don't want to confuse caller) and break out of retry loop + for (int i = 0; i <= HBRT_FW_REQUEST_RETRIES; ++i) + { + // Make the firmware_request call + int rc = g_hostInterfaces->firmware_request(i_reqLen, i_req, + o_respLen, o_resp); + + // Not all request messages that fail require an error log, most do + bool l_createErrorLog = true; + + // The error log user data 1 and user data 2 will change + // based on response message type + uint64_t l_userData1(0), l_userData2(0); + + // Error with FSP resetting and/or reloading? If so, then retry + if (HBRT_RC_FSPDEAD == rc) + { + // This is a reset/reload err + l_isResetReloadErr = true; + + // Commit any previous errors + if (l_err) + { + // Commit any previous error log + errlCommit(l_err, RUNTIME_COMP_ID); + } + + // Print trace info based on request message and populate error + // log user data 1 and user data 2 based on request message + switch (l_req_fw_msg->io_type) + { + case hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE: + { + TRACFCOMP(g_trac_runtime, + ERR_MRK"FSP is doing a reset/reload, " + "HCODE update failed. " + "retry:%d/%d, rc:%d, io_type:%d, chipId:0x%llX, " + "section:0x%X, operation:0x%X, scomAddr:0x%llX, " + "scomData:0x%llX", + i, + HBRT_FW_REQUEST_RETRIES, + rc, + l_req_fw_msg->io_type, + l_req_fw_msg->req_hcode_update.i_chipId, + l_req_fw_msg->req_hcode_update.i_section, + l_req_fw_msg->req_hcode_update.i_operation, + l_req_fw_msg->req_hcode_update.i_scomAddr, + l_req_fw_msg->req_hcode_update.i_scomData); + + // Pack user data 1 with Hypervisor return code and + // firmware request message type + l_userData1 = TWO_UINT32_TO_UINT64(rc, + l_req_fw_msg->io_type); + + // Pack user data 2 with HCODE scom address and + // HCODE scom data + l_userData2 = TWO_UINT32_TO_UINT64( + l_req_fw_msg->req_hcode_update.i_scomAddr, + l_req_fw_msg->req_hcode_update.i_scomData); + } + break;//END case hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE: + + case hostInterfaces::HBRT_FW_MSG_TYPE_ERROR_LOG: + { + TRACFCOMP(g_trac_runtime, + ERR_MRK"FSP is doing a reset/reload, " + "sending error log to FSP failed. " + "retry:%d/%d, rc:%d, plid:0x%08x", + i, + HBRT_FW_REQUEST_RETRIES, + rc, + l_req_fw_msg->error_log.i_plid); + + // Don't create an error log for this request type + l_createErrorLog = false; + } + break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_ERROR_LOG: + + case hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ: + { + TRACFCOMP(g_trac_runtime, + "FSP is doing a reset/reload, " + "doing a VPD write failed. " + "retry:%d/%d, rc:%d, io_type:%d, dataSize:%d, " + "seqnum:0x%X, msgq:0x%X, msgType:0x%X, __req:%d, " + "__onlyError:%d", + i, + HBRT_FW_REQUEST_RETRIES, + rc, + l_req_fw_msg->io_type, + l_req_fw_msg->generic_msg.dataSize, + l_req_fw_msg->generic_msg.seqnum, + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType, + l_req_fw_msg->generic_msg.__req, + l_req_fw_msg->generic_msg.__onlyError); + + // Pack user data 1 with Hypervisor return code and + // firmware request message sequence number + l_userData1 = TWO_UINT32_TO_UINT64( + rc, + l_req_fw_msg->generic_msg.seqnum); + + // Pack user data 2 with message queue and message type + l_userData2 = TWO_UINT32_TO_UINT64( + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType); + } + break; // END case hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ: + + default: + break; + } // END switch (l_req_fw_msg->io_type) + + if (l_createErrorLog) + { + /*@ + * @errortype + * @severity ERRL_SEV_INFORMATIONAL + * @moduleid MOD_RT_FIRMWARE_REQUEST + * @reasoncode RC_FW_REQUEST_RESET_RELOAD_ERR + * @userdata1[0:31] Hypervisor return code + * @userdata1[32:63] Firmware Request type (HCODE Update) || + sequence number (FSP MSG) + * @userdata2[0:31] SCOM address (HCODE Update) || + MBOX message type (FSP MSG) + * @userdata2[32:63] SCOM data (HCODE Update) || + Message Type (FSP MSG) + * @devdesc The Firmware Request call failed + */ + l_err = new ErrlEntry(ERRL_SEV_INFORMATIONAL, + MOD_RT_FIRMWARE_REQUEST, + RC_FW_REQUEST_RESET_RELOAD_ERR, + l_userData1, + l_userData2, + true); + } // END if (l_createErrorLog) + + // Try the firmware_request call again + continue; + } // END if (hbrt_rc_fspdead == rc) + // Error is not with FSP resetting and/or reloading, so log the error + else if (rc) + { + if (l_err) + { + // Commit any previous reset/reload error log + errlCommit(l_err, RUNTIME_COMP_ID); + } + + // This NOT a reset/reload error + l_isResetReloadErr = false; + + // Print trace info based on request message type and populate + // error log user data 1 & user data 2 based on response message + switch (l_req_fw_msg->io_type) + { + case hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE: + { + // Default user data 1 wirh Hypervisor return code + // and firmware request message type + l_userData1 = TWO_UINT32_TO_UINT64( + rc, + l_req_fw_msg->io_type); + + // Pack user data 1 with Hypervisor return code and + // generic response code if the response is of type + // "RESP_GENERIC" else leave as is + // 1st check if the response size is large enough + // for the type needed + // 2nd make sure the message type is of + // type HBRT_FW_MSG_TYPE_RESP_GENERIC + // 3rd make sure there is actaully a value in the status + // If all these conditions are correct, + // then extract HWSV error + if ((*o_respLen >= + (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(l_resp_fw_msg->resp_generic))) && + hostInterfaces::HBRT_FW_MSG_TYPE_RESP_GENERIC == + l_resp_fw_msg->io_type && + 0 != l_resp_fw_msg->resp_generic.o_status ) + { + l_userData1 = TWO_UINT32_TO_UINT64( + rc, + l_resp_fw_msg->resp_generic.o_status); + } // END if (*o_respLen >= ... + + // Pack user data 2 with HCODE scom + // and HCODE scom data + l_userData2 = TWO_UINT32_TO_UINT64( + l_req_fw_msg->req_hcode_update.i_scomAddr, + l_req_fw_msg->req_hcode_update.i_scomData); + + TRACFCOMP(g_trac_runtime, + ERR_MRK"Failed doing an HCODE update. " + "rc:%d, io_type:%d, chipId:0x%llX, section:0x%X, " + "operation:0x%X, scomAddr:0x%llX, scomData:0x%llX", + rc, + l_req_fw_msg->io_type, + l_req_fw_msg->req_hcode_update.i_chipId, + l_req_fw_msg->req_hcode_update.i_section, + l_req_fw_msg->req_hcode_update.i_operation, + l_req_fw_msg->req_hcode_update.i_scomAddr, + l_req_fw_msg->req_hcode_update.i_scomData); + + } + break;//END case hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE: + + case hostInterfaces::HBRT_FW_MSG_TYPE_ERROR_LOG: + { + TRACFCOMP(g_trac_runtime, + ERR_MRK"Failed sending error log to FSP " + "via firmware_request. rc:%d, plid:0x%08X", + rc, + l_req_fw_msg->error_log.i_plid); + + // Don't create an error log for this request type + l_createErrorLog = false; + } + break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_ERROR_LOG: + + + case hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ: + { + TRACFCOMP(g_trac_runtime, + ERR_MRK"Failed doing a VPD write. " + "rc:%d, io_type:%d, dataSize:%d, " + "seqnum:0x%X, msgq:0x%X, msgType:0x%X, __req:%d, " + "__onlyError:%d", + rc, + l_req_fw_msg->io_type, + l_req_fw_msg->generic_msg.dataSize, + l_req_fw_msg->generic_msg.seqnum, + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType, + l_req_fw_msg->generic_msg.__req, + l_req_fw_msg->generic_msg.__onlyError); + + // Pack user data 1 with Hypervisor return code and + // firmware request message sequence number + l_userData1 = TWO_UINT32_TO_UINT64( + rc, + l_req_fw_msg->generic_msg.seqnum); + + // Pack user data 2 with message queue and message type + l_userData2 = TWO_UINT32_TO_UINT64( + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType); + } + break; // END case hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ: + + default: + break; + } // END switch (l_req_fw_msg->io_type) + + if (l_createErrorLog) + { + /*@ + * @errortype + * @severity ERRL_SEV_PREDICTIVE + * @moduleid MOD_RT_FIRMWARE_REQUEST + * @reasoncode RC_FW_REQUEST_ERR + * @userdata1[0:31] Hypervisor return code + * @userdata1[32:63] Firmware Request type (HCODE Update) || + sequence number (FSP MSG) + * @userdata2[0:31] SCOM address (HCODE Update) || + MBOX message type (FSP MSG) + * @userdata2[32:63] SCOM data (HCODE Update) || + Message Type (FSP MSG) + * @devdesc The Firmware Request call failed + */ + l_err = new ErrlEntry(ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_REQUEST, + RC_FW_REQUEST_ERR, + l_userData1, + l_userData2, + true); + } // END if (l_createErrorLog) + + // Break out of the retry loop + break; + } // END else if (rc) generic_msg + // There was no RC returned from the FSP request, there could be an issue + // with HWSV. If so then a PLID will be returned in the first + // 4 bytes of the 'data' member for an HBRT_FW_MSG_HBRT_FSP_RESP type. + // 1st check if the response size is large enough for the type needed + // 2nd make sure the message is of HBRT_FW_MSG_HBRT_FSP_RESP type. + // 3rd check if the 'data' member will contain an error ID (PLID) + // 4th make sure the PLID has a value + // If all these conditions are correct, then pull out PLID + else if ((*o_respLen >= + (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(hostInterfaces::hbrt_fw_msg::generic_msg))) && + (hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP == + l_resp_fw_msg->io_type) && + (GenericFspMboxMessage_t::ERROR_ONLY == + l_resp_fw_msg->generic_msg.__onlyError) && + (0 != (l_resp_fw_msg->generic_msg.data >> 32))) + + { + if (l_err) + { + // Commit any previous reset/reload error log + errlCommit(l_err, RUNTIME_COMP_ID); + } + + // This NOT a reset/reload error + l_isResetReloadErr = false; + + uint32_t l_errPlid = l_resp_fw_msg->generic_msg.data >> 32; + + TRACFCOMP(g_trac_runtime, + ERR_MRK"Failed doing a VPD write. " + "rc:%d, plid:0x%X, io_type:%d, dataSize:%d, " + "seqnum:0x%X, msgq:0x%X, msgType:0x%X, __req:%d, " + "__onlyError:%d", + rc, + l_errPlid, + l_req_fw_msg->io_type, + l_req_fw_msg->generic_msg.dataSize, + l_req_fw_msg->generic_msg.seqnum, + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType, + l_req_fw_msg->generic_msg.__req, + l_req_fw_msg->generic_msg.__onlyError); + + /*@ + * @errortype + * @severity ERRL_SEV_PREDICTIVE + * @moduleid MOD_RT_FIRMWARE_REQUEST + * @reasoncode RC_FW_REQUEST_HWSV_ERR + * @userdata1[0:31] HWSV error log id (PLID) + * @userdata1[32:63] Sequence number + * @userdata2[0:31] MBOX message type + * @userdata2[32:63] Message Type + * @devdesc The Firmware Request call failed + */ + l_err = new ErrlEntry(ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_REQUEST, + RC_FW_REQUEST_HWSV_ERR, + TWO_UINT32_TO_UINT64( + l_errPlid, + l_req_fw_msg->generic_msg.seqnum), + TWO_UINT32_TO_UINT64( + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType), + true); + + // Break out of the retry loop + break; + } + else + { + // Break out of the retry loop, the call was successful + // But first delete any previous errors. It can be confusing + // if an error is committed or returned on a successful call + delete l_err, l_err = nullptr; + break; + } + } // END for (int i = 0; i <= HBRT_FW_REQUEST_RETRIES; ++i) + + // If there is an error, then call addFFDC + // with request/response sructs + if (l_err) + { + // Hit the max attempts (currently should only one retry) and hitting + // reset/reload error + if (l_isResetReloadErr) + { + // Change the severity of a reset/reload error to predictive + l_err->setSev(ERRL_SEV_PREDICTIVE); + } + + l_err->addFFDC(RUNTIME_COMP_ID, + l_req_fw_msg, + i_reqLen, + 0, 0, false ); + + if (*o_respLen > 0) + { + l_err->addFFDC(RUNTIME_COMP_ID, + l_resp_fw_msg, + *o_respLen, + 0, 0, false ); + } + + l_err->collectTrace( "FW_REQ", 256); + } // END if (l_err) + + return l_err; +}; diff --git a/src/usr/vpd/runtime/makefile b/src/usr/vpd/runtime/makefile index 7943ffcb0..1f2ed00d7 100644 --- a/src/usr/vpd/runtime/makefile +++ b/src/usr/vpd/runtime/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2015 +# Contributors Listed Below - COPYRIGHT 2013,2017 # [+] International Business Machines Corp. # # diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C index d85440e56..dba37f1c2 100644 --- a/src/usr/vpd/runtime/rt_vpd.C +++ b/src/usr/vpd/runtime/rt_vpd.C @@ -22,6 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + #include #include #include @@ -30,7 +31,8 @@ #include #include #include -#include +#include // g_hostInterfaces +#include // firmware_request_helper #include #include #include @@ -41,6 +43,8 @@ #include "cvpd.H" #include "spd.H" +using namespace ERRORLOG; + extern trace_desc_t* g_trac_vpd; // ------------------------ @@ -313,7 +317,8 @@ errlHndl_t writePNOR ( uint64_t i_byteAddr, //-------------------------------- if(INITSERVICE::spBaseServicesEnabled()) { - TRACFCOMP(g_trac_vpd,ERR_MRK"rt_vpd:writePNOR not supported with FSP, skipping"); + TRACFCOMP(g_trac_vpd, + ERR_MRK"rt_vpd:writePNOR not supported with FSP, skipping"); break; } @@ -378,6 +383,11 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, { errlHndl_t l_err = nullptr; + // Put the handle to the firmware messages out here + // so it is easier to free later + hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr; + hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr; + TRACFCOMP( g_trac_vpd, INFO_MRK "sendMboxWriteMsg: Send msg to FSP to write VPD type %.8X, " "record %d, offset 0x%X", @@ -385,9 +395,6 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, i_record.rec_num, i_record.offset ); - hostInterfaces::hbrt_fw_msg* l_req_fw_msg = nullptr; - hostInterfaces::hbrt_fw_msg* l_resp_fw_msg = nullptr; - do { if(!INITSERVICE::spBaseServicesEnabled()) @@ -401,153 +408,91 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, if ((nullptr == g_hostInterfaces) || (nullptr == g_hostInterfaces->firmware_request)) { + TRACFCOMP(g_trac_vpd, ERR_MRK"sendMboxWriteMsg: " + "Hypervisor firmware_request interface not linked"); + /*@ * @errortype - * @severity ERRORLOG::ERRL_SEV_INFORMATIONAL - * @moduleid VPD::VPD_SEND_MBOX_WRITE_MESSAGE - * @reasoncode VPD::VPD_RT_NULL_FIRMWARE_REQUEST_PTR + * @severity ERRL_SEV_INFORMATIONAL + * @moduleid VPD_SEND_MBOX_WRITE_MESSAGE + * @reasoncode VPD_RT_NULL_FIRMWARE_REQUEST_PTR * @userdata1 HUID of target * @userdata2 VPD message type * @devdesc MBOX send not supported in HBRT */ - l_err= new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, - VPD::VPD_SEND_MBOX_WRITE_MESSAGE, - VPD::VPD_RT_NULL_FIRMWARE_REQUEST_PTR, - TARGETING::get_huid(i_target), - i_type); + l_err= new ErrlEntry(ERRL_SEV_INFORMATIONAL, + VPD_SEND_MBOX_WRITE_MESSAGE, + VPD_RT_NULL_FIRMWARE_REQUEST_PTR, + TARGETING::get_huid(i_target), + i_type, true); break; } - // Get an accurate size of memory actually needed to transport the data - size_t l_generic_msg_size = - sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) + - i_numBytes - - sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data); - size_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - l_generic_msg_size; + // Get an accurate size of memory needed to transport + // the data for the firmware_request request struct + uint32_t l_req_data_size = sizeof(GenericFspMboxMessage_t) + + i_numBytes - + sizeof(GenericFspMboxMessage_t::data); + + // The request data size must be at a minimum the size of the + // FSP generic message (sizeof(GenericFspMboxMessage_t)) + if (l_req_data_size < sizeof(GenericFspMboxMessage_t)) + { + l_req_data_size = sizeof(GenericFspMboxMessage_t); + } + + // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which + // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to + // the previous calculated data size + uint64_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + l_req_data_size; - //create the firmware_request structure to carry the vpd write msg data + // Create the firmware_request request struct to send data l_req_fw_msg = - (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size) ; - memset(l_req_fw_msg, 0, l_req_fw_msg_size); + (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); - // populate the firmware_request structure with given data - l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + // Initialize the firmware_request request struct l_req_fw_msg->generic_msg.initialize(); - l_req_fw_msg->generic_msg.dataSize = l_generic_msg_size; + + // Populate the firmware_request request struct with given data + l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg->generic_msg.dataSize = l_req_data_size; l_req_fw_msg->generic_msg.msgq = MBOX::FSP_VPD_MSGQ; l_req_fw_msg->generic_msg.msgType = i_type; - l_req_fw_msg->generic_msg.__req = GFMM_REQUEST; - l_req_fw_msg->generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; + l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST; memcpy(&l_req_fw_msg->generic_msg.data, i_data, i_numBytes); - // set up the response struct, note that for messages to the FSP - // the response size must match the request size - l_resp_fw_msg = - (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size); - memset(l_resp_fw_msg, 0, l_req_fw_msg_size); + // Create the firmware_request response struct to receive data + // NOTE: For messages to the FSP the response size must match + // the request size. + // No need to check for expected response size > request + // size because they use the same base structure uint64_t l_resp_fw_msg_size = l_req_fw_msg_size; - // Note - no need to check for expected response size > request - // size because they use the same base structure - - // make the firmware request + l_resp_fw_msg = + (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size); + memset(l_resp_fw_msg, 0, l_resp_fw_msg_size); + + // Trace out the request structure TRACFBIN( g_trac_vpd, INFO_MRK"Sending firmware_request", l_req_fw_msg, - hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) ); - size_t rc = g_hostInterfaces->firmware_request(l_req_fw_msg_size, - l_req_fw_msg, - &l_resp_fw_msg_size, - l_resp_fw_msg); - uint64_t l_userData1(0), l_userData2(0); - - // Capture the err log id if any - // The return code (rc) may return OK, but there still may be an issue - // with the HWSV code on the FSP. - // Only checking for a PLID regardless of what the flag __onlyError is - // set to. I am not expecting any extra data and not sure what to do - // with it if I get it. - if ( (hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP == - l_resp_fw_msg->io_type) && - (0 != l_resp_fw_msg->generic_msg.data >> 32) ) - { - // extract the plid from the first 32 bits - l_userData2 = l_resp_fw_msg->generic_msg.data >> 32; - } + l_req_fw_msg_size); - // gather up the error data and create an err log out of it - if (rc || l_userData2) - { - TRACFCOMP(g_trac_vpd, - ERR_MRK"firmware request: " - "firmware request for FSP VPD write message rc: 0x%X, " - "HUID:0x%llX, plid:%.8X, VPD type:%.8X, " - "record:%d, offset:0x%X, ", - rc, get_huid(i_target), l_userData2, - i_type, i_record.rec_num, i_record.offset ); + // Make the firmware_request call + l_err = firmware_request_helper(l_req_fw_msg_size, + l_req_fw_msg, + &l_resp_fw_msg_size, + l_resp_fw_msg); - /*@ - * @errortype - * @moduleid VPD::VPD_RT_FIRMWARE_REQUEST - * @reasoncode VPD::VPD_RT_WRITE_MSG_ERR - * @userdata1[0:31] Firmware Request return code (if any) - * @userdata1[32:63] HUID of target - * @userdata2 HWSV error log id (if any) - * @devdesc Firmware Request for - * VPD Write Msg error - */ - - // Capture the return code (rc), if any - // this will indicate an issue with actually sending the msg - if (rc) - { - l_userData1 = TWO_UINT32_TO_UINT64(rc, - TARGETING::get_huid(i_target)); - } - else - { - l_userData1 = TARGETING::get_huid(i_target); - } - - l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE, - VPD::VPD_RT_FIRMWARE_REQUEST, - VPD::VPD_RT_WRITE_MSG_ERR, - l_userData1, - l_userData2); - - if (l_resp_fw_msg_size > 0) - { - l_err->addFFDC( MBOX_COMP_ID, - l_resp_fw_msg, - l_resp_fw_msg_size, - 0, 0, false ); - } - - if (l_req_fw_msg_size > 0) - { - l_err->addFFDC( MBOX_COMP_ID, - l_req_fw_msg, - l_req_fw_msg_size, - 0, 0, false ); - } - - l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); - - if (l_userData2) - { - l_err->plid(l_userData2); - } - - l_err->collectTrace( "VPD", 256); - } // end (rc || l_userData2) - - } - while (0); + if (l_err) + { + break; + } + } while (0); // release the memory created if( l_req_fw_msg ) { free(l_req_fw_msg); } if( l_resp_fw_msg ) { free(l_resp_fw_msg); } + l_req_fw_msg = l_resp_fw_msg = nullptr; if (l_err) { @@ -560,5 +505,4 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, return l_err; } - }; // end namepsace VPD -- cgit v1.2.1