pdbg.cpp (c7026261bb05cc509b0c7fb204ba967419a8b35d) pdbg.cpp (626270affc0f71eaab89c45c492e6732238fa360)
1//------------------------------------------------------------------------------
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
8#include <assert.h>
9#include <config.h>
10
11#include <hei_main.hpp>
1//------------------------------------------------------------------------------
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
8#include <assert.h>
9#include <config.h>
10
11#include <hei_main.hpp>
12#include <nlohmann/json.hpp>
13#include <util/dbus.hpp>
12#include <util/pdbg.hpp>
13#include <util/trace.hpp>
14
14#include <util/pdbg.hpp>
15#include <util/trace.hpp>
16
17#include <filesystem>
18#include <fstream>
19#include <string>
20
15#ifdef CONFIG_PHAL_API
16#include <attributes_info.H>
17#endif
18
19using namespace analyzer;
20
21#ifdef CONFIG_PHAL_API
22#include <attributes_info.H>
23#endif
24
25using namespace analyzer;
26
27namespace fs = std::filesystem;
28
21namespace util
22{
23
24namespace pdbg
25{
26
27//------------------------------------------------------------------------------
28

--- 161 unchanged lines hidden (view full) ---

190 getPath(i_parentChip), i_unitType, i_unitPos);
191 }
192
193 return unitTarget;
194}
195
196//------------------------------------------------------------------------------
197
29namespace util
30{
31
32namespace pdbg
33{
34
35//------------------------------------------------------------------------------
36

--- 161 unchanged lines hidden (view full) ---

198 getPath(i_parentChip), i_unitType, i_unitPos);
199 }
200
201 return unitTarget;
202}
203
204//------------------------------------------------------------------------------
205
206pdbg_target* getTargetAcrossBus(pdbg_target* i_rxTarget)
207{
208 assert(nullptr != i_rxTarget);
209
210 // Validate target type
211 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
212 assert(util::pdbg::TYPE_IOLINK == rxType ||
213 util::pdbg::TYPE_IOHS == rxType);
214
215 pdbg_target* o_peerTarget;
216 fs::path filePath;
217
218 // Open the appropriate data file depending on machine type
219 util::dbus::MachineType machineType = util::dbus::getMachineType();
220 switch (machineType)
221 {
222 // Rainier 4U
223 case util::dbus::MachineType::Rainier_2S4U:
224 case util::dbus::MachineType::Rainier_1S4U:
225 filePath =
226 fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-4u.json"};
227 break;
228 // Rainier 2U
229 case util::dbus::MachineType::Rainier_2S2U:
230 case util::dbus::MachineType::Rainier_1S2U:
231 filePath =
232 fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-2u.json"};
233 break;
234 // Everest
235 case util::dbus::MachineType::Everest:
236 filePath =
237 fs::path{PACKAGE_DIR "util-data/peer-targets-everest.json"};
238 break;
239 default:
240 trace::err("Invalid machine type found %d",
241 static_cast<uint8_t>(machineType));
242 break;
243 }
244
245 std::ifstream file{filePath};
246 assert(file.good());
247
248 try
249 {
250 auto trgtMap = nlohmann::json::parse(file);
251 std::string rxPath = util::pdbg::getPath(i_rxTarget);
252 std::string peerPath = trgtMap.at(rxPath).get<std::string>();
253
254 o_peerTarget = util::pdbg::getTrgt(peerPath);
255 }
256 catch (...)
257 {
258 trace::err("Failed to parse file: %s", filePath.string().c_str());
259 throw;
260 }
261
262 return o_peerTarget;
263}
264
265//------------------------------------------------------------------------------
266
198pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget,
199 const callout::BusType& i_busType)
200{
201 assert(nullptr != i_rxTarget);
202
203 pdbg_target* txTarget = nullptr;
204
205 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
206 std::string rxPath = util::pdbg::getPath(i_rxTarget);
207
208 if (callout::BusType::SMP_BUS == i_busType &&
209 util::pdbg::TYPE_IOLINK == rxType)
210 {
267pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget,
268 const callout::BusType& i_busType)
269{
270 assert(nullptr != i_rxTarget);
271
272 pdbg_target* txTarget = nullptr;
273
274 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
275 std::string rxPath = util::pdbg::getPath(i_rxTarget);
276
277 if (callout::BusType::SMP_BUS == i_busType &&
278 util::pdbg::TYPE_IOLINK == rxType)
279 {
211 // TODO: Will need to reference some sort of data that can tell us how
212 // the processors are connected in the system. For now, return the
213 // RX target to avoid returning a nullptr.
214 trace::inf("No support to get peer target on SMP bus");
215 txTarget = i_rxTarget;
280 txTarget = getTargetAcrossBus(i_rxTarget);
216 }
217 else if (callout::BusType::SMP_BUS == i_busType &&
218 util::pdbg::TYPE_IOHS == rxType)
219 {
281 }
282 else if (callout::BusType::SMP_BUS == i_busType &&
283 util::pdbg::TYPE_IOHS == rxType)
284 {
220 // TODO: Will need to reference some sort of data that can tell us how
221 // the processors are connected in the system. For now, return the
222 // RX target to avoid returning a nullptr.
223 trace::inf("No support to get peer target on SMP bus");
224 txTarget = i_rxTarget;
285 txTarget = getTargetAcrossBus(i_rxTarget);
225 }
226 else if (callout::BusType::OMI_BUS == i_busType &&
227 util::pdbg::TYPE_OMI == rxType)
228 {
229 // This is a bit clunky. The pdbg APIs only give us the ability to
286 }
287 else if (callout::BusType::OMI_BUS == i_busType &&
288 util::pdbg::TYPE_OMI == rxType)
289 {
290 // This is a bit clunky. The pdbg APIs only give us the ability to
230 // iterate over the children instead of just returning a list. So we'll
231 // push all the children to a list and go from there.
291 // iterate over the children instead of just returning a list. So
292 // we'll push all the children to a list and go from there.
232 std::vector<pdbg_target*> childList;
233
234 pdbg_target* childTarget = nullptr;
235 pdbg_for_each_target("ocmb", i_rxTarget, childTarget)
236 {
237 if (nullptr != childTarget)
238 {
239 childList.push_back(childTarget);

--- 64 unchanged lines hidden (view full) ---

304 assert(nullptr != fsiTrgt);
305
306 return fsiTrgt;
307}
308
309//------------------------------------------------------------------------------
310
311// IMPORTANT:
293 std::vector<pdbg_target*> childList;
294
295 pdbg_target* childTarget = nullptr;
296 pdbg_for_each_target("ocmb", i_rxTarget, childTarget)
297 {
298 if (nullptr != childTarget)
299 {
300 childList.push_back(childTarget);

--- 64 unchanged lines hidden (view full) ---

365 assert(nullptr != fsiTrgt);
366
367 return fsiTrgt;
368}
369
370//------------------------------------------------------------------------------
371
372// IMPORTANT:
312// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
313// point during the IPL. It is possible that this information is needed before
314// the sync occurs, in which case the value will return 0.
373// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at
374// some point during the IPL. It is possible that this information is needed
375// before the sync occurs, in which case the value will return 0.
315uint32_t __getChipId(pdbg_target* i_trgt)
316{
317 uint32_t attr = 0;
318 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
319 return attr;
320}
321
322// IMPORTANT:
376uint32_t __getChipId(pdbg_target* i_trgt)
377{
378 uint32_t attr = 0;
379 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
380 return attr;
381}
382
383// IMPORTANT:
323// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
324// during the IPL. It is possible that this information is needed before the
325// sync occurs, in which case the value will return 0.
384// The ATTR_EC attribute will be synced from Hostboot to the BMC at some
385// point during the IPL. It is possible that this information is needed
386// before the sync occurs, in which case the value will return 0.
326uint8_t __getChipEc(pdbg_target* i_trgt)
327{
328 uint8_t attr = 0;
329 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
330 return attr;
331}
332
333uint32_t __getChipIdEc(pdbg_target* i_trgt)
334{
335 auto chipId = __getChipId(i_trgt);
336 auto chipEc = __getChipEc(i_trgt);
337
338 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
339 {
340 // There is a special case where the model/level attributes have not
387uint8_t __getChipEc(pdbg_target* i_trgt)
388{
389 uint8_t attr = 0;
390 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
391 return attr;
392}
393
394uint32_t __getChipIdEc(pdbg_target* i_trgt)
395{
396 auto chipId = __getChipId(i_trgt);
397 auto chipEc = __getChipEc(i_trgt);
398
399 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
400 {
401 // There is a special case where the model/level attributes have not
341 // been initialized in the devtree. This is possible on the epoch IPL
342 // where an attention occurs before Hostboot is able to update the
343 // devtree information on the BMC. It may is still possible to get this
344 // information from chips with CFAM access (i.e. a processor) via the
345 // CFAM chip ID register.
402 // been initialized in the devtree. This is possible on the epoch
403 // IPL where an attention occurs before Hostboot is able to update
404 // the devtree information on the BMC. It may is still possible to
405 // get this information from chips with CFAM access (i.e. a
406 // processor) via the CFAM chip ID register.
346
347 uint32_t val = 0;
348 if (0 == getCfam(i_trgt, 0x100a, val))
349 {
350 chipId = ((val & 0x0F0FF000) >> 12);
351 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
352 }
353 }
354
355 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
356}
357
358void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
359 libhei::ChipType_t i_type)
360{
407
408 uint32_t val = 0;
409 if (0 == getCfam(i_trgt, 0x100a, val))
410 {
411 chipId = ((val & 0x0F0FF000) >> 12);
412 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
413 }
414 }
415
416 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
417}
418
419void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
420 libhei::ChipType_t i_type)
421{
361 // Trace each chip for debug. It is important to show the type just in case
362 // the model/EC does not exist. See note below.
422 // Trace each chip for debug. It is important to show the type just in
423 // case the model/EC does not exist. See note below.
363 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
364 getPath(i_trgt));
365
366 if (0 == i_type)
367 {
424 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
425 getPath(i_trgt));
426
427 if (0 == i_type)
428 {
368 // This is a special case. See the details in __getChipIdEC(). There is
369 // nothing more we can do with this chip since we don't know what it is.
370 // So ignore the chip for now.
429 // This is a special case. See the details in __getChipIdEC(). There
430 // is nothing more we can do with this chip since we don't know what
431 // it is. So ignore the chip for now.
371 }
372 else
373 {
374 o_chips.emplace_back(i_trgt, i_type);
375 }
376}
377
378void getActiveChips(std::vector<libhei::Chip>& o_chips)
379{
380 o_chips.clear();
381
382 // Iterate each processor.
383 pdbg_target* procTrgt;
384 pdbg_for_each_class_target("proc", procTrgt)
385 {
386 // We cannot use the proc target to determine if the chip is active.
387 // There is some design limitation in pdbg that requires the proc
432 }
433 else
434 {
435 o_chips.emplace_back(i_trgt, i_type);
436 }
437}
438
439void getActiveChips(std::vector<libhei::Chip>& o_chips)
440{
441 o_chips.clear();
442
443 // Iterate each processor.
444 pdbg_target* procTrgt;
445 pdbg_for_each_class_target("proc", procTrgt)
446 {
447 // We cannot use the proc target to determine if the chip is active.
448 // There is some design limitation in pdbg that requires the proc
388 // targets to always be active. Instead, we must get the associated pib
389 // target and check if it is active.
449 // targets to always be active. Instead, we must get the associated
450 // pib target and check if it is active.
390
391 // Active processors only.
392 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
393 continue;
394
395 // Add the processor to the list.
396 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
397

--- 31 unchanged lines hidden (view full) ---

429 o_chips.push_back(procTrgt);
430 }
431}
432
433//------------------------------------------------------------------------------
434
435pdbg_target* getPrimaryProcessor()
436{
451
452 // Active processors only.
453 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
454 continue;
455
456 // Add the processor to the list.
457 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
458

--- 31 unchanged lines hidden (view full) ---

490 o_chips.push_back(procTrgt);
491 }
492}
493
494//------------------------------------------------------------------------------
495
496pdbg_target* getPrimaryProcessor()
497{
437 // TODO: For at least P10, the primary processor (the one connected directly
498 // TODO: For at least P10, the primary processor (the one connected
499 // directly
438 // to the BMC), will always be PROC 0. We will need to update this
439 // later if we ever support an alternate primary processor.
440 return getTrgt("/proc0");
441}
442
443//------------------------------------------------------------------------------
444
445bool queryHardwareAnalysisSupported()

--- 68 unchanged lines hidden (view full) ---

514
515 if (nullptr != target)
516 {
517#ifdef CONFIG_PHAL_API
518
519 ATTR_PHYS_BIN_PATH_Type value;
520 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
521 {
500 // to the BMC), will always be PROC 0. We will need to update this
501 // later if we ever support an alternate primary processor.
502 return getTrgt("/proc0");
503}
504
505//------------------------------------------------------------------------------
506
507bool queryHardwareAnalysisSupported()

--- 68 unchanged lines hidden (view full) ---

576
577 if (nullptr != target)
578 {
579#ifdef CONFIG_PHAL_API
580
581 ATTR_PHYS_BIN_PATH_Type value;
582 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
583 {
522 // The attrirbute for this target does not exist. Get the immediate
523 // parent in the devtree path and try again. Note that if there is
524 // no parent target, nullptr will be returned and that will be
525 // checked above.
584 // The attrirbute for this target does not exist. Get the
585 // immediate parent in the devtree path and try again. Note that
586 // if there is no parent target, nullptr will be returned and
587 // that will be checked above.
526 return getPhysBinPath(pdbg_target_parent(nullptr, target));
527 }
528
529 // Attribute was found. Copy the attribute array to the returned
530 // vector. Note that the reason we return the vector instead of just
531 // returning the array is because the array type and details only
532 // exists in this specific configuration.
533 binPath.insert(binPath.end(), value, value + sizeof(value));

--- 12 unchanged lines hidden ---
588 return getPhysBinPath(pdbg_target_parent(nullptr, target));
589 }
590
591 // Attribute was found. Copy the attribute array to the returned
592 // vector. Note that the reason we return the vector instead of just
593 // returning the array is because the array type and details only
594 // exists in this specific configuration.
595 binPath.insert(binPath.end(), value, value + sizeof(value));

--- 12 unchanged lines hidden ---