1 #include <analyzer/resolution.hpp> 2 #include <util/pdbg.hpp> 3 #include <util/trace.hpp> 4 5 namespace analyzer 6 { 7 8 //------------------------------------------------------------------------------ 9 10 // Helper function to get the root cause chip target from the service data. 11 pdbg_target* __getRootCauseChipTarget(const ServiceData& i_sd) 12 { 13 auto target = util::pdbg::getTrgt(i_sd.getRootCause().getChip()); 14 assert(nullptr != target); // This would be a really bad bug. 15 return target; 16 } 17 18 //------------------------------------------------------------------------------ 19 20 // Helper function to get a unit target from the given unit path, which is a 21 // devtree path relative the the containing chip. An empty string indicates the 22 // chip target should be returned. 23 pdbg_target* __getUnitTarget(pdbg_target* i_chipTarget, 24 const std::string& i_unitPath) 25 { 26 assert(nullptr != i_chipTarget); 27 28 auto target = i_chipTarget; // default, if i_unitPath is empty 29 30 if (!i_unitPath.empty()) 31 { 32 auto path = std::string{util::pdbg::getPath(target)} + "/" + i_unitPath; 33 34 target = util::pdbg::getTrgt(path); 35 if (nullptr == target) 36 { 37 // Likely a bug the RAS data files. 38 throw std::logic_error("Unable to find target for " + path); 39 } 40 } 41 42 return target; 43 } 44 45 //------------------------------------------------------------------------------ 46 47 // Helper function to get the connected target on the other side of the 48 // given bus. 49 pdbg_target* __getConnectedTarget(pdbg_target* i_rxTarget, 50 const callout::BusType& i_busType) 51 { 52 assert(nullptr != i_rxTarget); 53 54 pdbg_target* txTarget = nullptr; 55 56 auto rxType = util::pdbg::getTrgtType(i_rxTarget); 57 std::string rxPath = util::pdbg::getPath(i_rxTarget); 58 59 if (callout::BusType::SMP_BUS == i_busType && 60 util::pdbg::TYPE_IOLINK == rxType) 61 { 62 // TODO: Will need to reference some sort of data that can tell us how 63 // the processors are connected in the system. For now, return the 64 // RX target to avoid returning a nullptr. 65 trace::inf("No support to get peer target on SMP bus"); 66 txTarget = i_rxTarget; 67 } 68 else if (callout::BusType::SMP_BUS == i_busType && 69 util::pdbg::TYPE_IOHS == rxType) 70 { 71 // TODO: Will need to reference some sort of data that can tell us how 72 // the processors are connected in the system. For now, return the 73 // RX target to avoid returning a nullptr. 74 trace::inf("No support to get peer target on SMP bus"); 75 txTarget = i_rxTarget; 76 } 77 else if (callout::BusType::OMI_BUS == i_busType && 78 util::pdbg::TYPE_OMI == rxType) 79 { 80 // This is a bit clunky. The pdbg APIs only give us the ability to 81 // iterate over the children instead of just returning a list. So we'll 82 // push all the children to a list and go from there. 83 std::vector<pdbg_target*> childList; 84 85 pdbg_target* childTarget = nullptr; 86 pdbg_for_each_target("ocmb", i_rxTarget, childTarget) 87 { 88 if (nullptr != childTarget) 89 { 90 childList.push_back(childTarget); 91 } 92 } 93 94 // We know there should only be one OCMB per OMI. 95 if (1 != childList.size()) 96 { 97 throw std::logic_error("Invalid child list size for " + rxPath); 98 } 99 100 // Get the connected target. 101 txTarget = childList.front(); 102 } 103 else if (callout::BusType::OMI_BUS == i_busType && 104 util::pdbg::TYPE_OCMB == rxType) 105 { 106 txTarget = pdbg_target_parent("omi", i_rxTarget); 107 if (nullptr == txTarget) 108 { 109 throw std::logic_error("No parent OMI found for " + rxPath); 110 } 111 } 112 else 113 { 114 // This would be a code bug. 115 throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath + 116 " i_busType=" + i_busType.getString()); 117 } 118 119 assert(nullptr != txTarget); // just in case we missed something above 120 121 return txTarget; 122 } 123 124 //------------------------------------------------------------------------------ 125 126 void __calloutBackplane(ServiceData& io_sd, const callout::Priority& i_priority) 127 { 128 // TODO: There isn't a device tree object for this. So will need to hardcode 129 // the location code for now. In the future, we will need a mechanism 130 // to make this data driven. 131 132 nlohmann::json callout; 133 callout["LocationCode"] = "P0"; 134 callout["Priority"] = i_priority.getUserDataString(); 135 callout["Deconfigured"] = false; 136 callout["Guarded"] = false; 137 io_sd.addCallout(callout); 138 } 139 140 //------------------------------------------------------------------------------ 141 142 void HardwareCalloutResolution::resolve(ServiceData& io_sd) const 143 { 144 // Get the target for the hardware callout. 145 auto target = __getUnitTarget(__getRootCauseChipTarget(io_sd), iv_unitPath); 146 147 // Get the location code and entity path for this target. 148 auto locCode = util::pdbg::getLocationCode(target); 149 auto entityPath = util::pdbg::getPhysDevPath(target); 150 151 // Add the actual callout to the service data. 152 nlohmann::json callout; 153 callout["LocationCode"] = locCode; 154 callout["Priority"] = iv_priority.getUserDataString(); 155 io_sd.addCallout(callout); 156 157 // Add the guard info to the service data. 158 Guard guard = io_sd.addGuard(entityPath, iv_guard); 159 160 // Add the callout FFDC to the service data. 161 nlohmann::json ffdc; 162 ffdc["Callout Type"] = "Hardware Callout"; 163 ffdc["Target"] = entityPath; 164 ffdc["Priority"] = iv_priority.getRegistryString(); 165 ffdc["Guard Type"] = guard.getString(); 166 io_sd.addCalloutFFDC(ffdc); 167 } 168 169 //------------------------------------------------------------------------------ 170 171 void ConnectedCalloutResolution::resolve(ServiceData& io_sd) const 172 { 173 // Get the chip target from the root cause signature. 174 auto chipTarget = __getRootCauseChipTarget(io_sd); 175 176 // Get the endpoint target for the receiving side of the bus. 177 auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath); 178 179 // Get the endpoint target for the transfer side of the bus. 180 auto txTarget = __getConnectedTarget(rxTarget, iv_busType); 181 182 // Callout the TX endpoint. 183 nlohmann::json txCallout; 184 txCallout["LocationCode"] = util::pdbg::getLocationCode(txTarget); 185 txCallout["Priority"] = iv_priority.getUserDataString(); 186 io_sd.addCallout(txCallout); 187 188 // Guard the TX endpoint. 189 Guard txGuard = 190 io_sd.addGuard(util::pdbg::getPhysDevPath(txTarget), iv_guard); 191 192 // Add the callout FFDC to the service data. 193 nlohmann::json ffdc; 194 ffdc["Callout Type"] = "Connected Callout"; 195 ffdc["Bus Type"] = iv_busType.getString(); 196 ffdc["Target"] = util::pdbg::getPhysDevPath(txTarget); 197 ffdc["Priority"] = iv_priority.getRegistryString(); 198 ffdc["Guard Type"] = txGuard.getString(); 199 io_sd.addCalloutFFDC(ffdc); 200 } 201 202 //------------------------------------------------------------------------------ 203 204 void BusCalloutResolution::resolve(ServiceData& io_sd) const 205 { 206 // Get the chip target from the root cause signature. 207 auto chipTarget = __getRootCauseChipTarget(io_sd); 208 209 // Get the endpoint target for the receiving side of the bus. 210 auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath); 211 212 // Get the endpoint target for the transfer side of the bus. 213 auto txTarget = __getConnectedTarget(rxTarget, iv_busType); 214 215 // Callout the RX endpoint. 216 nlohmann::json rxCallout; 217 rxCallout["LocationCode"] = util::pdbg::getLocationCode(rxTarget); 218 rxCallout["Priority"] = iv_priority.getUserDataString(); 219 io_sd.addCallout(rxCallout); 220 221 // Callout the TX endpoint. 222 nlohmann::json txCallout; 223 txCallout["LocationCode"] = util::pdbg::getLocationCode(txTarget); 224 txCallout["Priority"] = iv_priority.getUserDataString(); 225 io_sd.addCallout(txCallout); 226 227 // Callout everything else in between. 228 // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane. 229 __calloutBackplane(io_sd, iv_priority); 230 231 // Guard the RX endpoint. 232 Guard guard = 233 io_sd.addGuard(util::pdbg::getPhysDevPath(rxTarget), iv_guard); 234 235 // Guard the TX endpoint. 236 // No need to check return because it is the same as RX target. 237 io_sd.addGuard(util::pdbg::getPhysDevPath(txTarget), iv_guard); 238 239 // TODO: Currently no guard for "everything else in between". 240 241 // Add the callout FFDC to the service data. 242 nlohmann::json ffdc; 243 ffdc["Callout Type"] = "Bus Callout"; 244 ffdc["Bus Type"] = iv_busType.getString(); 245 ffdc["RX Target"] = util::pdbg::getPhysDevPath(rxTarget); 246 ffdc["TX Target"] = util::pdbg::getPhysDevPath(txTarget); 247 ffdc["Priority"] = iv_priority.getRegistryString(); 248 ffdc["Guard Type"] = guard.getString(); 249 io_sd.addCalloutFFDC(ffdc); 250 } 251 252 //------------------------------------------------------------------------------ 253 254 void ClockCalloutResolution::resolve(ServiceData& io_sd) const 255 { 256 // Callout the clock target. 257 // TODO: For P10, the callout is simply the backplane. Also, there are no 258 // clock targets in the device tree. So at the moment there is no 259 // guard support for clock targets. 260 __calloutBackplane(io_sd, iv_priority); 261 262 // Add the callout FFDC to the service data. 263 // TODO: Add the target and guard type if guard is ever supported. 264 nlohmann::json ffdc; 265 ffdc["Callout Type"] = "Clock Callout"; 266 ffdc["Clock Type"] = iv_clockType.getString(); 267 ffdc["Priority"] = iv_priority.getRegistryString(); 268 io_sd.addCalloutFFDC(ffdc); 269 } 270 271 //------------------------------------------------------------------------------ 272 273 void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const 274 { 275 // Add the actual callout to the service data. 276 nlohmann::json callout; 277 callout["Procedure"] = iv_procedure.getString(); 278 callout["Priority"] = iv_priority.getUserDataString(); 279 io_sd.addCallout(callout); 280 281 // Add the callout FFDC to the service data. 282 nlohmann::json ffdc; 283 ffdc["Callout Type"] = "Procedure Callout"; 284 ffdc["Procedure"] = iv_procedure.getString(); 285 ffdc["Priority"] = iv_priority.getRegistryString(); 286 io_sd.addCalloutFFDC(ffdc); 287 } 288 289 //------------------------------------------------------------------------------ 290 291 } // namespace analyzer 292