xref: /openbmc/openpower-hw-diags/util/pdbg.cpp (revision df9f8e4052fe31a59c0c15dbc6c4adbfd37cd2dc)
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