blob: ec600e5dd9785ad0867554229cebceadaa767ab1 [file] [log] [blame]
Ben Tyneref320152020-01-09 10:31:23 -06001#include <libpdbg.h>
2
Ben Tyner0205f3b2020-02-24 10:24:47 -06003#include <analyzer/analyzer_main.hpp>
Ben Tyneref320152020-01-09 10:31:23 -06004#include <phosphor-logging/log.hpp>
5#include <sdbusplus/bus.hpp>
6
7#include <iomanip>
8
9using namespace phosphor::logging;
10
11namespace attn
12{
13
14/**
15 * @brief Handle SBE vital attention
16 *
17 * @return 0 = success
18 */
19int handleVital();
20
21/**
22 * @brief Handle checkstop attention
23 *
24 * @return 0 = success
25 */
26int handleCheckstop();
27
28/**
29 * @brief Handle special attention
30 *
Ben Tyner970fd4f2020-02-19 13:46:42 -060031 * @param i_breakpoints true = breakpoint special attn handling enabled
Ben Tyneref320152020-01-09 10:31:23 -060032 * @return 0 = success
33 */
Ben Tyner970fd4f2020-02-19 13:46:42 -060034int handleSpecial(bool i_breakpoints);
Ben Tyneref320152020-01-09 10:31:23 -060035
36/**
37 * @brief Notify Cronus over dbus interface
38 *
39 * @param i_proc Processor number with Special attention
40 * @param i_core Core number with special attention
41 * @param i_thread Thread number with special attention
42 */
43void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread);
44
45/**
Ben Tyner7e6611f2020-02-13 16:42:56 -060046 * @brief Start host diagnostic mode
47 *
48 * Start the host diagnostic mode systemd unit
49 */
50void startHostDiagnosticMode();
51
52/**
Ben Tyneref320152020-01-09 10:31:23 -060053 * @brief The main attention handler logic
Ben Tyner970fd4f2020-02-19 13:46:42 -060054 *
55 * @param i_breakpoints true = breakpoint special attn handling enabled
Ben Tyneref320152020-01-09 10:31:23 -060056 */
Ben Tyner970fd4f2020-02-19 13:46:42 -060057void attnHandler(bool i_breakpoints)
Ben Tyneref320152020-01-09 10:31:23 -060058{
59 uint32_t isr_val, isr_mask;
60 uint32_t proc;
61
62 // loop through processors looking for active attentions
63 pdbg_target* target;
64 pdbg_for_each_class_target("fsi", target)
65 {
66 if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
67 {
68 proc = pdbg_target_index(target); // get processor number
69
70 std::stringstream ss; // log message stream
71 ss << "[ATTN] checking processor " << proc << std::endl;
72 log<level::INFO>(ss.str().c_str());
73
74 // get active attentions on processor
75 if (0 != fsi_read(target, 0x1007, &isr_val))
76 {
77 std::stringstream ss; // log message stream
78 ss << "[ATTN] Error! cfam read 0x1007 FAILED" << std::endl;
79 log<level::INFO>(ss.str().c_str());
80 }
81 else
82 {
83 std::stringstream ss; // log message stream
84 ss << "[ATTN] cfam 0x1007 = 0x";
85 ss << std::hex << std::setw(8) << std::setfill('0');
86 ss << isr_val << std::endl;
87 log<level::INFO>(ss.str().c_str());
88
89 // get interrupt enabled special attentions mask
90 if (0 != fsi_read(target, 0x100d, &isr_mask))
91 {
92 std::stringstream ss; // log message stream
93 ss << "[ATTN] Error! cfam read 0x100d FAILED" << std::endl;
94 log<level::INFO>(ss.str().c_str());
95 }
96 else
97 {
98 std::stringstream ss; // log message stream
99 ss << "[ATTN] cfam 0x100d = 0x";
100 ss << std::hex << std::setw(8) << std::setfill('0');
101 ss << isr_mask << std::endl;
102 log<level::INFO>(ss.str().c_str());
103
104 // bit 0 on "left": bit 30 = SBE vital attention
105 if (isr_val & isr_mask & 0x00000002)
106 {
107 handleVital();
108 }
109
110 // bit 0 on "left": bit 1 = checkstop
111 if (isr_val & isr_mask & 0x40000000)
112 {
113 handleCheckstop();
114 }
115
116 // bit 0 on "left": bit 2 = special attention
117 if (isr_val & isr_mask & 0x20000000)
118 {
Ben Tyner970fd4f2020-02-19 13:46:42 -0600119 handleSpecial(i_breakpoints);
Ben Tyneref320152020-01-09 10:31:23 -0600120 }
121 } // cfam 0x100d valid
122 } // cfam 0x1007 valid
123 } // fsi target enabled
124 } // next processor
125
126 return; // checked all processors
127}
128
129/**
130 * @brief Handle SBE vital attention
131 */
132int handleVital()
133{
134 int rc = 1; // vital attention handling not yet supported
135
136 std::stringstream ss; // log message stream
137 ss << "[ATTN] vital" << std::endl;
138 log<level::INFO>(ss.str().c_str());
139
140 if (0 != rc)
141 {
142 std::stringstream ss; // log message stream
143 ss << "[ATTN] vital NOT handled" << std::endl;
144 log<level::INFO>(ss.str().c_str());
145 }
146
147 return rc;
148}
149
150/**
151 * @brief Handle checkstop attention
152 */
153int handleCheckstop()
154{
155 int rc = 1; // checkstop handling not yet supported
156
157 std::stringstream ss; // log message stream
158 ss << "[ATTN] checkstop" << std::endl;
159 log<level::INFO>(ss.str().c_str());
160
Ben Tyner0205f3b2020-02-24 10:24:47 -0600161 analyzer::analyzeHardware();
Ben Tyneref320152020-01-09 10:31:23 -0600162
163 // TODO recoverable errors?
164
165 return rc;
166}
167
168/**
169 * @brief Handle special attention
Ben Tyner970fd4f2020-02-19 13:46:42 -0600170 *
171 * @param i_breakpoints true = breakpoint special attn handling enabled
Ben Tyneref320152020-01-09 10:31:23 -0600172 */
Ben Tyner970fd4f2020-02-19 13:46:42 -0600173int handleSpecial(bool i_breakpoints)
Ben Tyneref320152020-01-09 10:31:23 -0600174{
175 int rc = 0; // special attention handling supported
176
177 std::stringstream ss; // log message stream
178
179 ss << "[ATTN] special" << std::endl;
180
Ben Tyner970fd4f2020-02-19 13:46:42 -0600181 // Right now we always handle breakpoint special attentions if breakpoint
182 // attn handling is enabled. This will eventually check if breakpoint attn
183 // handing is enabled AND there is a breakpoint pending.
184 if (true == i_breakpoints)
185 {
186 ss << "[ATTN] breakpoint" << std::endl;
187 log<level::INFO>(ss.str().c_str());
Ben Tyneref320152020-01-09 10:31:23 -0600188
Ben Tyner970fd4f2020-02-19 13:46:42 -0600189 // Cronus will determine proc, core and thread so just notify
190 notifyCronus(0, 0, 0); // proc-0, core-0, thread-0
191 }
192 // Right now if breakpoint attn handling is not enabled we will treat the
193 // special attention as a TI. This will eventually be changed to check
194 // whether a TI is active and handle it regardless of whether breakpoint
195 // handling is enbaled or not.
196 else
197 {
198 ss << "[ATTN] TI (terminate immediately)" << std::endl;
199 log<level::INFO>(ss.str().c_str());
Ben Tyner7e6611f2020-02-13 16:42:56 -0600200
Ben Tyner970fd4f2020-02-19 13:46:42 -0600201 // Start host diagnostic mode
202 startHostDiagnosticMode();
203 }
Ben Tyneref320152020-01-09 10:31:23 -0600204
205 // TODO recoverable errors?
206
207 return rc;
208}
209
210/**
211 * @brief Notify Cronus over dbus interface
212 */
213void notifyCronus(uint32_t i_proc, uint32_t i_core, uint32_t i_thread)
214{
215 std::stringstream ss; // log message stream
216
217 // log status info
218 ss << "[ATTN] notify ";
219 ss << i_proc << ", " << i_core << ", " << i_thread << std::endl;
220 log<level::INFO>(ss.str().c_str());
221
222 // notify Cronus over dbus
223 auto bus = sdbusplus::bus::new_system();
224 auto msg = bus.new_signal("/", "org.openbmc.cronus", "Brkpt");
225
226 std::array<uint32_t, 3> params{i_proc, i_core, i_thread};
227 msg.append(params);
228
229 msg.signal_send();
Ben Tyner7e6611f2020-02-13 16:42:56 -0600230
231 return;
232}
233
234/**
235 * @brief Start host diagnostic mode
236 * */
237void startHostDiagnosticMode()
238{
239 std::stringstream ss; // log message stream
240
241 // log status info
242 ss << "[ATTN] start host diagnostic mode service" << std::endl;
243 log<level::INFO>(ss.str().c_str());
244
245 // Use the systemd service manager object interface to call the start unit
246 // method with the obmc-host-diagnostic-mode target.
247 auto bus = sdbusplus::bus::new_system();
248 auto method = bus.new_method_call(
249 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
250 "org.freedesktop.systemd1.Manager", "StartUnit");
251
252 method.append("obmc-host-diagnostic-mode@0.target"); // unit to activate
253 method.append("replace"); // mode = replace conflicting queued jobs
254 bus.call_noreply(method); // start the service
255
256 return;
Ben Tyneref320152020-01-09 10:31:23 -0600257}
258
259} // namespace attn