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