xref: /openbmc/openpower-hw-diags/util/pdbg.cpp (revision 236bb730eb4957f9b506e61b2ab086b4b5b663ac)
1 #include <assert.h>
2 
3 #include <hei_main.hpp>
4 #include <util/pdbg.hpp>
5 #include <util/trace.hpp>
6 
7 #ifdef CONFIG_PHAL_API
8 #include <attribute_info.H>
9 #endif
10 
11 namespace util
12 {
13 
14 namespace pdbg
15 {
16 
17 //------------------------------------------------------------------------------
18 
19 pdbg_target* getTrgt(const libhei::Chip& i_chip)
20 {
21     return (pdbg_target*)i_chip.getChip();
22 }
23 
24 //------------------------------------------------------------------------------
25 
26 pdbg_target* getTrgt(const std::string& i_path)
27 {
28     return pdbg_target_from_path(nullptr, i_path.c_str());
29 }
30 
31 //------------------------------------------------------------------------------
32 
33 const char* getPath(pdbg_target* i_trgt)
34 {
35     return pdbg_target_path(i_trgt);
36 }
37 
38 const char* getPath(const libhei::Chip& i_chip)
39 {
40     return getPath(getTrgt(i_chip));
41 }
42 
43 //------------------------------------------------------------------------------
44 
45 uint32_t getChipPos(pdbg_target* i_trgt)
46 {
47     uint32_t attr = 0;
48     pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
49     return attr;
50 }
51 
52 uint32_t getChipPos(const libhei::Chip& i_chip)
53 {
54     return getChipPos(getTrgt(i_chip));
55 }
56 
57 //------------------------------------------------------------------------------
58 
59 uint8_t getTrgtType(pdbg_target* i_trgt)
60 {
61     uint8_t attr = 0;
62     pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
63     return attr;
64 }
65 
66 uint8_t getTrgtType(const libhei::Chip& i_chip)
67 {
68     return getTrgtType(getTrgt(i_chip));
69 }
70 
71 //------------------------------------------------------------------------------
72 
73 pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
74 {
75     // The input target must be a processor.
76     assert(TYPE_PROC == getTrgtType(i_procTrgt));
77 
78     // Get the pib path.
79     char path[16];
80     sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
81 
82     // Return the pib target.
83     pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
84     assert(nullptr != pibTrgt);
85 
86     return pibTrgt;
87 }
88 
89 //------------------------------------------------------------------------------
90 
91 pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
92 {
93     // The input target must be a processor.
94     assert(TYPE_PROC == getTrgtType(i_procTrgt));
95 
96     // Get the fsi path.
97     char path[16];
98     sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
99 
100     // Return the fsi target.
101     pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
102     assert(nullptr != fsiTrgt);
103 
104     return fsiTrgt;
105 }
106 
107 //------------------------------------------------------------------------------
108 
109 int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
110 {
111     // Only processor targets are supported.
112     assert(TYPE_PROC == getTrgtType(i_trgt));
113 
114     auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
115 
116     int rc = fsi_read(fsiTrgt, i_addr, &o_val);
117 
118     if (0 != rc)
119     {
120         trace::err("fsi_read failure: trgt=%s addr=0x%08x",
121                    util::pdbg::getPath(fsiTrgt), i_addr);
122     }
123 
124     return rc;
125 }
126 
127 //------------------------------------------------------------------------------
128 
129 // IMPORTANT:
130 // The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
131 // point during the IPL. It is possible that this information is needed before
132 // the sync occurs, in which case the value will return 0.
133 uint32_t __getChipId(pdbg_target* i_trgt)
134 {
135     uint32_t attr = 0;
136     pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
137     return attr;
138 }
139 
140 // IMPORTANT:
141 // The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
142 // during the IPL. It is possible that this information is needed before the
143 // sync occurs, in which case the value will return 0.
144 uint8_t __getChipEc(pdbg_target* i_trgt)
145 {
146     uint8_t attr = 0;
147     pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
148     return attr;
149 }
150 
151 uint32_t __getChipIdEc(pdbg_target* i_trgt)
152 {
153     auto chipId = __getChipId(i_trgt);
154     auto chipEc = __getChipEc(i_trgt);
155 
156     if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
157     {
158         // There is a special case where the model/level attributes have not
159         // been initialized in the devtree. This is possible on the epoch IPL
160         // where an attention occurs before Hostboot is able to update the
161         // devtree information on the BMC. It may is still possible to get this
162         // information from chips with CFAM access (i.e. a processor) via the
163         // CFAM chip ID register.
164 
165         uint32_t val = 0;
166         if (0 == getCfam(i_trgt, 0x100a, val))
167         {
168             chipId = ((val & 0x0F0FF000) >> 12);
169             chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
170         }
171     }
172 
173     return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
174 }
175 
176 void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
177                libhei::ChipType_t i_type)
178 {
179     // Trace each chip for debug. It is important to show the type just in case
180     // the model/EC does not exist. See note below.
181     trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
182                getPath(i_trgt));
183 
184     if (0 == i_type)
185     {
186         // This is a special case. See the details in __getChipIdEC(). There is
187         // nothing more we can do with this chip since we don't know what it is.
188         // So ignore the chip for now.
189     }
190     else
191     {
192         o_chips.emplace_back(i_trgt, i_type);
193     }
194 }
195 
196 void getActiveChips(std::vector<libhei::Chip>& o_chips)
197 {
198     o_chips.clear();
199 
200     // Iterate each processor.
201     pdbg_target* procTrgt;
202     pdbg_for_each_class_target("proc", procTrgt)
203     {
204         // We cannot use the proc target to determine if the chip is active.
205         // There is some design limitation in pdbg that requires the proc
206         // targets to always be active. Instead, we must get the associated pib
207         // target and check if it is active.
208 
209         // Active processors only.
210         if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
211             continue;
212 
213         // Add the processor to the list.
214         __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
215 
216         // Iterate the connected OCMBs, if they exist.
217         pdbg_target* ocmbTrgt;
218         pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
219         {
220             // Active OCMBs only.
221             if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
222                 continue;
223 
224             // Add the OCMB to the list.
225             __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
226         }
227     }
228 }
229 
230 //------------------------------------------------------------------------------
231 
232 bool queryHardwareAnalysisSupported()
233 {
234     // Hardware analysis is only supported on P10 systems and up.
235     return (PDBG_PROC_P9 < pdbg_get_proc());
236 }
237 
238 //------------------------------------------------------------------------------
239 
240 std::string getLocationCode(pdbg_target* trgt)
241 {
242     if (nullptr == trgt)
243     {
244         // Either the path is wrong or the attribute doesn't exist.
245         return std::string{};
246     }
247 
248 #ifdef CONFIG_PHAL_API
249 
250     ATTR_LOCATION_CODE_Type val;
251     if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val))
252     {
253         // Get the immediate parent in the devtree path and try again.
254         return getLocationCode(pdbg_target_parent(nullptr, trgt));
255     }
256 
257     // Attribute found.
258     return std::string{val};
259 
260 #else
261 
262     return std::string{getPath(trgt)};
263 
264 #endif
265 }
266 
267 //------------------------------------------------------------------------------
268 
269 std::string getPhysDevPath(pdbg_target* trgt)
270 {
271     if (nullptr == trgt)
272     {
273         // Either the path is wrong or the attribute doesn't exist.
274         return std::string{};
275     }
276 
277 #ifdef CONFIG_PHAL_API
278 
279     ATTR_PHYS_DEV_PATH_Type val;
280     if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val))
281     {
282         // Get the immediate parent in the devtree path and try again.
283         return getPhysDevPath(pdbg_target_parent(nullptr, trgt));
284     }
285 
286     // Attribute found.
287     return std::string{val};
288 
289 #else
290 
291     return std::string{getPath(trgt)};
292 
293 #endif
294 }
295 
296 //------------------------------------------------------------------------------
297 
298 } // namespace pdbg
299 
300 } // namespace util
301