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