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