1 #include <assert.h> 2 #include <config.h> 3 4 #include <hei_main.hpp> 5 #include <util/pdbg.hpp> 6 #include <util/trace.hpp> 7 8 #ifdef CONFIG_PHAL_API 9 #include <attributes_info.H> 10 #endif 11 12 namespace util 13 { 14 15 namespace pdbg 16 { 17 18 //------------------------------------------------------------------------------ 19 20 pdbg_target* getTrgt(const libhei::Chip& i_chip) 21 { 22 return (pdbg_target*)i_chip.getChip(); 23 } 24 25 //------------------------------------------------------------------------------ 26 27 pdbg_target* getTrgt(const std::string& i_path) 28 { 29 return pdbg_target_from_path(nullptr, i_path.c_str()); 30 } 31 32 //------------------------------------------------------------------------------ 33 34 const char* getPath(pdbg_target* i_trgt) 35 { 36 return pdbg_target_path(i_trgt); 37 } 38 39 const char* getPath(const libhei::Chip& i_chip) 40 { 41 return getPath(getTrgt(i_chip)); 42 } 43 44 //------------------------------------------------------------------------------ 45 46 uint32_t getChipPos(pdbg_target* i_trgt) 47 { 48 uint32_t attr = 0; 49 pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr); 50 return attr; 51 } 52 53 uint32_t getChipPos(const libhei::Chip& i_chip) 54 { 55 return getChipPos(getTrgt(i_chip)); 56 } 57 58 //------------------------------------------------------------------------------ 59 60 uint8_t getTrgtType(pdbg_target* i_trgt) 61 { 62 uint8_t attr = 0; 63 pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr); 64 return attr; 65 } 66 67 uint8_t getTrgtType(const libhei::Chip& i_chip) 68 { 69 return getTrgtType(getTrgt(i_chip)); 70 } 71 72 //------------------------------------------------------------------------------ 73 74 pdbg_target* getPibTrgt(pdbg_target* i_procTrgt) 75 { 76 // The input target must be a processor. 77 assert(TYPE_PROC == getTrgtType(i_procTrgt)); 78 79 // Get the pib path. 80 char path[16]; 81 sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt)); 82 83 // Return the pib target. 84 pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path); 85 assert(nullptr != pibTrgt); 86 87 return pibTrgt; 88 } 89 90 //------------------------------------------------------------------------------ 91 92 pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt) 93 { 94 // The input target must be a processor. 95 assert(TYPE_PROC == getTrgtType(i_procTrgt)); 96 97 // Get the fsi path. 98 char path[16]; 99 sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt)); 100 101 // Return the fsi target. 102 pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path); 103 assert(nullptr != fsiTrgt); 104 105 return fsiTrgt; 106 } 107 108 //------------------------------------------------------------------------------ 109 110 int getScom(pdbg_target* i_trgt, uint64_t i_addr, uint64_t& o_val) 111 { 112 // Only processor targets are supported. 113 // TODO: Will need to add OCMB support later. 114 assert(TYPE_PROC == getTrgtType(i_trgt)); 115 116 auto pibTrgt = util::pdbg::getPibTrgt(i_trgt); 117 118 int rc = pib_read(pibTrgt, i_addr, &o_val); 119 120 if (0 != rc) 121 { 122 trace::err("pib_read failure: target=%s addr=0x%0" PRIx64, 123 util::pdbg::getPath(pibTrgt), i_addr); 124 } 125 126 return rc; 127 } 128 129 //------------------------------------------------------------------------------ 130 131 int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val) 132 { 133 // Only processor targets are supported. 134 assert(TYPE_PROC == getTrgtType(i_trgt)); 135 136 auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt); 137 138 int rc = fsi_read(fsiTrgt, i_addr, &o_val); 139 140 if (0 != rc) 141 { 142 trace::err("fsi_read failure: target=%s addr=0x%08x", 143 util::pdbg::getPath(fsiTrgt), i_addr); 144 } 145 146 return rc; 147 } 148 149 //------------------------------------------------------------------------------ 150 151 // IMPORTANT: 152 // The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some 153 // point during the IPL. It is possible that this information is needed before 154 // the sync occurs, in which case the value will return 0. 155 uint32_t __getChipId(pdbg_target* i_trgt) 156 { 157 uint32_t attr = 0; 158 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr); 159 return attr; 160 } 161 162 // IMPORTANT: 163 // The ATTR_EC attribute will be synced from Hostboot to the BMC at some point 164 // during the IPL. It is possible that this information is needed before the 165 // sync occurs, in which case the value will return 0. 166 uint8_t __getChipEc(pdbg_target* i_trgt) 167 { 168 uint8_t attr = 0; 169 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr); 170 return attr; 171 } 172 173 uint32_t __getChipIdEc(pdbg_target* i_trgt) 174 { 175 auto chipId = __getChipId(i_trgt); 176 auto chipEc = __getChipEc(i_trgt); 177 178 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt))) 179 { 180 // There is a special case where the model/level attributes have not 181 // been initialized in the devtree. This is possible on the epoch IPL 182 // where an attention occurs before Hostboot is able to update the 183 // devtree information on the BMC. It may is still possible to get this 184 // information from chips with CFAM access (i.e. a processor) via the 185 // CFAM chip ID register. 186 187 uint32_t val = 0; 188 if (0 == getCfam(i_trgt, 0x100a, val)) 189 { 190 chipId = ((val & 0x0F0FF000) >> 12); 191 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20); 192 } 193 } 194 195 return ((chipId & 0xffff) << 16) | (chipEc & 0xff); 196 } 197 198 void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt, 199 libhei::ChipType_t i_type) 200 { 201 // Trace each chip for debug. It is important to show the type just in case 202 // the model/EC does not exist. See note below. 203 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type, 204 getPath(i_trgt)); 205 206 if (0 == i_type) 207 { 208 // This is a special case. See the details in __getChipIdEC(). There is 209 // nothing more we can do with this chip since we don't know what it is. 210 // So ignore the chip for now. 211 } 212 else 213 { 214 o_chips.emplace_back(i_trgt, i_type); 215 } 216 } 217 218 void getActiveChips(std::vector<libhei::Chip>& o_chips) 219 { 220 o_chips.clear(); 221 222 // Iterate each processor. 223 pdbg_target* procTrgt; 224 pdbg_for_each_class_target("proc", procTrgt) 225 { 226 // We cannot use the proc target to determine if the chip is active. 227 // There is some design limitation in pdbg that requires the proc 228 // targets to always be active. Instead, we must get the associated pib 229 // target and check if it is active. 230 231 // Active processors only. 232 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt))) 233 continue; 234 235 // Add the processor to the list. 236 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt)); 237 238 // Iterate the connected OCMBs, if they exist. 239 pdbg_target* ocmbTrgt; 240 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt) 241 { 242 // Active OCMBs only. 243 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt)) 244 continue; 245 246 // Add the OCMB to the list. 247 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt)); 248 } 249 } 250 } 251 252 //------------------------------------------------------------------------------ 253 254 pdbg_target* getPrimaryProcessor() 255 { 256 // TODO: For at least P10, the primary processor (the one connected directly 257 // to the BMC), will always be PROC 0. We will need to update this 258 // later if we ever support an alternate primary processor. 259 return getTrgt("/proc0"); 260 } 261 262 //------------------------------------------------------------------------------ 263 264 bool queryHardwareAnalysisSupported() 265 { 266 // Hardware analysis is only supported on P10 systems and up. 267 return (PDBG_PROC_P9 < pdbg_get_proc()); 268 } 269 270 //------------------------------------------------------------------------------ 271 272 std::string getLocationCode(pdbg_target* trgt) 273 { 274 if (nullptr == trgt) 275 { 276 // Either the path is wrong or the attribute doesn't exist. 277 return std::string{}; 278 } 279 280 #ifdef CONFIG_PHAL_API 281 282 ATTR_LOCATION_CODE_Type val; 283 if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val)) 284 { 285 // Get the immediate parent in the devtree path and try again. 286 return getLocationCode(pdbg_target_parent(nullptr, trgt)); 287 } 288 289 // Attribute found. 290 return std::string{val}; 291 292 #else 293 294 return std::string{getPath(trgt)}; 295 296 #endif 297 } 298 299 //------------------------------------------------------------------------------ 300 301 std::string getPhysDevPath(pdbg_target* trgt) 302 { 303 if (nullptr == trgt) 304 { 305 // Either the path is wrong or the attribute doesn't exist. 306 return std::string{}; 307 } 308 309 #ifdef CONFIG_PHAL_API 310 311 ATTR_PHYS_DEV_PATH_Type val; 312 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val)) 313 { 314 // Get the immediate parent in the devtree path and try again. 315 return getPhysDevPath(pdbg_target_parent(nullptr, trgt)); 316 } 317 318 // Attribute found. 319 return std::string{val}; 320 321 #else 322 323 return std::string{getPath(trgt)}; 324 325 #endif 326 } 327 328 //------------------------------------------------------------------------------ 329 330 std::vector<uint8_t> getPhysBinPath(pdbg_target* target) 331 { 332 std::vector<uint8_t> binPath; 333 334 if (nullptr != target) 335 { 336 #ifdef CONFIG_PHAL_API 337 338 ATTR_PHYS_BIN_PATH_Type value; 339 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value)) 340 { 341 // The attrirbute for this target does not exist. Get the immediate 342 // parent in the devtree path and try again. Note that if there is 343 // no parent target, nullptr will be returned and that will be 344 // checked above. 345 return getPhysBinPath(pdbg_target_parent(nullptr, target)); 346 } 347 348 // Attribute was found. Copy the attribute array to the returned 349 // vector. Note that the reason we return the vector instead of just 350 // returning the array is because the array type and details only 351 // exists in this specific configuration. 352 binPath.insert(binPath.end(), value, value + sizeof(value)); 353 354 #endif 355 } 356 357 return binPath; 358 } 359 360 //------------------------------------------------------------------------------ 361 362 } // namespace pdbg 363 364 } // namespace util 365