10205f3b3SBen Tyner #include <analyzer/analyzer_main.hpp>
2b481d905SBen Tyner #include <attention.hpp>
39ae5ca41SBen Tyner #include <bp_handler.hpp>
49ae5ca41SBen Tyner #include <logging.hpp>
59ae5ca41SBen Tyner #include <ti_handler.hpp>
6ef320154SBen Tyner 
7b481d905SBen Tyner #include <algorithm>
8ef320154SBen Tyner #include <iomanip>
99ae5ca41SBen Tyner #include <sstream>
10b481d905SBen Tyner #include <vector>
11ef320154SBen Tyner 
12ef320154SBen Tyner namespace attn
13ef320154SBen Tyner {
14ef320154SBen Tyner 
15b481d905SBen Tyner /** @brief Return codes */
16b481d905SBen Tyner static constexpr int RC_SUCCESS     = 0;
17b481d905SBen Tyner static constexpr int RC_NOT_SUCCESS = 1;
18b481d905SBen Tyner 
19ef320154SBen Tyner /**
20ef320154SBen Tyner  * @brief Handle SBE vital attention
21ef320154SBen Tyner  *
22b481d905SBen Tyner  * @param i_attention Attention object
23ef320154SBen Tyner  * @return 0 = success
24ef320154SBen Tyner  */
25b481d905SBen Tyner int handleVital(Attention* i_attention);
26ef320154SBen Tyner 
27ef320154SBen Tyner /**
28ef320154SBen Tyner  * @brief Handle checkstop attention
29ef320154SBen Tyner  *
30b481d905SBen Tyner  * @param i_attention Attention object
31ef320154SBen Tyner  * @return 0 = success
32ef320154SBen Tyner  */
33b481d905SBen Tyner int handleCheckstop(Attention* i_attention);
34ef320154SBen Tyner 
35ef320154SBen Tyner /**
36ef320154SBen Tyner  * @brief Handle special attention
37ef320154SBen Tyner  *
38b481d905SBen Tyner  * @param i_attention Attention object
39ef320154SBen Tyner  * @return 0 = success
40ef320154SBen Tyner  */
41b481d905SBen Tyner int handleSpecial(Attention* i_attention);
42ef320154SBen Tyner 
43ef320154SBen Tyner /**
44ef320154SBen Tyner  * @brief The main attention handler logic
45970fd4fbSBen Tyner  *
46970fd4fbSBen Tyner  * @param i_breakpoints true = breakpoint special attn handling enabled
47ef320154SBen Tyner  */
48b481d905SBen Tyner void attnHandler(const bool i_breakpoints)
49ef320154SBen Tyner {
50b481d905SBen Tyner     // Vector of active attentions to be handled
51b481d905SBen Tyner     std::vector<Attention> active_attentions;
52b481d905SBen Tyner 
53ef320154SBen Tyner     uint32_t isr_val, isr_mask;
54ef320154SBen Tyner     uint32_t proc;
55ef320154SBen Tyner 
56ef320154SBen Tyner     // loop through processors looking for active attentions
57ef320154SBen Tyner     pdbg_target* target;
58ef320154SBen Tyner     pdbg_for_each_class_target("fsi", target)
59ef320154SBen Tyner     {
60ef320154SBen Tyner         if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
61ef320154SBen Tyner         {
62ef320154SBen Tyner             proc = pdbg_target_index(target); // get processor number
63ef320154SBen Tyner 
64ef320154SBen Tyner             std::stringstream ss; // log message stream
65*9dbab8beSBen Tyner             ss << "checking processor " << proc;
66ef320154SBen Tyner             log<level::INFO>(ss.str().c_str());
67ef320154SBen Tyner 
68ef320154SBen Tyner             // get active attentions on processor
69b481d905SBen Tyner             if (RC_SUCCESS != fsi_read(target, 0x1007, &isr_val))
70ef320154SBen Tyner             {
71*9dbab8beSBen Tyner                 log<level::INFO>("Error! cfam read 0x1007 FAILED");
72ef320154SBen Tyner             }
73ef320154SBen Tyner             else
74ef320154SBen Tyner             {
75ef320154SBen Tyner                 std::stringstream ss; // log message stream
769ae5ca41SBen Tyner                 ss << "cfam 0x1007 = 0x";
77ef320154SBen Tyner                 ss << std::hex << std::setw(8) << std::setfill('0');
78*9dbab8beSBen Tyner                 ss << isr_val;
79ef320154SBen Tyner                 log<level::INFO>(ss.str().c_str());
80ef320154SBen Tyner 
81ef320154SBen Tyner                 // get interrupt enabled special attentions mask
82b481d905SBen Tyner                 if (RC_SUCCESS != fsi_read(target, 0x100d, &isr_mask))
83ef320154SBen Tyner                 {
84*9dbab8beSBen Tyner                     log<level::INFO>("Error! cfam read 0x100d FAILED");
85ef320154SBen Tyner                 }
86ef320154SBen Tyner                 else
87ef320154SBen Tyner                 {
88ef320154SBen Tyner                     std::stringstream ss; // log message stream
899ae5ca41SBen Tyner                     ss << "cfam 0x100d = 0x";
90ef320154SBen Tyner                     ss << std::hex << std::setw(8) << std::setfill('0');
91*9dbab8beSBen Tyner                     ss << isr_mask;
92ef320154SBen Tyner                     log<level::INFO>(ss.str().c_str());
93ef320154SBen Tyner 
94ef320154SBen Tyner                     // bit 0 on "left": bit 30 = SBE vital attention
95ef320154SBen Tyner                     if (isr_val & isr_mask & 0x00000002)
96ef320154SBen Tyner                     {
97b481d905SBen Tyner                         active_attentions.emplace_back(Attention::Vital,
98b481d905SBen Tyner                                                        handleVital, target,
99b481d905SBen Tyner                                                        i_breakpoints);
100ef320154SBen Tyner                     }
101ef320154SBen Tyner 
102ef320154SBen Tyner                     // bit 0 on "left": bit 1 = checkstop
103ef320154SBen Tyner                     if (isr_val & isr_mask & 0x40000000)
104ef320154SBen Tyner                     {
105b481d905SBen Tyner                         active_attentions.emplace_back(Attention::Checkstop,
106b481d905SBen Tyner                                                        handleCheckstop, target,
107b481d905SBen Tyner                                                        i_breakpoints);
108ef320154SBen Tyner                     }
109ef320154SBen Tyner 
110ef320154SBen Tyner                     // bit 0 on "left": bit 2 = special attention
111ef320154SBen Tyner                     if (isr_val & isr_mask & 0x20000000)
112ef320154SBen Tyner                     {
113b481d905SBen Tyner                         active_attentions.emplace_back(Attention::Special,
114b481d905SBen Tyner                                                        handleSpecial, target,
115b481d905SBen Tyner                                                        i_breakpoints);
116ef320154SBen Tyner                     }
117ef320154SBen Tyner                 } // cfam 0x100d valid
118ef320154SBen Tyner             }     // cfam 0x1007 valid
119ef320154SBen Tyner         }         // fsi target enabled
120ef320154SBen Tyner     }             // next processor
121ef320154SBen Tyner 
122b481d905SBen Tyner     // convert to heap, highest priority is at front
123b481d905SBen Tyner     if (!std::is_heap(active_attentions.begin(), active_attentions.end()))
124b481d905SBen Tyner     {
125b481d905SBen Tyner         std::make_heap(active_attentions.begin(), active_attentions.end());
126b481d905SBen Tyner     }
127b481d905SBen Tyner 
128b481d905SBen Tyner     // call the attention handler until one is handled or all were attempted
129b481d905SBen Tyner     while (false == active_attentions.empty())
130b481d905SBen Tyner     {
131b481d905SBen Tyner         // handle highest priority attention, done if successful
132b481d905SBen Tyner         if (RC_SUCCESS == active_attentions.front().handle())
133b481d905SBen Tyner         {
134b481d905SBen Tyner             break;
135b481d905SBen Tyner         }
136b481d905SBen Tyner 
137b481d905SBen Tyner         // move attention to back of vector
138b481d905SBen Tyner         std::pop_heap(active_attentions.begin(), active_attentions.end());
139b481d905SBen Tyner 
140b481d905SBen Tyner         // remove attention from vector
141b481d905SBen Tyner         active_attentions.pop_back();
142b481d905SBen Tyner     }
143ef320154SBen Tyner }
144ef320154SBen Tyner 
145ef320154SBen Tyner /**
146ef320154SBen Tyner  * @brief Handle SBE vital attention
147ef320154SBen Tyner  */
148b481d905SBen Tyner int handleVital(Attention* i_attention)
149ef320154SBen Tyner {
150b481d905SBen Tyner     int rc = RC_NOT_SUCCESS; // vital attention handling not yet supported
151ef320154SBen Tyner 
152*9dbab8beSBen Tyner     log<level::INFO>("vital");
153ef320154SBen Tyner 
154b481d905SBen Tyner     if (RC_SUCCESS != rc)
155ef320154SBen Tyner     {
156*9dbab8beSBen Tyner         log<level::INFO>("vital NOT handled");
157ef320154SBen Tyner     }
158ef320154SBen Tyner 
159ef320154SBen Tyner     return rc;
160ef320154SBen Tyner }
161ef320154SBen Tyner 
162ef320154SBen Tyner /**
163ef320154SBen Tyner  * @brief Handle checkstop attention
164ef320154SBen Tyner  */
165b481d905SBen Tyner int handleCheckstop(Attention* i_attention)
166ef320154SBen Tyner {
167b481d905SBen Tyner     int rc = RC_SUCCESS; // checkstop handling supported
168ef320154SBen Tyner 
169*9dbab8beSBen Tyner     log<level::INFO>("checkstop");
170ef320154SBen Tyner 
1710205f3b3SBen Tyner     analyzer::analyzeHardware();
172ef320154SBen Tyner 
173ef320154SBen Tyner     return rc;
174ef320154SBen Tyner }
175ef320154SBen Tyner 
176ef320154SBen Tyner /**
177ef320154SBen Tyner  * @brief Handle special attention
178ef320154SBen Tyner  */
179b481d905SBen Tyner int handleSpecial(Attention* i_attention)
180ef320154SBen Tyner {
181b481d905SBen Tyner     int rc = RC_SUCCESS; // special attention handling supported
182ef320154SBen Tyner 
183*9dbab8beSBen Tyner     log<level::INFO>("special");
184ef320154SBen Tyner 
185970fd4fbSBen Tyner     // Right now we always handle breakpoint special attentions if breakpoint
186970fd4fbSBen Tyner     // attn handling is enabled. This will eventually check if breakpoint attn
187970fd4fbSBen Tyner     // handing is enabled AND there is a breakpoint pending.
188b481d905SBen Tyner     if (0 != (i_attention->getFlags() & enableBreakpoints))
189970fd4fbSBen Tyner     {
190*9dbab8beSBen Tyner         log<level::INFO>("breakpoint");
191ef320154SBen Tyner 
1929ae5ca41SBen Tyner         // Call the breakpoint special attention handler
1939ae5ca41SBen Tyner         bpHandler();
194970fd4fbSBen Tyner     }
195970fd4fbSBen Tyner     // Right now if breakpoint attn handling is not enabled we will treat the
196970fd4fbSBen Tyner     // special attention as a TI. This will eventually be changed to check
197970fd4fbSBen Tyner     // whether a TI is active and handle it regardless of whether breakpoint
198970fd4fbSBen Tyner     // handling is enbaled or not.
199970fd4fbSBen Tyner     else
200970fd4fbSBen Tyner     {
201*9dbab8beSBen Tyner         log<level::INFO>("TI (terminate immediately)");
202970fd4fbSBen Tyner 
2039ae5ca41SBen Tyner         // Call TI special attention handler
2049ae5ca41SBen Tyner         tiHandler();
205970fd4fbSBen Tyner     }
206ef320154SBen Tyner 
207ef320154SBen Tyner     // TODO recoverable errors?
208ef320154SBen Tyner 
209ef320154SBen Tyner     return rc;
210ef320154SBen Tyner }
211ef320154SBen Tyner 
212ef320154SBen Tyner } // namespace attn
213