blob: a69d079d5331907915b8b2c1a877af6c5f477336 [file] [log] [blame]
Zane Shelleye90b85d2021-12-17 17:24:49 -06001//------------------------------------------------------------------------------
2// IMPORTANT:
3// This file will be built in CI test and should work out-of-the-box in CI test
4// with use of the fake device tree. Any functions that require addition support
5// to simulate in CI test should be put in `pdbg_no_sim.cpp`.
6//------------------------------------------------------------------------------
7
Zane Shelley171a2e02020-11-13 13:56:13 -06008#include <assert.h>
Zane Shelleye4bfb472021-08-10 12:47:32 -05009#include <config.h>
Zane Shelley171a2e02020-11-13 13:56:13 -060010
Zane Shelley7ae9c8c2020-12-02 20:10:31 -060011#include <hei_main.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060012#include <util/pdbg.hpp>
Zane Shelley171a2e02020-11-13 13:56:13 -060013#include <util/trace.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060014
Zane Shelley3a851082021-03-23 16:45:28 -050015#ifdef CONFIG_PHAL_API
Zane Shelleye4bfb472021-08-10 12:47:32 -050016#include <attributes_info.H>
Zane Shelley3a851082021-03-23 16:45:28 -050017#endif
18
Zane Shelley38501e12022-01-10 15:42:28 -060019using namespace analyzer;
20
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060021namespace util
22{
23
24namespace pdbg
25{
26
27//------------------------------------------------------------------------------
28
Zane Shelleya0299852020-11-13 13:38:04 -060029pdbg_target* getTrgt(const libhei::Chip& i_chip)
30{
31 return (pdbg_target*)i_chip.getChip();
32}
33
34//------------------------------------------------------------------------------
35
Zane Shelley236bb732021-03-24 17:07:46 -050036pdbg_target* getTrgt(const std::string& i_path)
37{
38 return pdbg_target_from_path(nullptr, i_path.c_str());
39}
40
41//------------------------------------------------------------------------------
42
Zane Shelleya0299852020-11-13 13:38:04 -060043const char* getPath(pdbg_target* i_trgt)
44{
45 return pdbg_target_path(i_trgt);
46}
47
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060048const char* getPath(const libhei::Chip& i_chip)
49{
Zane Shelleya0299852020-11-13 13:38:04 -060050 return getPath(getTrgt(i_chip));
51}
52
53//------------------------------------------------------------------------------
54
55uint32_t getChipPos(pdbg_target* i_trgt)
56{
57 uint32_t attr = 0;
58 pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
59 return attr;
60}
61
62uint32_t getChipPos(const libhei::Chip& i_chip)
63{
64 return getChipPos(getTrgt(i_chip));
65}
66
67//------------------------------------------------------------------------------
68
69uint8_t getTrgtType(pdbg_target* i_trgt)
70{
71 uint8_t attr = 0;
72 pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
73 return attr;
74}
75
76uint8_t getTrgtType(const libhei::Chip& i_chip)
77{
78 return getTrgtType(getTrgt(i_chip));
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060079}
80
81//------------------------------------------------------------------------------
82
Zane Shelley38501e12022-01-10 15:42:28 -060083pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget,
84 const callout::BusType& i_busType)
85{
86 assert(nullptr != i_rxTarget);
87
88 pdbg_target* txTarget = nullptr;
89
90 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
91 std::string rxPath = util::pdbg::getPath(i_rxTarget);
92
93 if (callout::BusType::SMP_BUS == i_busType &&
94 util::pdbg::TYPE_IOLINK == rxType)
95 {
96 // TODO: Will need to reference some sort of data that can tell us how
97 // the processors are connected in the system. For now, return the
98 // RX target to avoid returning a nullptr.
99 trace::inf("No support to get peer target on SMP bus");
100 txTarget = i_rxTarget;
101 }
102 else if (callout::BusType::SMP_BUS == i_busType &&
103 util::pdbg::TYPE_IOHS == rxType)
104 {
105 // TODO: Will need to reference some sort of data that can tell us how
106 // the processors are connected in the system. For now, return the
107 // RX target to avoid returning a nullptr.
108 trace::inf("No support to get peer target on SMP bus");
109 txTarget = i_rxTarget;
110 }
111 else if (callout::BusType::OMI_BUS == i_busType &&
112 util::pdbg::TYPE_OMI == rxType)
113 {
114 // This is a bit clunky. The pdbg APIs only give us the ability to
115 // iterate over the children instead of just returning a list. So we'll
116 // push all the children to a list and go from there.
117 std::vector<pdbg_target*> childList;
118
119 pdbg_target* childTarget = nullptr;
120 pdbg_for_each_target("ocmb", i_rxTarget, childTarget)
121 {
122 if (nullptr != childTarget)
123 {
124 childList.push_back(childTarget);
125 }
126 }
127
128 // We know there should only be one OCMB per OMI.
129 if (1 != childList.size())
130 {
131 throw std::logic_error("Invalid child list size for " + rxPath);
132 }
133
134 // Get the connected target.
135 txTarget = childList.front();
136 }
137 else if (callout::BusType::OMI_BUS == i_busType &&
138 util::pdbg::TYPE_OCMB == rxType)
139 {
140 txTarget = pdbg_target_parent("omi", i_rxTarget);
141 if (nullptr == txTarget)
142 {
143 throw std::logic_error("No parent OMI found for " + rxPath);
144 }
145 }
146 else
147 {
148 // This would be a code bug.
149 throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath +
150 " i_busType=" + i_busType.getString());
151 }
152
153 assert(nullptr != txTarget); // just in case we missed something above
154
155 return txTarget;
156}
157
158//------------------------------------------------------------------------------
159
Zane Shelley171a2e02020-11-13 13:56:13 -0600160pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
161{
162 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -0600163 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelley171a2e02020-11-13 13:56:13 -0600164
165 // Get the pib path.
166 char path[16];
167 sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
168
169 // Return the pib target.
170 pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
171 assert(nullptr != pibTrgt);
172
173 return pibTrgt;
174}
175
176//------------------------------------------------------------------------------
177
Zane Shelleyff76b6b2020-11-18 13:54:26 -0600178pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
179{
180 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -0600181 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelleyff76b6b2020-11-18 13:54:26 -0600182
183 // Get the fsi path.
184 char path[16];
185 sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
186
187 // Return the fsi target.
188 pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
189 assert(nullptr != fsiTrgt);
190
191 return fsiTrgt;
192}
193
194//------------------------------------------------------------------------------
195
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600196int getScom(pdbg_target* i_trgt, uint64_t i_addr, uint64_t& o_val)
197{
198 // Only processor targets are supported.
199 // TODO: Will need to add OCMB support later.
200 assert(TYPE_PROC == getTrgtType(i_trgt));
201
202 auto pibTrgt = util::pdbg::getPibTrgt(i_trgt);
203
204 int rc = pib_read(pibTrgt, i_addr, &o_val);
205
206 if (0 != rc)
207 {
208 trace::err("pib_read failure: target=%s addr=0x%0" PRIx64,
209 util::pdbg::getPath(pibTrgt), i_addr);
210 }
211
212 return rc;
213}
214
215//------------------------------------------------------------------------------
216
Zane Shelley35171d92020-12-03 13:31:13 -0600217int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
218{
219 // Only processor targets are supported.
220 assert(TYPE_PROC == getTrgtType(i_trgt));
221
222 auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
223
224 int rc = fsi_read(fsiTrgt, i_addr, &o_val);
225
226 if (0 != rc)
227 {
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600228 trace::err("fsi_read failure: target=%s addr=0x%08x",
Zane Shelley35171d92020-12-03 13:31:13 -0600229 util::pdbg::getPath(fsiTrgt), i_addr);
230 }
231
232 return rc;
233}
234
235//------------------------------------------------------------------------------
236
237// IMPORTANT:
238// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
239// point during the IPL. It is possible that this information is needed before
240// the sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600241uint32_t __getChipId(pdbg_target* i_trgt)
242{
243 uint32_t attr = 0;
244 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
245 return attr;
246}
247
Zane Shelley35171d92020-12-03 13:31:13 -0600248// IMPORTANT:
249// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
250// during the IPL. It is possible that this information is needed before the
251// sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600252uint8_t __getChipEc(pdbg_target* i_trgt)
253{
254 uint8_t attr = 0;
255 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
256 return attr;
257}
258
259uint32_t __getChipIdEc(pdbg_target* i_trgt)
260{
Zane Shelley35171d92020-12-03 13:31:13 -0600261 auto chipId = __getChipId(i_trgt);
262 auto chipEc = __getChipEc(i_trgt);
263
264 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
265 {
266 // There is a special case where the model/level attributes have not
267 // been initialized in the devtree. This is possible on the epoch IPL
268 // where an attention occurs before Hostboot is able to update the
269 // devtree information on the BMC. It may is still possible to get this
270 // information from chips with CFAM access (i.e. a processor) via the
271 // CFAM chip ID register.
272
273 uint32_t val = 0;
274 if (0 == getCfam(i_trgt, 0x100a, val))
275 {
276 chipId = ((val & 0x0F0FF000) >> 12);
277 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
278 }
279 }
280
281 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
Zane Shelley171a2e02020-11-13 13:56:13 -0600282}
283
284void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
285 libhei::ChipType_t i_type)
286{
287 // Trace each chip for debug. It is important to show the type just in case
288 // the model/EC does not exist. See note below.
289 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
290 getPath(i_trgt));
291
292 if (0 == i_type)
293 {
Zane Shelley35171d92020-12-03 13:31:13 -0600294 // This is a special case. See the details in __getChipIdEC(). There is
295 // nothing more we can do with this chip since we don't know what it is.
296 // So ignore the chip for now.
Zane Shelley171a2e02020-11-13 13:56:13 -0600297 }
298 else
299 {
300 o_chips.emplace_back(i_trgt, i_type);
301 }
302}
303
304void getActiveChips(std::vector<libhei::Chip>& o_chips)
305{
306 o_chips.clear();
307
308 // Iterate each processor.
309 pdbg_target* procTrgt;
310 pdbg_for_each_class_target("proc", procTrgt)
311 {
312 // We cannot use the proc target to determine if the chip is active.
313 // There is some design limitation in pdbg that requires the proc
314 // targets to always be active. Instead, we must get the associated pib
315 // target and check if it is active.
316
317 // Active processors only.
318 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
319 continue;
320
321 // Add the processor to the list.
322 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
323
324 // Iterate the connected OCMBs, if they exist.
325 pdbg_target* ocmbTrgt;
326 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
327 {
328 // Active OCMBs only.
329 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
330 continue;
331
332 // Add the OCMB to the list.
333 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
334 }
335 }
336}
337
338//------------------------------------------------------------------------------
339
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600340pdbg_target* getPrimaryProcessor()
341{
342 // TODO: For at least P10, the primary processor (the one connected directly
343 // to the BMC), will always be PROC 0. We will need to update this
344 // later if we ever support an alternate primary processor.
345 return getTrgt("/proc0");
346}
347
348//------------------------------------------------------------------------------
349
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600350bool queryHardwareAnalysisSupported()
351{
352 // Hardware analysis is only supported on P10 systems and up.
Zane Shelley5183af32020-12-07 14:49:03 -0600353 return (PDBG_PROC_P9 < pdbg_get_proc());
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600354}
355
356//------------------------------------------------------------------------------
357
Zane Shelley3a851082021-03-23 16:45:28 -0500358std::string getLocationCode(pdbg_target* trgt)
359{
360 if (nullptr == trgt)
361 {
362 // Either the path is wrong or the attribute doesn't exist.
363 return std::string{};
364 }
365
366#ifdef CONFIG_PHAL_API
367
368 ATTR_LOCATION_CODE_Type val;
369 if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val))
370 {
371 // Get the immediate parent in the devtree path and try again.
372 return getLocationCode(pdbg_target_parent(nullptr, trgt));
373 }
374
375 // Attribute found.
376 return std::string{val};
377
378#else
379
380 return std::string{getPath(trgt)};
381
382#endif
383}
384
385//------------------------------------------------------------------------------
386
387std::string getPhysDevPath(pdbg_target* trgt)
388{
389 if (nullptr == trgt)
390 {
391 // Either the path is wrong or the attribute doesn't exist.
392 return std::string{};
393 }
394
395#ifdef CONFIG_PHAL_API
396
397 ATTR_PHYS_DEV_PATH_Type val;
398 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val))
399 {
400 // Get the immediate parent in the devtree path and try again.
401 return getPhysDevPath(pdbg_target_parent(nullptr, trgt));
402 }
403
404 // Attribute found.
405 return std::string{val};
406
407#else
408
409 return std::string{getPath(trgt)};
410
411#endif
412}
413
414//------------------------------------------------------------------------------
415
Zane Shelleybf3326f2021-11-12 13:41:39 -0600416std::vector<uint8_t> getPhysBinPath(pdbg_target* target)
417{
418 std::vector<uint8_t> binPath;
419
420 if (nullptr != target)
421 {
422#ifdef CONFIG_PHAL_API
423
424 ATTR_PHYS_BIN_PATH_Type value;
425 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
426 {
427 // The attrirbute for this target does not exist. Get the immediate
428 // parent in the devtree path and try again. Note that if there is
429 // no parent target, nullptr will be returned and that will be
430 // checked above.
431 return getPhysBinPath(pdbg_target_parent(nullptr, target));
432 }
433
434 // Attribute was found. Copy the attribute array to the returned
435 // vector. Note that the reason we return the vector instead of just
436 // returning the array is because the array type and details only
437 // exists in this specific configuration.
438 binPath.insert(binPath.end(), value, value + sizeof(value));
439
440#endif
441 }
442
443 return binPath;
444}
445
446//------------------------------------------------------------------------------
447
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -0600448} // namespace pdbg
449
450} // namespace util