1 #include <attn/attention.hpp>
2 #include <attn/attn_common.hpp>
3 #include <attn/attn_dump.hpp>
4 #include <attn/attn_handler.hpp>
5 #include <attn/attn_logging.hpp>
6 #include <sdbusplus/bus.hpp>
7 #include <util/dbus.hpp>
8 #include <util/pdbg.hpp>
9 #include <util/pldm.hpp>
10 #include <util/trace.hpp>
11
12 namespace attn
13 {
14 /*
15 * @brief Request SBE hreset and try to clear sbe attentions
16 *
17 * @param[in] sbeInstance - sbe instance to hreset (0 based)
18 *
19 * @return true if hreset is successful and attentions cleared
20 */
attemptSbeRecovery(int sbeInstance)21 bool attemptSbeRecovery(int sbeInstance)
22 {
23 // attempt sbe hreset and attention interrupt clear
24 if (!util::pldm::hresetSbe(sbeInstance))
25 {
26 return false;
27 }
28
29 trace::inf("hreset completed");
30
31 // try to clear attention interrupts
32 clearAttnInterrupts();
33
34 // loop through processors checking attention interrupts
35 bool recovered = true;
36 pdbg_target* procTarget;
37 pdbg_for_each_class_target("proc", procTarget)
38 {
39 // active processors only
40 if (PDBG_TARGET_ENABLED !=
41 pdbg_target_probe(util::pdbg::getPibTrgt(procTarget)))
42 {
43 continue;
44 }
45
46 // get cfam is an fsi read
47 pdbg_target* fsiTarget = util::pdbg::getFsiTrgt(procTarget);
48 uint32_t int_val;
49
50 // get attention interrupts on processor
51 if (RC_SUCCESS == fsi_read(fsiTarget, 0x100b, &int_val))
52 {
53 if (int_val & SBE_ATTN)
54 {
55 trace::err("sbe attention did not clear");
56 recovered = false;
57 break;
58 }
59 }
60 else
61 {
62 // log cfam read error
63 trace::err("cfam read error");
64 recovered = false;
65 break;
66 }
67 }
68
69 if (recovered)
70 {
71 trace::inf("sbe attention cleared");
72 }
73
74 return recovered;
75 }
76
77 /**
78 * @brief Check for active checkstop attention
79 *
80 * @param procInstance - proc to check for attentions
81 *
82 * @pre pdbg target associated with proc instance is enabled for fsi access
83 *
84 * @return true if checkstop acive false otherwise
85 * */
checkstopActive(int procInstance)86 bool checkstopActive(int procInstance)
87 {
88 // get fsi target
89 char path[16];
90 sprintf(path, "/proc%d/fsi", procInstance);
91 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path);
92 if (nullptr == fsiTarget)
93 {
94 trace::inf("fsi path or target not found");
95 return false;
96 }
97
98 // check for active checkstop attention
99 int r;
100 uint32_t isr_val, isr_mask;
101
102 isr_val = 0xffffffff;
103 r = fsi_read(fsiTarget, 0x1007, &isr_val);
104 if ((RC_SUCCESS != r) || (0xffffffff == isr_val))
105 {
106 trace::err("cfam 1007 read error");
107 return false;
108 }
109
110 isr_mask = 0xffffffff;
111 r = fsi_read(fsiTarget, 0x100d, &isr_mask);
112 if ((RC_SUCCESS != r) || (0xffffffff == isr_mask))
113 {
114 trace::err("cfam 100d read error");
115 return false;
116 }
117
118 return activeAttn(isr_val, isr_mask, CHECKSTOP_ATTN);
119 }
120
121 /**
122 * @brief Handle SBE vital attention
123 *
124 * @param i_attention - attention object
125 *
126 * @return non-zero if attention was not successfully handled
127 */
handleVital(Attention * i_attention)128 int handleVital(Attention* i_attention)
129 {
130 trace::inf("vital handler started");
131
132 // if vital handling disabled
133 if (false == (i_attention->getConfig()->getFlag(enVital)))
134 {
135 trace::inf("vital handling disabled");
136 return RC_NOT_HANDLED;
137 }
138
139 // if power fault then we don't do anything
140 sleepSeconds(POWER_FAULT_WAIT);
141 if (util::dbus::powerFault())
142 {
143 trace::inf("power fault was reported");
144 return RC_SUCCESS;
145 }
146
147 // if no checkstop and host is running
148 int instance =
149 pdbg_target_index(i_attention->getTarget()); // get processor number
150
151 if (!checkstopActive(instance) &&
152 util::dbus::HostRunningState::Started == util::dbus::hostRunningState())
153 {
154 // attempt to recover the sbe
155 if (attemptSbeRecovery(instance))
156 {
157 eventVital(levelPelInfo);
158 return RC_SUCCESS;
159 }
160 }
161
162 // host not running, checkstop active or recovery failed
163 auto pelId = eventVital(levelPelError);
164 requestDump(pelId, DumpParameters{0, DumpType::SBE});
165 util::dbus::transitionHost(util::dbus::HostState::Quiesce);
166
167 return RC_SUCCESS;
168 }
169
170 } // namespace attn
171