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