1ef320154SBen Tyner #include <libpdbg.h> 2ef320154SBen Tyner 3*0205f3b3SBen Tyner #include <analyzer/analyzer_main.hpp> 4ef320154SBen Tyner #include <phosphor-logging/log.hpp> 5ef320154SBen Tyner #include <sdbusplus/bus.hpp> 6ef320154SBen Tyner 7ef320154SBen Tyner #include <iomanip> 8ef320154SBen Tyner 9ef320154SBen Tyner using namespace phosphor::logging; 10ef320154SBen Tyner 11ef320154SBen Tyner namespace attn 12ef320154SBen Tyner { 13ef320154SBen Tyner 14ef320154SBen Tyner /** 15ef320154SBen Tyner * @brief Handle SBE vital attention 16ef320154SBen Tyner * 17ef320154SBen Tyner * @return 0 = success 18ef320154SBen Tyner */ 19ef320154SBen Tyner int handleVital(); 20ef320154SBen Tyner 21ef320154SBen Tyner /** 22ef320154SBen Tyner * @brief Handle checkstop attention 23ef320154SBen Tyner * 24ef320154SBen Tyner * @return 0 = success 25ef320154SBen Tyner */ 26ef320154SBen Tyner int handleCheckstop(); 27ef320154SBen Tyner 28ef320154SBen Tyner /** 29ef320154SBen Tyner * @brief Handle special attention 30ef320154SBen Tyner * 31970fd4fbSBen Tyner * @param i_breakpoints true = breakpoint special attn handling enabled 32ef320154SBen Tyner * @return 0 = success 33ef320154SBen Tyner */ 34970fd4fbSBen Tyner int handleSpecial(bool i_breakpoints); 35ef320154SBen Tyner 36ef320154SBen Tyner /** 37ef320154SBen Tyner * @brief Notify Cronus over dbus interface 38ef320154SBen Tyner * 39ef320154SBen Tyner * @param i_proc Processor number with Special attention 40ef320154SBen Tyner * @param i_core Core number with special attention 41ef320154SBen Tyner * @param i_thread Thread number with special attention 42ef320154SBen Tyner */ 43ef320154SBen Tyner void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread); 44ef320154SBen Tyner 45ef320154SBen Tyner /** 467e6611f9SBen Tyner * @brief Start host diagnostic mode 477e6611f9SBen Tyner * 487e6611f9SBen Tyner * Start the host diagnostic mode systemd unit 497e6611f9SBen Tyner */ 507e6611f9SBen Tyner void startHostDiagnosticMode(); 517e6611f9SBen Tyner 527e6611f9SBen Tyner /** 53ef320154SBen Tyner * @brief The main attention handler logic 54970fd4fbSBen Tyner * 55970fd4fbSBen Tyner * @param i_breakpoints true = breakpoint special attn handling enabled 56ef320154SBen Tyner */ 57970fd4fbSBen Tyner void attnHandler(bool i_breakpoints) 58ef320154SBen Tyner { 59ef320154SBen Tyner uint32_t isr_val, isr_mask; 60ef320154SBen Tyner uint32_t proc; 61ef320154SBen Tyner 62ef320154SBen Tyner // loop through processors looking for active attentions 63ef320154SBen Tyner pdbg_target* target; 64ef320154SBen Tyner pdbg_for_each_class_target("fsi", target) 65ef320154SBen Tyner { 66ef320154SBen Tyner if (PDBG_TARGET_ENABLED == pdbg_target_probe(target)) 67ef320154SBen Tyner { 68ef320154SBen Tyner proc = pdbg_target_index(target); // get processor number 69ef320154SBen Tyner 70ef320154SBen Tyner std::stringstream ss; // log message stream 71ef320154SBen Tyner ss << "[ATTN] checking processor " << proc << std::endl; 72ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 73ef320154SBen Tyner 74ef320154SBen Tyner // get active attentions on processor 75ef320154SBen Tyner if (0 != fsi_read(target, 0x1007, &isr_val)) 76ef320154SBen Tyner { 77ef320154SBen Tyner std::stringstream ss; // log message stream 78ef320154SBen Tyner ss << "[ATTN] Error! cfam read 0x1007 FAILED" << std::endl; 79ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 80ef320154SBen Tyner } 81ef320154SBen Tyner else 82ef320154SBen Tyner { 83ef320154SBen Tyner std::stringstream ss; // log message stream 84ef320154SBen Tyner ss << "[ATTN] cfam 0x1007 = 0x"; 85ef320154SBen Tyner ss << std::hex << std::setw(8) << std::setfill('0'); 86ef320154SBen Tyner ss << isr_val << std::endl; 87ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 88ef320154SBen Tyner 89ef320154SBen Tyner // get interrupt enabled special attentions mask 90ef320154SBen Tyner if (0 != fsi_read(target, 0x100d, &isr_mask)) 91ef320154SBen Tyner { 92ef320154SBen Tyner std::stringstream ss; // log message stream 93ef320154SBen Tyner ss << "[ATTN] Error! cfam read 0x100d FAILED" << std::endl; 94ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 95ef320154SBen Tyner } 96ef320154SBen Tyner else 97ef320154SBen Tyner { 98ef320154SBen Tyner std::stringstream ss; // log message stream 99ef320154SBen Tyner ss << "[ATTN] cfam 0x100d = 0x"; 100ef320154SBen Tyner ss << std::hex << std::setw(8) << std::setfill('0'); 101ef320154SBen Tyner ss << isr_mask << std::endl; 102ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 103ef320154SBen Tyner 104ef320154SBen Tyner // bit 0 on "left": bit 30 = SBE vital attention 105ef320154SBen Tyner if (isr_val & isr_mask & 0x00000002) 106ef320154SBen Tyner { 107ef320154SBen Tyner handleVital(); 108ef320154SBen Tyner } 109ef320154SBen Tyner 110ef320154SBen Tyner // bit 0 on "left": bit 1 = checkstop 111ef320154SBen Tyner if (isr_val & isr_mask & 0x40000000) 112ef320154SBen Tyner { 113ef320154SBen Tyner handleCheckstop(); 114ef320154SBen Tyner } 115ef320154SBen Tyner 116ef320154SBen Tyner // bit 0 on "left": bit 2 = special attention 117ef320154SBen Tyner if (isr_val & isr_mask & 0x20000000) 118ef320154SBen Tyner { 119970fd4fbSBen Tyner handleSpecial(i_breakpoints); 120ef320154SBen Tyner } 121ef320154SBen Tyner } // cfam 0x100d valid 122ef320154SBen Tyner } // cfam 0x1007 valid 123ef320154SBen Tyner } // fsi target enabled 124ef320154SBen Tyner } // next processor 125ef320154SBen Tyner 126ef320154SBen Tyner return; // checked all processors 127ef320154SBen Tyner } 128ef320154SBen Tyner 129ef320154SBen Tyner /** 130ef320154SBen Tyner * @brief Handle SBE vital attention 131ef320154SBen Tyner */ 132ef320154SBen Tyner int handleVital() 133ef320154SBen Tyner { 134ef320154SBen Tyner int rc = 1; // vital attention handling not yet supported 135ef320154SBen Tyner 136ef320154SBen Tyner std::stringstream ss; // log message stream 137ef320154SBen Tyner ss << "[ATTN] vital" << std::endl; 138ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 139ef320154SBen Tyner 140ef320154SBen Tyner if (0 != rc) 141ef320154SBen Tyner { 142ef320154SBen Tyner std::stringstream ss; // log message stream 143ef320154SBen Tyner ss << "[ATTN] vital NOT handled" << std::endl; 144ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 145ef320154SBen Tyner } 146ef320154SBen Tyner 147ef320154SBen Tyner return rc; 148ef320154SBen Tyner } 149ef320154SBen Tyner 150ef320154SBen Tyner /** 151ef320154SBen Tyner * @brief Handle checkstop attention 152ef320154SBen Tyner */ 153ef320154SBen Tyner int handleCheckstop() 154ef320154SBen Tyner { 155ef320154SBen Tyner int rc = 1; // checkstop handling not yet supported 156ef320154SBen Tyner 157ef320154SBen Tyner std::stringstream ss; // log message stream 158ef320154SBen Tyner ss << "[ATTN] checkstop" << std::endl; 159ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 160ef320154SBen Tyner 161*0205f3b3SBen Tyner analyzer::analyzeHardware(); 162ef320154SBen Tyner 163ef320154SBen Tyner // TODO recoverable errors? 164ef320154SBen Tyner 165ef320154SBen Tyner return rc; 166ef320154SBen Tyner } 167ef320154SBen Tyner 168ef320154SBen Tyner /** 169ef320154SBen Tyner * @brief Handle special attention 170970fd4fbSBen Tyner * 171970fd4fbSBen Tyner * @param i_breakpoints true = breakpoint special attn handling enabled 172ef320154SBen Tyner */ 173970fd4fbSBen Tyner int handleSpecial(bool i_breakpoints) 174ef320154SBen Tyner { 175ef320154SBen Tyner int rc = 0; // special attention handling supported 176ef320154SBen Tyner 177ef320154SBen Tyner std::stringstream ss; // log message stream 178ef320154SBen Tyner 179ef320154SBen Tyner ss << "[ATTN] special" << std::endl; 180ef320154SBen Tyner 181970fd4fbSBen Tyner // Right now we always handle breakpoint special attentions if breakpoint 182970fd4fbSBen Tyner // attn handling is enabled. This will eventually check if breakpoint attn 183970fd4fbSBen Tyner // handing is enabled AND there is a breakpoint pending. 184970fd4fbSBen Tyner if (true == i_breakpoints) 185970fd4fbSBen Tyner { 186970fd4fbSBen Tyner ss << "[ATTN] breakpoint" << std::endl; 187970fd4fbSBen Tyner log<level::INFO>(ss.str().c_str()); 188ef320154SBen Tyner 189ef320154SBen Tyner // Cronus will determine proc, core and thread so just notify 190970fd4fbSBen Tyner notifyCronus(0, 0, 0); // proc-0, core-0, thread-0 191970fd4fbSBen Tyner } 192970fd4fbSBen Tyner // Right now if breakpoint attn handling is not enabled we will treat the 193970fd4fbSBen Tyner // special attention as a TI. This will eventually be changed to check 194970fd4fbSBen Tyner // whether a TI is active and handle it regardless of whether breakpoint 195970fd4fbSBen Tyner // handling is enbaled or not. 196970fd4fbSBen Tyner else 197970fd4fbSBen Tyner { 1987e6611f9SBen Tyner ss << "[ATTN] TI (terminate immediately)" << std::endl; 1997e6611f9SBen Tyner log<level::INFO>(ss.str().c_str()); 200970fd4fbSBen Tyner 201970fd4fbSBen Tyner // Start host diagnostic mode 2027e6611f9SBen Tyner startHostDiagnosticMode(); 203970fd4fbSBen Tyner } 204ef320154SBen Tyner 205ef320154SBen Tyner // TODO recoverable errors? 206ef320154SBen Tyner 207ef320154SBen Tyner return rc; 208ef320154SBen Tyner } 209ef320154SBen Tyner 210ef320154SBen Tyner /** 211ef320154SBen Tyner * @brief Notify Cronus over dbus interface 212ef320154SBen Tyner */ 213ef320154SBen Tyner void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread) 214ef320154SBen Tyner { 215ef320154SBen Tyner std::stringstream ss; // log message stream 216ef320154SBen Tyner 217ef320154SBen Tyner // log status info 218ef320154SBen Tyner ss << "[ATTN] notify "; 219ef320154SBen Tyner ss << i_proc << ", " << i_core << ", " << i_thread << std::endl; 220ef320154SBen Tyner log<level::INFO>(ss.str().c_str()); 221ef320154SBen Tyner 222ef320154SBen Tyner // notify Cronus over dbus 223ef320154SBen Tyner auto bus = sdbusplus::bus::new_system(); 224ef320154SBen Tyner auto msg = bus.new_signal("/", "org.openbmc.cronus", "Brkpt"); 225ef320154SBen Tyner 226ef320154SBen Tyner std::array<uint32_t, 3> params{i_proc, i_core, i_thread}; 227ef320154SBen Tyner msg.append(params); 228ef320154SBen Tyner 229ef320154SBen Tyner msg.signal_send(); 2307e6611f9SBen Tyner 2317e6611f9SBen Tyner return; 2327e6611f9SBen Tyner } 2337e6611f9SBen Tyner 2347e6611f9SBen Tyner /** 2357e6611f9SBen Tyner * @brief Start host diagnostic mode 2367e6611f9SBen Tyner * */ 2377e6611f9SBen Tyner void startHostDiagnosticMode() 2387e6611f9SBen Tyner { 2397e6611f9SBen Tyner std::stringstream ss; // log message stream 2407e6611f9SBen Tyner 2417e6611f9SBen Tyner // log status info 2427e6611f9SBen Tyner ss << "[ATTN] start host diagnostic mode service" << std::endl; 2437e6611f9SBen Tyner log<level::INFO>(ss.str().c_str()); 2447e6611f9SBen Tyner 2457e6611f9SBen Tyner // Use the systemd service manager object interface to call the start unit 2467e6611f9SBen Tyner // method with the obmc-host-diagnostic-mode target. 2477e6611f9SBen Tyner auto bus = sdbusplus::bus::new_system(); 2487e6611f9SBen Tyner auto method = bus.new_method_call( 2497e6611f9SBen Tyner "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 2507e6611f9SBen Tyner "org.freedesktop.systemd1.Manager", "StartUnit"); 2517e6611f9SBen Tyner 2527e6611f9SBen Tyner method.append("obmc-host-diagnostic-mode@0.target"); // unit to activate 2537e6611f9SBen Tyner method.append("replace"); // mode = replace conflicting queued jobs 2547e6611f9SBen Tyner bus.call_noreply(method); // start the service 2557e6611f9SBen Tyner 2567e6611f9SBen Tyner return; 257ef320154SBen Tyner } 258ef320154SBen Tyner 259ef320154SBen Tyner } // namespace attn 260