| Zane Shelley | e90b85d | 2021-12-17 17:24:49 -0600 | [diff] [blame] | 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 |  | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 8 | #include <assert.h> | 
| Zane Shelley | e4bfb47 | 2021-08-10 12:47:32 -0500 | [diff] [blame] | 9 | #include <config.h> | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 10 |  | 
| Zane Shelley | 7ae9c8c | 2020-12-02 20:10:31 -0600 | [diff] [blame] | 11 | #include <hei_main.hpp> | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 12 | #include <nlohmann/json.hpp> | 
|  | 13 | #include <util/dbus.hpp> | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 14 | #include <util/pdbg.hpp> | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 15 | #include <util/trace.hpp> | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 16 |  | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 17 | #include <filesystem> | 
|  | 18 | #include <fstream> | 
|  | 19 | #include <string> | 
|  | 20 |  | 
| Zane Shelley | 3a85108 | 2021-03-23 16:45:28 -0500 | [diff] [blame] | 21 | #ifdef CONFIG_PHAL_API | 
| Zane Shelley | e4bfb47 | 2021-08-10 12:47:32 -0500 | [diff] [blame] | 22 | #include <attributes_info.H> | 
| Zane Shelley | 3a85108 | 2021-03-23 16:45:28 -0500 | [diff] [blame] | 23 | #endif | 
|  | 24 |  | 
| Zane Shelley | 38501e1 | 2022-01-10 15:42:28 -0600 | [diff] [blame] | 25 | using namespace analyzer; | 
|  | 26 |  | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 27 | namespace fs = std::filesystem; | 
|  | 28 |  | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 29 | namespace util | 
|  | 30 | { | 
|  | 31 |  | 
|  | 32 | namespace pdbg | 
|  | 33 | { | 
|  | 34 |  | 
|  | 35 | //------------------------------------------------------------------------------ | 
|  | 36 |  | 
| Zane Shelley | a029985 | 2020-11-13 13:38:04 -0600 | [diff] [blame] | 37 | pdbg_target* getTrgt(const libhei::Chip& i_chip) | 
|  | 38 | { | 
|  | 39 | return (pdbg_target*)i_chip.getChip(); | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | //------------------------------------------------------------------------------ | 
|  | 43 |  | 
| Zane Shelley | 236bb73 | 2021-03-24 17:07:46 -0500 | [diff] [blame] | 44 | pdbg_target* getTrgt(const std::string& i_path) | 
|  | 45 | { | 
|  | 46 | return pdbg_target_from_path(nullptr, i_path.c_str()); | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | //------------------------------------------------------------------------------ | 
|  | 50 |  | 
| Zane Shelley | a029985 | 2020-11-13 13:38:04 -0600 | [diff] [blame] | 51 | const char* getPath(pdbg_target* i_trgt) | 
|  | 52 | { | 
|  | 53 | return pdbg_target_path(i_trgt); | 
|  | 54 | } | 
|  | 55 |  | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 56 | const char* getPath(const libhei::Chip& i_chip) | 
|  | 57 | { | 
| Zane Shelley | a029985 | 2020-11-13 13:38:04 -0600 | [diff] [blame] | 58 | return getPath(getTrgt(i_chip)); | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | //------------------------------------------------------------------------------ | 
|  | 62 |  | 
|  | 63 | uint32_t getChipPos(pdbg_target* i_trgt) | 
|  | 64 | { | 
|  | 65 | uint32_t attr = 0; | 
|  | 66 | pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr); | 
|  | 67 | return attr; | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | uint32_t getChipPos(const libhei::Chip& i_chip) | 
|  | 71 | { | 
|  | 72 | return getChipPos(getTrgt(i_chip)); | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | //------------------------------------------------------------------------------ | 
|  | 76 |  | 
| Zane Shelley | 2a394cb | 2022-02-17 22:01:39 -0600 | [diff] [blame] | 77 | uint8_t getUnitPos(pdbg_target* i_trgt) | 
|  | 78 | { | 
|  | 79 | uint8_t attr = 0; | 
|  | 80 | pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_UNIT_POS", 1, 1, &attr); | 
|  | 81 | return attr; | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | //------------------------------------------------------------------------------ | 
|  | 85 |  | 
| Zane Shelley | a029985 | 2020-11-13 13:38:04 -0600 | [diff] [blame] | 86 | uint8_t getTrgtType(pdbg_target* i_trgt) | 
|  | 87 | { | 
|  | 88 | uint8_t attr = 0; | 
|  | 89 | pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr); | 
|  | 90 | return attr; | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | uint8_t getTrgtType(const libhei::Chip& i_chip) | 
|  | 94 | { | 
|  | 95 | return getTrgtType(getTrgt(i_chip)); | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 96 | } | 
|  | 97 |  | 
|  | 98 | //------------------------------------------------------------------------------ | 
|  | 99 |  | 
| Zane Shelley | 2a394cb | 2022-02-17 22:01:39 -0600 | [diff] [blame] | 100 | pdbg_target* getParentChip(pdbg_target* i_unitTarget) | 
|  | 101 | { | 
|  | 102 | assert(nullptr != i_unitTarget); | 
|  | 103 |  | 
|  | 104 | // Check if the given target is already a chip. | 
|  | 105 | auto targetType = getTrgtType(i_unitTarget); | 
|  | 106 | if (TYPE_PROC == targetType || TYPE_OCMB == targetType) | 
|  | 107 | { | 
|  | 108 | return i_unitTarget; // simply return the given target | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | // Check if this unit is on an OCMB. | 
|  | 112 | pdbg_target* parentChip = pdbg_target_parent("ocmb", i_unitTarget); | 
|  | 113 |  | 
|  | 114 | // If not on the OCMB, check if this unit is on a PROC. | 
|  | 115 | if (nullptr == parentChip) | 
|  | 116 | { | 
|  | 117 | parentChip = pdbg_target_parent("proc", i_unitTarget); | 
|  | 118 | } | 
|  | 119 |  | 
|  | 120 | // There should always be a parent chip. Throw an error if not found. | 
|  | 121 | if (nullptr == parentChip) | 
|  | 122 | { | 
|  | 123 | throw std::logic_error("No parent chip found: i_unitTarget=" + | 
|  | 124 | std::string{getPath(i_unitTarget)}); | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | return parentChip; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | //------------------------------------------------------------------------------ | 
|  | 131 |  | 
|  | 132 | pdbg_target* getChipUnit(pdbg_target* i_parentChip, TargetType_t i_unitType, | 
|  | 133 | uint8_t i_unitPos) | 
|  | 134 | { | 
|  | 135 | assert(nullptr != i_parentChip); | 
|  | 136 |  | 
|  | 137 | auto parentType = getTrgtType(i_parentChip); | 
|  | 138 |  | 
|  | 139 | std::string devTreeType{}; | 
|  | 140 |  | 
|  | 141 | if (TYPE_PROC == parentType) | 
|  | 142 | { | 
|  | 143 | // clang-format off | 
|  | 144 | static const std::map<TargetType_t, std::string> m = | 
|  | 145 | { | 
|  | 146 | {TYPE_MC,     "mc"      }, | 
|  | 147 | {TYPE_MCC,    "mcc"     }, | 
|  | 148 | {TYPE_OMI,    "omi"     }, | 
|  | 149 | {TYPE_OMIC,   "omic"    }, | 
|  | 150 | {TYPE_PAUC,   "pauc"    }, | 
|  | 151 | {TYPE_PAU,    "pau"     }, | 
|  | 152 | {TYPE_NMMU,   "nmmu"    }, | 
|  | 153 | {TYPE_IOHS,   "iohs"    }, | 
|  | 154 | {TYPE_IOLINK, "smpgroup"}, | 
|  | 155 | {TYPE_EQ,     "eq"      }, | 
|  | 156 | {TYPE_CORE,   "core"    }, | 
|  | 157 | {TYPE_PEC,    "pec"     }, | 
|  | 158 | {TYPE_PHB,    "phb"     }, | 
|  | 159 | {TYPE_NX,     "nx"      }, | 
|  | 160 | }; | 
|  | 161 | // clang-format on | 
|  | 162 |  | 
|  | 163 | devTreeType = m.at(i_unitType); | 
|  | 164 | } | 
|  | 165 | else if (TYPE_OCMB == parentType) | 
|  | 166 | { | 
|  | 167 | // clang-format off | 
|  | 168 | static const std::map<TargetType_t, std::string> m = | 
|  | 169 | { | 
|  | 170 | {TYPE_MEM_PORT, "mem_port"}, | 
|  | 171 | }; | 
|  | 172 | // clang-format on | 
|  | 173 |  | 
|  | 174 | devTreeType = m.at(i_unitType); | 
|  | 175 | } | 
|  | 176 | else | 
|  | 177 | { | 
|  | 178 | throw std::logic_error("Unexpected parent chip: " + | 
|  | 179 | std::string{getPath(i_parentChip)}); | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | // Iterate all children of the parent and match the unit position. | 
|  | 183 | pdbg_target* unitTarget = nullptr; | 
|  | 184 | pdbg_for_each_target(devTreeType.c_str(), i_parentChip, unitTarget) | 
|  | 185 | { | 
|  | 186 | if (nullptr != unitTarget && i_unitPos == getUnitPos(unitTarget)) | 
|  | 187 | { | 
|  | 188 | break; // found it | 
|  | 189 | } | 
|  | 190 | } | 
|  | 191 |  | 
|  | 192 | // Print a warning if the target unit is not found, but don't throw an | 
|  | 193 | // error.  Instead let the calling code deal with the it. | 
|  | 194 | if (nullptr == unitTarget) | 
|  | 195 | { | 
|  | 196 | trace::err("No unit target found: i_parentChip=%s i_unitType=0x%02x " | 
|  | 197 | "i_unitPos=%u", | 
|  | 198 | getPath(i_parentChip), i_unitType, i_unitPos); | 
|  | 199 | } | 
|  | 200 |  | 
|  | 201 | return unitTarget; | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 | //------------------------------------------------------------------------------ | 
|  | 205 |  | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 206 | pdbg_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 |  | 
| Zane Shelley | 38501e1 | 2022-01-10 15:42:28 -0600 | [diff] [blame] | 267 | pdbg_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 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 280 | txTarget = getTargetAcrossBus(i_rxTarget); | 
| Zane Shelley | 38501e1 | 2022-01-10 15:42:28 -0600 | [diff] [blame] | 281 | } | 
|  | 282 | else if (callout::BusType::SMP_BUS == i_busType && | 
|  | 283 | util::pdbg::TYPE_IOHS == rxType) | 
|  | 284 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 285 | txTarget = getTargetAcrossBus(i_rxTarget); | 
| Zane Shelley | 38501e1 | 2022-01-10 15:42:28 -0600 | [diff] [blame] | 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 | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 38501e1 | 2022-01-10 15:42:28 -0600 | [diff] [blame] | 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); | 
|  | 301 | } | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | // We know there should only be one OCMB per OMI. | 
|  | 305 | if (1 != childList.size()) | 
|  | 306 | { | 
|  | 307 | throw std::logic_error("Invalid child list size for " + rxPath); | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | // Get the connected target. | 
|  | 311 | txTarget = childList.front(); | 
|  | 312 | } | 
|  | 313 | else if (callout::BusType::OMI_BUS == i_busType && | 
|  | 314 | util::pdbg::TYPE_OCMB == rxType) | 
|  | 315 | { | 
|  | 316 | txTarget = pdbg_target_parent("omi", i_rxTarget); | 
|  | 317 | if (nullptr == txTarget) | 
|  | 318 | { | 
|  | 319 | throw std::logic_error("No parent OMI found for " + rxPath); | 
|  | 320 | } | 
|  | 321 | } | 
|  | 322 | else | 
|  | 323 | { | 
|  | 324 | // This would be a code bug. | 
|  | 325 | throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath + | 
|  | 326 | " i_busType=" + i_busType.getString()); | 
|  | 327 | } | 
|  | 328 |  | 
|  | 329 | assert(nullptr != txTarget); // just in case we missed something above | 
|  | 330 |  | 
|  | 331 | return txTarget; | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | //------------------------------------------------------------------------------ | 
|  | 335 |  | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 336 | pdbg_target* getPibTrgt(pdbg_target* i_procTrgt) | 
|  | 337 | { | 
|  | 338 | // The input target must be a processor. | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 339 | assert(TYPE_PROC == getTrgtType(i_procTrgt)); | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 340 |  | 
|  | 341 | // Get the pib path. | 
|  | 342 | char path[16]; | 
|  | 343 | sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt)); | 
|  | 344 |  | 
|  | 345 | // Return the pib target. | 
|  | 346 | pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path); | 
|  | 347 | assert(nullptr != pibTrgt); | 
|  | 348 |  | 
|  | 349 | return pibTrgt; | 
|  | 350 | } | 
|  | 351 |  | 
|  | 352 | //------------------------------------------------------------------------------ | 
|  | 353 |  | 
| Zane Shelley | ff76b6b | 2020-11-18 13:54:26 -0600 | [diff] [blame] | 354 | pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt) | 
|  | 355 | { | 
|  | 356 | // The input target must be a processor. | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 357 | assert(TYPE_PROC == getTrgtType(i_procTrgt)); | 
| Zane Shelley | ff76b6b | 2020-11-18 13:54:26 -0600 | [diff] [blame] | 358 |  | 
|  | 359 | // Get the fsi path. | 
|  | 360 | char path[16]; | 
|  | 361 | sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt)); | 
|  | 362 |  | 
|  | 363 | // Return the fsi target. | 
|  | 364 | pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path); | 
|  | 365 | assert(nullptr != fsiTrgt); | 
|  | 366 |  | 
|  | 367 | return fsiTrgt; | 
|  | 368 | } | 
|  | 369 |  | 
|  | 370 | //------------------------------------------------------------------------------ | 
|  | 371 |  | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 372 | // IMPORTANT: | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 376 | uint32_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 |  | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 383 | // IMPORTANT: | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 387 | uint8_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 |  | 
|  | 394 | uint32_t __getChipIdEc(pdbg_target* i_trgt) | 
|  | 395 | { | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 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 | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 35171d9 | 2020-12-03 13:31:13 -0600 | [diff] [blame] | 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); | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 417 | } | 
|  | 418 |  | 
|  | 419 | void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt, | 
|  | 420 | libhei::ChipType_t i_type) | 
|  | 421 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 424 | trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type, | 
|  | 425 | getPath(i_trgt)); | 
|  | 426 |  | 
|  | 427 | if (0 == i_type) | 
|  | 428 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 432 | } | 
|  | 433 | else | 
|  | 434 | { | 
|  | 435 | o_chips.emplace_back(i_trgt, i_type); | 
|  | 436 | } | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 | void 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 | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 449 | // targets to always be active. Instead, we must get the associated | 
|  | 450 | // pib target and check if it is active. | 
| Zane Shelley | 171a2e0 | 2020-11-13 13:56:13 -0600 | [diff] [blame] | 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 |  | 
|  | 459 | // Iterate the connected OCMBs, if they exist. | 
|  | 460 | pdbg_target* ocmbTrgt; | 
|  | 461 | pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt) | 
|  | 462 | { | 
|  | 463 | // Active OCMBs only. | 
|  | 464 | if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt)) | 
|  | 465 | continue; | 
|  | 466 |  | 
|  | 467 | // Add the OCMB to the list. | 
|  | 468 | __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt)); | 
|  | 469 | } | 
|  | 470 | } | 
|  | 471 | } | 
|  | 472 |  | 
|  | 473 | //------------------------------------------------------------------------------ | 
|  | 474 |  | 
| Zane Shelley | 3f363d4 | 2022-02-10 16:20:37 -0600 | [diff] [blame] | 475 | void getActiveProcessorChips(std::vector<pdbg_target*>& o_chips) | 
|  | 476 | { | 
|  | 477 | o_chips.clear(); | 
|  | 478 |  | 
|  | 479 | pdbg_target* procTrgt; | 
|  | 480 | pdbg_for_each_class_target("proc", procTrgt) | 
|  | 481 | { | 
|  | 482 | // We cannot use the proc target to determine if the chip is active. | 
|  | 483 | // There is some design limitation in pdbg that requires the proc | 
|  | 484 | // targets to always be active. Instead, we must get the associated pib | 
|  | 485 | // target and check if it is active. | 
|  | 486 |  | 
|  | 487 | if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt))) | 
|  | 488 | continue; | 
|  | 489 |  | 
|  | 490 | o_chips.push_back(procTrgt); | 
|  | 491 | } | 
|  | 492 | } | 
|  | 493 |  | 
|  | 494 | //------------------------------------------------------------------------------ | 
|  | 495 |  | 
| Zane Shelley | c18ba8f | 2021-12-01 16:29:20 -0600 | [diff] [blame] | 496 | pdbg_target* getPrimaryProcessor() | 
|  | 497 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 498 | // TODO: For at least P10, the primary processor (the one connected | 
|  | 499 | // directly | 
| Zane Shelley | c18ba8f | 2021-12-01 16:29:20 -0600 | [diff] [blame] | 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 |  | 
| Zane Shelley | 7ae9c8c | 2020-12-02 20:10:31 -0600 | [diff] [blame] | 507 | bool queryHardwareAnalysisSupported() | 
|  | 508 | { | 
|  | 509 | // Hardware analysis is only supported on P10 systems and up. | 
| Zane Shelley | 5183af3 | 2020-12-07 14:49:03 -0600 | [diff] [blame] | 510 | return (PDBG_PROC_P9 < pdbg_get_proc()); | 
| Zane Shelley | 7ae9c8c | 2020-12-02 20:10:31 -0600 | [diff] [blame] | 511 | } | 
|  | 512 |  | 
|  | 513 | //------------------------------------------------------------------------------ | 
|  | 514 |  | 
| Zane Shelley | 3a85108 | 2021-03-23 16:45:28 -0500 | [diff] [blame] | 515 | std::string getLocationCode(pdbg_target* trgt) | 
|  | 516 | { | 
|  | 517 | if (nullptr == trgt) | 
|  | 518 | { | 
|  | 519 | // Either the path is wrong or the attribute doesn't exist. | 
|  | 520 | return std::string{}; | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | #ifdef CONFIG_PHAL_API | 
|  | 524 |  | 
|  | 525 | ATTR_LOCATION_CODE_Type val; | 
|  | 526 | if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val)) | 
|  | 527 | { | 
|  | 528 | // Get the immediate parent in the devtree path and try again. | 
|  | 529 | return getLocationCode(pdbg_target_parent(nullptr, trgt)); | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | // Attribute found. | 
|  | 533 | return std::string{val}; | 
|  | 534 |  | 
|  | 535 | #else | 
|  | 536 |  | 
|  | 537 | return std::string{getPath(trgt)}; | 
|  | 538 |  | 
|  | 539 | #endif | 
|  | 540 | } | 
|  | 541 |  | 
|  | 542 | //------------------------------------------------------------------------------ | 
|  | 543 |  | 
|  | 544 | std::string getPhysDevPath(pdbg_target* trgt) | 
|  | 545 | { | 
|  | 546 | if (nullptr == trgt) | 
|  | 547 | { | 
|  | 548 | // Either the path is wrong or the attribute doesn't exist. | 
|  | 549 | return std::string{}; | 
|  | 550 | } | 
|  | 551 |  | 
|  | 552 | #ifdef CONFIG_PHAL_API | 
|  | 553 |  | 
|  | 554 | ATTR_PHYS_DEV_PATH_Type val; | 
|  | 555 | if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val)) | 
|  | 556 | { | 
|  | 557 | // Get the immediate parent in the devtree path and try again. | 
|  | 558 | return getPhysDevPath(pdbg_target_parent(nullptr, trgt)); | 
|  | 559 | } | 
|  | 560 |  | 
|  | 561 | // Attribute found. | 
|  | 562 | return std::string{val}; | 
|  | 563 |  | 
|  | 564 | #else | 
|  | 565 |  | 
|  | 566 | return std::string{getPath(trgt)}; | 
|  | 567 |  | 
|  | 568 | #endif | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | //------------------------------------------------------------------------------ | 
|  | 572 |  | 
| Zane Shelley | bf3326f | 2021-11-12 13:41:39 -0600 | [diff] [blame] | 573 | std::vector<uint8_t> getPhysBinPath(pdbg_target* target) | 
|  | 574 | { | 
|  | 575 | std::vector<uint8_t> binPath; | 
|  | 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 | { | 
| Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 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. | 
| Zane Shelley | bf3326f | 2021-11-12 13:41:39 -0600 | [diff] [blame] | 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)); | 
|  | 596 |  | 
|  | 597 | #endif | 
|  | 598 | } | 
|  | 599 |  | 
|  | 600 | return binPath; | 
|  | 601 | } | 
|  | 602 |  | 
|  | 603 | //------------------------------------------------------------------------------ | 
|  | 604 |  | 
| Zane Shelley | f4bd5ff | 2020-11-05 22:26:04 -0600 | [diff] [blame] | 605 | } // namespace pdbg | 
|  | 606 |  | 
|  | 607 | } // namespace util |