Add support for Get TI Info chipop
Use the Get TI Info chipop to determine if a special attention was
due to a TI or a breakpoint.
Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I256dcf1171c27e851032353226c174307105cd0a
diff --git a/attn/attention.cpp b/attn/attention.cpp
index 0806ef2..3fd3f83 100644
--- a/attn/attention.cpp
+++ b/attn/attention.cpp
@@ -30,6 +30,12 @@
return iv_handler(this);
}
+/* @brief Get attention handler target */
+pdbg_target* Attention::getTarget() const
+{
+ return iv_target;
+}
+
/** @brief less than operator, for heap creation */
bool Attention::operator<(const Attention& right) const
{
diff --git a/attn/attention.hpp b/attn/attention.hpp
index a4d3461..69f9fcf 100644
--- a/attn/attention.hpp
+++ b/attn/attention.hpp
@@ -52,6 +52,9 @@
/* @brief Call attention handler function */
int handle();
+ /* @brief Get attention handler target */
+ pdbg_target* getTarget() const;
+
/** @brief Copy constructor. */
Attention(const Attention&) = default;
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index 945156d..6ea2fdc 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -1,3 +1,5 @@
+#include <libpdbg.h>
+
#include <analyzer/analyzer_main.hpp>
#include <attention.hpp>
#include <attn_config.hpp>
@@ -62,7 +64,6 @@
pdbg_target* target;
pdbg_for_each_class_target("fsi", target)
{
- trace<level::INFO>("iterating targets");
if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
{
proc = pdbg_target_index(target); // get processor number
@@ -173,22 +174,11 @@
if (false == (i_attention->getConfig()->getFlag(enVital)))
{
trace<level::INFO>("vital handling disabled");
+ rc = RC_NOT_HANDLED;
}
else
{
- // TODO need vital attention handling
-
- // FIXME TEMP CODE - begin
- if (0)
- {
- eventVital();
- }
- else
- {
- trace<level::INFO>("vital NOT handled"); // enabled but not handled
- rc = RC_NOT_HANDLED;
- }
- // FIXME TEMP CODE -end
+ eventVital();
}
return rc;
@@ -248,24 +238,41 @@
{
int rc = RC_SUCCESS; // assume special attention handled
- trace<level::INFO>("special attention handler started");
+ // The TI infor chipop will give us a pointer to the TI info data
+ uint8_t* tiInfo = nullptr; // ptr to TI info data
+ uint32_t tiInfoLen = 0; // length of TI info data
+ pdbg_target* tiInfoTarget = i_attention->getTarget(); // get TI info target
- // TODO
- // Until the special attention chipop is availabe we will treat the special
- // attention as a TI. If TI handling is disabled we will treat the special
- // attention as a breakpopint.
+ // Get length and location of TI info data
+ sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen);
- // TI attention gets priority over breakpoints, if enabled then handle
- if (true == (i_attention->getConfig()->getFlag(enTerminate)))
+ // Note: If we want to support running this application on architectures
+ // of different endian-ness we need to handler that here. The TI data
+ // will always be written in big-endian order.
+
+ // If TI area exists and is marked valid we can assume TI occurred
+ if ((nullptr != tiInfo) && (0 != tiInfo[0]))
{
- trace<level::INFO>("TI (terminate immediately)");
+ TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
- // Call TI special attention handler
- tiHandler();
+ // trace a few known TI data area values
+ std::stringstream ss; // log message stream
+ ss << "TI data command = " << tiDataArea->command;
+ trace<level::INFO>(ss.str().c_str());
+ ss << "TI data SRC format = " << tiDataArea->srcFormat;
+ trace<level::INFO>(ss.str().c_str());
+ ss << "TI data hb_terminate_type = " << tiDataArea->hbTerminateType;
+ trace<level::INFO>(ss.str().c_str());
- // generate log event
- eventTerminate();
+ if (true == (i_attention->getConfig()->getFlag(enTerminate)))
+ {
+ trace<level::INFO>("TI (terminate immediately)");
+
+ // Call TI special attention handler
+ rc = tiHandler(tiDataArea);
+ }
}
+ // TI area not valid, assume breakpoint
else
{
if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
@@ -277,9 +284,15 @@
}
}
+ // release TI data buffer
+ if (nullptr != tiInfo)
+ {
+ free(tiInfo);
+ }
+
if (RC_SUCCESS != rc)
{
- trace<level::INFO>("Special attn handling disabled");
+ trace<level::INFO>("Special attn not handled");
}
return rc;
diff --git a/attn/ti_handler.cpp b/attn/ti_handler.cpp
index 4801f2c..f1354aa 100644
--- a/attn/ti_handler.cpp
+++ b/attn/ti_handler.cpp
@@ -1,27 +1,36 @@
+#include <attn_handler.hpp>
#include <attn_logging.hpp>
#include <sdbusplus/bus.hpp>
+#include <ti_handler.hpp>
namespace attn
{
/** @brief Start host diagnostic mode systemd unit */
-void tiHandler()
+int tiHandler(TiDataArea* i_tiDataArea)
{
- // trace message
- trace<level::INFO>("start host diagnostic mode service");
+ int rc = RC_NOT_HANDLED; // assume TI not handled
- // Use the systemd service manager object interface to call the start unit
- // method with the obmc-host-diagnostic-mode target.
- auto bus = sdbusplus::bus::new_system();
- auto method = bus.new_method_call(
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "StartUnit");
+ if (0xa1 == i_tiDataArea->command)
+ {
+ // trace message
+ trace<level::INFO>("start host diagnostic mode service");
- method.append("obmc-host-diagnostic-mode@0.target"); // unit to activate
- method.append("replace"); // mode = replace conflicting queued jobs
- bus.call_noreply(method); // start the service
+ // Use the systemd service manager object interface to call the start
+ // unit method with the obmc-host-diagnostic-mode target.
+ auto bus = sdbusplus::bus::new_system();
+ auto method = bus.new_method_call(
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "StartUnit");
- return;
+ method.append("obmc-host-diagnostic-mode@0.target"); // unit to activate
+ method.append("replace"); // mode = replace conflicting queued jobs
+ bus.call_noreply(method); // start the service
+
+ rc = RC_SUCCESS;
+ }
+
+ return rc;
}
} // namespace attn
diff --git a/attn/ti_handler.hpp b/attn/ti_handler.hpp
index d3b83cd..bc28f71 100644
--- a/attn/ti_handler.hpp
+++ b/attn/ti_handler.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <stdint.h>
+
/**
* @brief TI special attention handler
*
@@ -8,6 +10,47 @@
namespace attn
{
-void tiHandler();
+// TI data area definition
+#pragma pack(push)
+#pragma pack(1)
+struct TiDataArea
+{
+ uint8_t tiAreaValid; // 0x00, common (non-zero == valid)
+ uint8_t command; // 0x01, phyp/opal = 0xA1
+ uint16_t numDataBytes; // 0x02, phyp/opal
+ uint8_t reserved1; // 0x04, reserved
+ uint8_t hbTerminateType; // 0x05, hostboot only
+ uint16_t hardwareDumpType; // 0x06, phyp/opal
+ uint8_t srcFormat; // 0x08, phyp/opal = 0x02
+ uint8_t srcFlags; // 0x09, phyp/opal
+ uint8_t numAsciiWords; // 0x0a, phyp/opal
+ uint8_t numHexWords; // 0x0b, phyp/opal
+ uint8_t hbDumpFlag; // 0x0c, hostboot only
+ uint8_t source; // 0x0d, hostboot only
+ uint16_t lenSrc; // 0x0e, phyp/opal
+ uint32_t srcWord12HbWord0; // 0x10, common
+ uint32_t srcWord13HbWord2; // 0x14, common (Word1 intentionally skipped)
+ uint32_t srcWord14HbWord3; // 0x18, common
+ uint32_t srcWord15HbWord4; // 0x1c, common
+ uint32_t srcWord16HbWord5; // 0x20, common
+ uint32_t srcWord17HbWord6; // 0x24, common
+ uint32_t srcWord18HbWord7; // 0x28, common
+ uint32_t srcWord19HbWord8; // 0x2c, common
+ uint32_t asciiData0; // 0x30, phyp/opal, hostboot error_data
+ uint32_t asciiData1; // 0x34, phyp/opal, hostboot EID
+ uint32_t asciiData2; // 0x38, phyp/opal
+ uint32_t asciiData3; // 0x3c, phyp/opal
+ uint32_t asciiData4; // 0x40, phyp/opal
+ uint32_t asciiData5; // 0x44, phyp/opal
+ uint32_t asciiData6; // 0x48, phyp/opal
+ uint32_t asciiData7; // 0x4c, phyp/opal
+ uint8_t location; // 0x50, phyp/opal
+ uint8_t codeSection; // 0x51, phyp/opal
+ uint8_t additionalSize; // 0x52, phyp/opal
+ uint8_t andData; // 0x53, phyp/opal
+};
+#pragma pack(pop)
+
+int tiHandler(TiDataArea* i_tiDataArea);
} // namespace attn