pdbg.cpp (c7026261bb05cc509b0c7fb204ba967419a8b35d) | pdbg.cpp (626270affc0f71eaab89c45c492e6732238fa360) |
---|---|
1//------------------------------------------------------------------------------ 2// IMPORTANT: 3// This file will be built in CI test and should work out-of-the-box in CI test 4// with use of the fake device tree. Any functions that require addition support 5// to simulate in CI test should be put in `pdbg_no_sim.cpp`. 6//------------------------------------------------------------------------------ 7 8#include <assert.h> 9#include <config.h> 10 11#include <hei_main.hpp> | 1//------------------------------------------------------------------------------ 2// IMPORTANT: 3// This file will be built in CI test and should work out-of-the-box in CI test 4// with use of the fake device tree. Any functions that require addition support 5// to simulate in CI test should be put in `pdbg_no_sim.cpp`. 6//------------------------------------------------------------------------------ 7 8#include <assert.h> 9#include <config.h> 10 11#include <hei_main.hpp> |
12#include <nlohmann/json.hpp> 13#include <util/dbus.hpp> |
|
12#include <util/pdbg.hpp> 13#include <util/trace.hpp> 14 | 14#include <util/pdbg.hpp> 15#include <util/trace.hpp> 16 |
17#include <filesystem> 18#include <fstream> 19#include <string> 20 |
|
15#ifdef CONFIG_PHAL_API 16#include <attributes_info.H> 17#endif 18 19using namespace analyzer; 20 | 21#ifdef CONFIG_PHAL_API 22#include <attributes_info.H> 23#endif 24 25using namespace analyzer; 26 |
27namespace fs = std::filesystem; 28 |
|
21namespace util 22{ 23 24namespace pdbg 25{ 26 27//------------------------------------------------------------------------------ 28 --- 161 unchanged lines hidden (view full) --- 190 getPath(i_parentChip), i_unitType, i_unitPos); 191 } 192 193 return unitTarget; 194} 195 196//------------------------------------------------------------------------------ 197 | 29namespace util 30{ 31 32namespace pdbg 33{ 34 35//------------------------------------------------------------------------------ 36 --- 161 unchanged lines hidden (view full) --- 198 getPath(i_parentChip), i_unitType, i_unitPos); 199 } 200 201 return unitTarget; 202} 203 204//------------------------------------------------------------------------------ 205 |
206pdbg_target* getTargetAcrossBus(pdbg_target* i_rxTarget) 207{ 208 assert(nullptr != i_rxTarget); 209 210 // Validate target type 211 auto rxType = util::pdbg::getTrgtType(i_rxTarget); 212 assert(util::pdbg::TYPE_IOLINK == rxType || 213 util::pdbg::TYPE_IOHS == rxType); 214 215 pdbg_target* o_peerTarget; 216 fs::path filePath; 217 218 // Open the appropriate data file depending on machine type 219 util::dbus::MachineType machineType = util::dbus::getMachineType(); 220 switch (machineType) 221 { 222 // Rainier 4U 223 case util::dbus::MachineType::Rainier_2S4U: 224 case util::dbus::MachineType::Rainier_1S4U: 225 filePath = 226 fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-4u.json"}; 227 break; 228 // Rainier 2U 229 case util::dbus::MachineType::Rainier_2S2U: 230 case util::dbus::MachineType::Rainier_1S2U: 231 filePath = 232 fs::path{PACKAGE_DIR "util-data/peer-targets-rainier-2u.json"}; 233 break; 234 // Everest 235 case util::dbus::MachineType::Everest: 236 filePath = 237 fs::path{PACKAGE_DIR "util-data/peer-targets-everest.json"}; 238 break; 239 default: 240 trace::err("Invalid machine type found %d", 241 static_cast<uint8_t>(machineType)); 242 break; 243 } 244 245 std::ifstream file{filePath}; 246 assert(file.good()); 247 248 try 249 { 250 auto trgtMap = nlohmann::json::parse(file); 251 std::string rxPath = util::pdbg::getPath(i_rxTarget); 252 std::string peerPath = trgtMap.at(rxPath).get<std::string>(); 253 254 o_peerTarget = util::pdbg::getTrgt(peerPath); 255 } 256 catch (...) 257 { 258 trace::err("Failed to parse file: %s", filePath.string().c_str()); 259 throw; 260 } 261 262 return o_peerTarget; 263} 264 265//------------------------------------------------------------------------------ 266 |
|
198pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget, 199 const callout::BusType& i_busType) 200{ 201 assert(nullptr != i_rxTarget); 202 203 pdbg_target* txTarget = nullptr; 204 205 auto rxType = util::pdbg::getTrgtType(i_rxTarget); 206 std::string rxPath = util::pdbg::getPath(i_rxTarget); 207 208 if (callout::BusType::SMP_BUS == i_busType && 209 util::pdbg::TYPE_IOLINK == rxType) 210 { | 267pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget, 268 const callout::BusType& i_busType) 269{ 270 assert(nullptr != i_rxTarget); 271 272 pdbg_target* txTarget = nullptr; 273 274 auto rxType = util::pdbg::getTrgtType(i_rxTarget); 275 std::string rxPath = util::pdbg::getPath(i_rxTarget); 276 277 if (callout::BusType::SMP_BUS == i_busType && 278 util::pdbg::TYPE_IOLINK == rxType) 279 { |
211 // TODO: Will need to reference some sort of data that can tell us how 212 // the processors are connected in the system. For now, return the 213 // RX target to avoid returning a nullptr. 214 trace::inf("No support to get peer target on SMP bus"); 215 txTarget = i_rxTarget; | 280 txTarget = getTargetAcrossBus(i_rxTarget); |
216 } 217 else if (callout::BusType::SMP_BUS == i_busType && 218 util::pdbg::TYPE_IOHS == rxType) 219 { | 281 } 282 else if (callout::BusType::SMP_BUS == i_busType && 283 util::pdbg::TYPE_IOHS == rxType) 284 { |
220 // TODO: Will need to reference some sort of data that can tell us how 221 // the processors are connected in the system. For now, return the 222 // RX target to avoid returning a nullptr. 223 trace::inf("No support to get peer target on SMP bus"); 224 txTarget = i_rxTarget; | 285 txTarget = getTargetAcrossBus(i_rxTarget); |
225 } 226 else if (callout::BusType::OMI_BUS == i_busType && 227 util::pdbg::TYPE_OMI == rxType) 228 { 229 // This is a bit clunky. The pdbg APIs only give us the ability to | 286 } 287 else if (callout::BusType::OMI_BUS == i_busType && 288 util::pdbg::TYPE_OMI == rxType) 289 { 290 // This is a bit clunky. The pdbg APIs only give us the ability to |
230 // iterate over the children instead of just returning a list. So we'll 231 // push all the children to a list and go from there. | 291 // iterate over the children instead of just returning a list. So 292 // we'll push all the children to a list and go from there. |
232 std::vector<pdbg_target*> childList; 233 234 pdbg_target* childTarget = nullptr; 235 pdbg_for_each_target("ocmb", i_rxTarget, childTarget) 236 { 237 if (nullptr != childTarget) 238 { 239 childList.push_back(childTarget); --- 64 unchanged lines hidden (view full) --- 304 assert(nullptr != fsiTrgt); 305 306 return fsiTrgt; 307} 308 309//------------------------------------------------------------------------------ 310 311// IMPORTANT: | 293 std::vector<pdbg_target*> childList; 294 295 pdbg_target* childTarget = nullptr; 296 pdbg_for_each_target("ocmb", i_rxTarget, childTarget) 297 { 298 if (nullptr != childTarget) 299 { 300 childList.push_back(childTarget); --- 64 unchanged lines hidden (view full) --- 365 assert(nullptr != fsiTrgt); 366 367 return fsiTrgt; 368} 369 370//------------------------------------------------------------------------------ 371 372// IMPORTANT: |
312// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some 313// point during the IPL. It is possible that this information is needed before 314// the sync occurs, in which case the value will return 0. | 373// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at 374// some point during the IPL. It is possible that this information is needed 375// before the sync occurs, in which case the value will return 0. |
315uint32_t __getChipId(pdbg_target* i_trgt) 316{ 317 uint32_t attr = 0; 318 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr); 319 return attr; 320} 321 322// IMPORTANT: | 376uint32_t __getChipId(pdbg_target* i_trgt) 377{ 378 uint32_t attr = 0; 379 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr); 380 return attr; 381} 382 383// IMPORTANT: |
323// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point 324// during the IPL. It is possible that this information is needed before the 325// sync occurs, in which case the value will return 0. | 384// The ATTR_EC attribute will be synced from Hostboot to the BMC at some 385// point during the IPL. It is possible that this information is needed 386// before the sync occurs, in which case the value will return 0. |
326uint8_t __getChipEc(pdbg_target* i_trgt) 327{ 328 uint8_t attr = 0; 329 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr); 330 return attr; 331} 332 333uint32_t __getChipIdEc(pdbg_target* i_trgt) 334{ 335 auto chipId = __getChipId(i_trgt); 336 auto chipEc = __getChipEc(i_trgt); 337 338 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt))) 339 { 340 // There is a special case where the model/level attributes have not | 387uint8_t __getChipEc(pdbg_target* i_trgt) 388{ 389 uint8_t attr = 0; 390 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr); 391 return attr; 392} 393 394uint32_t __getChipIdEc(pdbg_target* i_trgt) 395{ 396 auto chipId = __getChipId(i_trgt); 397 auto chipEc = __getChipEc(i_trgt); 398 399 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt))) 400 { 401 // There is a special case where the model/level attributes have not |
341 // been initialized in the devtree. This is possible on the epoch IPL 342 // where an attention occurs before Hostboot is able to update the 343 // devtree information on the BMC. It may is still possible to get this 344 // information from chips with CFAM access (i.e. a processor) via the 345 // CFAM chip ID register. | 402 // been initialized in the devtree. This is possible on the epoch 403 // IPL where an attention occurs before Hostboot is able to update 404 // the devtree information on the BMC. It may is still possible to 405 // get this information from chips with CFAM access (i.e. a 406 // processor) via the CFAM chip ID register. |
346 347 uint32_t val = 0; 348 if (0 == getCfam(i_trgt, 0x100a, val)) 349 { 350 chipId = ((val & 0x0F0FF000) >> 12); 351 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20); 352 } 353 } 354 355 return ((chipId & 0xffff) << 16) | (chipEc & 0xff); 356} 357 358void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt, 359 libhei::ChipType_t i_type) 360{ | 407 408 uint32_t val = 0; 409 if (0 == getCfam(i_trgt, 0x100a, val)) 410 { 411 chipId = ((val & 0x0F0FF000) >> 12); 412 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20); 413 } 414 } 415 416 return ((chipId & 0xffff) << 16) | (chipEc & 0xff); 417} 418 419void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt, 420 libhei::ChipType_t i_type) 421{ |
361 // Trace each chip for debug. It is important to show the type just in case 362 // the model/EC does not exist. See note below. | 422 // Trace each chip for debug. It is important to show the type just in 423 // case the model/EC does not exist. See note below. |
363 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type, 364 getPath(i_trgt)); 365 366 if (0 == i_type) 367 { | 424 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type, 425 getPath(i_trgt)); 426 427 if (0 == i_type) 428 { |
368 // This is a special case. See the details in __getChipIdEC(). There is 369 // nothing more we can do with this chip since we don't know what it is. 370 // So ignore the chip for now. | 429 // This is a special case. See the details in __getChipIdEC(). There 430 // is nothing more we can do with this chip since we don't know what 431 // it is. So ignore the chip for now. |
371 } 372 else 373 { 374 o_chips.emplace_back(i_trgt, i_type); 375 } 376} 377 378void getActiveChips(std::vector<libhei::Chip>& o_chips) 379{ 380 o_chips.clear(); 381 382 // Iterate each processor. 383 pdbg_target* procTrgt; 384 pdbg_for_each_class_target("proc", procTrgt) 385 { 386 // We cannot use the proc target to determine if the chip is active. 387 // There is some design limitation in pdbg that requires the proc | 432 } 433 else 434 { 435 o_chips.emplace_back(i_trgt, i_type); 436 } 437} 438 439void getActiveChips(std::vector<libhei::Chip>& o_chips) 440{ 441 o_chips.clear(); 442 443 // Iterate each processor. 444 pdbg_target* procTrgt; 445 pdbg_for_each_class_target("proc", procTrgt) 446 { 447 // We cannot use the proc target to determine if the chip is active. 448 // There is some design limitation in pdbg that requires the proc |
388 // targets to always be active. Instead, we must get the associated pib 389 // target and check if it is active. | 449 // targets to always be active. Instead, we must get the associated 450 // pib target and check if it is active. |
390 391 // Active processors only. 392 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt))) 393 continue; 394 395 // Add the processor to the list. 396 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt)); 397 --- 31 unchanged lines hidden (view full) --- 429 o_chips.push_back(procTrgt); 430 } 431} 432 433//------------------------------------------------------------------------------ 434 435pdbg_target* getPrimaryProcessor() 436{ | 451 452 // Active processors only. 453 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt))) 454 continue; 455 456 // Add the processor to the list. 457 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt)); 458 --- 31 unchanged lines hidden (view full) --- 490 o_chips.push_back(procTrgt); 491 } 492} 493 494//------------------------------------------------------------------------------ 495 496pdbg_target* getPrimaryProcessor() 497{ |
437 // TODO: For at least P10, the primary processor (the one connected directly | 498 // TODO: For at least P10, the primary processor (the one connected 499 // directly |
438 // to the BMC), will always be PROC 0. We will need to update this 439 // later if we ever support an alternate primary processor. 440 return getTrgt("/proc0"); 441} 442 443//------------------------------------------------------------------------------ 444 445bool queryHardwareAnalysisSupported() --- 68 unchanged lines hidden (view full) --- 514 515 if (nullptr != target) 516 { 517#ifdef CONFIG_PHAL_API 518 519 ATTR_PHYS_BIN_PATH_Type value; 520 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value)) 521 { | 500 // to the BMC), will always be PROC 0. We will need to update this 501 // later if we ever support an alternate primary processor. 502 return getTrgt("/proc0"); 503} 504 505//------------------------------------------------------------------------------ 506 507bool queryHardwareAnalysisSupported() --- 68 unchanged lines hidden (view full) --- 576 577 if (nullptr != target) 578 { 579#ifdef CONFIG_PHAL_API 580 581 ATTR_PHYS_BIN_PATH_Type value; 582 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value)) 583 { |
522 // The attrirbute for this target does not exist. Get the immediate 523 // parent in the devtree path and try again. Note that if there is 524 // no parent target, nullptr will be returned and that will be 525 // checked above. | 584 // The attrirbute for this target does not exist. Get the 585 // immediate parent in the devtree path and try again. Note that 586 // if there is no parent target, nullptr will be returned and 587 // that will be checked above. |
526 return getPhysBinPath(pdbg_target_parent(nullptr, target)); 527 } 528 529 // Attribute was found. Copy the attribute array to the returned 530 // vector. Note that the reason we return the vector instead of just 531 // returning the array is because the array type and details only 532 // exists in this specific configuration. 533 binPath.insert(binPath.end(), value, value + sizeof(value)); --- 12 unchanged lines hidden --- | 588 return getPhysBinPath(pdbg_target_parent(nullptr, target)); 589 } 590 591 // Attribute was found. Copy the attribute array to the returned 592 // vector. Note that the reason we return the vector instead of just 593 // returning the array is because the array type and details only 594 // exists in this specific configuration. 595 binPath.insert(binPath.end(), value, value + sizeof(value)); --- 12 unchanged lines hidden --- |