summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSwathi Madhuri Bhattiprolu <bhmadhur@in.ibm.com>2018-04-20 06:18:21 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-05-16 12:51:54 -0400
commitb7a44c2259760465b375795baeea883b9f08b44d (patch)
tree94e7071daacc2f8751c9aadc45372c1a07b82c14
parent6855bca779b8435856b0f6881480d7a4ed205b6b (diff)
downloadtalos-hostboot-b7a44c2259760465b375795baeea883b9f08b44d.tar.gz
talos-hostboot-b7a44c2259760465b375795baeea883b9f08b44d.zip
Verify frequency attributes across nodes to match with that of master node
-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: Ia1daf1f0eeb90fbafb68417b979488b040efe535 RTC:158036 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57542 Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@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: Roland Veloz <rveloz@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/include/usr/hwas/common/hwasCallout.H7
-rw-r--r--src/include/usr/isteps/istep_reasoncodes.H8
-rw-r--r--src/include/usr/mbox/ipc_msg_types.H1
-rw-r--r--src/include/usr/mbox/mbox_queues.H1
-rw-r--r--src/usr/isteps/istep21/call_host_runtime_setup.C15
-rw-r--r--src/usr/isteps/istep21/freqAttrData.C765
-rw-r--r--src/usr/isteps/istep21/freqAttrData.H120
-rw-r--r--src/usr/isteps/istep21/makefile1
-rw-r--r--src/usr/mbox/ipcSp.C84
9 files changed, 1002 insertions, 0 deletions
diff --git a/src/include/usr/hwas/common/hwasCallout.H b/src/include/usr/hwas/common/hwasCallout.H
index c5fbf2f21..a74330aaf 100644
--- a/src/include/usr/hwas/common/hwasCallout.H
+++ b/src/include/usr/hwas/common/hwasCallout.H
@@ -61,6 +61,13 @@ typedef enum {
GARD_Void = 0xFF
} GARD_ErrorType;
+// Used in EPUB_PRC_INVALID_PART
+// userdata 3 of the SRC
+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/istep_reasoncodes.H b/src/include/usr/isteps/istep_reasoncodes.H
index 1595210e3..aa63ce0d8 100644
--- a/src/include/usr/isteps/istep_reasoncodes.H
+++ b/src/include/usr/isteps/istep_reasoncodes.H
@@ -61,6 +61,7 @@ namespace ISTEP
MOD_OCC_XSTOP_HANDLER = 0x1E,
MOD_VERIFY_AND_MOVE_PAYLOAD = 0x1F,
MOD_REDISCOVER_I2C_TARGETS = 0x20,
+ MOD_FREQ_ATTR_DATA = 0x21,
};
/**
@@ -118,6 +119,13 @@ namespace ISTEP
RC_FAILED_TO_BOOT_SBE = ISTEP_COMP_ID | 0x38,
RC_REDISCOVERED_TARGETS = ISTEP_COMP_ID | 0x39,
RC_HDAT_SIZE_CHECK_FAILED = ISTEP_COMP_ID | 0x3A,
+ RC_FREQ_ATTR_TIMER_EXPIRED = ISTEP_COMP_ID | 0x40,
+ RC_FREQ_ATTR_TIMER_THREAD_FAIL = ISTEP_COMP_ID | 0x41,
+ RC_FLOOR_FREQ_MISMATCH = ISTEP_COMP_ID | 0x42,
+ RC_CEIL_FREQ_MISMATCH = ISTEP_COMP_ID | 0x43,
+ RC_TURBO_FREQ_MISMATCH = ISTEP_COMP_ID | 0x44,
+ RC_ULTRA_TURBO_FREQ_MISMATCH = ISTEP_COMP_ID | 0x45,
+ RC_NEST_FREQ_MISMATCH = ISTEP_COMP_ID | 0x46,
};
};
diff --git a/src/include/usr/mbox/ipc_msg_types.H b/src/include/usr/mbox/ipc_msg_types.H
index 6a907ed8d..ee0896348 100644
--- a/src/include/usr/mbox/ipc_msg_types.H
+++ b/src/include/usr/mbox/ipc_msg_types.H
@@ -41,6 +41,7 @@ namespace IPC
IPC_SET_SBE_CHIPINFO,
IPC_CLOSE_TCES,
IPC_POPULATE_TPM_INFO_BY_NODE,
+ 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 882aad2b4..3b3b6ba10 100644
--- a/src/include/usr/mbox/mbox_queues.H
+++ b/src/include/usr/mbox/mbox_queues.H
@@ -56,6 +56,7 @@ namespace MBOX
HB_SBE_SYSCONFIG_MSGQ = 12, //For SBE System Config response
HB_CLOSE_TCES_MSGQ = 13, // close/disable TCEs
HB_POP_TPM_INFO_MSGQ = 14, // response to populate TPM info by node
+ HB_FREQ_ATTR_DATA_MSGQ = 15, // 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_runtime_setup.C b/src/usr/isteps/istep21/call_host_runtime_setup.C
index 237f45691..a509feafe 100644
--- a/src/usr/isteps/istep21/call_host_runtime_setup.C
+++ b/src/usr/isteps/istep21/call_host_runtime_setup.C
@@ -53,6 +53,8 @@
#include <hbotcompid.H>
+#include "freqAttrData.H"
+
#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS
#include <isteps/pm/occAccess.H>
#include <isteps/pm/occCheckstop.H>
@@ -593,6 +595,19 @@ void* call_host_runtime_setup (void *io_pArgs)
do
{
+ // Send the master node frequency attribute info
+ // to slave nodes
+ l_err = sendFreqAttrData();
+
+ if(l_err)
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_runtime_setup: ERROR: sendFreqAttrData Failed");
+
+ // break from do loop if error occurred
+ break;
+ }
+
// Close PAYLOAD TCEs
if (TCE::utilUseTcesForDmas())
{
diff --git a/src/usr/isteps/istep21/freqAttrData.C b/src/usr/isteps/istep21/freqAttrData.C
new file mode 100644
index 000000000..9dc60bfff
--- /dev/null
+++ b/src/usr/isteps/istep21/freqAttrData.C
@@ -0,0 +1,765 @@
+/* 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>
+#include <errl/errlreasoncodes.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 {
+
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "sendFreqAttrData" );
+
+ 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);
+
+ uint32_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)
+ {
+ // Single node system
+ break;
+ }
+
+ // 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, "sendFreqAttrData 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};
+
+ // Fill in the frequency attribute data of master node
+ // Copy the master node frequency data into two uint64_t
+ // so that this data will be sent to the slaves using IPC below
+ 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>();
+
+ // 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 (uint32_t l_node=0; (l_node < MAX_NODES_PER_SYS ); l_node++ )
+ {
+ // skip sending to ourselves
+ if(l_node == nodeid)
+ {
+ continue;
+ }
+
+ if( 0 != ((mask >> l_node) & hb_images ) )
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "send IPC_FREQ_ATTR_DATA "
+ "message to node %d",l_node );
+
+
+ msg_t * msg = msg_allocate();
+
+ msg->type = IPC::IPC_FREQ_ATTR_DATA;
+
+ // pack destination node and master node in msg->data[0]
+ msg->data[0] = TWO_UINT32_TO_UINT64(l_node, nodeid);
+
+ msg->data[1] = freq_data_obj.freqData1;
+
+ msg->extra_data = reinterpret_cast<uint64_t*>(freq_data_obj.freqData2);
+
+ // 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)
+ {
+ break;
+ }
+ //wait for all hb images to respond
+ //want to spawn a timer thread
+ l_progTid = task_create(sendFreqAttrData_timer,&msgQ);
+
+ assert( l_progTid > 0 ,"sendFreqAttrData_timer failed");
+
+ while(msg_count)
+ {
+ msg_t* response = msg_wait(msgQ);
+
+ if (response->type == HB_FREQ_ATTR_DATA_TIMER_MSG)
+ {
+ if (response->data[1] == TIME_EXPIRED)
+ {
+ //timer has expired
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "IPC_FREQ_ATTR_DATA failed to "
+ "receive messages from all hb images in time" );
+ //tell the timer thread to exit
+ response->data[1] = HB_FREQ_ATTR_DATA_MSG_DONE;
+ msg_respond(msgQ,response);
+
+ // @Todo RTRC:192370 Add node specific info
+ // Include the number of nodes, number of non-responses (bit masks)
+ // to know exactly which nodes didn't answer and which did
+
+ //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( response->data[1] == CONTINUE_WAIT_FOR_MSGS)
+ {
+ response->data[1] = HB_FREQ_ATTR_DATA_WAITING_FOR_MSG;
+ msg_respond(msgQ,response);
+ }
+ }
+ else if (response->type == IPC::IPC_FREQ_ATTR_DATA)
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "sendFreqAttrData Got response from node %d", response->data[0]>>32 );
+ --msg_count;
+ msg_free(response);
+ }
+ else
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "sendFreqAttrData_timer : unexpected message from drawer %d ",
+ response->data[0]>>32);
+ }
+
+ }
+
+ 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.
+ //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)
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "IPC_FREQ_ATTR_DATA msg_count: %d", msg_count);
+
+ msg_t* response = msg_wait(msgQ);
+
+ if (response->type == HB_FREQ_ATTR_DATA_TIMER_MSG)
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "IPC_FREQ_ATTR_DATA received from all hb "
+ "images in time");
+
+ response->data[1] = HB_FREQ_ATTR_DATA_MSG_DONE;
+ msg_respond(msgQ,response);
+ }
+ }
+
+ //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(uint64_t freqData1, uint64_t freqData2)
+{
+ TARGETING::Target * sys = nullptr;
+ errlHndl_t l_elog = nullptr;
+ freq_data freq_data_obj{0};
+ ISTEP_ERROR::IStepError l_stepError;
+ uint16_t errCaseId = 0xFF;
+ freq_data master_freq_data_obj{0};
+
+ TARGETING::targetService().getTopLevelTarget( sys );
+ assert(sys != nullptr);
+
+ master_freq_data_obj.freqData1 = freqData1;
+ master_freq_data_obj.freqData2 = freqData2;
+
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "callCheckFreqAttrData - Mater Freq Data: 0x%016lx 0x%016lx",
+ freqData1, freqData2);
+
+
+
+ // 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.powerModeNom )||
+ (freq_data_obj.powerModeTurbo != master_freq_data_obj.powerModeTurbo ))
+ {
+ errCaseId = 0;
+ }
+ else if(freq_data_obj.nominalFreq != master_freq_data_obj.nominalFreq )
+ {
+ errCaseId = 1;
+ }
+ else if(freq_data_obj.floorFreq != master_freq_data_obj.floorFreq )
+ {
+ errCaseId = 2;
+ }
+ else if(freq_data_obj.ceilingFreq != master_freq_data_obj.ceilingFreq )
+ {
+ errCaseId = 3;
+ }
+ else if(freq_data_obj.ultraTurboFreq != master_freq_data_obj.ultraTurboFreq )
+ {
+ errCaseId = 4;
+ }
+ else if(freq_data_obj.turboFreq != master_freq_data_obj.turboFreq )
+ {
+ errCaseId = 5;
+ }
+ else if(freq_data_obj.nestFreq != master_freq_data_obj.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.powerModeNom,
+ freq_data_obj.powerModeNom,
+ master_freq_data_obj.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.powerModeNom,
+ freq_data_obj.powerModeNom),
+ TWO_UINT32_TO_UINT64(
+ master_freq_data_obj.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.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.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.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.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.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.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.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.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.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.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.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.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");
+
+ l_elog->addFFDC(ISTEP_COMP_ID,
+ &master_freq_data_obj,
+ sizeof(freq_data),
+ 0, // Version
+ ERRL_UDT_CALLOUT,
+ false);
+
+ l_elog->addFFDC(ISTEP_COMP_ID,
+ &freq_data_obj,
+ sizeof(freq_data),
+ 0, // Version
+ ERRL_UDT_CALLOUT,
+ false);
+
+ // Create IStep error log and
+ // cross reference occurred error
+ l_stepError.addErrorDetails( l_elog );
+ }
+ }while(0);
+
+ return l_elog;
+
+}
+
+}
diff --git a/src/usr/isteps/istep21/freqAttrData.H b/src/usr/isteps/istep21/freqAttrData.H
new file mode 100644
index 000000000..d46ad4e84
--- /dev/null
+++ b/src/usr/isteps/istep21/freqAttrData.H
@@ -0,0 +1,120 @@
+/* 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 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 = 0xA3,
+ };
+
+ /**
+ * @brief structure to hold frequency attribute data
+ *
+ */
+ typedef union
+ {
+ struct{
+ uint16_t nominalFreq; //ATTR_NOMINAL_FREQ_MHZ
+ uint16_t floorFreq; //ATTR_FREQ_FLOOR_MHZ
+ uint16_t ceilingFreq ; //ATTR_FREQ_CORE_CEILING_MHZ
+ uint16_t ultraTurboFreq; //ATTR_ULTRA_TURBO_FREQ_MHZ
+ uint16_t turboFreq; //ATTR_FREQ_CORE_MAX
+ uint16_t nestFreq; //ATTR_FREQ_PB_MHZ
+ uint16_t powerModeNom; //ATTR_SOCKET_POWER_NOMINAL
+ uint16_t powerModeTurbo; //ATTR_SOCKET_POWER_TURBO
+ };
+
+ struct {
+ uint64_t freqData1;
+ uint64_t freqData2;
+ };
+
+ }freq_data;
+
+
+
+ /**
+ * @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] uint64_t freqData1, freqData2 frequency attribute data
+ *
+ * @return errlHndl_t
+ */
+ errlHndl_t callCheckFreqAttrData( uint64_t freqData1, uint64_t freqData2) ;
+
+};
+
+#endif
diff --git a/src/usr/isteps/istep21/makefile b/src/usr/isteps/istep21/makefile
index 0d5a5d171..e89430c98 100644
--- a/src/usr/isteps/istep21/makefile
+++ b/src/usr/isteps/istep21/makefile
@@ -35,6 +35,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include/
EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2/
OBJS += call_host_runtime_setup.o
+OBJS += freqAttrData.o
OBJS += call_host_verify_hdat.o
OBJS += call_host_start_payload.o
diff --git a/src/usr/mbox/ipcSp.C b/src/usr/mbox/ipcSp.C
index f456ead91..d0110db98 100644
--- a/src/usr/mbox/ipcSp.C
+++ b/src/usr/mbox/ipcSp.C
@@ -41,6 +41,8 @@ namespace ISTEP_21
extern errlHndl_t callShutdown ( uint64_t i_hbInstance,
bool i_masterInstance,
const uint64_t i_commBase );
+
+ extern errlHndl_t callCheckFreqAttrData(uint64_t freqData1, uint64_t freqData2);
};
trace_desc_t* g_trac_ipc = NULL;
@@ -48,6 +50,7 @@ TRAC_INIT(&g_trac_ipc, IPC_TRACE_NAME, KILOBYTE);
using namespace IPC;
using namespace ERRORLOG;
+using namespace TARGETING;
IpcSp::IpcSp()
:
@@ -328,6 +331,87 @@ void IpcSp::msgHandler()
break;
}
+ case IPC_FREQ_ATTR_DATA:
+ {
+
+ TRACFCOMP( g_trac_ipc,
+ "IPC received the IPC_FREQ_ATTR_DATA msg - %u:%u",
+ msg->data[0]>>32, (msg->data[0]& 0xFFFFFFFF));
+
+ 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)
+ {
+ uint64_t l_freqData1 =
+ reinterpret_cast<uint64_t>(msg->data[1]);
+
+ uint64_t l_freqData2 =
+ reinterpret_cast<uint64_t>(msg->extra_data);
+
+ // Function checks frequency attribute data. Returns an error
+ // if there is a mismatch with that of HB master data
+ err = ISTEP_21::callCheckFreqAttrData(l_freqData1, l_freqData2);
+ }
+
+ 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;
+ }
+
+ }
+
+ //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[0]& 0xFFFFFFFF) );
+
+ if (err)
+ {
+ uint32_t l_errPlid = err->plid();
+ errlCommit(err,IPC_COMP_ID);
+ INITSERVICE::doShutdown(l_errPlid, true);
+ }
+
+
+
+ break;
+
+ }
+
case IPC_START_PAYLOAD:
{
const int NUM_MOD = 4;
OpenPOWER on IntegriCloud