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