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