1b1eda6a3SJayanth Othayoth extern "C"
2b1eda6a3SJayanth Othayoth {
3792f32f7SBen Tyner #include <libpdbg.h>
4b1eda6a3SJayanth Othayoth #include <libpdbg_sbe.h>
5b1eda6a3SJayanth Othayoth }
6792f32f7SBen Tyner 
7a06dcf82SZane Shelley #include <config.h>
8a06dcf82SZane Shelley 
9b9715179SBen Tyner #ifdef CONFIG_PHAL_API
10b9715179SBen Tyner #include <libphal.H>
11b9715179SBen Tyner #endif
12b9715179SBen Tyner 
130205f3b3SBen Tyner #include <analyzer/analyzer_main.hpp>
14b797b3e1SBen Tyner #include <attn/attention.hpp>
15bcf65a8bSBen Tyner #include <attn/attn_common.hpp>
16b797b3e1SBen Tyner #include <attn/attn_config.hpp>
174bbcb38fSBen Tyner #include <attn/attn_dbus.hpp>
18b797b3e1SBen Tyner #include <attn/attn_handler.hpp>
19b797b3e1SBen Tyner #include <attn/attn_logging.hpp>
20b797b3e1SBen Tyner #include <attn/bp_handler.hpp>
21b797b3e1SBen Tyner #include <attn/ti_handler.hpp>
22bcf65a8bSBen Tyner #include <attn/vital_handler.hpp>
23fe2c50d7SBen Tyner #include <util/dbus.hpp>
2476e52f6dSBen Tyner #include <util/ffdc_file.hpp>
256a69e6e5SBen Tyner #include <util/pdbg.hpp>
2676e52f6dSBen Tyner #include <util/trace.hpp>
27ef320154SBen Tyner 
28b481d905SBen Tyner #include <algorithm>
29ef320154SBen Tyner #include <iomanip>
30b1ebfcb1SBen Tyner #include <map>
319ae5ca41SBen Tyner #include <sstream>
32b481d905SBen Tyner #include <vector>
33ef320154SBen Tyner 
34ef320154SBen Tyner namespace attn
35ef320154SBen Tyner {
36ef320154SBen Tyner /**
37ef320154SBen Tyner  * @brief Handle checkstop attention
38ef320154SBen Tyner  *
39b481d905SBen Tyner  * @param i_attention Attention object
403fb52e53SBen Tyner  * @return 0 indicates that the checkstop attention was successfully handled
413fb52e53SBen Tyner  *         1 indicates that the checkstop attention was NOT successfully
423fb52e53SBen Tyner  *           handled.
43ef320154SBen Tyner  */
44b481d905SBen Tyner int handleCheckstop(Attention* i_attention);
45ef320154SBen Tyner 
46ef320154SBen Tyner /**
47ef320154SBen Tyner  * @brief Handle special attention
48ef320154SBen Tyner  *
49b481d905SBen Tyner  * @param i_attention Attention object
503fb52e53SBen Tyner  * @return 0 indicates that the special attention was successfully handled
513fb52e53SBen Tyner  *         1 indicates that the special attention was NOT successfully handled
52ef320154SBen Tyner  */
53b481d905SBen Tyner int handleSpecial(Attention* i_attention);
54ef320154SBen Tyner 
55b9715179SBen Tyner #ifdef CONFIG_PHAL_API
56b9715179SBen Tyner /** @brief Handle phal sbe exception */
57b9715179SBen Tyner void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e,
5876e52f6dSBen Tyner                              uint32_t chipPosition, uint32_t command);
59b9715179SBen Tyner #endif
60b9715179SBen Tyner 
61b9715179SBen Tyner /** @brief Get static TI info data based on host state */
62b9715179SBen Tyner void getStaticTiInfo(uint8_t*& tiInfoPtr);
63b9715179SBen Tyner 
64b9715179SBen Tyner /** @brief Check if TI info data is valid */
65b9715179SBen Tyner bool tiInfoValid(uint8_t* tiInfo);
66b9715179SBen Tyner 
67ef320154SBen Tyner /**
68ef320154SBen Tyner  * @brief The main attention handler logic
69970fd4fbSBen Tyner  *
70970fd4fbSBen Tyner  * @param i_breakpoints true = breakpoint special attn handling enabled
71ef320154SBen Tyner  */
attnHandler(Config * i_config)723fb52e53SBen Tyner void attnHandler(Config* i_config)
73ef320154SBen Tyner {
74d28d5f8bSaustinfcui     // Check if enClrAttnIntr is enabled
75d28d5f8bSaustinfcui     if (true == i_config->getFlag(enClrAttnIntr))
76d28d5f8bSaustinfcui     {
776a69e6e5SBen Tyner         // Clear attention interrupts that may still be active (MPIPL)
786a69e6e5SBen Tyner         clearAttnInterrupts();
79d28d5f8bSaustinfcui     }
806a69e6e5SBen Tyner 
81b481d905SBen Tyner     // Vector of active attentions to be handled
82b481d905SBen Tyner     std::vector<Attention> active_attentions;
83b481d905SBen Tyner 
84ef320154SBen Tyner     uint32_t isr_val, isr_mask;
85ef320154SBen Tyner 
86ef320154SBen Tyner     // loop through processors looking for active attentions
87bfa831a8Saustinfcui     trace::inf("Attention handler started");
88117af99bSBen Tyner 
89ef320154SBen Tyner     pdbg_target* target;
905e622d87SBen Tyner     pdbg_for_each_class_target("proc", target)
91ef320154SBen Tyner     {
92ef320154SBen Tyner         if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
93ef320154SBen Tyner         {
94a79f6c8fSZane Shelley             auto proc = pdbg_target_index(target); // get processor number
95ef320154SBen Tyner 
96b83c852aSBen Tyner             // Use PIB target to determine if a processor is enabled
975e622d87SBen Tyner             char path[16];
98b83c852aSBen Tyner             sprintf(path, "/proc%d/pib", proc);
998882c32aSBen Tyner             pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path);
1005e622d87SBen Tyner 
101b83c852aSBen Tyner             // sanity check
1028882c32aSBen Tyner             if (nullptr == pibTarget)
103b83c852aSBen Tyner             {
104bfa831a8Saustinfcui                 trace::inf("pib path or target not found");
105b83c852aSBen Tyner                 continue;
106b83c852aSBen Tyner             }
107b83c852aSBen Tyner 
1088882c32aSBen Tyner             // check if pib target is enabled
1098882c32aSBen Tyner             if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget))
1105e622d87SBen Tyner             {
111b83c852aSBen Tyner                 // The processor FSI target is required for CFAM read
112b83c852aSBen Tyner                 sprintf(path, "/proc%d/fsi", proc);
1138882c32aSBen Tyner                 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path);
114b83c852aSBen Tyner 
115b83c852aSBen Tyner                 // sanity check
1168882c32aSBen Tyner                 if (nullptr == fsiTarget)
117b83c852aSBen Tyner                 {
118bfa831a8Saustinfcui                     trace::inf("fsi path or target not found");
119b83c852aSBen Tyner                     continue;
120b83c852aSBen Tyner                 }
121b83c852aSBen Tyner 
1228882c32aSBen Tyner                 // trace the proc number
123bfa831a8Saustinfcui                 trace::inf("proc: %u", proc);
1241965e504SBen Tyner 
1255adc96eeSBen Tyner                 isr_val = 0xffffffff; // invalid isr value
1265adc96eeSBen Tyner 
127ef320154SBen Tyner                 // get active attentions on processor
1288882c32aSBen Tyner                 if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val))
129ef320154SBen Tyner                 {
130fb190545SBen Tyner                     // log cfam read error
131bfa831a8Saustinfcui                     trace::err("cfam read 0x1007 FAILED");
1327a0dd543SBen Tyner                     eventAttentionFail((int)AttnSection::attnHandler |
1337a0dd543SBen Tyner                                        ATTN_PDBG_CFAM);
134ef320154SBen Tyner                 }
1355adc96eeSBen Tyner                 else if (0xffffffff == isr_val)
1365adc96eeSBen Tyner                 {
137bfa831a8Saustinfcui                     trace::err("cfam read 0x1007 INVALID");
1385adc96eeSBen Tyner                     continue;
1395adc96eeSBen Tyner                 }
140ef320154SBen Tyner                 else
141ef320154SBen Tyner                 {
1428882c32aSBen Tyner                     // trace isr value
143bfa831a8Saustinfcui                     trace::inf("cfam 0x1007 = 0x%08x", isr_val);
1441965e504SBen Tyner 
1455adc96eeSBen Tyner                     isr_mask = 0xffffffff; // invalid isr mask
1465adc96eeSBen Tyner 
147ef320154SBen Tyner                     // get interrupt enabled special attentions mask
1488882c32aSBen Tyner                     if (RC_SUCCESS != fsi_read(fsiTarget, 0x100d, &isr_mask))
149ef320154SBen Tyner                     {
150fb190545SBen Tyner                         // log cfam read error
151bfa831a8Saustinfcui                         trace::err("cfam read 0x100d FAILED");
1527a0dd543SBen Tyner                         eventAttentionFail((int)AttnSection::attnHandler |
1537a0dd543SBen Tyner                                            ATTN_PDBG_CFAM);
154ef320154SBen Tyner                     }
1555adc96eeSBen Tyner                     else if (0xffffffff == isr_mask)
1565adc96eeSBen Tyner                     {
157bfa831a8Saustinfcui                         trace::err("cfam read 0x100d INVALID");
1585adc96eeSBen Tyner                         continue;
1595adc96eeSBen Tyner                     }
160ef320154SBen Tyner                     else
161ef320154SBen Tyner                     {
1628882c32aSBen Tyner                         // trace true mask
163bfa831a8Saustinfcui                         trace::inf("cfam 0x100d = 0x%08x", isr_mask);
1641965e504SBen Tyner 
165fb190545SBen Tyner                         // SBE vital attention active and not masked?
1661965e504SBen Tyner                         if (true == activeAttn(isr_val, isr_mask, SBE_ATTN))
167ef320154SBen Tyner                         {
1685e622d87SBen Tyner                             active_attentions.emplace_back(Attention::Vital,
1695e622d87SBen Tyner                                                            handleVital, target,
1705e622d87SBen Tyner                                                            i_config);
171ef320154SBen Tyner                         }
172ef320154SBen Tyner 
173fb190545SBen Tyner                         // Checkstop attention active and not masked?
174fb190545SBen Tyner                         if (true ==
1751965e504SBen Tyner                             activeAttn(isr_val, isr_mask, CHECKSTOP_ATTN))
176ef320154SBen Tyner                         {
177b481d905SBen Tyner                             active_attentions.emplace_back(Attention::Checkstop,
1785e622d87SBen Tyner                                                            handleCheckstop,
1795e622d87SBen Tyner                                                            target, i_config);
180ef320154SBen Tyner                         }
181ef320154SBen Tyner 
182fb190545SBen Tyner                         // Special attention active and not masked?
1831965e504SBen Tyner                         if (true == activeAttn(isr_val, isr_mask, SPECIAL_ATTN))
184ef320154SBen Tyner                         {
185b481d905SBen Tyner                             active_attentions.emplace_back(Attention::Special,
1865e622d87SBen Tyner                                                            handleSpecial,
1875e622d87SBen Tyner                                                            target, i_config);
188ef320154SBen Tyner                         }
189ef320154SBen Tyner                     } // cfam 0x100d valid
190ef320154SBen Tyner                 }     // cfam 0x1007 valid
191ef320154SBen Tyner             }         // fsi target enabled
1928882c32aSBen Tyner         }             // pib target enabled
193ef320154SBen Tyner     }                 // next processor
194ef320154SBen Tyner 
195b481d905SBen Tyner     // convert to heap, highest priority is at front
196b481d905SBen Tyner     if (!std::is_heap(active_attentions.begin(), active_attentions.end()))
197b481d905SBen Tyner     {
198b481d905SBen Tyner         std::make_heap(active_attentions.begin(), active_attentions.end());
199b481d905SBen Tyner     }
200b481d905SBen Tyner 
201b481d905SBen Tyner     // call the attention handler until one is handled or all were attempted
202b481d905SBen Tyner     while (false == active_attentions.empty())
203b481d905SBen Tyner     {
204b481d905SBen Tyner         // handle highest priority attention, done if successful
205b481d905SBen Tyner         if (RC_SUCCESS == active_attentions.front().handle())
206b481d905SBen Tyner         {
207b1ebfcb1SBen Tyner             // an attention was handled so we are done
208b481d905SBen Tyner             break;
209b481d905SBen Tyner         }
210b481d905SBen Tyner 
211b481d905SBen Tyner         // move attention to back of vector
212b481d905SBen Tyner         std::pop_heap(active_attentions.begin(), active_attentions.end());
213b481d905SBen Tyner 
214b481d905SBen Tyner         // remove attention from vector
215b481d905SBen Tyner         active_attentions.pop_back();
216b481d905SBen Tyner     }
217ef320154SBen Tyner }
218ef320154SBen Tyner 
219ef320154SBen Tyner /**
220ef320154SBen Tyner  * @brief Handle checkstop attention
2213fb52e53SBen Tyner  *
2223fb52e53SBen Tyner  * @param i_attention Attention object
2233fb52e53SBen Tyner  * @return 0 indicates that the checkstop attention was successfully handled
2243fb52e53SBen Tyner  *         1 indicates that the checkstop attention was NOT successfully
2253fb52e53SBen Tyner  *           handled.
226ef320154SBen Tyner  */
handleCheckstop(Attention * i_attention)227b481d905SBen Tyner int handleCheckstop(Attention* i_attention)
228ef320154SBen Tyner {
2293fb52e53SBen Tyner     int rc = RC_SUCCESS; // assume checkstop handled
230ef320154SBen Tyner 
231bfa831a8Saustinfcui     trace::inf("checkstop handler started");
232b1ebfcb1SBen Tyner 
233b8335568SBen Tyner     // capture some additional data for logs/traces
234b8335568SBen Tyner     addHbStatusRegs();
235b8335568SBen Tyner 
2363fb52e53SBen Tyner     // if checkstop handling enabled, handle checkstop attention
2373fb52e53SBen Tyner     if (false == (i_attention->getConfig()->getFlag(enCheckstop)))
2383fb52e53SBen Tyner     {
239bfa831a8Saustinfcui         trace::inf("Checkstop handling disabled");
2403fb52e53SBen Tyner     }
2413fb52e53SBen Tyner     else
2423fb52e53SBen Tyner     {
2432b26b2bbSBen Tyner         // check for power fault before starting analyses
24407ebb9beSBen Tyner         sleepSeconds(POWER_FAULT_WAIT);
2452b26b2bbSBen Tyner         if (!util::dbus::powerFault())
2462b26b2bbSBen Tyner         {
2479fb7393eSZane Shelley             // Look for any attentions found in hardware. This will generate and
2487ae9c8c7SZane Shelley             // commit a PEL if any errors are found.
2497029e525SBen Tyner             DumpParameters dumpParameters;
250ebff0d37SZane Shelley             auto logid = analyzer::analyzeHardware(
251ebff0d37SZane Shelley                 analyzer::AnalysisType::SYSTEM_CHECKSTOP, dumpParameters);
252611b3442SZane Shelley             if (0 == logid)
253b1ebfcb1SBen Tyner             {
254611b3442SZane Shelley                 // A PEL should exist for a checkstop attention.
255b1ebfcb1SBen Tyner                 rc = RC_ANALYZER_ERROR;
256b1ebfcb1SBen Tyner             }
2577029e525SBen Tyner             else
2587029e525SBen Tyner             {
259611b3442SZane Shelley                 requestDump(logid, dumpParameters);
2607029e525SBen Tyner                 util::dbus::transitionHost(util::dbus::HostState::Quiesce);
2617029e525SBen Tyner             }
2623fb52e53SBen Tyner         }
2632b26b2bbSBen Tyner     }
264ef320154SBen Tyner 
265ef320154SBen Tyner     return rc;
266ef320154SBen Tyner }
267ef320154SBen Tyner 
268ef320154SBen Tyner /**
269ef320154SBen Tyner  * @brief Handle special attention
2703fb52e53SBen Tyner  *
2713fb52e53SBen Tyner  * @param i_attention Attention object
2723fb52e53SBen Tyner  * @return 0 indicates that the special attention was successfully handled
2733fb52e53SBen Tyner  *         1 indicates that the special attention was NOT successfully handled
274ef320154SBen Tyner  */
handleSpecial(Attention * i_attention)275b481d905SBen Tyner int handleSpecial(Attention* i_attention)
276ef320154SBen Tyner {
277b1ebfcb1SBen Tyner     int rc = RC_SUCCESS; // assume special attention handled
278ef320154SBen Tyner 
279fb190545SBen Tyner     // The TI info chipop will give us a pointer to the TI info data
280792f32f7SBen Tyner     uint8_t* tiInfo = nullptr;                        // ptr to TI info data
281792f32f7SBen Tyner     uint32_t tiInfoLen = 0;                           // length of TI info data
28298430b30SBen Tyner     pdbg_target* attnProc = i_attention->getTarget(); // proc with attention
283b1ebfcb1SBen Tyner 
28429651ef8SBen Tyner     bool tiInfoStatic = false; // assume TI info was provided (not created)
28529651ef8SBen Tyner 
286b9715179SBen Tyner     // need proc target to get dynamic TI info
287b9715179SBen Tyner     if (nullptr != attnProc)
28898430b30SBen Tyner     {
289b9715179SBen Tyner #ifdef CONFIG_PHAL_API
290bfa831a8Saustinfcui         trace::inf("using libphal to get TI info");
291b9715179SBen Tyner 
292b9715179SBen Tyner         // phal library uses proc target for get ti info
293b9715179SBen Tyner         if (PDBG_TARGET_ENABLED == pdbg_target_probe(attnProc))
294b9715179SBen Tyner         {
295b9715179SBen Tyner             try
296b9715179SBen Tyner             {
297b9715179SBen Tyner                 // get dynamic TI info
298b9715179SBen Tyner                 openpower::phal::sbe::getTiInfo(attnProc, &tiInfo, &tiInfoLen);
299b9715179SBen Tyner             }
30076e52f6dSBen Tyner             catch (openpower::phal::exception::SbeError& sbeError)
301b9715179SBen Tyner             {
302b9715179SBen Tyner                 // library threw an exception
30376e52f6dSBen Tyner                 // note: phal::sbe::getTiInfo = command class | command ==
30476e52f6dSBen Tyner                 // 0xa900 | 0x04 = 0xa904. The sbe fifo command class and
3056a69e6e5SBen Tyner                 // commands are defined in the sbefifo library source code
3066a69e6e5SBen Tyner                 // but do not seem to be exported/installed for consumption
30776e52f6dSBen Tyner                 // externally.
308b9715179SBen Tyner                 uint32_t procNum = pdbg_target_index(attnProc);
30976e52f6dSBen Tyner                 phalSbeExceptionHandler(sbeError, procNum, 0xa904);
310b9715179SBen Tyner             }
311b9715179SBen Tyner         }
312b9715179SBen Tyner #else
313bfa831a8Saustinfcui         trace::inf("using libpdbg to get TI info");
314b9715179SBen Tyner 
315b9715179SBen Tyner         // pdbg library uses pib target for get ti info
31698430b30SBen Tyner         char path[16];
31798430b30SBen Tyner         sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc));
31898430b30SBen Tyner         pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path);
31989c0a7afSBen Tyner 
32098430b30SBen Tyner         if (nullptr != tiInfoTarget)
32189c0a7afSBen Tyner         {
32289c0a7afSBen Tyner             if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget))
32389c0a7afSBen Tyner             {
324792f32f7SBen Tyner                 sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen);
325b9715179SBen Tyner             }
326b9715179SBen Tyner         }
327b9715179SBen Tyner #endif
328b9715179SBen Tyner     }
3294bbcb38fSBen Tyner 
330b9715179SBen Tyner     // dynamic TI info is not available
3314bbcb38fSBen Tyner     if (nullptr == tiInfo)
33298430b30SBen Tyner     {
333bfa831a8Saustinfcui         trace::inf("TI info data ptr is invalid");
334b9715179SBen Tyner         getStaticTiInfo(tiInfo);
335b9715179SBen Tyner         tiInfoStatic = true;
336b9715179SBen Tyner     }
3374bbcb38fSBen Tyner 
338b9715179SBen Tyner     // check TI info for validity and handle
339b9715179SBen Tyner     if (true == tiInfoValid(tiInfo))
3404bbcb38fSBen Tyner     {
341b9715179SBen Tyner         // TI info is valid handle TI if support enabled
3423fb52e53SBen Tyner         if (true == (i_attention->getConfig()->getFlag(enTerminate)))
343970fd4fbSBen Tyner         {
3449ae5ca41SBen Tyner             // Call TI special attention handler
345b9715179SBen Tyner             rc = tiHandler((TiDataArea*)tiInfo);
3463fb52e53SBen Tyner         }
347792f32f7SBen Tyner     }
348b9715179SBen Tyner     else
3493fb52e53SBen Tyner     {
350bfa831a8Saustinfcui         trace::inf("TI info NOT valid");
351e4f5dbefSBen Tyner 
352e4f5dbefSBen Tyner         // if configured to handle TI as default special attention
353fe15649eSBen Tyner         if (i_attention->getConfig()->getFlag(dfltTi))
354e4f5dbefSBen Tyner         {
355fe15649eSBen Tyner             // TI handling may be disabled
356e4f5dbefSBen Tyner             if (true == (i_attention->getConfig()->getFlag(enTerminate)))
357e4f5dbefSBen Tyner             {
358e4f5dbefSBen Tyner                 // Call TI special attention handler
359b9715179SBen Tyner                 rc = tiHandler((TiDataArea*)tiInfo);
360e4f5dbefSBen Tyner             }
361e4f5dbefSBen Tyner         }
362b9715179SBen Tyner         // configured to handle breakpoint as default special attention
363fe15649eSBen Tyner         else
364fe15649eSBen Tyner         {
365fe15649eSBen Tyner             // breakpoint handling may be disabled
366fe15649eSBen Tyner             if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
367fe15649eSBen Tyner             {
368fe15649eSBen Tyner                 // Call the breakpoint special attention handler
369fe15649eSBen Tyner                 rc = bpHandler();
370fe15649eSBen Tyner             }
371fe15649eSBen Tyner         }
372e4f5dbefSBen Tyner     }
373ef320154SBen Tyner 
374b9715179SBen Tyner     // release TI data buffer if not ours
375b9715179SBen Tyner     if (false == tiInfoStatic)
376b9715179SBen Tyner     {
377b9715179SBen Tyner         // sanity check
378b9715179SBen Tyner         if (nullptr != tiInfo)
379792f32f7SBen Tyner         {
380792f32f7SBen Tyner             free(tiInfo);
381792f32f7SBen Tyner         }
382b9715179SBen Tyner     }
383792f32f7SBen Tyner 
384b9715179SBen Tyner     // trace non-successful exit condition
3853fb52e53SBen Tyner     if (RC_SUCCESS != rc)
3863fb52e53SBen Tyner     {
387bfa831a8Saustinfcui         trace::inf("Special attn not handled");
3883fb52e53SBen Tyner     }
389ef320154SBen Tyner 
390ef320154SBen Tyner     return rc;
391ef320154SBen Tyner }
392ef320154SBen Tyner 
393*90516851SBen Tyner /** @brief Determine if attention is active and not masked */
activeAttn(uint32_t i_val,uint32_t i_mask,uint32_t i_attn)3941965e504SBen Tyner bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn)
395fb190545SBen Tyner {
396fb190545SBen Tyner     bool rc = false; // assume attn masked and/or inactive
397fb190545SBen Tyner 
398fb190545SBen Tyner     // if attention active
399fb190545SBen Tyner     if (0 != (i_val & i_attn))
400fb190545SBen Tyner     {
401bfa831a8Saustinfcui         std::string msg;
402fb190545SBen Tyner 
4039fb657f9SZane Shelley         bool validAttn = true; // known attention type
4049fb657f9SZane Shelley 
405fb190545SBen Tyner         switch (i_attn)
406fb190545SBen Tyner         {
407fb190545SBen Tyner             case SBE_ATTN:
408bfa831a8Saustinfcui                 msg = "SBE attn";
409fb190545SBen Tyner                 break;
410fb190545SBen Tyner             case CHECKSTOP_ATTN:
411bfa831a8Saustinfcui                 msg = "Checkstop attn";
412fb190545SBen Tyner                 break;
413fb190545SBen Tyner             case SPECIAL_ATTN:
414bfa831a8Saustinfcui                 msg = "Special attn";
415fb190545SBen Tyner                 break;
416fb190545SBen Tyner             default:
417bfa831a8Saustinfcui                 msg = "Unknown attn";
418fb190545SBen Tyner                 validAttn = false;
419fb190545SBen Tyner         }
420fb190545SBen Tyner 
421fb190545SBen Tyner         // see if attention is masked
422fb190545SBen Tyner         if (true == validAttn)
423fb190545SBen Tyner         {
424fb190545SBen Tyner             if (0 != (i_mask & i_attn))
425fb190545SBen Tyner             {
426fb190545SBen Tyner                 rc = true; // attention active and not masked
427fb190545SBen Tyner             }
428fb190545SBen Tyner             else
429fb190545SBen Tyner             {
430bfa831a8Saustinfcui                 msg += " masked";
431fb190545SBen Tyner             }
432fb190545SBen Tyner         }
433fb190545SBen Tyner 
434bfa831a8Saustinfcui         trace::inf(msg.c_str()); // commit trace stream
435fb190545SBen Tyner     }
436fb190545SBen Tyner 
437fb190545SBen Tyner     return rc;
438fb190545SBen Tyner }
439b9715179SBen Tyner 
440b9715179SBen Tyner #ifdef CONFIG_PHAL_API
44176e52f6dSBen Tyner 
442b9715179SBen Tyner /**
443b9715179SBen Tyner  * @brief Handle phal sbe exception
444b9715179SBen Tyner  *
445b9715179SBen Tyner  * @param[in] e - exception object
446b9715179SBen Tyner  * @param[in] procNum - processor number associated with sbe exception
447b9715179SBen Tyner  */
phalSbeExceptionHandler(openpower::phal::exception::SbeError & sbeError,uint32_t chipPosition,uint32_t command)44876e52f6dSBen Tyner void phalSbeExceptionHandler(openpower::phal::exception::SbeError& sbeError,
44976e52f6dSBen Tyner                              uint32_t chipPosition, uint32_t command)
450b9715179SBen Tyner {
45176e52f6dSBen Tyner     trace::err("Attention handler phal exception handler");
452b9715179SBen Tyner 
45376e52f6dSBen Tyner     // Trace exception details
45476e52f6dSBen Tyner     trace::err(sbeError.what());
45576e52f6dSBen Tyner 
45676e52f6dSBen Tyner     // Create event log entry with SBE FFDC data if provided
45776e52f6dSBen Tyner     auto fd = sbeError.getFd();
45876e52f6dSBen Tyner     if (fd > 0)
459b9715179SBen Tyner     {
46076e52f6dSBen Tyner         trace::err("SBE FFDC data is available");
46176e52f6dSBen Tyner 
46276e52f6dSBen Tyner         // FFDC parser expects chip position and command (command class |
46376e52f6dSBen Tyner         // command) to be in the additional data.
46476e52f6dSBen Tyner         std::map<std::string, std::string> additionalData = {
46576e52f6dSBen Tyner             {"SRC6", std::to_string((chipPosition << 16) | command)}};
46676e52f6dSBen Tyner 
4676a69e6e5SBen Tyner         // See phosphor-logging/extensions/openpower-pels/README.md, "Self
4686a69e6e5SBen Tyner         // Boot Engine(SBE) First Failure Data Capture(FFDC)" - SBE FFDC
4696a69e6e5SBen Tyner         // file type is 0xCB, version is 0x01.
47076e52f6dSBen Tyner         std::vector<util::FFDCTuple> ffdc{util::FFDCTuple{
47176e52f6dSBen Tyner             util::FFDCFormat::Custom, static_cast<uint8_t>(0xCB),
47276e52f6dSBen Tyner             static_cast<uint8_t>(0x01), fd}};
47376e52f6dSBen Tyner 
47476e52f6dSBen Tyner         // Create event log entry with FFDC data
4751315968cSBen Tyner         util::dbus::createPel("org.open_power.Processor.Error.SbeChipOpFailure",
4761315968cSBen Tyner                               levelPelError, additionalData, ffdc);
477b9715179SBen Tyner     }
478b9715179SBen Tyner }
479b9715179SBen Tyner #endif
480b9715179SBen Tyner 
481b9715179SBen Tyner /**
482b9715179SBen Tyner  * @brief Get static TI info data based on host state
483b9715179SBen Tyner  *
484b9715179SBen Tyner  * @param[out] tiInfo - pointer to static TI info data
485b9715179SBen Tyner  */
getStaticTiInfo(uint8_t * & tiInfo)486b9715179SBen Tyner void getStaticTiInfo(uint8_t*& tiInfo)
487b9715179SBen Tyner {
488b9715179SBen Tyner     util::dbus::HostRunningState runningState = util::dbus::hostRunningState();
489b9715179SBen Tyner 
490b9715179SBen Tyner     // assume host state is unknown
491b9715179SBen Tyner     std::string stateString = "host state unknown";
492b9715179SBen Tyner 
493b9715179SBen Tyner     if ((util::dbus::HostRunningState::Started == runningState) ||
494b9715179SBen Tyner         (util::dbus::HostRunningState::Unknown == runningState))
495b9715179SBen Tyner     {
496b9715179SBen Tyner         if (util::dbus::HostRunningState::Started == runningState)
497b9715179SBen Tyner         {
498b9715179SBen Tyner             stateString = "host started";
499b9715179SBen Tyner         }
500b9715179SBen Tyner         tiInfo = (uint8_t*)defaultPhypTiInfo;
501b9715179SBen Tyner     }
502b9715179SBen Tyner     else
503b9715179SBen Tyner     {
504b9715179SBen Tyner         stateString = "host not started";
505b9715179SBen Tyner         tiInfo = (uint8_t*)defaultHbTiInfo;
506b9715179SBen Tyner     }
507b9715179SBen Tyner 
508b9715179SBen Tyner     // trace host state
509bfa831a8Saustinfcui     trace::inf(stateString.c_str());
510b9715179SBen Tyner }
511b9715179SBen Tyner 
512b9715179SBen Tyner /**
513b9715179SBen Tyner  * @brief Check if TI info data is valid
514b9715179SBen Tyner  *
515b9715179SBen Tyner  * @param[in] tiInfo - pointer to TI info data
516b9715179SBen Tyner  * @return true if TI info data is valid, else false
517b9715179SBen Tyner  */
tiInfoValid(uint8_t * tiInfo)518b9715179SBen Tyner bool tiInfoValid(uint8_t* tiInfo)
519b9715179SBen Tyner {
520b9715179SBen Tyner     bool tiInfoValid = false; // assume TI info invalid
521b9715179SBen Tyner 
522b9715179SBen Tyner     // TI info data[0] non-zero indicates TI info valid (usually)
523b9715179SBen Tyner     if ((nullptr != tiInfo) && (0 != tiInfo[0]))
524b9715179SBen Tyner     {
525b9715179SBen Tyner         TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
526b9715179SBen Tyner 
527b9715179SBen Tyner         // trace a few known TI data area values
528535a8d4aSBen Tyner         trace::inf("TI data command = 0x%02x", tiDataArea->command);
529b9715179SBen Tyner 
530b9715179SBen Tyner         // Another check for valid TI Info since it has been seen that
531b9715179SBen Tyner         // tiInfo[0] != 0 but TI info is not valid
532b9715179SBen Tyner         if (0xa1 == tiDataArea->command)
533b9715179SBen Tyner         {
534b9715179SBen Tyner             tiInfoValid = true;
535b9715179SBen Tyner 
536b9715179SBen Tyner             // trace some more data since TI info appears valid
537535a8d4aSBen Tyner             trace::inf("TI data term-type = 0x%02x",
538bfa831a8Saustinfcui                        tiDataArea->hbTerminateType);
539b9715179SBen Tyner 
540535a8d4aSBen Tyner             trace::inf("TI data SRC format = 0x%02x", tiDataArea->srcFormat);
541b9715179SBen Tyner 
542535a8d4aSBen Tyner             trace::inf("TI data source = 0x%02x", tiDataArea->source);
543b9715179SBen Tyner         }
544b9715179SBen Tyner     }
545b9715179SBen Tyner 
546b9715179SBen Tyner     return tiInfoValid;
547b9715179SBen Tyner }
548b9715179SBen Tyner 
549*90516851SBen Tyner /** @brief Clear attention interrupts */
clearAttnInterrupts()5506a69e6e5SBen Tyner void clearAttnInterrupts()
5516a69e6e5SBen Tyner {
5526a69e6e5SBen Tyner     trace::inf("Clearing attention interrupts");
5536a69e6e5SBen Tyner 
5546a69e6e5SBen Tyner     // loop through processors clearing attention interrupts
5556a69e6e5SBen Tyner     pdbg_target* procTarget;
5566a69e6e5SBen Tyner     pdbg_for_each_class_target("proc", procTarget)
5576a69e6e5SBen Tyner     {
5586a69e6e5SBen Tyner         // active processors only
5596a69e6e5SBen Tyner         if (PDBG_TARGET_ENABLED !=
5606a69e6e5SBen Tyner             pdbg_target_probe(util::pdbg::getPibTrgt(procTarget)))
5616a69e6e5SBen Tyner         {
5626a69e6e5SBen Tyner             continue;
5636a69e6e5SBen Tyner         }
5646a69e6e5SBen Tyner 
5656a69e6e5SBen Tyner         // get cfam is an fsi read
5666a69e6e5SBen Tyner         pdbg_target* fsiTarget = util::pdbg::getFsiTrgt(procTarget);
5676a69e6e5SBen Tyner         uint32_t int_val;
5686a69e6e5SBen Tyner 
5696a69e6e5SBen Tyner         // get attention interrupts on processor
5706a69e6e5SBen Tyner         if (RC_SUCCESS == fsi_read(fsiTarget, 0x100b, &int_val))
5716a69e6e5SBen Tyner         {
5726a69e6e5SBen Tyner             // trace int value
5736a69e6e5SBen Tyner             trace::inf("cfam 0x100b = 0x%08x", int_val);
5746a69e6e5SBen Tyner 
5756a69e6e5SBen Tyner             int_val &= ~(ANY_ATTN | CHECKSTOP_ATTN | SPECIAL_ATTN |
5766a69e6e5SBen Tyner                          RECOVERABLE_ATTN | SBE_ATTN);
5776a69e6e5SBen Tyner 
5786a69e6e5SBen Tyner             // clear attention interrupts on processor
5796a69e6e5SBen Tyner             if (RC_SUCCESS != fsi_write(fsiTarget, 0x100b, int_val))
5806a69e6e5SBen Tyner             {
5816a69e6e5SBen Tyner                 // log cfam write error
5826a69e6e5SBen Tyner                 trace::err("cfam write 0x100b FAILED");
5836a69e6e5SBen Tyner             }
5846a69e6e5SBen Tyner         }
5856a69e6e5SBen Tyner         else
5866a69e6e5SBen Tyner         {
5876a69e6e5SBen Tyner             // log cfam read error
5886a69e6e5SBen Tyner             trace::err("cfam read 0x100b FAILED");
5896a69e6e5SBen Tyner         }
5906a69e6e5SBen Tyner     }
5916a69e6e5SBen Tyner }
5926a69e6e5SBen Tyner 
593ef320154SBen Tyner } // namespace attn
594