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::OMI_BUS == i_busType && 69 util::pdbg::TYPE_OMI == rxType) 70 { 71 // This is a bit clunky. The pdbg APIs only give us the ability to 72 // iterate over the children instead of just returning a list. So we'll 73 // push all the children to a list and go from there. 74 std::vector<pdbg_target*> childList; 75 76 pdbg_target* childTarget = nullptr; 77 pdbg_for_each_target("ocmb", i_rxTarget, childTarget) 78 { 79 if (nullptr != childTarget) 80 { 81 childList.push_back(childTarget); 82 } 83 } 84 85 // We know there should only be one OCMB per OMI. 86 if (1 != childList.size()) 87 { 88 throw std::logic_error("Invalid child list size for " + rxPath); 89 } 90 91 // Get the connected target. 92 txTarget = childList.front(); 93 } 94 else if (callout::BusType::OMI_BUS == i_busType && 95 util::pdbg::TYPE_OCMB == rxType) 96 { 97 txTarget = pdbg_target_parent("omi", i_rxTarget); 98 if (nullptr == txTarget) 99 { 100 throw std::logic_error("No parent OMI found for " + rxPath); 101 } 102 } 103 else 104 { 105 // This would be a code bug. 106 throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath + 107 " i_busType=" + i_busType.getString()); 108 } 109 110 assert(nullptr != txTarget); // just in case we missed something above 111 112 return txTarget; 113 } 114 115 //------------------------------------------------------------------------------ 116 117 void HardwareCalloutResolution::resolve(ServiceData& io_sd) const 118 { 119 // Get the target for the hardware callout. 120 auto target = __getUnitTarget(__getRootCauseChipTarget(io_sd), iv_unitPath); 121 122 // Get the location code and entity path for this target. 123 auto locCode = util::pdbg::getLocationCode(target); 124 auto entityPath = util::pdbg::getPhysDevPath(target); 125 126 // Add the actual callout to the service data. 127 nlohmann::json callout; 128 callout["LocationCode"] = locCode; 129 callout["Priority"] = iv_priority.getUserDataString(); 130 io_sd.addCallout(callout); 131 132 // Add the guard info to the service data. 133 Guard guard = io_sd.addGuard(entityPath, iv_guard); 134 135 // Add the callout FFDC to the service data. 136 nlohmann::json ffdc; 137 ffdc["Callout Type"] = "Hardware Callout"; 138 ffdc["Target"] = entityPath; 139 ffdc["Priority"] = iv_priority.getRegistryString(); 140 ffdc["Guard Type"] = guard.getString(); 141 io_sd.addCalloutFFDC(ffdc); 142 } 143 144 //------------------------------------------------------------------------------ 145 146 void ConnectedCalloutResolution::resolve(ServiceData& io_sd) const 147 { 148 // Get the chip target from the root cause signature. 149 auto chipTarget = __getRootCauseChipTarget(io_sd); 150 151 // Get the endpoint target for the receiving side of the bus. 152 auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath); 153 154 // Get the endpoint target for the transfer side of the bus. 155 auto txTarget = __getConnectedTarget(rxTarget, iv_busType); 156 157 // Callout the TX endpoint. 158 nlohmann::json txCallout; 159 txCallout["LocationCode"] = util::pdbg::getLocationCode(txTarget); 160 txCallout["Priority"] = iv_priority.getUserDataString(); 161 io_sd.addCallout(txCallout); 162 163 // Guard the TX endpoint. 164 Guard txGuard = 165 io_sd.addGuard(util::pdbg::getPhysDevPath(txTarget), iv_guard); 166 167 // Add the callout FFDC to the service data. 168 nlohmann::json ffdc; 169 ffdc["Callout Type"] = "Connected Callout"; 170 ffdc["Bus Type"] = iv_busType.getString(); 171 ffdc["Target"] = util::pdbg::getPhysDevPath(txTarget); 172 ffdc["Priority"] = iv_priority.getRegistryString(); 173 ffdc["Guard Type"] = txGuard.getString(); 174 io_sd.addCalloutFFDC(ffdc); 175 } 176 177 //------------------------------------------------------------------------------ 178 179 void ClockCalloutResolution::resolve(ServiceData& io_sd) const 180 { 181 // Add the callout to the service data. 182 // TODO: For P10, the callout is simply the backplane. There isn't a devtree 183 // object for this, yet. So will need to hardcode the location code 184 // for now. In the future, we will need a mechanism to make this data 185 // driven. 186 nlohmann::json callout; 187 callout["LocationCode"] = "P0"; 188 callout["Priority"] = iv_priority.getUserDataString(); 189 io_sd.addCallout(callout); 190 191 // Add the guard info to the service data. 192 // TODO: Still waiting for clock targets to be defined in the device tree. 193 // For get the processor path for the FFDC. 194 // static const std::map<callout::ClockType, std::string> m = { 195 // {callout::ClockType::OSC_REF_CLOCK_0, ""}, 196 // {callout::ClockType::OSC_REF_CLOCK_1, ""}, 197 // }; 198 // auto target = std::string{util::pdbg::getPath(m.at(iv_clockType))}; 199 // auto guardPath = util::pdbg::getPhysDevPath(target); 200 // Guard guard = io_sd.addGuard(guardPath, iv_guard); 201 auto target = __getRootCauseChipTarget(io_sd); 202 auto guardPath = util::pdbg::getPhysDevPath(target); 203 204 // Add the callout FFDC to the service data. 205 nlohmann::json ffdc; 206 ffdc["Callout Type"] = "Clock Callout"; 207 ffdc["Clock Type"] = iv_clockType.getString(); 208 ffdc["Target"] = guardPath; 209 ffdc["Priority"] = iv_priority.getRegistryString(); 210 ffdc["Guard Type"] = ""; // TODO: guard.getString(); 211 io_sd.addCalloutFFDC(ffdc); 212 } 213 214 //------------------------------------------------------------------------------ 215 216 void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const 217 { 218 // Add the actual callout to the service data. 219 nlohmann::json callout; 220 callout["Procedure"] = iv_procedure.getString(); 221 callout["Priority"] = iv_priority.getUserDataString(); 222 io_sd.addCallout(callout); 223 224 // Add the callout FFDC to the service data. 225 nlohmann::json ffdc; 226 ffdc["Callout Type"] = "Procedure Callout"; 227 ffdc["Procedure"] = iv_procedure.getString(); 228 ffdc["Priority"] = iv_priority.getRegistryString(); 229 io_sd.addCalloutFFDC(ffdc); 230 } 231 232 //------------------------------------------------------------------------------ 233 234 } // namespace analyzer 235