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 void __calloutTarget(ServiceData& io_sd, pdbg_target* i_target,
49                      const callout::Priority& i_priority, bool i_guard)
50 {
51     nlohmann::json callout;
52     callout["LocationCode"] = util::pdbg::getLocationCode(i_target);
53     callout["Priority"]     = i_priority.getUserDataString();
54     callout["Deconfigured"] = false;
55     callout["Guarded"]      = false; // default
56 
57     // Check if guard info should be added.
58     if (i_guard)
59     {
60         auto guardType = io_sd.queryGuardPolicy();
61 
62         if (!(callout::GuardType::NONE == guardType))
63         {
64             callout["Guarded"]    = true;
65             callout["EntityPath"] = util::pdbg::getPhysBinPath(i_target);
66             callout["GuardType"]  = guardType.getString();
67         }
68     }
69 
70     io_sd.addCallout(callout);
71 }
72 
73 //------------------------------------------------------------------------------
74 
75 void __calloutBackplane(ServiceData& io_sd, const callout::Priority& i_priority)
76 {
77     // TODO: There isn't a device tree object for this. So will need to hardcode
78     //       the location code for now. In the future, we will need a mechanism
79     //       to make this data driven.
80 
81     nlohmann::json callout;
82     callout["LocationCode"] = "P0";
83     callout["Priority"]     = i_priority.getUserDataString();
84     callout["Deconfigured"] = false;
85     callout["Guarded"]      = false;
86     io_sd.addCallout(callout);
87 }
88 
89 //------------------------------------------------------------------------------
90 
91 void HardwareCalloutResolution::resolve(ServiceData& io_sd) const
92 {
93     // Get the target for the hardware callout.
94     auto target = __getUnitTarget(__getRootCauseChipTarget(io_sd), iv_unitPath);
95 
96     // Add the actual callout to the service data.
97     __calloutTarget(io_sd, target, iv_priority, iv_guard);
98 
99     // Add the callout FFDC to the service data.
100     nlohmann::json ffdc;
101     ffdc["Callout Type"] = "Hardware Callout";
102     ffdc["Target"]       = util::pdbg::getPhysDevPath(target);
103     ffdc["Priority"]     = iv_priority.getRegistryString();
104     ffdc["Guard"]        = iv_guard;
105     io_sd.addCalloutFFDC(ffdc);
106 }
107 
108 //------------------------------------------------------------------------------
109 
110 void ConnectedCalloutResolution::resolve(ServiceData& io_sd) const
111 {
112     // Get the chip target from the root cause signature.
113     auto chipTarget = __getRootCauseChipTarget(io_sd);
114 
115     // Get the endpoint target for the receiving side of the bus.
116     auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath);
117 
118     // Get the endpoint target for the transfer side of the bus.
119     auto txTarget = util::pdbg::getConnectedTarget(rxTarget, iv_busType);
120 
121     // Callout the TX endpoint.
122     __calloutTarget(io_sd, txTarget, iv_priority, iv_guard);
123 
124     // Add the callout FFDC to the service data.
125     nlohmann::json ffdc;
126     ffdc["Callout Type"] = "Connected Callout";
127     ffdc["Bus Type"]     = iv_busType.getString();
128     ffdc["Target"]       = util::pdbg::getPhysDevPath(txTarget);
129     ffdc["Priority"]     = iv_priority.getRegistryString();
130     ffdc["Guard"]        = iv_guard;
131     io_sd.addCalloutFFDC(ffdc);
132 }
133 
134 //------------------------------------------------------------------------------
135 
136 void BusCalloutResolution::resolve(ServiceData& io_sd) const
137 {
138     // Get the chip target from the root cause signature.
139     auto chipTarget = __getRootCauseChipTarget(io_sd);
140 
141     // Get the endpoint target for the receiving side of the bus.
142     auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath);
143 
144     // Get the endpoint target for the transfer side of the bus.
145     auto txTarget = util::pdbg::getConnectedTarget(rxTarget, iv_busType);
146 
147     // Callout the RX endpoint.
148     __calloutTarget(io_sd, rxTarget, iv_priority, iv_guard);
149 
150     // Callout the TX endpoint.
151     __calloutTarget(io_sd, txTarget, iv_priority, iv_guard);
152 
153     // Callout everything else in between.
154     // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
155     __calloutBackplane(io_sd, iv_priority);
156 
157     // Add the callout FFDC to the service data.
158     nlohmann::json ffdc;
159     ffdc["Callout Type"] = "Bus Callout";
160     ffdc["Bus Type"]     = iv_busType.getString();
161     ffdc["RX Target"]    = util::pdbg::getPhysDevPath(rxTarget);
162     ffdc["TX Target"]    = util::pdbg::getPhysDevPath(txTarget);
163     ffdc["Priority"]     = iv_priority.getRegistryString();
164     ffdc["Guard"]        = iv_guard;
165     io_sd.addCalloutFFDC(ffdc);
166 }
167 
168 //------------------------------------------------------------------------------
169 
170 void ClockCalloutResolution::resolve(ServiceData& io_sd) const
171 {
172     // Callout the clock target.
173     // TODO: For P10, the callout is simply the backplane. Also, there are no
174     //       clock targets in the device tree. So at the moment there is no
175     //       guard support for clock targets.
176     __calloutBackplane(io_sd, iv_priority);
177 
178     // Add the callout FFDC to the service data.
179     // TODO: Add the target and guard type if guard is ever supported.
180     nlohmann::json ffdc;
181     ffdc["Callout Type"] = "Clock Callout";
182     ffdc["Clock Type"]   = iv_clockType.getString();
183     ffdc["Priority"]     = iv_priority.getRegistryString();
184     io_sd.addCalloutFFDC(ffdc);
185 }
186 
187 //------------------------------------------------------------------------------
188 
189 void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
190 {
191     // Add the actual callout to the service data.
192     nlohmann::json callout;
193     callout["Procedure"] = iv_procedure.getString();
194     callout["Priority"]  = iv_priority.getUserDataString();
195     io_sd.addCallout(callout);
196 
197     // Add the callout FFDC to the service data.
198     nlohmann::json ffdc;
199     ffdc["Callout Type"] = "Procedure Callout";
200     ffdc["Procedure"]    = iv_procedure.getString();
201     ffdc["Priority"]     = iv_priority.getRegistryString();
202     io_sd.addCalloutFFDC(ffdc);
203 }
204 
205 //------------------------------------------------------------------------------
206 
207 void PluginResolution::resolve(ServiceData& io_sd) const
208 {
209     // Get the plugin function and call it.
210 
211     auto chip = io_sd.getRootCause().getChip();
212 
213     auto func = PluginMap::getSingleton().get(chip.getType(), iv_name);
214 
215     func(iv_instance, chip, io_sd);
216 }
217 
218 //------------------------------------------------------------------------------
219 
220 } // namespace analyzer
221