blob: cac1f84c2cfc7cdb2bc0a61ab2f2d1afccad9c1a [file] [log] [blame]
#include <libpdbg.h>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <iomanip>
using namespace phosphor::logging;
namespace attn
{
/**
* @brief Handle SBE vital attention
*
* @return 0 = success
*/
int handleVital();
/**
* @brief Handle checkstop attention
*
* @return 0 = success
*/
int handleCheckstop();
/**
* @brief Handle special attention
*
* @return 0 = success
*/
int handleSpecial();
/**
* @brief Notify Cronus over dbus interface
*
* @param i_proc Processor number with Special attention
* @param i_core Core number with special attention
* @param i_thread Thread number with special attention
*/
void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread);
/**
* @brief The main attention handler logic
*/
void attnHandler()
{
uint32_t isr_val, isr_mask;
uint32_t proc;
// loop through processors looking for active attentions
pdbg_target* target;
pdbg_for_each_class_target("fsi", target)
{
if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
{
proc = pdbg_target_index(target); // get processor number
std::stringstream ss; // log message stream
ss << "[ATTN] checking processor " << proc << std::endl;
log<level::INFO>(ss.str().c_str());
// get active attentions on processor
if (0 != fsi_read(target, 0x1007, &isr_val))
{
std::stringstream ss; // log message stream
ss << "[ATTN] Error! cfam read 0x1007 FAILED" << std::endl;
log<level::INFO>(ss.str().c_str());
}
else
{
std::stringstream ss; // log message stream
ss << "[ATTN] cfam 0x1007 = 0x";
ss << std::hex << std::setw(8) << std::setfill('0');
ss << isr_val << std::endl;
log<level::INFO>(ss.str().c_str());
// get interrupt enabled special attentions mask
if (0 != fsi_read(target, 0x100d, &isr_mask))
{
std::stringstream ss; // log message stream
ss << "[ATTN] Error! cfam read 0x100d FAILED" << std::endl;
log<level::INFO>(ss.str().c_str());
}
else
{
std::stringstream ss; // log message stream
ss << "[ATTN] cfam 0x100d = 0x";
ss << std::hex << std::setw(8) << std::setfill('0');
ss << isr_mask << std::endl;
log<level::INFO>(ss.str().c_str());
// bit 0 on "left": bit 30 = SBE vital attention
if (isr_val & isr_mask & 0x00000002)
{
handleVital();
}
// bit 0 on "left": bit 1 = checkstop
if (isr_val & isr_mask & 0x40000000)
{
handleCheckstop();
}
// bit 0 on "left": bit 2 = special attention
if (isr_val & isr_mask & 0x20000000)
{
handleSpecial();
}
} // cfam 0x100d valid
} // cfam 0x1007 valid
} // fsi target enabled
} // next processor
return; // checked all processors
}
/**
* @brief Handle SBE vital attention
*/
int handleVital()
{
int rc = 1; // vital attention handling not yet supported
std::stringstream ss; // log message stream
ss << "[ATTN] vital" << std::endl;
log<level::INFO>(ss.str().c_str());
if (0 != rc)
{
std::stringstream ss; // log message stream
ss << "[ATTN] vital NOT handled" << std::endl;
log<level::INFO>(ss.str().c_str());
}
return rc;
}
/**
* @brief Handle checkstop attention
*/
int handleCheckstop()
{
int rc = 1; // checkstop handling not yet supported
std::stringstream ss; // log message stream
ss << "[ATTN] checkstop" << std::endl;
log<level::INFO>(ss.str().c_str());
if (0 != rc)
{
std::stringstream ss; // log message stream
ss << "[ATTN] checkstop NOT handled" << std::endl;
log<level::INFO>(ss.str().c_str());
}
// TODO recoverable errors?
return rc;
}
/**
* @brief Handle special attention
*/
int handleSpecial()
{
int rc = 0; // special attention handling supported
std::stringstream ss; // log message stream
ss << "[ATTN] special" << std::endl;
// Currently we are only handling Cronus breakpoints
ss << "[ATTN] breakpoint" << std::endl;
log<level::INFO>(ss.str().c_str());
// Cronus will determine proc, core and thread so just notify
notifyCronus(0, 0, 0); // proc-0, core-0, thread-0
// TODO recoverable errors?
return rc;
}
/**
* @brief Notify Cronus over dbus interface
*/
void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread)
{
std::stringstream ss; // log message stream
// log status info
ss << "[ATTN] notify ";
ss << i_proc << ", " << i_core << ", " << i_thread << std::endl;
log<level::INFO>(ss.str().c_str());
// notify Cronus over dbus
auto bus = sdbusplus::bus::new_system();
auto msg = bus.new_signal("/", "org.openbmc.cronus", "Brkpt");
std::array<uint32_t, 3> params{i_proc, i_core, i_thread};
msg.append(params);
msg.signal_send();
}
} // namespace attn