diff options
author | Swathi Madhuri Bhattiprolu <bhmadhur@in.ibm.com> | 2018-02-28 07:08:54 -0600 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2018-04-05 14:34:23 -0400 |
commit | 571e1d84dfe50aaa674aa7e33abb75868b432d78 (patch) | |
tree | 2ab7eb56240999e074be13138d7d2ac5e24802cc | |
parent | ad4459feb84ab2a4ec9f512b220a9aa67be858c8 (diff) | |
download | talos-hostboot-571e1d84dfe50aaa674aa7e33abb75868b432d78.tar.gz talos-hostboot-571e1d84dfe50aaa674aa7e33abb75868b432d78.zip |
Verify frequency attributes across nodes
-Existing code ensures consistency of frequency data
across all modules in istep6.12.
-In a multi-drawer config this data needs to be
consistent across all drawers.
-Master drawer sends the frequency data to all the
other via IPC mechanism.
-This data is compared and error is returned if there
is a mismatch.
Change-Id: I922d32456c9d3c4e53dae528f088dbb013c3ded9
RTC:158036
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/54825
CI-Ready: SWATHI M. BHATTIPROLU <bhmadhur@in.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Richard Ward <rward15@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
-rw-r--r-- | src/include/usr/hwas/common/hwasCallout.H | 8 | ||||
-rw-r--r-- | src/include/usr/isteps/hwpf_reasoncodes.H | 2 | ||||
-rw-r--r-- | src/include/usr/isteps/istep_reasoncodes.H | 10 | ||||
-rw-r--r-- | src/include/usr/mbox/ipc_msg_types.H | 2 | ||||
-rw-r--r-- | src/include/usr/mbox/mbox_queues.H | 1 | ||||
-rw-r--r-- | src/usr/isteps/istep21/call_host_start_payload.C | 14 | ||||
-rw-r--r-- | src/usr/isteps/istep21/freqAttrData.C | 716 | ||||
-rw-r--r-- | src/usr/isteps/istep21/freqAttrData.H | 112 | ||||
-rw-r--r-- | src/usr/isteps/istep21/makefile | 3 | ||||
-rw-r--r-- | src/usr/mbox/ipcSp.C | 81 | ||||
-rw-r--r-- | src/usr/mbox/ipcSp.H | 4 |
11 files changed, 944 insertions, 9 deletions
diff --git a/src/include/usr/hwas/common/hwasCallout.H b/src/include/usr/hwas/common/hwasCallout.H index 8f5126e6e..840323657 100644 --- a/src/include/usr/hwas/common/hwasCallout.H +++ b/src/include/usr/hwas/common/hwasCallout.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* Contributors Listed Below - COPYRIGHT 2012,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -61,6 +61,12 @@ typedef enum { GARD_Void = 0xFF } GARD_ErrorType; +enum ErrorCategory { + ERR_CATEGORY_INVALID_SERIAL = 0x01, + ERR_CATEGORY_INVALID_PART = 0x02, + +}; + // from src/epub/fsp/epub_service_codes.H v1.24.24.4 // - Any additions should be added to FipS code first diff --git a/src/include/usr/isteps/hwpf_reasoncodes.H b/src/include/usr/isteps/hwpf_reasoncodes.H index 78024bdcc..75a88f7ee 100644 --- a/src/include/usr/isteps/hwpf_reasoncodes.H +++ b/src/include/usr/isteps/hwpf_reasoncodes.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ diff --git a/src/include/usr/isteps/istep_reasoncodes.H b/src/include/usr/isteps/istep_reasoncodes.H index 2d165b7e5..646c58c54 100644 --- a/src/include/usr/isteps/istep_reasoncodes.H +++ b/src/include/usr/isteps/istep_reasoncodes.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -60,6 +60,7 @@ namespace ISTEP MOD_SET_IPL_PARMS = 0x1D, MOD_OCC_XSTOP_HANDLER = 0x1E, MOD_VERIFY_AND_MOVE_PAYLOAD = 0x1F, + MOD_FREQ_ATTR_DATA = 0x20, }; /** @@ -114,6 +115,13 @@ namespace ISTEP RC_P9N_DD1_NOT_SUPPORTED = ISTEP_COMP_ID | 0x35, RC_PREVENT_REBOOT_IN_MFG_TERM_MODE = ISTEP_COMP_ID | 0x36, RC_FAILED_WRITE_SPR = ISTEP_COMP_ID | 0x37, + RC_FREQ_ATTR_TIMER_EXPIRED = ISTEP_COMP_ID | 0x38, + RC_FREQ_ATTR_TIMER_THREAD_FAIL = ISTEP_COMP_ID | 0x39, + RC_FLOOR_FREQ_MISMATCH = ISTEP_COMP_ID | 0x40, + RC_CEIL_FREQ_MISMATCH = ISTEP_COMP_ID | 0x41, + RC_TURBO_FREQ_MISMATCH = ISTEP_COMP_ID | 0x42, + RC_ULTRA_TURBO_FREQ_MISMATCH = ISTEP_COMP_ID | 0x43, + RC_NEST_FREQ_MISMATCH = ISTEP_COMP_ID | 0x44, }; }; diff --git a/src/include/usr/mbox/ipc_msg_types.H b/src/include/usr/mbox/ipc_msg_types.H index 5a2ead6c9..7009c01d1 100644 --- a/src/include/usr/mbox/ipc_msg_types.H +++ b/src/include/usr/mbox/ipc_msg_types.H @@ -40,6 +40,8 @@ namespace IPC IPC_QUERY_CHIPINFO, IPC_SET_SBE_CHIPINFO, IPC_CLOSE_TCES, + IPC_FREQ_ATTR_DATA, // frequency attribute data from master to other drawers + }; }; // namespace IPC diff --git a/src/include/usr/mbox/mbox_queues.H b/src/include/usr/mbox/mbox_queues.H index e1e698c91..5b76c51f8 100644 --- a/src/include/usr/mbox/mbox_queues.H +++ b/src/include/usr/mbox/mbox_queues.H @@ -55,6 +55,7 @@ namespace MBOX HB_COALESCE_MSGQ = 11, //host_coalesce response HB_SBE_SYSCONFIG_MSGQ = 12, //For SBE System Config response HB_CLOSE_TCES_MSGQ = 13, // close/disable TCEs + HB_FREQ_ATTR_DATA_MSGQ = 14, // freq attributes data from master to all other drawers // Add HB mbox msg queue ids (services) before this line HB_LAST_VALID_MSGQ, // end of valid HB mbox msgQ ids diff --git a/src/usr/isteps/istep21/call_host_start_payload.C b/src/usr/isteps/istep21/call_host_start_payload.C index f51073803..a2c392bf1 100644 --- a/src/usr/isteps/istep21/call_host_start_payload.C +++ b/src/usr/isteps/istep21/call_host_start_payload.C @@ -56,6 +56,7 @@ #include <p9_int_scom.H> #include <sbeio/sbeioif.H> #include <runtime/runtime.H> +#include "freqAttrData.H" #ifdef CONFIG_DRTM_TRIGGERING #include <secureboot/drtm.H> @@ -192,6 +193,19 @@ void* call_host_start_payload (void *io_pArgs) do{ + // Synchronize the frequency attribute across drawers + l_errl = ISTEP_21::sendFreqAttrData(); + + if(l_errl) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_start_payload: ERROR: sendFreqAttrData Failed"); + l_errl->collectTrace("ISTEPS_TRACE",256); + errlCommit(l_errl, ISTEP_COMP_ID ); + + break; + } + // Place a separator in the TPM to indicate we are passing control // to the next level of firmware in the stack. Send the synchronous // message to make sure that the traces are flushed prior to the daemon diff --git a/src/usr/isteps/istep21/freqAttrData.C b/src/usr/isteps/istep21/freqAttrData.C new file mode 100644 index 000000000..5f590ab71 --- /dev/null +++ b/src/usr/isteps/istep21/freqAttrData.C @@ -0,0 +1,716 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/isteps/istep21/freqAttrData.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* [+] 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 */ +/** + * @file freqAttrSync.C + * @brief Interrupt Resource Provider + */ + +#include "freqAttrData.H" +#include <trace/interface.H> +#include <errno.h> +#include <initservice/taskargs.H> +#include <initservice/initserviceif.H> +#include <initservice/istepdispatcherif.H> +#include <initservice/isteps_trace.H> +#include <isteps/hwpisteperror.H> +#include <isteps/istep_reasoncodes.H> +#include <isteps/hwpf_reasoncodes.H> +#include <util/singleton.H> +#include <kernel/ipc.H> +#include <sys/task.h> +#include <vmmconst.h> +#include <targeting/common/targetservice.H> +#include <targeting/common/attributes.H> +#include <targeting/common/utilFilter.H> +#include <devicefw/userif.H> +#include <sys/time.h> +#include <sys/vfs.h> +#include <arch/ppc.H> +#include <config.h> +#include <mbox/ipc_msg_types.H> + +#include <fapi2.H> +#include <fapi2/target.H> +#include <fapi2/plat_hwp_invoker.H> + +#define INTR_TRACE_NAME INTR_COMP_NAME + +using namespace TARGETING; +using namespace ISTEP; +using namespace ISTEP_ERROR; +using namespace ERRORLOG; + +namespace ISTEP_21 +{ +void* sendFreqAttrData_timer(void* i_msgQPtr) + +{ + int rc=0; + + msg_t* msg = msg_allocate(); + msg->type = HB_FREQ_ATTR_DATA_TIMER_MSG; + uint32_t l_time_ms =0; + + msg_q_t* msgQ = static_cast<msg_q_t*>(i_msgQPtr); + + + //this loop will be broken when the main thread receives + //all the messages and the timer thread receives the + //HB_FREQ_ATTR_DATA_MSG_DONE message + + do + { + if (l_time_ms < MAX_TIME_ALLOWED_MS) + { + msg->data[1] = CONTINUE_WAIT_FOR_MSGS; + } + else + { + // HB_FREQ_ATTR_DATA_TIMER_MSG is sent to the main thread indicating + // timer expired so the main thread responds back with HB_FREQ_ATTR_DATA_MSG_DONE + // indicating the timer is not needed and exit the loop + msg->data[1]=TIME_EXPIRED; + } + + rc= msg_sendrecv(*msgQ, msg); + if (rc) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "sendFreqAttrData_timer failed msg sendrecv."); + } + if (msg->data[1] == HB_FREQ_ATTR_DATA_MSG_DONE) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "sendFreqAttrData_timer not needed."); + break; + } + + nanosleep(0,NS_PER_MSEC); + l_time_ms++; + + }while(1); + + msg_free(msg); + + return NULL; +} + +errlHndl_t sendFreqAttrData() +{ + errlHndl_t l_elog = nullptr; + tid_t l_progTid = 0; + + do { + + TARGETING::Target * sys = nullptr; + + TARGETING::targetService().getTopLevelTarget( sys ); + assert(sys != nullptr); + + // Figure out which node we are running on + TARGETING::Target* mproc = nullptr; + + TARGETING::targetService().masterProcChipTargetHandle(mproc); + + TARGETING::EntityPath epath = mproc->getAttr<TARGETING::ATTR_PHYS_PATH>(); + + const TARGETING::EntityPath::PathElement pe = + epath.pathElementOfType(TARGETING::TYPE_NODE); + + uint64_t nodeid = pe.instance; + + // ATTR_HB_EXISTING_IMAGE only gets set on a multi-drawer system. + // Currently set up in host_sys_fab_iovalid_processing() which only + // gets called if there are multiple physical nodes. It eventually + // needs to be setup by a hb routine that snoops for multiple nodes. + TARGETING::ATTR_HB_EXISTING_IMAGE_type hb_images = + sys->getAttr<TARGETING::ATTR_HB_EXISTING_IMAGE>(); + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "sendFreqAttrData hb_images = 0x%x, nodeid = 0x%x", hb_images, nodeid); + + if (0 != hb_images) //Multi-node + { + // multi-node system + // This msgQ catches the node responses from the commands + msg_q_t msgQ = msg_q_create(); + l_elog = MBOX::msgq_register(MBOX::HB_FREQ_ATTR_DATA_MSGQ,msgQ); + if(l_elog) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "MBOX::msgq_register failed!" ); + break; + } + + // keep track of the number of messages we send so we + // know how many responses to expect + uint64_t msg_count = 0; + freq_data freq_data_obj{0}; + + // loop thru rest all nodes -- sending msg to each + TARGETING::ATTR_HB_EXISTING_IMAGE_type mask = 0x1 << + ((sizeof(TARGETING::ATTR_HB_EXISTING_IMAGE_type) * 8) -1); + + for (uint64_t l_node=0; (l_node < NUMBER_OF_POSSIBLE_DRAWERS); l_node++ ) + { + // skip sending to ourselves, we did our construction above + if(l_node == nodeid) + continue; + + if( 0 != ((mask >> l_node) & hb_images ) ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "send IPC_DATA_FREQ_ATTR_DATA " + "message to node %d",l_node ); + + msg_t * msg = msg_allocate(); + msg->type = IPC::IPC_FREQ_ATTR_DATA; + msg->data[0] = l_node; // destination node + msg->data[1] = nodeid; // respond to this node + + msg->extra_data = MBOX::allocate(sizeof(freq_data)); + + // Fill in the frequency attribute data + freq_data_obj.nominalFreq = sys->getAttr<ATTR_NOMINAL_FREQ_MHZ>(); + freq_data_obj.floorFreq = sys->getAttr<ATTR_MIN_FREQ_MHZ>(); + freq_data_obj.ceilingFreq = sys->getAttr<ATTR_FREQ_CORE_CEILING_MHZ>(); + freq_data_obj.ultraTurboFreq = sys->getAttr<ATTR_ULTRA_TURBO_FREQ_MHZ>(); + freq_data_obj.turboFreq = sys->getAttr<ATTR_FREQ_CORE_MAX>(); + freq_data_obj.nestFreq = sys->getAttr<ATTR_FREQ_PB_MHZ>(); + freq_data_obj.powerModeNom = sys->getAttr<ATTR_SOCKET_POWER_NOMINAL>(); + freq_data_obj.powerModeTurbo = sys->getAttr<ATTR_SOCKET_POWER_TURBO>(); + + memcpy(msg->extra_data, (void *)&freq_data_obj, sizeof(freq_data)); + + // send the message to the slave hb instance + l_elog = MBOX::send(MBOX::HB_IPC_MSGQ, msg, l_node); + if( l_elog ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "MBOX::send to node %d" + " failed", l_node); + break; + } + + ++msg_count; + + } // end if node to process + } // end for loop on nodes + + if(l_elog == NULL) + { + //wait for all hb images to respond + //want to spawn a timer thread + l_progTid = task_create(ISTEP_21::sendFreqAttrData_timer,msgQ); + + assert( l_progTid > 0 ,"sendFreqAttrData_timer failed"); + + while(msg_count) + { + msg_t* msg = msg_wait(msgQ); + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Send frequency attribute message for drawer %d completed.", + msg->data[0]); + + if (msg->type == HB_FREQ_ATTR_DATA_TIMER_MSG) + { + if (msg->data[1] == TIME_EXPIRED) + { + //timer has expired + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "IPC_DATA_FREQ_ATTR_DATA failed to " + "receive messages from all hb images in time" ); + //tell the timer thread to exit + msg->data[1] = HB_FREQ_ATTR_DATA_MSG_DONE; + msg_respond(msgQ,msg); + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_FREQ_ATTR_TIMER_EXPIRED, + * @userdata1 MAX_TIME_ALLOWED_MS + * @userdata2 Number of nodes that have not + * responded + * + * @devdesc messages from other nodes have + * not returned in time + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_FREQ_ATTR_TIMER_EXPIRED, + MAX_TIME_ALLOWED_MS, + msg_count ); + l_elog->collectTrace("ISTEPS_TRACE"); + l_elog->collectTrace("IPC"); + l_elog->collectTrace("MBOXMSG"); + + l_elog->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + + // Break the While loop and wait for the child thread to exit + break; + + } + else if( msg->data[1] == CONTINUE_WAIT_FOR_MSGS) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "coalesce host timer continue waiting message."); + msg->data[1] =HB_FREQ_ATTR_DATA_WAITING_FOR_MSG; + msg_respond(msgQ,msg); + } + } + else if (msg->type == IPC::IPC_FREQ_ATTR_DATA) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Got response from node %d", msg->data[0] ); + --msg_count; + msg_free(msg); + } + if(l_elog) + break; + } + + } + + if(l_elog) + break; + + //the msg_count should be 0 at this point to have + //exited from the loop above. If the msg count + //is not zero then the timer must have expired + //and the code would have asserted + //Now need to tell the child timer thread to exit + + //simics takes a long time for FLEETWOOD to IPL + //A check to tell the child timer thread to exit if didn't + //already timeout + if (msg_count ==0) + { + msg_t* msg = msg_wait(msgQ); + if (msg->type == HB_FREQ_ATTR_DATA_TIMER_MSG) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "IPC_DATA_FREQ_ATTR_DATA received from all hb " + "images in time"); + + msg->data[1] = HB_FREQ_ATTR_DATA_MSG_DONE; + msg_respond(msgQ,msg); + } + } + + //wait for the child thread to end + int l_childsts =0; + void* l_childrc = NULL; + tid_t l_tidretrc = task_wait_tid(l_progTid,&l_childsts,&l_childrc); + if ((static_cast<int16_t>(l_tidretrc) < 0) + || (l_childsts != TASK_STATUS_EXITED_CLEAN )) + { + // the launched task failed or crashed, + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "task_wait_tid failed; l_tidretrc=0x%x, l_childsts=0x%x", + l_tidretrc, l_childsts); + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_FREQ_ATTR_TIMER_THREAD_FAIL, + * @userdata1 l_tidretrc, + * @userdata2 l_childsts, + * + * @devdesc Freq attribute DATA timer thread + * failed + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_FREQ_ATTR_TIMER_THREAD_FAIL, + l_tidretrc, + l_childsts); + + l_elog->collectTrace("ISTEPS_TRACE"); + + l_elog->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + + errlCommit(l_elog, HWPF_COMP_ID); + + } + + MBOX::msgq_unregister(MBOX::HB_FREQ_ATTR_DATA_MSGQ); + msg_q_destroy(msgQ); + } + + } while(0); + + return(l_elog); +} + +errlHndl_t callCheckFreqAttrData(void *ptr) +{ + TARGETING::Target * sys = nullptr; + errlHndl_t l_elog = nullptr; + freq_data freq_data_obj{0}; + ISTEP_ERROR::IStepError l_stepError; + uint16_t errCaseId = 0xFF; + + TARGETING::targetService().getTopLevelTarget( sys ); + assert(sys != nullptr); + + freq_data *master_freq_data_obj_ptr = reinterpret_cast<freq_data *>(ptr); + + // Get the frequency attributes + freq_data_obj.nominalFreq = sys->getAttr<TARGETING::ATTR_NOMINAL_FREQ_MHZ>(); + freq_data_obj.powerModeNom = sys->getAttr<TARGETING::ATTR_SOCKET_POWER_NOMINAL>(); + freq_data_obj.powerModeTurbo = sys->getAttr<TARGETING::ATTR_SOCKET_POWER_TURBO>(); + + freq_data_obj.floorFreq = sys->getAttr<TARGETING::ATTR_MIN_FREQ_MHZ>(); + freq_data_obj.ceilingFreq = sys->getAttr<TARGETING::ATTR_FREQ_CORE_CEILING_MHZ>(); + freq_data_obj.ultraTurboFreq = sys->getAttr<TARGETING::ATTR_ULTRA_TURBO_FREQ_MHZ>(); + freq_data_obj.turboFreq = sys->getAttr<TARGETING::ATTR_FREQ_CORE_MAX>(); + freq_data_obj.nestFreq = sys->getAttr<TARGETING::ATTR_FREQ_PB_MHZ>(); + + + do { + + // All of the buckets should report the same Power mode + if((freq_data_obj.powerModeNom != master_freq_data_obj_ptr->powerModeNom )|| + (freq_data_obj.powerModeTurbo != master_freq_data_obj_ptr->powerModeTurbo )) + { + errCaseId = 0; + } + else if(freq_data_obj.nominalFreq != master_freq_data_obj_ptr->nominalFreq ) + { + errCaseId = 1; + } + else if(freq_data_obj.floorFreq != master_freq_data_obj_ptr->floorFreq ) + { + errCaseId = 2; + } + else if(freq_data_obj.ceilingFreq != master_freq_data_obj_ptr->ceilingFreq ) + { + errCaseId = 3; + } + else if(freq_data_obj.ultraTurboFreq != master_freq_data_obj_ptr->ultraTurboFreq ) + { + errCaseId = 4; + } + else if(freq_data_obj.turboFreq != master_freq_data_obj_ptr->turboFreq ) + { + errCaseId = 5; + } + else if(freq_data_obj.nestFreq != master_freq_data_obj_ptr->nestFreq ) + { + errCaseId = 6; + } + + switch(errCaseId) + { + case 0: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "frequency attribute data MISMATCH! " + "expected PowerNom %d actual PowerMom %d " + "expected PowerTurbo %d actual PowerTurbo %d", + master_freq_data_obj_ptr->powerModeNom, + freq_data_obj.powerModeNom, + master_freq_data_obj_ptr->powerModeTurbo, + freq_data_obj.powerModeTurbo); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_POWER_MODE_MISMATCH, + * @userdata1[00:31] Master node nominal power mode + * @userdata1[32:63] Current node nominal power mode + * @userdata2[00:31] Master node turbo power mode + * @userdata2[32:63] Current node turbo power mode + * @devdesc Power Mode mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_POWER_MODE_MISMATCH, + TWO_UINT32_TO_UINT64( + master_freq_data_obj_ptr->powerModeNom, + freq_data_obj.powerModeNom), + TWO_UINT32_TO_UINT64( + master_freq_data_obj_ptr->powerModeTurbo, + freq_data_obj.powerModeTurbo), false); + + + + break; + + + case 1: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "nominal frequency data MISMATCH! " + "expected Nominal %d actual Nominal %d ", + master_freq_data_obj_ptr->nominalFreq, + freq_data_obj.nominalFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_NOMINAL_FREQ_MISMATCH, + * @userdata1 Master node nominal frequency + * @userdata2[00:31] Current node nominal frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc Nominal Mode mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_NOMINAL_FREQ_MISMATCH, + master_freq_data_obj_ptr->nominalFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.nominalFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + case 2: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Floor frequency data MISMATCH! " + "expected Floor Freq %d actual Floor Freq %d ", + master_freq_data_obj_ptr->floorFreq, + freq_data_obj.floorFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_FLOOR_FREQ_MISMATCH, + * @userdata1 Master node Floor frequency + * @userdata2[00:31] Current node floor frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc Floor Freq mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_FLOOR_FREQ_MISMATCH, + master_freq_data_obj_ptr->floorFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.floorFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + case 3: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Ceiling frequency data MISMATCH! " + "expected Ceiling Freq %d actual Ceiling Freq %d ", + master_freq_data_obj_ptr->ceilingFreq, + freq_data_obj.ceilingFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_CEIL_FREQ_MISMATCH, + * @userdata1 Master node Ceil frequency + * @userdata2[00:31] Current node Ceil frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc Ceil Freq mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_CEIL_FREQ_MISMATCH, + master_freq_data_obj_ptr->ceilingFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.ceilingFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + + case 4: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "UltraTurbo frequency data MISMATCH! " + "expected UltraTurbo Freq %d actual UltraTurbo Freq %d ", + master_freq_data_obj_ptr->ultraTurboFreq, + freq_data_obj.ultraTurboFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_ULTRA_TURBO_FREQ_MISMATCH, + * @userdata1 Master node UltraTurbo frequency + * @userdata2[00:31] Current node UltraTurbo frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc UltraTurbo Freq mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_ULTRA_TURBO_FREQ_MISMATCH, + master_freq_data_obj_ptr->ultraTurboFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.ultraTurboFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + case 5: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Turbo frequency data MISMATCH! " + "expected Turbo Freq %d actual Turbo Freq %d ", + master_freq_data_obj_ptr->turboFreq, + freq_data_obj.turboFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_TURBO_FREQ_MISMATCH, + * @userdata1 Master node Turbo frequency + * @userdata2[00:31] Current node Turbo frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc Turbo Freq mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_TURBO_FREQ_MISMATCH, + master_freq_data_obj_ptr->turboFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.turboFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + case 6: + + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Nest frequency data MISMATCH! " + "expected Nest Freq %d actual Nest Freq %d ", + master_freq_data_obj_ptr->nestFreq, + freq_data_obj.nestFreq); + + + //generate an errorlog + /*@ + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid ISTEP::MOD_FREQ_ATTR_DATA, + * @reasoncode ISTEP::RC_NEST_FREQ_MISMATCH, + * @userdata1 Master node Nest frequency + * @userdata2[00:31] Current node Nest frequency + * @userdata2[32:63] Error category INVALID_PART + * @devdesc Nest Freq mismatch between drawers + * @custdesc Incompatible processor modules + * installed between drawers. + + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + ISTEP::MOD_FREQ_ATTR_DATA, + ISTEP::RC_NEST_FREQ_MISMATCH, + master_freq_data_obj_ptr->nestFreq, + TWO_UINT32_TO_UINT64 ( + freq_data_obj.nestFreq, + HWAS::ERR_CATEGORY_INVALID_PART ), false); + + + break; + + default: // do nothing + break; + + } + if(errCaseId != 0xFF) + { + TargetHandleList procList; + + // Get the child proc chips + getChildAffinityTargets(procList, + sys, + CLASS_CHIP, + TYPE_PROC ); + for( const auto & proc : procList ) + { + l_elog->addHwCallout(proc, + HWAS::SRCI_PRIORITY_MEDA, + HWAS::NO_DECONFIG, + HWAS::GARD_NULL ); + } + + l_elog->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_LOW); + + l_elog->addProcedureCallout(HWAS::EPUB_PRC_INVALID_PART, + HWAS::SRCI_PRIORITY_HIGH); + + l_elog->collectTrace("ISTEPS_TRACE"); + + // Create IStep error log and + // cross reference occurred error + l_stepError.addErrorDetails( l_elog ); + } + }while(0); + + return l_elog; + +} + +}
\ No newline at end of file diff --git a/src/usr/isteps/istep21/freqAttrData.H b/src/usr/isteps/istep21/freqAttrData.H new file mode 100644 index 000000000..cbe212607 --- /dev/null +++ b/src/usr/isteps/istep21/freqAttrData.H @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/isteps/istep21/freqAttrData.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* [+] 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 */ +#ifndef FREQATTRDATA_H +#define FREQATTRDATA_H + +#include <stdint.h> +#include <builtins.h> +#include <limits.h> +#include <errl/errlentry.H> +#include <kernel/intmsghandler.H> +#include <sys/msg.h> +#include <sys/misc.h> +#include <sys/time.h> +#include <sys/internode.h> + +#include <map> +#include <algorithm> +#include <arch/pirformat.H> + +namespace ISTEP_21 +{ + /******************************************************************************/ + // Globals/Constants + /******************************************************************************/ + constexpr uint8_t HB_FREQ_ATTR_DATA_WAITING_FOR_MSG = 0x0; + constexpr uint8_t HB_FREQ_ATTR_DATA_MSG_DONE = 0x1; + constexpr uint32_t MAX_TIME_ALLOWED_MS = 10000; + constexpr uint8_t NUMBER_OF_POSSIBLE_DRAWERS = 8; + constexpr uint8_t CONTINUE_WAIT_FOR_MSGS = 0x2; + constexpr uint8_t TIME_EXPIRED=0x3; + + /** + * enum used for sending messages within sendFreqAttrData + */ + enum + { + HB_FREQ_ATTR_DATA_TIMER_MSG = 0xA1, + }; + + /** + * @brief structure to hold frequency attribute data + * + */ + struct freq_data { + uint32_t nominalFreq; //ATTR_NOMINAL_FREQ_MHZ + uint32_t floorFreq; //ATTR_FREQ_FLOOR_MHZ + uint32_t ceilingFreq ; //ATTR_FREQ_CORE_CEILING_MHZ + uint32_t ultraTurboFreq; //ATTR_ULTRA_TURBO_FREQ_MHZ + uint32_t turboFreq; //ATTR_FREQ_CORE_MAX + uint32_t nestFreq; //ATTR_FREQ_PB_MHZ + uint32_t powerModeNom; //ATTR_SOCKET_POWER_NOMINAL + uint32_t powerModeTurbo; //ATTR_SOCKET_POWER_TURBO + }; + + + + /** + * @brief Timer function for safe error handling in sendFreqAttrData + * + * @description Used inside the sendFreqAttrData() to wait for + * responses from other nodes + * @param[in] i_msgQPtr -- Pointer to the Message Queue to wait for messages + * + * @return void + */ + void* sendFreqAttrData_timer(void* i_msgQPtr); + + /** + * @brief Sends the frequency attributes with that of master HB + * + * @description On multi-drawer system call_host_start_payload invokes this method + * @param[in] None + * + * @return errlHndl_t + */ + errlHndl_t sendFreqAttrData(); + + /** + * @brief Checks the frequency attributes with that of master HB + * + * @description Invoked by IpcSp for the message type IPC_FREQ_ATTR_DATA + * @param[in] freq_data_obj_ptr -- Pointer to the freq_data structure + * + * @return errlHndl_t + */ + errlHndl_t callCheckFreqAttrData(void *freq_data_obj_ptr) ; + +}; + +#endif diff --git a/src/usr/isteps/istep21/makefile b/src/usr/isteps/istep21/makefile index c905b60ae..121340292 100644 --- a/src/usr/isteps/istep21/makefile +++ b/src/usr/isteps/istep21/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2015,2017 +# Contributors Listed Below - COPYRIGHT 2015,2018 # [+] International Business Machines Corp. # # @@ -36,6 +36,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2/ OBJS += call_host_runtime_setup.o OBJS += call_host_verify_hdat.o +OBJS += freqAttrData.o OBJS += call_host_start_payload.o include ${ROOTPATH}/config.mk diff --git a/src/usr/mbox/ipcSp.C b/src/usr/mbox/ipcSp.C index d2c824f03..f04dc81c8 100644 --- a/src/usr/mbox/ipcSp.C +++ b/src/usr/mbox/ipcSp.C @@ -40,13 +40,17 @@ namespace ISTEP_21 { extern errlHndl_t callShutdown ( uint64_t i_hbInstance, bool i_masterInstance ); + + extern errlHndl_t callCheckFreqAttrData(void *freq_data_obj_ptr); }; + trace_desc_t* g_trac_ipc = NULL; TRAC_INIT(&g_trac_ipc, IPC_TRACE_NAME, KILOBYTE); using namespace IPC; using namespace ERRORLOG; +using namespace TARGETING; IpcSp::IpcSp() : @@ -263,7 +267,79 @@ void IpcSp::msgHandler() } break; } - case IPC_START_PAYLOAD: + + case IPC_FREQ_ATTR_DATA: + { + TRACFCOMP( g_trac_ipc, + "IPC received the IPC_FREQ_ATTR_DATA msg - %d:%d", + msg->data[0], msg->data[1]); + + const int NUM_MOD = 2; + const char * mods[NUM_MOD] = + { "libistep21.so","libruntime.so"}; + bool loaded_mods[NUM_MOD] = {false, false}; + for (auto cnt = 0; cnt < NUM_MOD; ++cnt) + { + if ( !VFS::module_is_loaded( mods[cnt] ) ) + { + err = VFS::module_load( mods[cnt] ); + + if ( err ) + { + TRACFCOMP( g_trac_ipc, + "Could not load %s module", mods[cnt] ); + break; + } + else + { + loaded_mods[cnt] = true; + } + } + } + + if(!err) + { + + // Function will not return unless error + err = ISTEP_21::callCheckFreqAttrData((void *)msg->extra_data); + } + + if (err) + { + uint32_t l_errPlid = err->plid(); + errlCommit(err,IPC_COMP_ID); + INITSERVICE::doShutdown(l_errPlid, true); + } + + //Send response back to the master HB to indicate set freq attr successful + err = MBOX::send(MBOX::HB_FREQ_ATTR_DATA_MSGQ, msg, msg->data[1] ); + + if (err) + { + uint32_t l_errPlid = err->plid(); + errlCommit(err,IPC_COMP_ID); + INITSERVICE::doShutdown(l_errPlid, true); + } + + for (auto cnt = 0; cnt < NUM_MOD; ++cnt) + { + if ( loaded_mods[cnt] ) + { + err = VFS::module_unload( mods[cnt] ); + + if (err) + { + errlCommit(err, IPC_COMP_ID); + } + loaded_mods[cnt] = false; + } + + } + + break; + + } + case IPC_START_PAYLOAD: { const int NUM_MOD = 3; const char * mods[NUM_MOD] = @@ -288,11 +364,8 @@ void IpcSp::msgHandler() } } - if (err) break; - if(!err) { - // Function will not return unless error err = ISTEP_21::callShutdown(msg->data[0],false); } diff --git a/src/usr/mbox/ipcSp.H b/src/usr/mbox/ipcSp.H index 69e9f91e3..1a3ce0045 100644 --- a/src/usr/mbox/ipcSp.H +++ b/src/usr/mbox/ipcSp.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* [+] 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. */ |