1e90b85dcSZane Shelley //------------------------------------------------------------------------------
2e90b85dcSZane Shelley // IMPORTANT:
3e90b85dcSZane Shelley // This file will be built in CI test and should work out-of-the-box in CI test
4e90b85dcSZane Shelley // with use of the fake device tree. Any functions that require addition support
5e90b85dcSZane Shelley // to simulate in CI test should be put in `pdbg_no_sim.cpp`.
6e90b85dcSZane Shelley //------------------------------------------------------------------------------
7e90b85dcSZane Shelley
8171a2e04SZane Shelley #include <assert.h>
9e4bfb47cSZane Shelley #include <config.h>
10171a2e04SZane Shelley
117ae9c8c7SZane Shelley #include <hei_main.hpp>
12626270afSCaleb Palmer #include <nlohmann/json.hpp>
13626270afSCaleb Palmer #include <util/dbus.hpp>
14f4bd5ff6SZane Shelley #include <util/pdbg.hpp>
15171a2e04SZane Shelley #include <util/trace.hpp>
16f4bd5ff6SZane Shelley
17626270afSCaleb Palmer #include <filesystem>
18626270afSCaleb Palmer #include <fstream>
19626270afSCaleb Palmer #include <string>
20626270afSCaleb Palmer
213a85108fSZane Shelley #ifdef CONFIG_PHAL_API
22e4bfb47cSZane Shelley #include <attributes_info.H>
233a85108fSZane Shelley #endif
243a85108fSZane Shelley
2538501e12SZane Shelley using namespace analyzer;
2638501e12SZane Shelley
27626270afSCaleb Palmer namespace fs = std::filesystem;
28626270afSCaleb Palmer
29f4bd5ff6SZane Shelley namespace util
30f4bd5ff6SZane Shelley {
31f4bd5ff6SZane Shelley
32f4bd5ff6SZane Shelley namespace pdbg
33f4bd5ff6SZane Shelley {
34f4bd5ff6SZane Shelley
35f4bd5ff6SZane Shelley //------------------------------------------------------------------------------
36f4bd5ff6SZane Shelley
getTrgt(const libhei::Chip & i_chip)37a0299858SZane Shelley pdbg_target* getTrgt(const libhei::Chip& i_chip)
38a0299858SZane Shelley {
39a0299858SZane Shelley return (pdbg_target*)i_chip.getChip();
40a0299858SZane Shelley }
41a0299858SZane Shelley
42a0299858SZane Shelley //------------------------------------------------------------------------------
43a0299858SZane Shelley
getTrgt(const std::string & i_path)44236bb730SZane Shelley pdbg_target* getTrgt(const std::string& i_path)
45236bb730SZane Shelley {
46236bb730SZane Shelley return pdbg_target_from_path(nullptr, i_path.c_str());
47236bb730SZane Shelley }
48236bb730SZane Shelley
49236bb730SZane Shelley //------------------------------------------------------------------------------
50236bb730SZane Shelley
getPath(pdbg_target * i_trgt)51a0299858SZane Shelley const char* getPath(pdbg_target* i_trgt)
52a0299858SZane Shelley {
53a0299858SZane Shelley return pdbg_target_path(i_trgt);
54a0299858SZane Shelley }
55a0299858SZane Shelley
getPath(const libhei::Chip & i_chip)56f4bd5ff6SZane Shelley const char* getPath(const libhei::Chip& i_chip)
57f4bd5ff6SZane Shelley {
58a0299858SZane Shelley return getPath(getTrgt(i_chip));
59a0299858SZane Shelley }
60a0299858SZane Shelley
61a0299858SZane Shelley //------------------------------------------------------------------------------
62a0299858SZane Shelley
getChipPos(pdbg_target * i_trgt)63a0299858SZane Shelley uint32_t getChipPos(pdbg_target* i_trgt)
64a0299858SZane Shelley {
65a0299858SZane Shelley uint32_t attr = 0;
66a0299858SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
67a0299858SZane Shelley return attr;
68a0299858SZane Shelley }
69a0299858SZane Shelley
getChipPos(const libhei::Chip & i_chip)70a0299858SZane Shelley uint32_t getChipPos(const libhei::Chip& i_chip)
71a0299858SZane Shelley {
72a0299858SZane Shelley return getChipPos(getTrgt(i_chip));
73a0299858SZane Shelley }
74a0299858SZane Shelley
75a0299858SZane Shelley //------------------------------------------------------------------------------
76a0299858SZane Shelley
getUnitPos(pdbg_target * i_trgt)772a394cbbSZane Shelley uint8_t getUnitPos(pdbg_target* i_trgt)
782a394cbbSZane Shelley {
792a394cbbSZane Shelley uint8_t attr = 0;
802a394cbbSZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_UNIT_POS", 1, 1, &attr);
812a394cbbSZane Shelley return attr;
822a394cbbSZane Shelley }
832a394cbbSZane Shelley
842a394cbbSZane Shelley //------------------------------------------------------------------------------
852a394cbbSZane Shelley
getTrgtType(pdbg_target * i_trgt)86a0299858SZane Shelley uint8_t getTrgtType(pdbg_target* i_trgt)
87a0299858SZane Shelley {
88a0299858SZane Shelley uint8_t attr = 0;
89a0299858SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
90a0299858SZane Shelley return attr;
91a0299858SZane Shelley }
92a0299858SZane Shelley
getTrgtType(const libhei::Chip & i_chip)93a0299858SZane Shelley uint8_t getTrgtType(const libhei::Chip& i_chip)
94a0299858SZane Shelley {
95a0299858SZane Shelley return getTrgtType(getTrgt(i_chip));
96f4bd5ff6SZane Shelley }
97f4bd5ff6SZane Shelley
98f4bd5ff6SZane Shelley //------------------------------------------------------------------------------
99f4bd5ff6SZane Shelley
getParentChip(pdbg_target * i_unitTarget)1002a394cbbSZane Shelley pdbg_target* getParentChip(pdbg_target* i_unitTarget)
1012a394cbbSZane Shelley {
1022a394cbbSZane Shelley assert(nullptr != i_unitTarget);
1032a394cbbSZane Shelley
1042a394cbbSZane Shelley // Check if the given target is already a chip.
1052a394cbbSZane Shelley auto targetType = getTrgtType(i_unitTarget);
1062a394cbbSZane Shelley if (TYPE_PROC == targetType || TYPE_OCMB == targetType)
1072a394cbbSZane Shelley {
1082a394cbbSZane Shelley return i_unitTarget; // simply return the given target
1092a394cbbSZane Shelley }
1102a394cbbSZane Shelley
1112a394cbbSZane Shelley // Check if this unit is on an OCMB.
1122a394cbbSZane Shelley pdbg_target* parentChip = pdbg_target_parent("ocmb", i_unitTarget);
1132a394cbbSZane Shelley
1142a394cbbSZane Shelley // If not on the OCMB, check if this unit is on a PROC.
1152a394cbbSZane Shelley if (nullptr == parentChip)
1162a394cbbSZane Shelley {
1172a394cbbSZane Shelley parentChip = pdbg_target_parent("proc", i_unitTarget);
1182a394cbbSZane Shelley }
1192a394cbbSZane Shelley
1202a394cbbSZane Shelley // There should always be a parent chip. Throw an error if not found.
1212a394cbbSZane Shelley if (nullptr == parentChip)
1222a394cbbSZane Shelley {
1232a394cbbSZane Shelley throw std::logic_error("No parent chip found: i_unitTarget=" +
1242a394cbbSZane Shelley std::string{getPath(i_unitTarget)});
1252a394cbbSZane Shelley }
1262a394cbbSZane Shelley
1272a394cbbSZane Shelley return parentChip;
1282a394cbbSZane Shelley }
1292a394cbbSZane Shelley
1302a394cbbSZane Shelley //------------------------------------------------------------------------------
1312a394cbbSZane Shelley
getParentProcessor(pdbg_target * i_target)132c62813d4SZane Shelley pdbg_target* getParentProcessor(pdbg_target* i_target)
133c62813d4SZane Shelley {
134c62813d4SZane Shelley assert(nullptr != i_target);
135c62813d4SZane Shelley
136c62813d4SZane Shelley // Check if the given target is already a processor chip.
137c62813d4SZane Shelley if (TYPE_PROC == getTrgtType(i_target))
138c62813d4SZane Shelley {
139c62813d4SZane Shelley return i_target; // simply return the given target
140c62813d4SZane Shelley }
141c62813d4SZane Shelley
142c62813d4SZane Shelley // Get the parent processor chip.
143c62813d4SZane Shelley pdbg_target* parentChip = pdbg_target_parent("proc", i_target);
144c62813d4SZane Shelley
145c62813d4SZane Shelley // There should always be a parent chip. Throw an error if not found.
146c62813d4SZane Shelley if (nullptr == parentChip)
147c62813d4SZane Shelley {
148a0c724d3SPatrick Williams throw std::logic_error(
149a0c724d3SPatrick Williams "No parent chip found: i_target=" + std::string{getPath(i_target)});
150c62813d4SZane Shelley }
151c62813d4SZane Shelley
152c62813d4SZane Shelley return parentChip;
153c62813d4SZane Shelley }
154c62813d4SZane Shelley
155c62813d4SZane Shelley //------------------------------------------------------------------------------
156c62813d4SZane Shelley
getChipUnit(pdbg_target * i_parentChip,TargetType_t i_unitType,uint8_t i_unitPos)1572a394cbbSZane Shelley pdbg_target* getChipUnit(pdbg_target* i_parentChip, TargetType_t i_unitType,
1582a394cbbSZane Shelley uint8_t i_unitPos)
1592a394cbbSZane Shelley {
1602a394cbbSZane Shelley assert(nullptr != i_parentChip);
1612a394cbbSZane Shelley
1622a394cbbSZane Shelley auto parentType = getTrgtType(i_parentChip);
1632a394cbbSZane Shelley
1642a394cbbSZane Shelley std::string devTreeType{};
1652a394cbbSZane Shelley
1662a394cbbSZane Shelley if (TYPE_PROC == parentType)
1672a394cbbSZane Shelley {
1682a394cbbSZane Shelley // clang-format off
1692a394cbbSZane Shelley static const std::map<TargetType_t, std::string> m =
1702a394cbbSZane Shelley {
1712a394cbbSZane Shelley {TYPE_MC, "mc" },
1722a394cbbSZane Shelley {TYPE_MCC, "mcc" },
1732a394cbbSZane Shelley {TYPE_OMI, "omi" },
1742a394cbbSZane Shelley {TYPE_OMIC, "omic" },
1752a394cbbSZane Shelley {TYPE_PAUC, "pauc" },
1762a394cbbSZane Shelley {TYPE_PAU, "pau" },
1772a394cbbSZane Shelley {TYPE_NMMU, "nmmu" },
1782a394cbbSZane Shelley {TYPE_IOHS, "iohs" },
1792a394cbbSZane Shelley {TYPE_IOLINK, "smpgroup"},
1802a394cbbSZane Shelley {TYPE_EQ, "eq" },
1812a394cbbSZane Shelley {TYPE_CORE, "core" },
1822a394cbbSZane Shelley {TYPE_PEC, "pec" },
1832a394cbbSZane Shelley {TYPE_PHB, "phb" },
1842a394cbbSZane Shelley {TYPE_NX, "nx" },
1852a394cbbSZane Shelley };
1862a394cbbSZane Shelley // clang-format on
1872a394cbbSZane Shelley
1882a394cbbSZane Shelley devTreeType = m.at(i_unitType);
1892a394cbbSZane Shelley }
1902a394cbbSZane Shelley else if (TYPE_OCMB == parentType)
1912a394cbbSZane Shelley {
1922a394cbbSZane Shelley // clang-format off
1932a394cbbSZane Shelley static const std::map<TargetType_t, std::string> m =
1942a394cbbSZane Shelley {
1952a394cbbSZane Shelley {TYPE_MEM_PORT, "mem_port"},
1962a394cbbSZane Shelley };
1972a394cbbSZane Shelley // clang-format on
1982a394cbbSZane Shelley
1992a394cbbSZane Shelley devTreeType = m.at(i_unitType);
2002a394cbbSZane Shelley }
2012a394cbbSZane Shelley else
2022a394cbbSZane Shelley {
203a0c724d3SPatrick Williams throw std::logic_error(
204a0c724d3SPatrick Williams "Unexpected parent chip: " + std::string{getPath(i_parentChip)});
2052a394cbbSZane Shelley }
2062a394cbbSZane Shelley
2072a394cbbSZane Shelley // Iterate all children of the parent and match the unit position.
2082a394cbbSZane Shelley pdbg_target* unitTarget = nullptr;
2092a394cbbSZane Shelley pdbg_for_each_target(devTreeType.c_str(), i_parentChip, unitTarget)
2102a394cbbSZane Shelley {
2112a394cbbSZane Shelley if (nullptr != unitTarget && i_unitPos == getUnitPos(unitTarget))
2122a394cbbSZane Shelley {
2132a394cbbSZane Shelley break; // found it
2142a394cbbSZane Shelley }
2152a394cbbSZane Shelley }
2162a394cbbSZane Shelley
2172a394cbbSZane Shelley // Print a warning if the target unit is not found, but don't throw an
2182a394cbbSZane Shelley // error. Instead let the calling code deal with the it.
2192a394cbbSZane Shelley if (nullptr == unitTarget)
2202a394cbbSZane Shelley {
2212a394cbbSZane Shelley trace::err("No unit target found: i_parentChip=%s i_unitType=0x%02x "
2222a394cbbSZane Shelley "i_unitPos=%u",
2232a394cbbSZane Shelley getPath(i_parentChip), i_unitType, i_unitPos);
2242a394cbbSZane Shelley }
2252a394cbbSZane Shelley
2262a394cbbSZane Shelley return unitTarget;
2272a394cbbSZane Shelley }
2282a394cbbSZane Shelley
2292a394cbbSZane Shelley //------------------------------------------------------------------------------
2302a394cbbSZane Shelley
getTargetAcrossBus(pdbg_target * i_rxTarget)231626270afSCaleb Palmer pdbg_target* getTargetAcrossBus(pdbg_target* i_rxTarget)
232626270afSCaleb Palmer {
233626270afSCaleb Palmer assert(nullptr != i_rxTarget);
234626270afSCaleb Palmer
235626270afSCaleb Palmer // Validate target type
236626270afSCaleb Palmer auto rxType = util::pdbg::getTrgtType(i_rxTarget);
237626270afSCaleb Palmer assert(util::pdbg::TYPE_IOLINK == rxType ||
238626270afSCaleb Palmer util::pdbg::TYPE_IOHS == rxType);
239626270afSCaleb Palmer
240626270afSCaleb Palmer pdbg_target* o_peerTarget;
241626270afSCaleb Palmer fs::path filePath;
242626270afSCaleb Palmer
243626270afSCaleb Palmer // Open the appropriate data file depending on machine type
244626270afSCaleb Palmer util::dbus::MachineType machineType = util::dbus::getMachineType();
245626270afSCaleb Palmer switch (machineType)
246626270afSCaleb Palmer {
247*df9f8e40SZane Shelley // Rainier/Blue Ridge 4U
248626270afSCaleb Palmer case util::dbus::MachineType::Rainier_2S4U:
249626270afSCaleb Palmer case util::dbus::MachineType::Rainier_1S4U:
250*df9f8e40SZane Shelley case util::dbus::MachineType::BlueRidge_2S4U:
251*df9f8e40SZane Shelley case util::dbus::MachineType::BlueRidge_1S4U:
252a0c724d3SPatrick Williams filePath =
253a0c724d3SPatrick Williams fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-4u.json"};
254626270afSCaleb Palmer break;
255*df9f8e40SZane Shelley // Rainier/Blue Ridge 2U
256626270afSCaleb Palmer case util::dbus::MachineType::Rainier_2S2U:
257626270afSCaleb Palmer case util::dbus::MachineType::Rainier_1S2U:
258*df9f8e40SZane Shelley case util::dbus::MachineType::BlueRidge_2S2U:
259a0c724d3SPatrick Williams filePath =
260a0c724d3SPatrick Williams fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-2u.json"};
261626270afSCaleb Palmer break;
262*df9f8e40SZane Shelley // Everest/Fuji
263626270afSCaleb Palmer case util::dbus::MachineType::Everest:
264*df9f8e40SZane Shelley case util::dbus::MachineType::Fuji:
265a0c724d3SPatrick Williams filePath =
266a0c724d3SPatrick Williams fs::path{PACKAGE_DIR "util-data/peer-targets-everest.json"};
267626270afSCaleb Palmer break;
268*df9f8e40SZane Shelley // Bonnell/Balcones
269a7dc66baSZane Shelley case util::dbus::MachineType::Bonnell:
270*df9f8e40SZane Shelley case util::dbus::MachineType::Balcones:
271a0c724d3SPatrick Williams filePath =
272a0c724d3SPatrick Williams fs::path{PACKAGE_DIR "util-data/peer-targets-bonnell.json"};
273a7dc66baSZane Shelley break;
274626270afSCaleb Palmer default:
275626270afSCaleb Palmer trace::err("Invalid machine type found %d",
276626270afSCaleb Palmer static_cast<uint8_t>(machineType));
277626270afSCaleb Palmer break;
278626270afSCaleb Palmer }
279626270afSCaleb Palmer
280626270afSCaleb Palmer std::ifstream file{filePath};
281626270afSCaleb Palmer assert(file.good());
282626270afSCaleb Palmer
283626270afSCaleb Palmer try
284626270afSCaleb Palmer {
285626270afSCaleb Palmer auto trgtMap = nlohmann::json::parse(file);
286626270afSCaleb Palmer std::string rxPath = util::pdbg::getPath(i_rxTarget);
287626270afSCaleb Palmer std::string peerPath = trgtMap.at(rxPath).get<std::string>();
288626270afSCaleb Palmer
289626270afSCaleb Palmer o_peerTarget = util::pdbg::getTrgt(peerPath);
290626270afSCaleb Palmer }
291626270afSCaleb Palmer catch (...)
292626270afSCaleb Palmer {
293626270afSCaleb Palmer trace::err("Failed to parse file: %s", filePath.string().c_str());
294626270afSCaleb Palmer throw;
295626270afSCaleb Palmer }
296626270afSCaleb Palmer
297626270afSCaleb Palmer return o_peerTarget;
298626270afSCaleb Palmer }
299626270afSCaleb Palmer
300626270afSCaleb Palmer //------------------------------------------------------------------------------
301626270afSCaleb Palmer
getConnectedTarget(pdbg_target * i_rxTarget,const callout::BusType & i_busType)30238501e12SZane Shelley pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget,
30338501e12SZane Shelley const callout::BusType& i_busType)
30438501e12SZane Shelley {
30538501e12SZane Shelley assert(nullptr != i_rxTarget);
30638501e12SZane Shelley
30738501e12SZane Shelley pdbg_target* txTarget = nullptr;
30838501e12SZane Shelley
30938501e12SZane Shelley auto rxType = util::pdbg::getTrgtType(i_rxTarget);
31038501e12SZane Shelley std::string rxPath = util::pdbg::getPath(i_rxTarget);
31138501e12SZane Shelley
31238501e12SZane Shelley if (callout::BusType::SMP_BUS == i_busType &&
31338501e12SZane Shelley util::pdbg::TYPE_IOLINK == rxType)
31438501e12SZane Shelley {
315626270afSCaleb Palmer txTarget = getTargetAcrossBus(i_rxTarget);
31638501e12SZane Shelley }
31738501e12SZane Shelley else if (callout::BusType::SMP_BUS == i_busType &&
31838501e12SZane Shelley util::pdbg::TYPE_IOHS == rxType)
31938501e12SZane Shelley {
320626270afSCaleb Palmer txTarget = getTargetAcrossBus(i_rxTarget);
32138501e12SZane Shelley }
32238501e12SZane Shelley else if (callout::BusType::OMI_BUS == i_busType &&
32338501e12SZane Shelley util::pdbg::TYPE_OMI == rxType)
32438501e12SZane Shelley {
32538501e12SZane Shelley // This is a bit clunky. The pdbg APIs only give us the ability to
326626270afSCaleb Palmer // iterate over the children instead of just returning a list. So
327626270afSCaleb Palmer // we'll push all the children to a list and go from there.
32838501e12SZane Shelley std::vector<pdbg_target*> childList;
32938501e12SZane Shelley
33038501e12SZane Shelley pdbg_target* childTarget = nullptr;
33138501e12SZane Shelley pdbg_for_each_target("ocmb", i_rxTarget, childTarget)
33238501e12SZane Shelley {
33338501e12SZane Shelley if (nullptr != childTarget)
33438501e12SZane Shelley {
33538501e12SZane Shelley childList.push_back(childTarget);
33638501e12SZane Shelley }
33738501e12SZane Shelley }
33838501e12SZane Shelley
33938501e12SZane Shelley // We know there should only be one OCMB per OMI.
34038501e12SZane Shelley if (1 != childList.size())
34138501e12SZane Shelley {
34238501e12SZane Shelley throw std::logic_error("Invalid child list size for " + rxPath);
34338501e12SZane Shelley }
34438501e12SZane Shelley
34538501e12SZane Shelley // Get the connected target.
34638501e12SZane Shelley txTarget = childList.front();
34738501e12SZane Shelley }
34838501e12SZane Shelley else if (callout::BusType::OMI_BUS == i_busType &&
34938501e12SZane Shelley util::pdbg::TYPE_OCMB == rxType)
35038501e12SZane Shelley {
35138501e12SZane Shelley txTarget = pdbg_target_parent("omi", i_rxTarget);
35238501e12SZane Shelley if (nullptr == txTarget)
35338501e12SZane Shelley {
35438501e12SZane Shelley throw std::logic_error("No parent OMI found for " + rxPath);
35538501e12SZane Shelley }
35638501e12SZane Shelley }
35738501e12SZane Shelley else
35838501e12SZane Shelley {
35938501e12SZane Shelley // This would be a code bug.
36038501e12SZane Shelley throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath +
36138501e12SZane Shelley " i_busType=" + i_busType.getString());
36238501e12SZane Shelley }
36338501e12SZane Shelley
36438501e12SZane Shelley assert(nullptr != txTarget); // just in case we missed something above
36538501e12SZane Shelley
36638501e12SZane Shelley return txTarget;
36738501e12SZane Shelley }
36838501e12SZane Shelley
36938501e12SZane Shelley //------------------------------------------------------------------------------
37038501e12SZane Shelley
getPibTrgt(pdbg_target * i_procTrgt)371171a2e04SZane Shelley pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
372171a2e04SZane Shelley {
373171a2e04SZane Shelley // The input target must be a processor.
37435171d90SZane Shelley assert(TYPE_PROC == getTrgtType(i_procTrgt));
375171a2e04SZane Shelley
376171a2e04SZane Shelley // Get the pib path.
377171a2e04SZane Shelley char path[16];
378171a2e04SZane Shelley sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
379171a2e04SZane Shelley
380171a2e04SZane Shelley // Return the pib target.
381171a2e04SZane Shelley pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
382171a2e04SZane Shelley assert(nullptr != pibTrgt);
383171a2e04SZane Shelley
384171a2e04SZane Shelley return pibTrgt;
385171a2e04SZane Shelley }
386171a2e04SZane Shelley
387171a2e04SZane Shelley //------------------------------------------------------------------------------
388171a2e04SZane Shelley
getFsiTrgt(pdbg_target * i_procTrgt)389ff76b6b4SZane Shelley pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
390ff76b6b4SZane Shelley {
391ff76b6b4SZane Shelley // The input target must be a processor.
39235171d90SZane Shelley assert(TYPE_PROC == getTrgtType(i_procTrgt));
393ff76b6b4SZane Shelley
394ff76b6b4SZane Shelley // Get the fsi path.
395ff76b6b4SZane Shelley char path[16];
396ff76b6b4SZane Shelley sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
397ff76b6b4SZane Shelley
398ff76b6b4SZane Shelley // Return the fsi target.
399ff76b6b4SZane Shelley pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
400ff76b6b4SZane Shelley assert(nullptr != fsiTrgt);
401ff76b6b4SZane Shelley
402ff76b6b4SZane Shelley return fsiTrgt;
403ff76b6b4SZane Shelley }
404ff76b6b4SZane Shelley
405ff76b6b4SZane Shelley //------------------------------------------------------------------------------
406ff76b6b4SZane Shelley
40735171d90SZane Shelley // IMPORTANT:
408626270afSCaleb Palmer // The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at
409626270afSCaleb Palmer // some point during the IPL. It is possible that this information is needed
410626270afSCaleb Palmer // before the sync occurs, in which case the value will return 0.
__getChipId(pdbg_target * i_trgt)411171a2e04SZane Shelley uint32_t __getChipId(pdbg_target* i_trgt)
412171a2e04SZane Shelley {
413171a2e04SZane Shelley uint32_t attr = 0;
414171a2e04SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
415171a2e04SZane Shelley return attr;
416171a2e04SZane Shelley }
417171a2e04SZane Shelley
41835171d90SZane Shelley // IMPORTANT:
419626270afSCaleb Palmer // The ATTR_EC attribute will be synced from Hostboot to the BMC at some
420626270afSCaleb Palmer // point during the IPL. It is possible that this information is needed
421626270afSCaleb Palmer // before the sync occurs, in which case the value will return 0.
__getChipEc(pdbg_target * i_trgt)422171a2e04SZane Shelley uint8_t __getChipEc(pdbg_target* i_trgt)
423171a2e04SZane Shelley {
424171a2e04SZane Shelley uint8_t attr = 0;
425171a2e04SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
426171a2e04SZane Shelley return attr;
427171a2e04SZane Shelley }
428171a2e04SZane Shelley
__getChipIdEc(pdbg_target * i_trgt)429171a2e04SZane Shelley uint32_t __getChipIdEc(pdbg_target* i_trgt)
430171a2e04SZane Shelley {
43135171d90SZane Shelley auto chipId = __getChipId(i_trgt);
43235171d90SZane Shelley auto chipEc = __getChipEc(i_trgt);
43335171d90SZane Shelley
43435171d90SZane Shelley if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
43535171d90SZane Shelley {
43635171d90SZane Shelley // There is a special case where the model/level attributes have not
437626270afSCaleb Palmer // been initialized in the devtree. This is possible on the epoch
438626270afSCaleb Palmer // IPL where an attention occurs before Hostboot is able to update
439626270afSCaleb Palmer // the devtree information on the BMC. It may is still possible to
440626270afSCaleb Palmer // get this information from chips with CFAM access (i.e. a
441626270afSCaleb Palmer // processor) via the CFAM chip ID register.
44235171d90SZane Shelley
44335171d90SZane Shelley uint32_t val = 0;
44435171d90SZane Shelley if (0 == getCfam(i_trgt, 0x100a, val))
44535171d90SZane Shelley {
44635171d90SZane Shelley chipId = ((val & 0x0F0FF000) >> 12);
44735171d90SZane Shelley chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
44835171d90SZane Shelley }
44935171d90SZane Shelley }
45035171d90SZane Shelley
45135171d90SZane Shelley return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
452171a2e04SZane Shelley }
453171a2e04SZane Shelley
__addChip(std::vector<libhei::Chip> & o_chips,pdbg_target * i_trgt,libhei::ChipType_t i_type)454171a2e04SZane Shelley void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
455171a2e04SZane Shelley libhei::ChipType_t i_type)
456171a2e04SZane Shelley {
457626270afSCaleb Palmer // Trace each chip for debug. It is important to show the type just in
458626270afSCaleb Palmer // case the model/EC does not exist. See note below.
459171a2e04SZane Shelley trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
460171a2e04SZane Shelley getPath(i_trgt));
461171a2e04SZane Shelley
462171a2e04SZane Shelley if (0 == i_type)
463171a2e04SZane Shelley {
464626270afSCaleb Palmer // This is a special case. See the details in __getChipIdEC(). There
465626270afSCaleb Palmer // is nothing more we can do with this chip since we don't know what
466626270afSCaleb Palmer // it is. So ignore the chip for now.
467171a2e04SZane Shelley }
468171a2e04SZane Shelley else
469171a2e04SZane Shelley {
470171a2e04SZane Shelley o_chips.emplace_back(i_trgt, i_type);
471171a2e04SZane Shelley }
472171a2e04SZane Shelley }
473171a2e04SZane Shelley
474cd6373d3SZane Shelley // Should ignore OCMBs that have been masked on the processor side of the bus.
__isMaskedOcmb(const libhei::Chip & i_chip)475cd6373d3SZane Shelley bool __isMaskedOcmb(const libhei::Chip& i_chip)
476cd6373d3SZane Shelley {
477cd6373d3SZane Shelley // TODO: This function only works for P10 processors will need to update for
478cd6373d3SZane Shelley // subsequent chips.
479cd6373d3SZane Shelley
480cd6373d3SZane Shelley // Map of MCC target position to DSTL_FIR_MASK address.
481cd6373d3SZane Shelley static const std::map<unsigned int, uint64_t> addrs = {
482cd6373d3SZane Shelley {0, 0x0C010D03}, {1, 0x0C010D43}, {2, 0x0D010D03}, {3, 0x0D010D43},
483cd6373d3SZane Shelley {4, 0x0E010D03}, {5, 0x0E010D43}, {6, 0x0F010D03}, {7, 0x0F010D43},
484cd6373d3SZane Shelley };
485cd6373d3SZane Shelley
486cd6373d3SZane Shelley auto ocmb = getTrgt(i_chip);
487cd6373d3SZane Shelley
488cd6373d3SZane Shelley // Confirm this chip is an OCMB.
489cd6373d3SZane Shelley if (TYPE_OCMB != getTrgtType(ocmb))
490cd6373d3SZane Shelley {
491cd6373d3SZane Shelley return false;
492cd6373d3SZane Shelley }
493cd6373d3SZane Shelley
494cd6373d3SZane Shelley // Get the connected MCC target on the processor chip.
495cd6373d3SZane Shelley auto mcc = pdbg_target_parent("mcc", ocmb);
496cd6373d3SZane Shelley if (nullptr == mcc)
497cd6373d3SZane Shelley {
498a0c724d3SPatrick Williams throw std::logic_error(
499a0c724d3SPatrick Williams "No parent MCC found for " + std::string{getPath(ocmb)});
500cd6373d3SZane Shelley }
501cd6373d3SZane Shelley
502cd6373d3SZane Shelley // Read the associated DSTL_FIR_MASK.
503cd6373d3SZane Shelley uint64_t val = 0;
504cd6373d3SZane Shelley if (getScom(getParentChip(mcc), addrs.at(getUnitPos(mcc)), val))
505cd6373d3SZane Shelley {
506cd6373d3SZane Shelley // Just let this go. The SCOM code will log the error.
507cd6373d3SZane Shelley return false;
508cd6373d3SZane Shelley }
509cd6373d3SZane Shelley
510cd6373d3SZane Shelley // The DSTL_FIR has bits for each of the two memory channels on the MCC.
511cd6373d3SZane Shelley auto chnlPos = getChipPos(ocmb) % 2;
512cd6373d3SZane Shelley
513cd6373d3SZane Shelley // Channel 0 => bits 0-3, channel 1 => bits 4-7.
514cd6373d3SZane Shelley auto mask = (val >> (60 - (4 * chnlPos))) & 0xf;
515cd6373d3SZane Shelley
516cd6373d3SZane Shelley // Return true if the mask is set to all 1's.
517cd6373d3SZane Shelley if (0xf == mask)
518cd6373d3SZane Shelley {
519cd6373d3SZane Shelley trace::inf("OCMB masked on processor side of bus: %s", getPath(ocmb));
520cd6373d3SZane Shelley return true;
521cd6373d3SZane Shelley }
522cd6373d3SZane Shelley
523cd6373d3SZane Shelley return false; // default
524cd6373d3SZane Shelley }
525cd6373d3SZane Shelley
getActiveChips(std::vector<libhei::Chip> & o_chips)526171a2e04SZane Shelley void getActiveChips(std::vector<libhei::Chip>& o_chips)
527171a2e04SZane Shelley {
528171a2e04SZane Shelley o_chips.clear();
529171a2e04SZane Shelley
530171a2e04SZane Shelley // Iterate each processor.
531171a2e04SZane Shelley pdbg_target* procTrgt;
532171a2e04SZane Shelley pdbg_for_each_class_target("proc", procTrgt)
533171a2e04SZane Shelley {
534171a2e04SZane Shelley // We cannot use the proc target to determine if the chip is active.
535171a2e04SZane Shelley // There is some design limitation in pdbg that requires the proc
536626270afSCaleb Palmer // targets to always be active. Instead, we must get the associated
537626270afSCaleb Palmer // pib target and check if it is active.
538171a2e04SZane Shelley
539171a2e04SZane Shelley // Active processors only.
540171a2e04SZane Shelley if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
541171a2e04SZane Shelley continue;
542171a2e04SZane Shelley
543171a2e04SZane Shelley // Add the processor to the list.
544171a2e04SZane Shelley __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
545171a2e04SZane Shelley
546171a2e04SZane Shelley // Iterate the connected OCMBs, if they exist.
547171a2e04SZane Shelley pdbg_target* ocmbTrgt;
548171a2e04SZane Shelley pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
549171a2e04SZane Shelley {
550171a2e04SZane Shelley // Active OCMBs only.
551171a2e04SZane Shelley if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
552171a2e04SZane Shelley continue;
553171a2e04SZane Shelley
554171a2e04SZane Shelley // Add the OCMB to the list.
555171a2e04SZane Shelley __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
556171a2e04SZane Shelley }
557171a2e04SZane Shelley }
558cd6373d3SZane Shelley
559cd6373d3SZane Shelley // Ignore OCMBs that have been masked on the processor side of the bus.
560cd6373d3SZane Shelley o_chips.erase(
561cd6373d3SZane Shelley std::remove_if(o_chips.begin(), o_chips.end(), __isMaskedOcmb),
562cd6373d3SZane Shelley o_chips.end());
563171a2e04SZane Shelley }
564171a2e04SZane Shelley
565171a2e04SZane Shelley //------------------------------------------------------------------------------
566171a2e04SZane Shelley
getActiveProcessorChips(std::vector<pdbg_target * > & o_chips)5673f363d4aSZane Shelley void getActiveProcessorChips(std::vector<pdbg_target*>& o_chips)
5683f363d4aSZane Shelley {
5693f363d4aSZane Shelley o_chips.clear();
5703f363d4aSZane Shelley
5713f363d4aSZane Shelley pdbg_target* procTrgt;
5723f363d4aSZane Shelley pdbg_for_each_class_target("proc", procTrgt)
5733f363d4aSZane Shelley {
5743f363d4aSZane Shelley // We cannot use the proc target to determine if the chip is active.
5753f363d4aSZane Shelley // There is some design limitation in pdbg that requires the proc
5763f363d4aSZane Shelley // targets to always be active. Instead, we must get the associated pib
5773f363d4aSZane Shelley // target and check if it is active.
5783f363d4aSZane Shelley
5793f363d4aSZane Shelley if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
5803f363d4aSZane Shelley continue;
5813f363d4aSZane Shelley
5823f363d4aSZane Shelley o_chips.push_back(procTrgt);
5833f363d4aSZane Shelley }
5843f363d4aSZane Shelley }
5853f363d4aSZane Shelley
5863f363d4aSZane Shelley //------------------------------------------------------------------------------
5873f363d4aSZane Shelley
getPrimaryProcessor()588c18ba8fbSZane Shelley pdbg_target* getPrimaryProcessor()
589c18ba8fbSZane Shelley {
590626270afSCaleb Palmer // TODO: For at least P10, the primary processor (the one connected
591626270afSCaleb Palmer // directly
592c18ba8fbSZane Shelley // to the BMC), will always be PROC 0. We will need to update this
593c18ba8fbSZane Shelley // later if we ever support an alternate primary processor.
594c18ba8fbSZane Shelley return getTrgt("/proc0");
595c18ba8fbSZane Shelley }
596c18ba8fbSZane Shelley
597c18ba8fbSZane Shelley //------------------------------------------------------------------------------
598c18ba8fbSZane Shelley
queryHardwareAnalysisSupported()5997ae9c8c7SZane Shelley bool queryHardwareAnalysisSupported()
6007ae9c8c7SZane Shelley {
6017ae9c8c7SZane Shelley // Hardware analysis is only supported on P10 systems and up.
6025183af30SZane Shelley return (PDBG_PROC_P9 < pdbg_get_proc());
6037ae9c8c7SZane Shelley }
6047ae9c8c7SZane Shelley
6057ae9c8c7SZane Shelley //------------------------------------------------------------------------------
6067ae9c8c7SZane Shelley
getLocationCode(pdbg_target * trgt)6073a85108fSZane Shelley std::string getLocationCode(pdbg_target* trgt)
6083a85108fSZane Shelley {
6093a85108fSZane Shelley if (nullptr == trgt)
6103a85108fSZane Shelley {
6113a85108fSZane Shelley // Either the path is wrong or the attribute doesn't exist.
6123a85108fSZane Shelley return std::string{};
6133a85108fSZane Shelley }
6143a85108fSZane Shelley
6153a85108fSZane Shelley #ifdef CONFIG_PHAL_API
6163a85108fSZane Shelley
6173a85108fSZane Shelley ATTR_LOCATION_CODE_Type val;
6183a85108fSZane Shelley if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val))
6193a85108fSZane Shelley {
6203a85108fSZane Shelley // Get the immediate parent in the devtree path and try again.
6213a85108fSZane Shelley return getLocationCode(pdbg_target_parent(nullptr, trgt));
6223a85108fSZane Shelley }
6233a85108fSZane Shelley
6243a85108fSZane Shelley // Attribute found.
6253a85108fSZane Shelley return std::string{val};
6263a85108fSZane Shelley
6273a85108fSZane Shelley #else
6283a85108fSZane Shelley
6293a85108fSZane Shelley return std::string{getPath(trgt)};
6303a85108fSZane Shelley
6313a85108fSZane Shelley #endif
6323a85108fSZane Shelley }
6333a85108fSZane Shelley
6343a85108fSZane Shelley //------------------------------------------------------------------------------
6353a85108fSZane Shelley
getPhysDevPath(pdbg_target * trgt)6363a85108fSZane Shelley std::string getPhysDevPath(pdbg_target* trgt)
6373a85108fSZane Shelley {
6383a85108fSZane Shelley if (nullptr == trgt)
6393a85108fSZane Shelley {
6403a85108fSZane Shelley // Either the path is wrong or the attribute doesn't exist.
6413a85108fSZane Shelley return std::string{};
6423a85108fSZane Shelley }
6433a85108fSZane Shelley
6443a85108fSZane Shelley #ifdef CONFIG_PHAL_API
6453a85108fSZane Shelley
6463a85108fSZane Shelley ATTR_PHYS_DEV_PATH_Type val;
6473a85108fSZane Shelley if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val))
6483a85108fSZane Shelley {
6493a85108fSZane Shelley // Get the immediate parent in the devtree path and try again.
6503a85108fSZane Shelley return getPhysDevPath(pdbg_target_parent(nullptr, trgt));
6513a85108fSZane Shelley }
6523a85108fSZane Shelley
6533a85108fSZane Shelley // Attribute found.
6543a85108fSZane Shelley return std::string{val};
6553a85108fSZane Shelley
6563a85108fSZane Shelley #else
6573a85108fSZane Shelley
6583a85108fSZane Shelley return std::string{getPath(trgt)};
6593a85108fSZane Shelley
6603a85108fSZane Shelley #endif
6613a85108fSZane Shelley }
6623a85108fSZane Shelley
6633a85108fSZane Shelley //------------------------------------------------------------------------------
6643a85108fSZane Shelley
getPhysBinPath(pdbg_target * target)665bf3326fbSZane Shelley std::vector<uint8_t> getPhysBinPath(pdbg_target* target)
666bf3326fbSZane Shelley {
667bf3326fbSZane Shelley std::vector<uint8_t> binPath;
668bf3326fbSZane Shelley
669bf3326fbSZane Shelley if (nullptr != target)
670bf3326fbSZane Shelley {
671bf3326fbSZane Shelley #ifdef CONFIG_PHAL_API
672bf3326fbSZane Shelley
673bf3326fbSZane Shelley ATTR_PHYS_BIN_PATH_Type value;
674bf3326fbSZane Shelley if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
675bf3326fbSZane Shelley {
676626270afSCaleb Palmer // The attrirbute for this target does not exist. Get the
677626270afSCaleb Palmer // immediate parent in the devtree path and try again. Note that
678626270afSCaleb Palmer // if there is no parent target, nullptr will be returned and
679626270afSCaleb Palmer // that will be checked above.
680bf3326fbSZane Shelley return getPhysBinPath(pdbg_target_parent(nullptr, target));
681bf3326fbSZane Shelley }
682bf3326fbSZane Shelley
683bf3326fbSZane Shelley // Attribute was found. Copy the attribute array to the returned
684bf3326fbSZane Shelley // vector. Note that the reason we return the vector instead of just
685bf3326fbSZane Shelley // returning the array is because the array type and details only
686bf3326fbSZane Shelley // exists in this specific configuration.
687bf3326fbSZane Shelley binPath.insert(binPath.end(), value, value + sizeof(value));
688bf3326fbSZane Shelley
689bf3326fbSZane Shelley #endif
690bf3326fbSZane Shelley }
691bf3326fbSZane Shelley
692bf3326fbSZane Shelley return binPath;
693bf3326fbSZane Shelley }
694bf3326fbSZane Shelley
695bf3326fbSZane Shelley //------------------------------------------------------------------------------
696bf3326fbSZane Shelley
697f4bd5ff6SZane Shelley } // namespace pdbg
698f4bd5ff6SZane Shelley
699f4bd5ff6SZane Shelley } // namespace util
700