1 #include <analyzer/analyzer_main.hpp>
2 #include <attention.hpp>
3 #include <attn_config.hpp>
4 #include <bp_handler.hpp>
5 #include <logging.hpp>
6 #include <ti_handler.hpp>
7 
8 #include <algorithm>
9 #include <iomanip>
10 #include <sstream>
11 #include <vector>
12 
13 namespace attn
14 {
15 
16 /** @brief Return codes */
17 static constexpr int RC_SUCCESS     = 0;
18 static constexpr int RC_NOT_SUCCESS = 1;
19 
20 /**
21  * @brief Handle SBE vital attention
22  *
23  * @param i_attention Attention object
24  * @return 0 indicates that the vital attention was successfully handled
25  *         1 indicates that the vital attention was NOT successfully handled
26  */
27 int handleVital(Attention* i_attention);
28 
29 /**
30  * @brief Handle checkstop attention
31  *
32  * @param i_attention Attention object
33  * @return 0 indicates that the checkstop attention was successfully handled
34  *         1 indicates that the checkstop attention was NOT successfully
35  *           handled.
36  */
37 int handleCheckstop(Attention* i_attention);
38 
39 /**
40  * @brief Handle special attention
41  *
42  * @param i_attention Attention object
43  * @return 0 indicates that the special attention was successfully handled
44  *         1 indicates that the special attention was NOT successfully handled
45  */
46 int handleSpecial(Attention* i_attention);
47 
48 /**
49  * @brief The main attention handler logic
50  *
51  * @param i_breakpoints true = breakpoint special attn handling enabled
52  */
53 void attnHandler(Config* i_config)
54 {
55     // Vector of active attentions to be handled
56     std::vector<Attention> active_attentions;
57 
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 << "checking processor " << proc;
71             log<level::INFO>(ss.str().c_str());
72 
73             // get active attentions on processor
74             if (RC_SUCCESS != fsi_read(target, 0x1007, &isr_val))
75             {
76                 log<level::INFO>("Error! cfam read 0x1007 FAILED");
77             }
78             else
79             {
80                 std::stringstream ss; // log message stream
81                 ss << "cfam 0x1007 = 0x";
82                 ss << std::hex << std::setw(8) << std::setfill('0');
83                 ss << isr_val;
84                 log<level::INFO>(ss.str().c_str());
85 
86                 // get interrupt enabled special attentions mask
87                 if (RC_SUCCESS != fsi_read(target, 0x100d, &isr_mask))
88                 {
89                     log<level::INFO>("Error! cfam read 0x100d FAILED");
90                 }
91                 else
92                 {
93                     std::stringstream ss; // log message stream
94                     ss << "cfam 0x100d = 0x";
95                     ss << std::hex << std::setw(8) << std::setfill('0');
96                     ss << isr_mask;
97                     log<level::INFO>(ss.str().c_str());
98 
99                     // bit 0 on "left": bit 30 = SBE vital attention
100                     if (isr_val & isr_mask & 0x00000002)
101                     {
102                         active_attentions.emplace_back(
103                             Attention::Vital, handleVital, target, i_config);
104                     }
105 
106                     // bit 0 on "left": bit 1 = checkstop
107                     if (isr_val & isr_mask & 0x40000000)
108                     {
109                         active_attentions.emplace_back(Attention::Checkstop,
110                                                        handleCheckstop, target,
111                                                        i_config);
112                     }
113 
114                     // bit 0 on "left": bit 2 = special attention
115                     if (isr_val & isr_mask & 0x20000000)
116                     {
117                         active_attentions.emplace_back(Attention::Special,
118                                                        handleSpecial, target,
119                                                        i_config);
120                     }
121                 } // cfam 0x100d valid
122             }     // cfam 0x1007 valid
123         }         // fsi target enabled
124     }             // next processor
125 
126     // convert to heap, highest priority is at front
127     if (!std::is_heap(active_attentions.begin(), active_attentions.end()))
128     {
129         std::make_heap(active_attentions.begin(), active_attentions.end());
130     }
131 
132     // call the attention handler until one is handled or all were attempted
133     while (false == active_attentions.empty())
134     {
135         // handle highest priority attention, done if successful
136         if (RC_SUCCESS == active_attentions.front().handle())
137         {
138             break;
139         }
140 
141         // move attention to back of vector
142         std::pop_heap(active_attentions.begin(), active_attentions.end());
143 
144         // remove attention from vector
145         active_attentions.pop_back();
146     }
147 }
148 
149 /**
150  * @brief Handle SBE vital attention
151  *
152  * @param i_attention Attention object
153  * @return 0 indicates that the vital attention was successfully handled
154  *         1 indicates that the vital attention was NOT successfully handled
155  */
156 int handleVital(Attention* i_attention)
157 {
158     int rc = RC_SUCCESS; // assume vital handled
159 
160     // if vital handling enabled, handle vital attention
161     if (false == (i_attention->getConfig()->getFlag(enVital)))
162     {
163         log<level::INFO>("vital handling disabled");
164         rc = RC_NOT_SUCCESS;
165     }
166     else
167     {
168         log<level::INFO>("vital NOT handled");
169         rc = RC_NOT_SUCCESS;
170     }
171 
172     return rc;
173 }
174 
175 /**
176  * @brief Handle checkstop attention
177  *
178  * @param i_attention Attention object
179  * @return 0 indicates that the checkstop attention was successfully handled
180  *         1 indicates that the checkstop attention was NOT successfully
181  *           handled.
182  */
183 int handleCheckstop(Attention* i_attention)
184 {
185     int rc = RC_SUCCESS; // assume checkstop handled
186 
187     // if checkstop handling enabled, handle checkstop attention
188     if (false == (i_attention->getConfig()->getFlag(enCheckstop)))
189     {
190         log<level::INFO>("Checkstop handling disabled");
191         rc = RC_NOT_SUCCESS;
192     }
193     else
194     {
195         analyzer::analyzeHardware();
196         rc = RC_SUCCESS;
197     }
198 
199     return rc;
200 }
201 
202 /**
203  * @brief Handle special attention
204  *
205  * @param i_attention Attention object
206  * @return 0 indicates that the special attention was successfully handled
207  *         1 indicates that the special attention was NOT successfully handled
208  */
209 int handleSpecial(Attention* i_attention)
210 {
211     int rc = RC_NOT_SUCCESS; // assume special attention handling disabled
212 
213     // Until the special attention chipop is availabe we will treat the special
214     // attention as a TI. If TI handling is disabled we will treat the special
215     // attention as a breakpopint.
216 
217     // TI attention gets priority over breakpoints, if enabled then handle
218     if (true == (i_attention->getConfig()->getFlag(enTerminate)))
219     {
220         log<level::INFO>("TI (terminate immediately)");
221 
222         // Call TI special attention handler
223         tiHandler();
224         rc = RC_SUCCESS;
225     }
226     else
227     {
228         if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
229         {
230             log<level::INFO>("breakpoint");
231 
232             // Call the breakpoint special attention handler
233             bpHandler();
234             rc = RC_SUCCESS;
235         }
236     }
237 
238     if (RC_SUCCESS != rc)
239     {
240         log<level::INFO>("Special attn handling disabled");
241     }
242 
243     return rc;
244 }
245 
246 } // namespace attn
247