summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/mbox/ipc_msg_types.H6
-rw-r--r--src/include/usr/mbox/mbox_queues.H1
-rw-r--r--src/include/usr/runtime/runtime.H57
-rw-r--r--src/include/usr/runtime/runtime_reasoncodes.H3
-rw-r--r--src/usr/isteps/istep21/call_host_runtime_setup.C64
-rw-r--r--src/usr/mbox/ipcSp.C91
-rw-r--r--src/usr/runtime/populate_hbruntime.C424
7 files changed, 586 insertions, 60 deletions
diff --git a/src/include/usr/mbox/ipc_msg_types.H b/src/include/usr/mbox/ipc_msg_types.H
index 543f7269c..c2d4d623a 100644
--- a/src/include/usr/mbox/ipc_msg_types.H
+++ b/src/include/usr/mbox/ipc_msg_types.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. */
@@ -35,6 +37,8 @@ namespace IPC
IPC_POPULATE_ATTRIBUTES = MBOX::FIRST_SECURE_MSG + 1,
IPC_TEST_CONNECTION = MBOX::FIRST_SECURE_MSG + 2,
IPC_START_PAYLOAD,
+ IPC_QUERY_CHIPINFO,
+ IPC_SET_SBE_CHIPINFO,
};
}; // namespace IPC
diff --git a/src/include/usr/mbox/mbox_queues.H b/src/include/usr/mbox/mbox_queues.H
index ec02dada0..20f957038 100644
--- a/src/include/usr/mbox/mbox_queues.H
+++ b/src/include/usr/mbox/mbox_queues.H
@@ -53,6 +53,7 @@ namespace MBOX
HB_IPC_MSGQ = 9, //For inter-drawer HB messages
HB_POP_ATTR_MSGQ = 10, // populate Attribute response
HB_COALESCE_MSGQ = 11, //host_coalesce response
+ HB_SBE_SYSCONFIG_MSGQ = 12, //For SBE System Config response
// 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/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H
index 855ef86ac..fdb8e9a49 100644
--- a/src/include/usr/runtime/runtime.H
+++ b/src/include/usr/runtime/runtime.H
@@ -35,7 +35,28 @@
namespace RUNTIME
{
+ /******************************************************************************/
+ // Globals/Constants
+ /******************************************************************************/
+ constexpr uint8_t HB_SBE_WAITING_FOR_MSG = 0x0;
+ constexpr uint8_t HB_SBE_MSG_DONE = 0x1;
+ constexpr uint32_t MAX_TIME_ALLOWED_MS = 10000;
+ // NUMBER_OF_POSSIBLE_DRAWERS definition here should be in sync with
+ // src/usr/isteps/istep18/establish_system_smp.H's definition of the same constant.
+ constexpr uint8_t NUMBER_OF_POSSIBLE_DRAWERS = 8;
+ constexpr uint8_t MAX_PROCS_PER_NODE = 8;
+ constexpr uint8_t CONTINUE_WAIT_FOR_MSGS = 0x2;
+ constexpr uint8_t TIME_EXPIRED=0x3;
+
+
+/**
+ * enum used for sending messages within sendSBEsystemConfig
+ */
+ enum
+ {
+ HB_SBE_SYSCONFIG_TIMER_MSG = 0xA2,
+ };
/**
* @brief Add the host data mainstore location to VMM
*
@@ -106,6 +127,42 @@ errlHndl_t populate_hbTpmInfo( void );
*/
errlHndl_t populate_TpmInfoByNode();
+/**
+ * @brief Timer function for safe error handling in sendSBESystemConfig
+ *
+ * @description Used inside the sendSBEsystemConfig() to wait for
+ * responses from other nodes
+ * @param[in] i_msgQPtr -- Pointer to the Message Queue to wait for messages
+ *
+ * @return void
+ */
+void* sendSBEsystemConfig_timer(void* i_msgQPtr);
+
+/**
+ * @brief Waits and Collects responses from all drawers
+ *
+ * @description Used inside the sendSBEsystemConfig() to wait and
+ * collect responses from other nodes
+ * @param[in] i_msgQPtr -- Pointer to the Message Queue to wait for messages
+ * @param[in] i_msgCount -- Number of messages to wait for
+ * @param[in] i_msgType -- Type of the message to wait for
+ * @param[in, out] i_systemFabricConfigurationMap -- to consolidate node info from all nodes
+ *
+ * @return void
+ */
+errlHndl_t collectRespFromAllDrawers( void* i_msgQPtr, uint64_t i_msgCount, uint32_t i_msgType, uint64_t& i_systemFabricConfigurationMap );
+
+/**
+ * @brief Sends the chip config down to the SBEs
+ *
+ * @description Determines the system wide chip information to send to
+ * the SBE so it knows which chips are present for syncing with in MPIPL.
+ * Uses IPC to communication between HB instances if multinode
+ *
+ * @return errlHndl_t nullptr on success else pointer to error log
+ */
+errlHndl_t sendSBESystemConfig();
+
// How many pointers/sections there are in HB runtime data
#define HBRT_NUM_PTRS 2
diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H
index 3937e553f..12d9db472 100644
--- a/src/include/usr/runtime/runtime_reasoncodes.H
+++ b/src/include/usr/runtime/runtime_reasoncodes.H
@@ -59,6 +59,7 @@ namespace RUNTIME
MOD_POPULATE_TPMINFOBYNODE = 0x19, /**< populate_hbruntime.C */
MOD_FILL_RSVMEM_HBDATA = 0x20, /**< populate_hbruntime.C */
MOD_ATTR_RUNTIME_CHECK_PREP_FAIL = 0x21, /**< populate_hbruntime.C */
+ MOD_SEND_SBE_SYSCONFIG = 0x22, /**< populate_hbruntime.C */
MOD_RT_FIRMWARE_NOTIFY = 0x23, /**< rt_fwnotify.C */
MOD_RT_FIRMWARE_REQUEST = 0x24, /**< rt_fwreq_helper.C */
MOD_RT_ATTR_SYNC_REQUEST = 0x25, /**< rt_fwnotify.C */
@@ -129,6 +130,8 @@ namespace RUNTIME
RC_TPM_HDAT_MAP_BLOCK_ERR = RUNTIME_COMP_ID | 0x3B,
RC_ATTR_UPDATE_FAILED = RUNTIME_COMP_ID | 0x3C,
RC_HB_RES_MEM_EXCEEDED = RUNTIME_COMP_ID | 0x3D,
+ RC_SEND_SBE_TIMER_EXPIRED = RUNTIME_COMP_ID | 0x3E,
+ RC_HOST_TIMER_THREAD_FAIL = RUNTIME_COMP_ID | 0x3F,
};
enum UserDetailsTypes
diff --git a/src/usr/isteps/istep21/call_host_runtime_setup.C b/src/usr/isteps/istep21/call_host_runtime_setup.C
index ab9fd21d0..bad88d537 100644
--- a/src/usr/isteps/istep21/call_host_runtime_setup.C
+++ b/src/usr/isteps/istep21/call_host_runtime_setup.C
@@ -457,62 +457,6 @@ void* call_host_runtime_setup (void *io_pArgs)
}
}
- //Need to send System Configuration down to SBE
- //Use targeting code to get a list of all processors
- TARGETING::TargetHandleList l_procChips;
- getAllChips( l_procChips, TARGETING::TYPE_PROC , true);
- uint64_t l_systemFabricConfigurationMap = 0x0;
-
-
- for(auto l_proc : l_procChips)
- {
- //Get fabric info from proc
- uint8_t l_fabricChipId =
- l_proc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
- uint8_t l_fabricGroupId =
- l_proc->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>();
- //Calculate what bit position this will be
- uint8_t l_bitPos = l_fabricChipId + (8 * l_fabricGroupId);
-
- //Set the bit @ l_bitPos to be 1 because this is a functional proc
- l_systemFabricConfigurationMap |= (0x8000000000000000 >> l_bitPos);
- }
-
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "Setting sending systemConfig to all Procs...");
-
- for(auto l_proc : l_procChips)
- {
- TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "calling sendSystemConfig on proc 0x%x",
- l_proc->getAttr<TARGETING::ATTR_POSITION>());
- l_err = SBEIO::sendSystemConfig(l_systemFabricConfigurationMap,
- l_proc);
- if ( l_err )
- {
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "sendSystemConfig ERROR : Error sending sbe chip-op to proc 0x%.8X. Returning errorlog, reason=0x%x",
- TARGETING::get_huid(l_proc),
- l_err->reasonCode() );
- break;
- }
- else
- {
- TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "sendSystemConfig SUCCESS" );
- }
- }
-
- if(l_err)
- {
- break;
- }
- else
- {
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "Successfully sent all system configs to procs via SBE chip op !!");
- }
-
// Need to load up the runtime module if it isn't already loaded
if ( !VFS::module_is_loaded( "libruntime.so" ) )
{
@@ -528,6 +472,14 @@ void* call_host_runtime_setup (void *io_pArgs)
}
}
+ //Need to send System Configuration down to SBE for all HB
+ //instances
+ l_err = RUNTIME::sendSBESystemConfig();
+ if(l_err)
+ {
+ break;
+ }
+
// Configure the ATTR_HBRT_HYP_ID attributes so that runtime code and
// whichever hypervisor is loaded can reference equivalent targets
l_err = RUNTIME::configureHbrtHypIds(TARGETING::is_phyp_load());
diff --git a/src/usr/mbox/ipcSp.C b/src/usr/mbox/ipcSp.C
index f38b92454..5878a1bf1 100644
--- a/src/usr/mbox/ipcSp.C
+++ b/src/usr/mbox/ipcSp.C
@@ -32,6 +32,8 @@
#include <mbox/mbox_reasoncodes.H>
#include <intr/interrupt.H>
#include <initservice/initserviceif.H>
+#include <sbeio/sbeioif.H>
+
namespace ISTEP_21
{
@@ -173,7 +175,94 @@ void IpcSp::msgHandler()
}
break;
- case IPC_START_PAYLOAD:
+ case IPC_QUERY_CHIPINFO:
+ {
+ TARGETING::TargetHandleList l_procChips;
+ getAllChips( l_procChips, TARGETING::TYPE_PROC , true);
+ uint64_t l_systemFabricConfigurationMap = 0x0;
+ for(auto l_proc : l_procChips)
+ {
+ //Get fabric info from proc
+ uint8_t l_fabricChipId =
+ l_proc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+ uint8_t l_fabricGroupId =
+ l_proc->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>();
+ //Calculate what bit position this will be
+ uint8_t l_bitPos = l_fabricChipId + (RUNTIME::MAX_PROCS_PER_NODE * l_fabricGroupId);
+
+ //Set the bit @ l_bitPos to be 1 because this is a functional proc
+ l_systemFabricConfigurationMap |= (0x8000000000000000 >> l_bitPos);
+ }
+
+ TRACFCOMP( g_trac_ipc,
+ "IPC Query ChipInfo 0x%lx", l_systemFabricConfigurationMap);
+
+ //Send a response with this HB instances chip info
+ msg->extra_data = reinterpret_cast<uint64_t*>(l_systemFabricConfigurationMap);
+ err = MBOX::send(MBOX::HB_SBE_SYSCONFIG_MSGQ, msg, msg->data[1] );
+ if (err)
+ {
+ uint32_t l_errPlid = err->plid();
+ errlCommit(err,IPC_COMP_ID);
+ INITSERVICE::doShutdown(l_errPlid, true);
+ }
+ break;
+ }
+ case IPC_SET_SBE_CHIPINFO:
+ {
+ //Need to send System Configuration down to SBE
+ //Master sends info to set into SBE via msg->extra_data
+ uint64_t l_systemFabricConfigurationMap =
+ reinterpret_cast<uint64_t>(msg->extra_data);
+
+ TRACFCOMP( g_trac_ipc,
+ "sending systemConfig[0x%lx] to SBEs",
+ l_systemFabricConfigurationMap);
+
+ TARGETING::TargetHandleList l_procChips;
+ getAllChips( l_procChips, TARGETING::TYPE_PROC , true);
+ for(auto l_proc : l_procChips)
+ {
+ TRACDCOMP( g_trac_ipc,
+ "calling sendSystemConfig on proc 0x%x",
+ TARGETING::get_huid(l_proc));
+ err = SBEIO::sendSystemConfig(l_systemFabricConfigurationMap,
+ l_proc);
+ if ( err )
+ {
+ TRACFCOMP( g_trac_ipc,
+ "sendSystemConfig ERROR : Error sending sbe chip-op to proc 0x%.8X. Returning errorlog, reason=0x%x",
+ TARGETING::get_huid(l_proc),
+ err->reasonCode() );
+ break;
+ }
+ }
+
+ //If error terminate here
+ if(err)
+ {
+ TRACFCOMP( g_trac_ipc, "In ipcSp: SBEIO::sendSystemConfig errored - must shutdown now!!!");
+ uint32_t l_errPlid = err->plid();
+ errlCommit(err, IPC_COMP_ID);
+ INITSERVICE::doShutdown(l_errPlid, true);
+ }
+ else
+ {
+ TRACFCOMP( g_trac_ipc,
+ "Successfully sent all system configs to procs via SBE chip op !!");
+ }
+
+ //Send response back to the master HB to indicate successful configuration down to SBE
+ err = MBOX::send(MBOX::HB_SBE_SYSCONFIG_MSGQ, msg, msg->data[1] );
+ 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 = 3;
const char * mods[NUM_MOD] =
diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C
index a7ec23403..437db6f74 100644
--- a/src/usr/runtime/populate_hbruntime.C
+++ b/src/usr/runtime/populate_hbruntime.C
@@ -1254,11 +1254,17 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId, bool i_master_node)
// Align size for OPAL
size_t l_secRomSizeAligned = ALIGN_X(l_secureRomSize,
HBRT_RSVD_MEM_OPAL_ALIGN);
+ // @TODO: RTC:183697 determine if OPAL can also use the
+ // actual size and remove the need for l_hdatEntrySize
+ // Size to add to HDAT entry
+ size_t l_hdatEntrySize = l_secRomSizeAligned;
uint64_t l_secureRomAddr = 0x0;
if(TARGETING::is_phyp_load())
{
l_secureRomAddr = l_prevDataAddr + l_prevDataSize;
+ // Specify actual size in HDAT entry for POWERVM
+ l_hdatEntrySize = l_secureRomSize;
}
else if(TARGETING::is_sapphire_load())
{
@@ -1268,7 +1274,7 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId, bool i_master_node)
l_elog = setNextHbRsvMemEntry(HDAT::RHB_TYPE_SECUREBOOT,
i_nodeId,
l_secureRomAddr,
- l_secureRomSize,
+ l_hdatEntrySize,
HBRT_RSVD_MEM__SECUREBOOT);
if(l_elog)
{
@@ -1276,7 +1282,7 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId, bool i_master_node)
}
l_prevDataAddr = l_secureRomAddr;
- l_prevDataSize = l_secureRomSize;
+ l_prevDataSize = l_secRomSizeAligned;
// Load the Cached SecureROM into memory
l_elog = mapPhysAddr(l_secureRomAddr, l_secureRomSize, l_vAddr);
@@ -2393,6 +2399,419 @@ errlHndl_t populate_hbTpmInfo()
return (l_elog);
} // end populate_hbTpmInfo
+//******************************************************************************
+//sendSBEsystemConfig_timer function
+//Used inside the sendSBEsystemConfig() to wait for responses from other nodes
+//******************************************************************************
+void* sendSBEsystemConfig_timer(void* i_msgQPtr)
+
+{
+ int rc=0;
+
+ msg_t* msg = msg_allocate();
+ msg->type = HB_SBE_SYSCONFIG_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_SBE_MSG_DONE message
+
+ do
+ {
+ if (l_time_ms < MAX_TIME_ALLOWED_MS)
+ {
+ msg->data[1] = CONTINUE_WAIT_FOR_MSGS;
+ }
+ else
+ {
+ // HB_SBE_SYSCONFIG_TIMER_MSG is sent to the main thread indicating
+ // timer expired so the main thread responds back with HB_SBE_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( g_trac_runtime,
+ "sendSBEsystemConfig timer failed msg sendrecv %d",rc);
+ }
+ if (msg->data[1] == HB_SBE_MSG_DONE)
+ {
+ TRACFCOMP( g_trac_runtime,
+ "sendSBEsystemConfig timer not needed.");
+ break;
+ }
+
+ nanosleep(0,NS_PER_MSEC);
+ l_time_ms++;
+
+ }while(1);
+
+ msg_free(msg);
+
+ return NULL;
+}
+
+//******************************************************************************
+//collectRespFromAllDrawers function
+//Used inside the sendSBEsystemConfig() to wait and collect responses from
+//all other drawers
+//******************************************************************************
+errlHndl_t collectRespFromAllDrawers( void* i_msgQPtr, uint64_t i_msgCount,
+ uint32_t i_msgType,
+ uint64_t& i_systemFabricConfigurationMap )
+{
+ errlHndl_t l_elog = nullptr;
+ uint64_t msg_count = i_msgCount;
+ msg_q_t* msgQ = static_cast<msg_q_t*>(i_msgQPtr);
+
+ //wait for all hb images to respond
+ //want to spawn a timer thread
+ tid_t l_progTid = task_create(
+ RUNTIME::sendSBEsystemConfig_timer,msgQ);
+ assert( l_progTid > 0 ,"sendSBEsystemConfig_timer failed");
+ while(msg_count)
+ {
+ msg_t* response = msg_wait(*msgQ);
+
+ if (response->type == HB_SBE_SYSCONFIG_TIMER_MSG)
+ {
+ if (response->data[1] == TIME_EXPIRED)
+ {
+ //timer has expired
+ TRACFCOMP( g_trac_runtime,
+ "collectRespFromAllDrawers failed to "
+ "receive messages from all hb images in time" );
+ //tell the timer thread to exit
+ response->data[1] = HB_SBE_MSG_DONE;
+ msg_respond(*msgQ,response);
+
+ //generate an errorlog
+ /*@
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid RUNTIME::MOD_SEND_SBE_SYSCONFIG,
+ * @reasoncode RUNTIME::RC_SEND_SBE_TIMER_EXPIRED,
+ * @userdata1 Message Type IPC_QUERY_CHIPINFO or
+ * IPC_SET_SBE_CHIPINFO
+ * @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,
+ RUNTIME::MOD_SEND_SBE_SYSCONFIG,
+ RUNTIME::RC_SEND_SBE_TIMER_EXPIRED,
+ i_msgType,
+ msg_count );
+ l_elog->collectTrace(RUNTIME_COMP_NAME);
+ l_elog->collectTrace("IPC");
+ l_elog->collectTrace("MBOXMSG");
+ //Commit the Error log
+ errlCommit(l_elog,RUNTIME_COMP_ID);
+ // Break the While loop and wait for the child thread to exit
+ break;
+
+ }
+ else if( response->data[1] == CONTINUE_WAIT_FOR_MSGS)
+ {
+ TRACFCOMP( g_trac_runtime,
+ "collectRespFromAllDrawers timer continue waiting message.");
+ response->data[1] =HB_SBE_WAITING_FOR_MSG;
+ msg_respond(*msgQ,response);
+ }
+ }
+ else if (response->type == IPC::IPC_QUERY_CHIPINFO)
+ {
+ uint64_t l_nodeInfo =
+ reinterpret_cast<uint64_t>(response->extra_data);
+
+
+ //Process msg, if we are waiting for IPC_QUERY_CHIPINFO response.
+ if (i_msgType == IPC::IPC_QUERY_CHIPINFO)
+ {
+ TRACFCOMP(g_trac_runtime,
+ "IPC_QUERY_CHIPINFO : drawer %d completed info 0x%lx",
+ response->data[0], l_nodeInfo);
+ //Apend the nodeInfo to be used in sendSBESystemConfig
+ i_systemFabricConfigurationMap |= l_nodeInfo;
+ --msg_count;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_runtime,
+ "IPC_QUERY_CHIPINFO : unexpected message from drawer %d ",
+ response->data[0]);
+ }
+
+ msg_free(response);
+
+ }
+ else if (response->type == IPC::IPC_SET_SBE_CHIPINFO)
+ {
+ //Process msg, if we are waiting for IPC_SET_SBE_CHIPINFO response.
+ if (i_msgType == IPC::IPC_SET_SBE_CHIPINFO)
+ {
+ TRACFCOMP(g_trac_runtime,
+ "IPC_SET_SBE_CHIPINFO : drawer %d completed",
+ response->data[0]);
+ --msg_count;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_runtime,
+ "IPC_SET_SBE_CHIPINFO : unexpected message from drawer %d ",
+ response->data[0]);
+ }
+
+ msg_free(response);
+ }
+ }
+
+ //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
+
+ //tell the child timer thread to exit if didn't
+ //already timeout
+ if (msg_count ==0)
+ {
+ msg_t* response = msg_wait(*msgQ);
+ if (response->type == HB_SBE_SYSCONFIG_TIMER_MSG)
+ {
+ TRACFCOMP( g_trac_runtime,
+ "collectRespFromAllDrawers received all hb "
+ "images in time for message type %d",i_msgType);
+
+ response->data[1] = HB_SBE_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( g_trac_runtime,
+ "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 RUNTIME::MOD_SEND_SBE_SYSCONFIG,
+ * @reasoncode RUNTIME::RC_HOST_TIMER_THREAD_FAIL,,
+ * @userdata1 l_tidretrc,
+ * @userdata2 l_childsts,
+ *
+ * @devdesc sendSBESystemConfig timer thread
+ * failed
+ */
+ l_elog = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ RUNTIME::MOD_SEND_SBE_SYSCONFIG,
+ RUNTIME::RC_HOST_TIMER_THREAD_FAIL,
+ l_tidretrc,
+ l_childsts);
+
+ l_elog->collectTrace(RUNTIME_COMP_NAME);
+ return l_elog;
+ }
+
+ return(l_elog);
+
+}
+// Sends the chip config down to the SBEs
+// Determines the system wide chip information to send to
+// the SBE so it knows which chips are present for syncing with in MPIPL.
+// Uses IPC to communication between HB instances if multinode
+errlHndl_t sendSBESystemConfig( void )
+{
+ errlHndl_t l_elog = nullptr;
+ uint64_t l_systemFabricConfigurationMap = 0x0;
+
+
+ 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;
+
+
+ //Determine this HB Instance SBE config.
+ TARGETING::TargetHandleList l_procChips;
+ getAllChips( l_procChips, TARGETING::TYPE_PROC , true);
+ for(auto l_proc : l_procChips)
+ {
+ //Get fabric info from proc
+ uint8_t l_fabricChipId =
+ l_proc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+ uint8_t l_fabricGroupId =
+ l_proc->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>();
+ //Calculate what bit position this will be
+ uint8_t l_bitPos = l_fabricChipId + (MAX_PROCS_PER_NODE * l_fabricGroupId);
+
+ //Set the bit @ l_bitPos to be 1 because this is a functional proc
+ l_systemFabricConfigurationMap |= (0x8000000000000000 >> l_bitPos);
+ }
+
+ // 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( g_trac_runtime, "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_SBE_SYSCONFIG_MSGQ,msgQ);
+ if(l_elog)
+ {
+ TRACFCOMP( g_trac_runtime, "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;
+
+ // 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 < MAX_NODES_PER_SYS); l_node++ )
+ {
+ // skip sending to ourselves, we did our construction above
+ if(l_node == nodeid)
+ continue;
+
+ if( 0 != ((mask >> l_node) & hb_images ) )
+ {
+ TRACFCOMP( g_trac_runtime, "send IPC_QUERY_CHIPINFO "
+ "message to node %d",l_node );
+
+ msg_t * msg = msg_allocate();
+ msg->type = IPC::IPC_QUERY_CHIPINFO;
+ msg->data[0] = l_node; // destination node
+ msg->data[1] = nodeid; // respond to this node
+
+ // send the message to the slave hb instance
+ l_elog = MBOX::send(MBOX::HB_IPC_MSGQ, msg, l_node);
+ if( l_elog )
+ {
+ TRACFCOMP( g_trac_runtime, "MBOX::send to node %d"
+ " failed", l_node);
+ break;
+ }
+
+ ++msg_count;
+
+ } // end if node to process
+ } // end for loop on nodes
+
+ // wait for a response to each message we sent
+ if( l_elog == nullptr )
+ {
+ l_elog = collectRespFromAllDrawers( &msgQ, msg_count, IPC::IPC_QUERY_CHIPINFO, l_systemFabricConfigurationMap);
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Now send each HB instance the full info to write to the SBEs
+ ////////////////////////////
+ if( l_elog == nullptr )
+ {
+ msg_count = 0;
+ for (uint64_t l_node=0; (l_node < MAX_NODES_PER_SYS); l_node++ )
+ {
+ // skip sending to ourselves, we will do our set below
+ if(l_node == nodeid)
+ continue;
+
+ if( 0 != ((mask >> l_node) & hb_images ) )
+ {
+ TRACFCOMP( g_trac_runtime, "send IPC_SET_SBE_CHIPINFO "
+ "message to node %d",l_node );
+
+ msg_t * msg = msg_allocate();
+ msg->type = IPC::IPC_SET_SBE_CHIPINFO;
+ msg->data[0] = l_node; // destination node
+ msg->data[1] = nodeid; // respond to this node
+ msg->extra_data = reinterpret_cast<uint64_t*>(l_systemFabricConfigurationMap);
+
+ // send the message to the slave hb instance
+ l_elog = MBOX::send(MBOX::HB_IPC_MSGQ, msg, l_node);
+ if( l_elog )
+ {
+ TRACFCOMP( g_trac_runtime, "MBOX::send to node %d"
+ " failed", l_node);
+ break;
+ }
+
+ ++msg_count;
+
+ } // end if node to process
+ } // end for loop on nodes
+ }
+
+ // wait for a response to each message we sent
+ if( l_elog == nullptr )
+ {
+ l_elog = collectRespFromAllDrawers( &msgQ, msg_count, IPC::IPC_SET_SBE_CHIPINFO, l_systemFabricConfigurationMap);
+ }
+
+ MBOX::msgq_unregister(MBOX::HB_SBE_SYSCONFIG_MSGQ);
+ msg_q_destroy(msgQ);
+ }
+
+ //Now do this HB instance
+ if( l_elog == nullptr )
+ {
+ for(auto l_proc : l_procChips)
+ {
+ TRACDCOMP( g_trac_runtime,
+ "calling sendSystemConfig on proc 0x%x",
+ TARGETING::get_huid(l_proc));
+ l_elog = SBEIO::sendSystemConfig(l_systemFabricConfigurationMap,
+ l_proc);
+ if ( l_elog )
+ {
+ TRACFCOMP( g_trac_runtime,
+ "sendSystemConfig ERROR : Error sending sbe chip-op to proc 0x%.8X. Returning errorlog, reason=0x%x",
+ TARGETING::get_huid(l_proc),
+ l_elog->reasonCode() );
+ break;
+ }
+ }
+ }
+
+ } while(0);
+
+ return(l_elog);
+
+} // end sendSBESystemConfig
+
// populate the hostboot runtime data section for the system
// will send msg to slave nodes in multinode system
@@ -2570,6 +2989,7 @@ errlHndl_t populate_hbRuntimeData( void )
} // end populate_hbRuntimeData
+
errlHndl_t persistent_rwAttrRuntimeCheck( void )
{
errlHndl_t l_err = nullptr;
OpenPOWER on IntegriCloud