summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSwathi Madhuri Bhattiprolu <bhmadhur@in.ibm.com>2018-02-28 07:08:54 -0600
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2018-04-05 14:34:23 -0400
commit571e1d84dfe50aaa674aa7e33abb75868b432d78 (patch)
tree2ab7eb56240999e074be13138d7d2ac5e24802cc
parentad4459feb84ab2a4ec9f512b220a9aa67be858c8 (diff)
downloadtalos-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.H8
-rw-r--r--src/include/usr/isteps/hwpf_reasoncodes.H2
-rw-r--r--src/include/usr/isteps/istep_reasoncodes.H10
-rw-r--r--src/include/usr/mbox/ipc_msg_types.H2
-rw-r--r--src/include/usr/mbox/mbox_queues.H1
-rw-r--r--src/usr/isteps/istep21/call_host_start_payload.C14
-rw-r--r--src/usr/isteps/istep21/freqAttrData.C716
-rw-r--r--src/usr/isteps/istep21/freqAttrData.H112
-rw-r--r--src/usr/isteps/istep21/makefile3
-rw-r--r--src/usr/mbox/ipcSp.C81
-rw-r--r--src/usr/mbox/ipcSp.H4
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. */
OpenPOWER on IntegriCloud