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 getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val) 111 { 112 // Only processor targets are supported. 113 assert(TYPE_PROC == getTrgtType(i_trgt)); 114 115 auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt); 116 117 int rc = fsi_read(fsiTrgt, i_addr, &o_val); 118 119 if (0 != rc) 120 { 121 trace::err("fsi_read failure: trgt=%s addr=0x%08x", 122 util::pdbg::getPath(fsiTrgt), i_addr); 123 } 124 125 return rc; 126 } 127 128 //------------------------------------------------------------------------------ 129 130 // IMPORTANT: 131 // The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some 132 // point during the IPL. It is possible that this information is needed before 133 // the sync occurs, in which case the value will return 0. 134 uint32_t __getChipId(pdbg_target* i_trgt) 135 { 136 uint32_t attr = 0; 137 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr); 138 return attr; 139 } 140 141 // IMPORTANT: 142 // The ATTR_EC attribute will be synced from Hostboot to the BMC at some point 143 // during the IPL. It is possible that this information is needed before the 144 // sync occurs, in which case the value will return 0. 145 uint8_t __getChipEc(pdbg_target* i_trgt) 146 { 147 uint8_t attr = 0; 148 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr); 149 return attr; 150 } 151 152 uint32_t __getChipIdEc(pdbg_target* i_trgt) 153 { 154 auto chipId = __getChipId(i_trgt); 155 auto chipEc = __getChipEc(i_trgt); 156 157 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt))) 158 { 159 // There is a special case where the model/level attributes have not 160 // been initialized in the devtree. This is possible on the epoch IPL 161 // where an attention occurs before Hostboot is able to update the 162 // devtree information on the BMC. It may is still possible to get this 163 // information from chips with CFAM access (i.e. a processor) via the 164 // CFAM chip ID register. 165 166 uint32_t val = 0; 167 if (0 == getCfam(i_trgt, 0x100a, val)) 168 { 169 chipId = ((val & 0x0F0FF000) >> 12); 170 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20); 171 } 172 } 173 174 return ((chipId & 0xffff) << 16) | (chipEc & 0xff); 175 } 176 177 void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt, 178 libhei::ChipType_t i_type) 179 { 180 // Trace each chip for debug. It is important to show the type just in case 181 // the model/EC does not exist. See note below. 182 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type, 183 getPath(i_trgt)); 184 185 if (0 == i_type) 186 { 187 // This is a special case. See the details in __getChipIdEC(). There is 188 // nothing more we can do with this chip since we don't know what it is. 189 // So ignore the chip for now. 190 } 191 else 192 { 193 o_chips.emplace_back(i_trgt, i_type); 194 } 195 } 196 197 void getActiveChips(std::vector<libhei::Chip>& o_chips) 198 { 199 o_chips.clear(); 200 201 // Iterate each processor. 202 pdbg_target* procTrgt; 203 pdbg_for_each_class_target("proc", procTrgt) 204 { 205 // We cannot use the proc target to determine if the chip is active. 206 // There is some design limitation in pdbg that requires the proc 207 // targets to always be active. Instead, we must get the associated pib 208 // target and check if it is active. 209 210 // Active processors only. 211 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt))) 212 continue; 213 214 // Add the processor to the list. 215 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt)); 216 217 // Iterate the connected OCMBs, if they exist. 218 pdbg_target* ocmbTrgt; 219 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt) 220 { 221 // Active OCMBs only. 222 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt)) 223 continue; 224 225 // Add the OCMB to the list. 226 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt)); 227 } 228 } 229 } 230 231 //------------------------------------------------------------------------------ 232 233 bool queryHardwareAnalysisSupported() 234 { 235 // Hardware analysis is only supported on P10 systems and up. 236 return (PDBG_PROC_P9 < pdbg_get_proc()); 237 } 238 239 //------------------------------------------------------------------------------ 240 241 std::string getLocationCode(pdbg_target* trgt) 242 { 243 if (nullptr == trgt) 244 { 245 // Either the path is wrong or the attribute doesn't exist. 246 return std::string{}; 247 } 248 249 #ifdef CONFIG_PHAL_API 250 251 ATTR_LOCATION_CODE_Type val; 252 if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val)) 253 { 254 // Get the immediate parent in the devtree path and try again. 255 return getLocationCode(pdbg_target_parent(nullptr, trgt)); 256 } 257 258 // Attribute found. 259 return std::string{val}; 260 261 #else 262 263 return std::string{getPath(trgt)}; 264 265 #endif 266 } 267 268 //------------------------------------------------------------------------------ 269 270 std::string getPhysDevPath(pdbg_target* trgt) 271 { 272 if (nullptr == trgt) 273 { 274 // Either the path is wrong or the attribute doesn't exist. 275 return std::string{}; 276 } 277 278 #ifdef CONFIG_PHAL_API 279 280 ATTR_PHYS_DEV_PATH_Type val; 281 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val)) 282 { 283 // Get the immediate parent in the devtree path and try again. 284 return getPhysDevPath(pdbg_target_parent(nullptr, trgt)); 285 } 286 287 // Attribute found. 288 return std::string{val}; 289 290 #else 291 292 return std::string{getPath(trgt)}; 293 294 #endif 295 } 296 297 //------------------------------------------------------------------------------ 298 299 } // namespace pdbg 300 301 } // namespace util 302