summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot/node_comm/node_comm.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/secureboot/node_comm/node_comm.C')
-rw-r--r--src/usr/secureboot/node_comm/node_comm.C372
1 files changed, 370 insertions, 2 deletions
diff --git a/src/usr/secureboot/node_comm/node_comm.C b/src/usr/secureboot/node_comm/node_comm.C
index cdaf51755..95008344a 100644
--- a/src/usr/secureboot/node_comm/node_comm.C
+++ b/src/usr/secureboot/node_comm/node_comm.C
@@ -33,6 +33,8 @@
// Includes
// ----------------------------------------------
#include <string.h>
+#include <sys/time.h>
+#include <sys/task.h>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <errl/errludtarget.H>
@@ -55,14 +57,220 @@ namespace SECUREBOOT
namespace NODECOMM
{
+// ----------------------------------------------
+// Defines
+// ----------------------------------------------
+// If the link(s) are up the operation should complete right away
+// so there will only be a short polling window
+#define NODE_COMM_POLL_DELAY_NS (10 * NS_PER_MSEC) // Sleep for 10ms per poll
+// FSP is expecting a reply in 30 seconds, so leave some buffer
+#define NODE_COMM_POLL_DELAY_TOTAL_NS (25 * NS_PER_SEC) // Total time 25s
+
+
+/**
+ * @brief This function waits for the processor to receive a message over
+ * ABUS from a processor on another node.
+ */
+errlHndl_t nodeCommAbusRecvMessage(TARGETING::Target* i_pProc,
+ uint64_t & o_data,
+ uint8_t & o_linkId,
+ uint8_t & o_mboxId)
+{
+ errlHndl_t err = nullptr;
+ bool attn_found = false;
+
+ const uint64_t interval_ns = NODE_COMM_POLL_DELAY_NS;
+ uint64_t time_polled_ns = 0;
+
+ TRACFCOMP(g_trac_nc,ENTER_MRK"nodeCommAbusRecvMessage: pProc=0x%.08X",
+ get_huid(i_pProc));
+
+ do
+ {
+ do
+ {
+
+ // Look for Attention
+ err = nodeCommMapAttn(i_pProc,
+ NCDD_MODE_ABUS,
+ attn_found,
+ o_linkId,
+ o_mboxId);
+ if (err)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommAbusRecvMessage: Error Back "
+ "From nodeCommMapAttn: Tgt=0x%.08X: "
+ TRACE_ERR_FMT,
+ get_huid(i_pProc),
+ TRACE_ERR_ARGS(err));
+ break;
+ }
+ if (attn_found == true)
+ {
+ TRACFCOMP(g_trac_nc,INFO_MRK"nodeCommAbusRecvMessage: "
+ "nodeCommMapAttn attn_found (%d) for Tgt=0x%.08X, link=%d, "
+ "mbox=%d",
+ attn_found, get_huid(i_pProc), o_linkId, o_mboxId);
+ break;
+ }
+
+ if (time_polled_ns >= NODE_COMM_POLL_DELAY_TOTAL_NS)
+ {
+ TRACFCOMP(g_trac_nc,EXIT_MRK"nodeCommAbusRecvMessage: "
+ "timeout: time_polled_ns-0x%.16llX, MAX=0x%.16llX, "
+ "interval=0x%.16llX",
+ time_polled_ns, NODE_COMM_POLL_DELAY_TOTAL_NS, interval_ns);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_NC_WAITING_TIMEOUT
+ * @moduleid MOD_NC_RECV
+ * @userdata1[0:31] Master Proc Target HUID
+ * @userdata1[32:63] Time Polled in ns
+ * @userdata2[0:31] Defined MAX Poll Time in ns
+ * @userdata2[32:63] Time Interval Between Polls in ns
+ * @devdesc Timed out waiting to receive message over
+ * ABUS Link Mailbox
+ * @custdesc Secure Boot failure
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_NC_RECV,
+ RC_NC_WAITING_TIMEOUT,
+ TWO_UINT32_TO_UINT64(
+ get_huid(i_pProc),
+ time_polled_ns),
+ TWO_UINT32_TO_UINT64(
+ NODE_COMM_POLL_DELAY_TOTAL_NS,
+ interval_ns));
+
+ // Bus Callout will be handled by caller since
+ // it should know expected peer target
+
+ // Or HB code failed to do the procedure correctly
+ err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_LOW);
+
+ // Grab FFDC from the target
+ getNodeCommFFDC(NCDD_MODE_ABUS,
+ i_pProc,
+ err);
+
+ break;
+ }
+
+ // Sleep before polling again
+ nanosleep( 0, interval_ns );
+ task_yield(); // wait patiently
+ time_polled_ns += interval_ns;
+
+ } while(attn_found == false);
+
+ if (err)
+ {
+ break;
+ }
+
+ if (attn_found == true)
+ {
+ // Read message on proc with Link Mailbox found above
+ o_data = 0;
+ size_t expSize = sizeof(o_data);
+ auto reqSize = expSize;
+ err = DeviceFW::deviceRead(i_pProc,
+ &o_data,
+ reqSize,
+ DEVICE_NODECOMM_ADDRESS(NCDD_MODE_ABUS,
+ o_linkId,
+ o_mboxId));
+
+ if (err)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommRecvMessage: Error Back From "
+ "Abus MBox Read: Tgt=0x%.08X, link=%d, mbox=%d: "
+ TRACE_ERR_FMT,
+ get_huid(i_pProc), o_linkId, o_mboxId,
+ TRACE_ERR_ARGS(err));
+ break;
+ }
+ assert(reqSize==expSize,"nodeCommRecvMessage: SCOM deviceRead didn't return expected data size of %d (it was %d)",
+ expSize,reqSize);
+
+ }
+
+ } while( 0 );
+
+ TRACFCOMP(g_trac_nc,EXIT_MRK"nodeCommAbusRecvMessage: "
+ "Tgt=0x%.08X, link=%d, mbox=%d attn_found=%d: "
+ "data=0x%.16llX. "
+ TRACE_ERR_FMT,
+ get_huid(i_pProc), o_linkId, o_mboxId, attn_found, o_data,
+ TRACE_ERR_ARGS(err));
+
+ return err;
+
+} // end of nodeCommAbusRecvMessage
+
+
+/**
+ * @brief This function sends a message over the ABUS from the processor of
+ * the current node to a processor on another node.
+ */
+errlHndl_t nodeCommAbusSendMessage(TARGETING::Target* i_pProc,
+ const uint64_t & i_data,
+ const uint8_t & i_linkId,
+ const uint8_t & i_mboxId)
+{
+ errlHndl_t err = nullptr;
+
+ TRACFCOMP(g_trac_nc,ENTER_MRK"nodeCommAbusSendMessage: iProc=0x%.08X "
+ "to send data=0x%.16llX through linkId=%d mboxId=%d",
+ get_huid(i_pProc), i_data, i_linkId, i_mboxId);
+
+ do
+ {
+ // Send Data
+ uint64_t data = i_data; // to keep i_data const
+ size_t expSize = sizeof(i_data);
+ auto reqSize = expSize;
+ err = DeviceFW::deviceWrite(i_pProc,
+ &data,
+ reqSize,
+ DEVICE_NODECOMM_ADDRESS(NCDD_MODE_ABUS,
+ i_linkId,
+ i_mboxId));
+ if (err)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommAbusSendMessage: Error Back "
+ "From Abus MBox Send: Tgt=0x%.08X, data=0x%.16llX, "
+ "link=%d, mbox=%d: "
+ TRACE_ERR_FMT,
+ get_huid(i_pProc), i_data, i_linkId, i_mboxId,
+ TRACE_ERR_ARGS(err));
+ break;
+ }
+ assert(reqSize==expSize,"nodeCommAbusSendMessage: SCOM deviceRead didn't return expected data size of %d (it was %d)",
+ expSize,reqSize);
+
+ } while( 0 );
+
+ TRACFCOMP(g_trac_nc,EXIT_MRK"nodeCommAbusSendMessage: "
+ TRACE_ERR_FMT,
+ TRACE_ERR_ARGS(err));
+
+ return err;
+
+} // end of nodeCommAbusSendMessage
+
+
+
/**
* @brief Map Attention Bits in FIR Register to specific Link Mailbox
*/
errlHndl_t nodeCommMapAttn(TARGETING::Target* i_pProc,
const node_comm_modes_t i_mode,
bool & o_attn_found,
- uint64_t & o_linkId,
- uint64_t & o_mboxId)
+ uint8_t & o_linkId,
+ uint8_t & o_mboxId)
{
errlHndl_t err = nullptr;
uint64_t fir_data = 0x0;
@@ -270,6 +478,166 @@ void getNodeCommFFDC( node_comm_modes_t i_mode,
} // end of getNodeCommFFDC
+/**
+ * @brief Add a bus callout to an error log
+ */
+void addNodeCommBusCallout(node_comm_modes_t i_mode,
+ TARGETING::Target* i_pProc,
+ uint8_t & i_linkId,
+ errlHndl_t & io_log,
+ HWAS::callOutPriority i_priority)
+{
+ TRACFCOMP(g_trac_nc,ENTER_MRK
+ "addNodeCommBusCallout: tgt=0x%X, mode=%s, linkId=%d, "
+ "err_plid=0x%X, priority=%d",
+ get_huid(i_pProc),
+ (i_mode == NCDD_MODE_ABUS)
+ ? NCDD_ABUS_STRING : NCDD_XBUS_STRING,
+ i_linkId,
+ ERRL_GETPLID_SAFE(io_log), i_priority);
+
+ // Bus associated with i_pProc and i_linkId (PHYS_PATH)
+ char * l_ep1_path_str = nullptr;
+
+ // PEER_PATH associated with l_ep1
+ char * l_ep2_path_str = nullptr;
+
+ bool found_peer_endpoint = false;
+
+ do
+ {
+ if ((io_log == nullptr) ||
+ (i_pProc == nullptr) ||
+ ((i_mode != NCDD_MODE_ABUS) &&
+ (i_mode != NCDD_MODE_XBUS)))
+ {
+ TRACFCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: io_log==nullptr or "
+ "tgt=0x%X is nullptr or i_mode=%d is invalid (not ABUS (%d) "
+ "or XBUS (%d)) so no bus callout has beed added",
+ get_huid(i_pProc), i_mode, NCDD_MODE_ABUS, NCDD_MODE_XBUS);
+ break;
+ }
+
+ // Get Bus Type
+ HWAS::busTypeEnum l_bus_type = (i_mode == NCDD_MODE_ABUS)
+ ? HWAS::O_BUS_TYPE : HWAS::X_BUS_TYPE; // using O_ instead of A_BUS_TYPE
+
+ // Get all Chiplets for this target aligned with the input mode
+ TargetHandleList l_busTargetList;
+ TYPE l_type = (i_mode == NCDD_MODE_ABUS)
+ ? TYPE_OBUS : TYPE_XBUS;
+ getChildChiplets(l_busTargetList, i_pProc, l_type);
+
+ // Get BUS Instance
+ // For each OBUS or XBUS instance there are 2 links and 2 mailboxes,
+ // so divide the linkId by 2 to get bus instance
+ uint8_t l_bus_instance_ep1 = i_linkId / 2;
+
+
+ // Look through Bus Targets looking for specific Bus Instance
+ // to find the right PEER_TARGET
+ for (const auto & l_busTgt : l_busTargetList)
+ {
+ found_peer_endpoint = false;
+ EntityPath l_ep1 = l_busTgt->getAttr<ATTR_PHYS_PATH>();
+ if (l_ep1_path_str != nullptr)
+ {
+ free(l_ep1_path_str);
+ }
+ l_ep1_path_str = l_ep1.toString();
+
+
+ EntityPath l_ep2 = l_busTgt->getAttr<ATTR_PEER_PATH>();
+ if (l_ep2_path_str != nullptr)
+ {
+ free(l_ep2_path_str);
+ }
+ l_ep2_path_str = l_ep2.toString();
+
+ TRACUCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: Checking "
+ "i_pProc 0x%.08X BUS HUID 0x%.08X's (%s) PEER_PATH: %s",
+ get_huid(i_pProc), get_huid(l_busTgt),
+ l_ep1_path_str,
+ l_ep2_path_str);
+
+ EntityPath::PathElement l_ep2_peBus =
+ l_ep2.pathElementOfType(l_type);
+ if(l_ep2_peBus.type == TYPE_NA)
+ {
+ TRACUCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: "
+ "Skipping i_pProc 0x%.08X "
+ "BUS HUID 0x%.08X's (%s) PEER_PATH %s because "
+ "cannot find BUS in PEER_PATH",
+ get_huid(i_pProc), get_huid(l_busTgt),
+ l_ep1_path_str, l_ep2_path_str);
+ continue;
+ }
+
+ if (l_bus_instance_ep1 == l_busTgt->getAttr<ATTR_REL_POS>())
+ {
+ TRACFCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: "
+ "Using i_pProc 0x%.08X BUS HUID 0x%.08X (%s) "
+ "PEER_PATH %s as it had right instance %d for ep1",
+ get_huid(i_pProc), get_huid(l_busTgt), l_ep1_path_str,
+ l_ep2_path_str, l_bus_instance_ep1);
+
+ found_peer_endpoint = true;
+
+ // Add Bus Callout
+ io_log->addBusCallout(l_ep1,
+ l_ep2,
+ l_bus_type,
+ i_priority);
+
+ // @TODO RTC 184518 - Possibly go to depth of TYPE_SMPGROUP,
+ // which is one level below OBUS for ABUS/OBUS callouts
+
+ break;
+ }
+ else
+ {
+ TRACUCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: "
+ "Skipping i_pProc 0x%.08X BUS HUID 0x%.08X's "
+ "PEER_PATH %s because ep1 bus instance (%d) does not "
+ "match instance (%d) converted from i_linkId (%d)",
+ get_huid(i_pProc), get_huid(l_busTgt),
+ l_ep2_path_str, l_busTgt->getAttr<ATTR_ORDINAL_ID>(),
+ l_bus_instance_ep1, i_linkId);
+ }
+ }
+
+ if (found_peer_endpoint == false)
+ {
+ TRACFCOMP(g_trac_nc,INFO_MRK"addNodeCommBusCallout: Unable to find a "
+ "peer_tgt for tgt=0x%X, mode=%s, linkId=%d, so no bus "
+ "callout has been added",
+ get_huid(i_pProc),
+ (i_mode == NCDD_MODE_ABUS)
+ ? NCDD_ABUS_STRING : NCDD_XBUS_STRING,
+ i_linkId);
+ break;
+ }
+
+ } while( 0 );
+
+ if (l_ep1_path_str != nullptr)
+ {
+ free(l_ep1_path_str);
+ l_ep1_path_str = nullptr;
+ }
+
+ if (l_ep2_path_str != nullptr)
+ {
+ free(l_ep2_path_str);
+ l_ep2_path_str = nullptr;
+ }
+
+ TRACFCOMP(g_trac_nc,EXIT_MRK"addNodeCommBusCallout");
+
+ return;
+
+} // end of addNodeCommBusCallout
+
} // End NODECOMM namespace
} // End SECUREBOOT namespace
OpenPOWER on IntegriCloud