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