xref: /openbmc/openpower-hw-diags/attn/attn_common.cpp (revision 07ebb9be50d6a449971e4ae36f5fd712a6d09d5a)
1 #include <libpdbg.h>
2 
3 #include <attn/attn_common.hpp>
4 #include <attn/attn_handler.hpp>
5 #include <attn/attn_logging.hpp>
6 #include <sdbusplus/bus.hpp>
7 #include <util/pdbg.hpp>
8 
9 #include <iomanip>
10 #include <iostream>
11 #include <map>
12 
13 namespace attn
14 {
15 
16 /** @brief Traces some regs for hostboot */
17 void addHbStatusRegs()
18 {
19     // Only do this for P10 systems
20     if (util::pdbg::queryHardwareAnalysisSupported())
21     {
22         // We only need this for PRIMARY processor
23         pdbg_target* pibTarget = pdbg_target_from_path(nullptr, "/proc0/pib");
24         pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi");
25 
26         uint32_t l_cfamData  = 0xFFFFFFFF;
27         uint64_t l_scomData1 = 0xFFFFFFFFFFFFFFFFull;
28         uint64_t l_scomData2 = 0xFFFFFFFFFFFFFFFFull;
29         uint32_t l_cfamAddr  = 0x283C;
30         uint64_t l_scomAddr1 = 0x4602F489;
31         uint64_t l_scomAddr2 = 0x4602F487;
32 
33         if ((nullptr != fsiTarget) && (nullptr != pibTarget))
34         {
35             // buffer for formatted strings (+1 for null, just in case)
36             char buffer[sizeof("some read error: 0x0123456789ABCDEF ")];
37 
38             // get first debug reg (CFAM)
39             if (RC_SUCCESS != fsi_read(fsiTarget, l_cfamAddr, &l_cfamData))
40             {
41                 sprintf(buffer, "cfam read error: 0x%08x", l_cfamAddr);
42                 trace<level::ERROR>(buffer);
43                 l_cfamData = 0xFFFFFFFF;
44             }
45 
46             // Get SCOM regs next (just 2 of them)
47             if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr1, &l_scomData1))
48             {
49                 sprintf(buffer, "scom read error: 0x%016" PRIx64 "",
50                         l_scomAddr1);
51                 trace<level::ERROR>(buffer);
52                 l_scomData1 = 0xFFFFFFFFFFFFFFFFull;
53             }
54 
55             if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr2, &l_scomData2))
56             {
57                 sprintf(buffer, "scom read error: 0x%016" PRIx64 "",
58                         l_scomAddr2);
59                 trace<level::ERROR>(buffer);
60                 l_scomData2 = 0xFFFFFFFFFFFFFFFFull;
61             }
62         }
63 
64         // Trace out the results here of all 3 regs
65         // (Format should resemble FSP: HostBoot Reg:0000283C  Data:AA801504
66         // 00000000  Proc:00050001 )
67         std::stringstream ss1, ss2, ss3;
68 
69         ss1 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex
70             << l_cfamAddr << " Data:" << l_cfamData << " Proc:00000000";
71 
72         ss2 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex
73             << l_scomAddr1 << " Data:" << std::setw(16) << l_scomData1
74             << " Proc:00000000";
75 
76         ss3 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex
77             << l_scomAddr2 << " Data:" << std::setw(16) << l_scomData2
78             << " Proc:00000000";
79 
80         std::string strobj1 = ss1.str();
81         std::string strobj2 = ss2.str();
82         std::string strobj3 = ss3.str();
83 
84         trace<level::INFO>(strobj1.c_str());
85         trace<level::INFO>(strobj2.c_str());
86         trace<level::INFO>(strobj3.c_str());
87     }
88 
89     return;
90 
91 } // end addHbStatusRegs
92 
93 /** @brief Check for recoverable errors present */
94 bool recoverableErrors()
95 {
96     bool recoverableErrors = false; // assume no recoverable attentions
97 
98     pdbg_target* target;
99     pdbg_for_each_class_target("proc", target)
100     {
101         if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
102         {
103             auto proc = pdbg_target_index(target); // get processor number
104 
105             // Use PIB target to determine if a processor is enabled
106             char path[16];
107             sprintf(path, "/proc%d/pib", proc);
108             pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path);
109 
110             // sanity check
111             if (nullptr == pibTarget)
112             {
113                 trace<level::INFO>("pib path or target not found");
114                 continue;
115             }
116 
117             // check if pib target is enabled - indicates proc is enabled
118             if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget))
119             {
120                 // The processor FSI target is required for CFAM read
121                 sprintf(path, "/proc%d/fsi", proc);
122                 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path);
123 
124                 // sanity check
125                 if (nullptr == fsiTarget)
126                 {
127                     trace<level::INFO>("fsi path or target not found");
128                     continue;
129                 }
130 
131                 uint32_t isr_val = 0xffffffff; // invalid isr value
132 
133                 // get active attentions on processor
134                 if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val))
135                 {
136                     // log cfam read error
137                     trace<level::ERROR>("Error! cfam read 0x1007 FAILED");
138                     eventAttentionFail((int)AttnSection::attnHandler |
139                                        ATTN_PDBG_CFAM);
140                 }
141                 // check for invalid/stale value
142                 else if (0xffffffff == isr_val)
143                 {
144                     trace<level::ERROR>("Error! cfam read 0x1007 INVALID");
145                     continue;
146                 }
147                 // check recoverable error status bit
148                 else if (0 != (isr_val & RECOVERABLE_ATTN))
149                 {
150                     recoverableErrors = true;
151                     break;
152                 }
153             } // fsi target enabled
154         }     // pib target enabled
155     }         // next processor
156 
157     return recoverableErrors;
158 }
159 
160 /** @brief timesec less-than-equal-to compare */
161 bool operator<=(const timespec& lhs, const timespec& rhs)
162 {
163     if (lhs.tv_sec == rhs.tv_sec)
164         return lhs.tv_nsec <= rhs.tv_nsec;
165     else
166         return lhs.tv_sec <= rhs.tv_sec;
167 }
168 
169 /** @brief sleep for n-seconds */
170 void sleepSeconds(const unsigned int seconds)
171 {
172     auto count = seconds;
173     struct timespec requested, remaining;
174 
175     while (0 < count)
176     {
177         requested.tv_sec  = 1;
178         requested.tv_nsec = 0;
179         remaining         = requested;
180 
181         while (-1 == nanosleep(&requested, &remaining))
182         {
183             // if not changing or implausible then abort
184             if (requested <= remaining)
185             {
186                 break;
187             }
188 
189             // back to sleep
190             requested = remaining;
191         }
192         count--;
193     }
194 }
195 
196 } // namespace attn
197