1ef320154SBen Tyner #include <libpdbg.h> 2ef320154SBen Tyner 3ef320154SBen Tyner #include <phosphor-logging/log.hpp> 4ef320154SBen Tyner #include <sdbusplus/bus.hpp> 5ef320154SBen Tyner 6ef320154SBen Tyner #include <iomanip> 7ef320154SBen Tyner 8ef320154SBen Tyner using namespace phosphor::logging; 9ef320154SBen Tyner 10ef320154SBen Tyner namespace attn 11ef320154SBen Tyner { 12ef320154SBen Tyner 13ef320154SBen Tyner /** 14ef320154SBen Tyner * @brief Handle SBE vital attention 15ef320154SBen Tyner * 16ef320154SBen Tyner * @return 0 = success 17ef320154SBen Tyner */ 18ef320154SBen Tyner int handleVital(); 19ef320154SBen Tyner 20ef320154SBen Tyner /** 21ef320154SBen Tyner * @brief Handle checkstop attention 22ef320154SBen Tyner * 23ef320154SBen Tyner * @return 0 = success 24ef320154SBen Tyner */ 25ef320154SBen Tyner int handleCheckstop(); 26ef320154SBen Tyner 27ef320154SBen Tyner /** 28ef320154SBen Tyner * @brief Handle special attention 29ef320154SBen Tyner * 30ef320154SBen Tyner * @return 0 = success 31ef320154SBen Tyner */ 32ef320154SBen Tyner int handleSpecial(); 33ef320154SBen Tyner 34ef320154SBen Tyner /** 35ef320154SBen Tyner * @brief Notify Cronus over dbus interface 36ef320154SBen Tyner * 37ef320154SBen Tyner * @param i_proc Processor number with Special attention 38ef320154SBen Tyner * @param i_core Core number with special attention 39ef320154SBen Tyner * @param i_thread Thread number with special attention 40ef320154SBen Tyner */ 41ef320154SBen Tyner void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread); 42ef320154SBen Tyner 43ef320154SBen Tyner /** 44*7e6611f9SBen Tyner * @brief Start host diagnostic mode 45*7e6611f9SBen Tyner * 46*7e6611f9SBen Tyner * Start the host diagnostic mode systemd unit 47*7e6611f9SBen Tyner */ 48*7e6611f9SBen Tyner void startHostDiagnosticMode(); 49*7e6611f9SBen Tyner 50*7e6611f9SBen Tyner /** 51ef320154SBen Tyner * @brief The main attention handler logic 52ef320154SBen Tyner */ 53ef320154SBen Tyner void attnHandler() 54ef320154SBen Tyner { 55ef320154SBen Tyner uint32_t isr_val, isr_mask; 56ef320154SBen Tyner uint32_t proc; 57ef320154SBen Tyner 58ef320154SBen Tyner // loop through processors looking for active attentions 59ef320154SBen Tyner pdbg_target* target; 60ef320154SBen Tyner pdbg_for_each_class_target("fsi", target) 61ef320154SBen Tyner { 62ef320154SBen Tyner if (PDBG_TARGET_ENABLED == pdbg_target_probe(target)) 63ef320154SBen Tyner { 64ef320154SBen Tyner proc = pdbg_target_index(target); // get processor number 65ef320154SBen Tyner 66ef320154SBen Tyner std::stringstream ss; // log message stream 67ef320154SBen Tyner ss << "[ATTN] checking processor " << proc << std::endl; 68ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 69ef320154SBen Tyner 70ef320154SBen Tyner // get active attentions on processor 71ef320154SBen Tyner if (0 != fsi_read(target, 0x1007, &isr_val)) 72ef320154SBen Tyner { 73ef320154SBen Tyner std::stringstream ss; // log message stream 74ef320154SBen Tyner ss << "[ATTN] Error! cfam read 0x1007 FAILED" << std::endl; 75ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 76ef320154SBen Tyner } 77ef320154SBen Tyner else 78ef320154SBen Tyner { 79ef320154SBen Tyner std::stringstream ss; // log message stream 80ef320154SBen Tyner ss << "[ATTN] cfam 0x1007 = 0x"; 81ef320154SBen Tyner ss << std::hex << std::setw(8) << std::setfill('0'); 82ef320154SBen Tyner ss << isr_val << std::endl; 83ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 84ef320154SBen Tyner 85ef320154SBen Tyner // get interrupt enabled special attentions mask 86ef320154SBen Tyner if (0 != fsi_read(target, 0x100d, &isr_mask)) 87ef320154SBen Tyner { 88ef320154SBen Tyner std::stringstream ss; // log message stream 89ef320154SBen Tyner ss << "[ATTN] Error! cfam read 0x100d FAILED" << std::endl; 90ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 91ef320154SBen Tyner } 92ef320154SBen Tyner else 93ef320154SBen Tyner { 94ef320154SBen Tyner std::stringstream ss; // log message stream 95ef320154SBen Tyner ss << "[ATTN] cfam 0x100d = 0x"; 96ef320154SBen Tyner ss << std::hex << std::setw(8) << std::setfill('0'); 97ef320154SBen Tyner ss << isr_mask << std::endl; 98ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 99ef320154SBen Tyner 100ef320154SBen Tyner // bit 0 on "left": bit 30 = SBE vital attention 101ef320154SBen Tyner if (isr_val & isr_mask & 0x00000002) 102ef320154SBen Tyner { 103ef320154SBen Tyner handleVital(); 104ef320154SBen Tyner } 105ef320154SBen Tyner 106ef320154SBen Tyner // bit 0 on "left": bit 1 = checkstop 107ef320154SBen Tyner if (isr_val & isr_mask & 0x40000000) 108ef320154SBen Tyner { 109ef320154SBen Tyner handleCheckstop(); 110ef320154SBen Tyner } 111ef320154SBen Tyner 112ef320154SBen Tyner // bit 0 on "left": bit 2 = special attention 113ef320154SBen Tyner if (isr_val & isr_mask & 0x20000000) 114ef320154SBen Tyner { 115ef320154SBen Tyner handleSpecial(); 116ef320154SBen Tyner } 117ef320154SBen Tyner } // cfam 0x100d valid 118ef320154SBen Tyner } // cfam 0x1007 valid 119ef320154SBen Tyner } // fsi target enabled 120ef320154SBen Tyner } // next processor 121ef320154SBen Tyner 122ef320154SBen Tyner return; // checked all processors 123ef320154SBen Tyner } 124ef320154SBen Tyner 125ef320154SBen Tyner /** 126ef320154SBen Tyner * @brief Handle SBE vital attention 127ef320154SBen Tyner */ 128ef320154SBen Tyner int handleVital() 129ef320154SBen Tyner { 130ef320154SBen Tyner int rc = 1; // vital attention handling not yet supported 131ef320154SBen Tyner 132ef320154SBen Tyner std::stringstream ss; // log message stream 133ef320154SBen Tyner ss << "[ATTN] vital" << std::endl; 134ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 135ef320154SBen Tyner 136ef320154SBen Tyner if (0 != rc) 137ef320154SBen Tyner { 138ef320154SBen Tyner std::stringstream ss; // log message stream 139ef320154SBen Tyner ss << "[ATTN] vital NOT handled" << std::endl; 140ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 141ef320154SBen Tyner } 142ef320154SBen Tyner 143ef320154SBen Tyner return rc; 144ef320154SBen Tyner } 145ef320154SBen Tyner 146ef320154SBen Tyner /** 147ef320154SBen Tyner * @brief Handle checkstop attention 148ef320154SBen Tyner */ 149ef320154SBen Tyner int handleCheckstop() 150ef320154SBen Tyner { 151ef320154SBen Tyner int rc = 1; // checkstop handling not yet supported 152ef320154SBen Tyner 153ef320154SBen Tyner std::stringstream ss; // log message stream 154ef320154SBen Tyner ss << "[ATTN] checkstop" << std::endl; 155ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 156ef320154SBen Tyner 157ef320154SBen Tyner if (0 != rc) 158ef320154SBen Tyner { 159ef320154SBen Tyner std::stringstream ss; // log message stream 160ef320154SBen Tyner ss << "[ATTN] checkstop NOT handled" << std::endl; 161ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 162ef320154SBen Tyner } 163ef320154SBen Tyner 164ef320154SBen Tyner // TODO recoverable errors? 165ef320154SBen Tyner 166ef320154SBen Tyner return rc; 167ef320154SBen Tyner } 168ef320154SBen Tyner 169ef320154SBen Tyner /** 170ef320154SBen Tyner * @brief Handle special attention 171ef320154SBen Tyner */ 172ef320154SBen Tyner int handleSpecial() 173ef320154SBen Tyner { 174ef320154SBen Tyner int rc = 0; // special attention handling supported 175ef320154SBen Tyner 176ef320154SBen Tyner std::stringstream ss; // log message stream 177ef320154SBen Tyner 178ef320154SBen Tyner ss << "[ATTN] special" << std::endl; 179ef320154SBen Tyner 180ef320154SBen Tyner // Currently we are only handling Cronus breakpoints 181*7e6611f9SBen Tyner // ss << "[ATTN] breakpoint" << std::endl; 182*7e6611f9SBen Tyner // log<level::INFO>(ss.str().c_str()); 183ef320154SBen Tyner 184ef320154SBen Tyner // Cronus will determine proc, core and thread so just notify 185*7e6611f9SBen Tyner // notifyCronus(0, 0, 0); // proc-0, core-0, thread-0 186*7e6611f9SBen Tyner 187*7e6611f9SBen Tyner // For TI special attention start host diagnostic mode 188*7e6611f9SBen Tyner ss << "[ATTN] TI (terminate immediately)" << std::endl; 189*7e6611f9SBen Tyner log<level::INFO>(ss.str().c_str()); 190*7e6611f9SBen Tyner startHostDiagnosticMode(); 191ef320154SBen Tyner 192ef320154SBen Tyner // TODO recoverable errors? 193ef320154SBen Tyner 194ef320154SBen Tyner return rc; 195ef320154SBen Tyner } 196ef320154SBen Tyner 197ef320154SBen Tyner /** 198ef320154SBen Tyner * @brief Notify Cronus over dbus interface 199ef320154SBen Tyner */ 200ef320154SBen Tyner void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread) 201ef320154SBen Tyner { 202ef320154SBen Tyner std::stringstream ss; // log message stream 203ef320154SBen Tyner 204ef320154SBen Tyner // log status info 205ef320154SBen Tyner ss << "[ATTN] notify "; 206ef320154SBen Tyner ss << i_proc << ", " << i_core << ", " << i_thread << std::endl; 207ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 208ef320154SBen Tyner 209ef320154SBen Tyner // notify Cronus over dbus 210ef320154SBen Tyner auto bus = sdbusplus::bus::new_system(); 211ef320154SBen Tyner auto msg = bus.new_signal("/", "org.openbmc.cronus", "Brkpt"); 212ef320154SBen Tyner 213ef320154SBen Tyner std::array<uint32_t, 3> params{i_proc, i_core, i_thread}; 214ef320154SBen Tyner msg.append(params); 215ef320154SBen Tyner 216ef320154SBen Tyner msg.signal_send(); 217*7e6611f9SBen Tyner 218*7e6611f9SBen Tyner return; 219*7e6611f9SBen Tyner } 220*7e6611f9SBen Tyner 221*7e6611f9SBen Tyner /** 222*7e6611f9SBen Tyner * @brief Start host diagnostic mode 223*7e6611f9SBen Tyner * */ 224*7e6611f9SBen Tyner void startHostDiagnosticMode() 225*7e6611f9SBen Tyner { 226*7e6611f9SBen Tyner std::stringstream ss; // log message stream 227*7e6611f9SBen Tyner 228*7e6611f9SBen Tyner // log status info 229*7e6611f9SBen Tyner ss << "[ATTN] start host diagnostic mode service" << std::endl; 230*7e6611f9SBen Tyner log<level::INFO>(ss.str().c_str()); 231*7e6611f9SBen Tyner 232*7e6611f9SBen Tyner // Use the systemd service manager object interface to call the start unit 233*7e6611f9SBen Tyner // method with the obmc-host-diagnostic-mode target. 234*7e6611f9SBen Tyner auto bus = sdbusplus::bus::new_system(); 235*7e6611f9SBen Tyner auto method = bus.new_method_call( 236*7e6611f9SBen Tyner "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 237*7e6611f9SBen Tyner "org.freedesktop.systemd1.Manager", "StartUnit"); 238*7e6611f9SBen Tyner 239*7e6611f9SBen Tyner method.append("obmc-host-diagnostic-mode@0.target"); // unit to activate 240*7e6611f9SBen Tyner method.append("replace"); // mode = replace conflicting queued jobs 241*7e6611f9SBen Tyner bus.call_noreply(method); // start the service 242*7e6611f9SBen Tyner 243*7e6611f9SBen Tyner return; 244ef320154SBen Tyner } 245ef320154SBen Tyner 246ef320154SBen Tyner } // namespace attn 247