blob: d50213d06046a1f7ceb081771460555f802214e6 [file] [log] [blame]
Zane Shelley0b8368c2021-03-18 17:33:41 -05001#include <stdio.h>
2
3#include <analyzer/resolution.hpp>
Zane Shelley5d63cef2021-09-17 18:10:17 -05004#include <util/trace.hpp>
5
6#include <regex>
Zane Shelley0b8368c2021-03-18 17:33:41 -05007
8#include "gtest/gtest.h"
9
10// Chip string
11constexpr auto chip_str = "/proc0";
12
13// Unit paths
Zane Shelley5d63cef2021-09-17 18:10:17 -050014constexpr auto proc_str = "";
15constexpr auto iolink_str = "pib/perv24/pauc0/iohs0/smpgroup0";
16constexpr auto omi_str = "pib/perv12/mc0/mi0/mcc0/omi0";
17constexpr auto ocmb_str = "pib/perv12/mc0/mi0/mcc0/omi0/ocmb0";
18constexpr auto core_str = "pib/perv39/eq7/fc1/core1";
Zane Shelley0b8368c2021-03-18 17:33:41 -050019
20// Local implementation of this function.
21namespace analyzer
22{
23
Zane Shelley84721d92021-09-08 13:30:27 -050024//------------------------------------------------------------------------------
25
Zane Shelley96d54862021-09-17 11:16:12 -050026// Helper function to get the root cause chip target path from the service data.
27std::string __getRootCauseChipPath(const ServiceData& i_sd)
28{
29 return std::string{(const char*)i_sd.getRootCause().getChip().getChip()};
30}
31
32//------------------------------------------------------------------------------
33
34// Helper function to get a unit target path from the given unit path, which is
35// a devtree path relative the the containing chip. An empty string indicates
36// the chip target path should be returned.
37std::string __getUnitPath(const std::string& i_chipPath,
38 const std::string& i_unitPath)
39{
40 auto path = i_chipPath; // default, if i_unitPath is empty
41
42 if (!i_unitPath.empty())
43 {
44 path += "/" + i_unitPath;
45 }
46
47 return path;
48}
49
50//------------------------------------------------------------------------------
51
Zane Shelley5d63cef2021-09-17 18:10:17 -050052// Helper function to get the connected target Path on the other side of the
53// given bus.
54std::tuple<std::string, std::string>
55 __getConnectedPath(const std::string& i_rxPath,
56 const callout::BusType& i_busType)
57{
58 std::string txUnitPath{};
59 std::string txChipPath{};
60
61 // Need to get the target type from the RX path.
62 const std::regex re{"(/proc0)(.*)/([a-z]+)([0-9]+)"};
63 std::smatch match;
64 std::regex_match(i_rxPath, match, re);
65 assert(5 == match.size());
66 std::string rxType = match[3].str();
67
68 if (callout::BusType::SMP_BUS == i_busType && "smpgroup" == rxType)
69 {
70 // Use the RX unit path on a different processor.
71 txUnitPath = "/proc1" + match[2].str() + "/" + rxType + match[4].str();
72 txChipPath = "/proc1";
73 }
74 else if (callout::BusType::OMI_BUS == i_busType && "omi" == rxType)
75 {
76 // Append the OCMB to the RX path.
77 txUnitPath = i_rxPath + "/ocmb0";
78 txChipPath = txUnitPath;
79 }
80 else if (callout::BusType::OMI_BUS == i_busType && "ocmb" == rxType)
81 {
82 // Strip the OCMB off of the RX path.
83 txUnitPath = match[1].str() + match[2].str();
84 txChipPath = "/proc0";
85 }
86 else
87 {
88 // This would be a code bug.
89 throw std::logic_error("Unsupported config: i_rxTarget=" + i_rxPath +
90 " i_busType=" + i_busType.getString());
91 }
92
93 assert(!txUnitPath.empty()); // just in case we missed something above
94
95 return std::make_tuple(txUnitPath, txChipPath);
96}
97
98//------------------------------------------------------------------------------
99
Zane Shelley0b8368c2021-03-18 17:33:41 -0500100void HardwareCalloutResolution::resolve(ServiceData& io_sd) const
101{
Zane Shelley96d54862021-09-17 11:16:12 -0500102 // Get the location code and entity path for this target.
103 auto locCode = __getRootCauseChipPath(io_sd);
104 auto entityPath = __getUnitPath(locCode, iv_unitPath);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500105
Zane Shelleyc85716c2021-08-17 10:54:06 -0500106 // Add the actual callout to the service data.
107 nlohmann::json callout;
Zane Shelley96d54862021-09-17 11:16:12 -0500108 callout["LocationCode"] = locCode;
Zane Shelleyc85716c2021-08-17 10:54:06 -0500109 callout["Priority"] = iv_priority.getUserDataString();
110 io_sd.addCallout(callout);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500111
Zane Shelley95135822021-08-23 09:00:05 -0500112 // Add the guard info to the service data.
Zane Shelley96d54862021-09-17 11:16:12 -0500113 Guard guard = io_sd.addGuard(entityPath, iv_guard);
114
115 // Add the callout FFDC to the service data.
116 nlohmann::json ffdc;
117 ffdc["Callout Type"] = "Hardware Callout";
118 ffdc["Target"] = entityPath;
119 ffdc["Priority"] = iv_priority.getRegistryString();
120 ffdc["Guard Type"] = guard.getString();
121 io_sd.addCalloutFFDC(ffdc);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500122}
123
Zane Shelleyc85716c2021-08-17 10:54:06 -0500124//------------------------------------------------------------------------------
125
Zane Shelley5d63cef2021-09-17 18:10:17 -0500126void ConnectedCalloutResolution::resolve(ServiceData& io_sd) const
127{
128 // Get the chip target path from the root cause signature.
129 auto chipPath = __getRootCauseChipPath(io_sd);
130
131 // Get the endpoint target path for the receiving side of the bus.
132 auto rxPath = __getUnitPath(chipPath, iv_unitPath);
133
134 // Get the endpoint target path for the transfer side of the bus.
135 auto txPath = __getConnectedPath(rxPath, iv_busType);
136
137 // Callout the TX endpoint.
138 nlohmann::json txCallout;
139 txCallout["LocationCode"] = std::get<1>(txPath);
140 txCallout["Priority"] = iv_priority.getUserDataString();
141 io_sd.addCallout(txCallout);
142
143 // Guard the TX endpoint.
144 Guard txGuard = io_sd.addGuard(std::get<0>(txPath), iv_guard);
145
146 // Add the callout FFDC to the service data.
147 nlohmann::json ffdc;
148 ffdc["Callout Type"] = "Connected Callout";
149 ffdc["Bus Type"] = iv_busType.getString();
150 ffdc["Target"] = std::get<0>(txPath);
151 ffdc["Priority"] = iv_priority.getRegistryString();
152 ffdc["Guard Type"] = txGuard.getString();
153 io_sd.addCalloutFFDC(ffdc);
154}
155
156//------------------------------------------------------------------------------
157
Zane Shelleyc85716c2021-08-17 10:54:06 -0500158void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
159{
160 // Add the actual callout to the service data.
161 nlohmann::json callout;
162 callout["Procedure"] = iv_procedure.getString();
163 callout["Priority"] = iv_priority.getUserDataString();
164 io_sd.addCallout(callout);
Zane Shelley96d54862021-09-17 11:16:12 -0500165
166 // Add the callout FFDC to the service data.
167 nlohmann::json ffdc;
168 ffdc["Callout Type"] = "Procedure Callout";
169 ffdc["Procedure"] = iv_procedure.getString();
170 ffdc["Priority"] = iv_priority.getRegistryString();
171 io_sd.addCalloutFFDC(ffdc);
Zane Shelleyc85716c2021-08-17 10:54:06 -0500172}
173
Zane Shelley84721d92021-09-08 13:30:27 -0500174//------------------------------------------------------------------------------
175
176void ClockCalloutResolution::resolve(ServiceData& io_sd) const
177{
Zane Shelley96d54862021-09-17 11:16:12 -0500178 // Add the callout to the service data.
179 // TODO: For P10, the callout is simply the backplane. There isn't a devtree
180 // object for this, yet. So will need to hardcode the location code
181 // for now. In the future, we will need a mechanism to make this data
182 // driven.
Zane Shelley84721d92021-09-08 13:30:27 -0500183 nlohmann::json callout;
Zane Shelley96d54862021-09-17 11:16:12 -0500184 callout["LocationCode"] = "P0";
Zane Shelley84721d92021-09-08 13:30:27 -0500185 callout["Priority"] = iv_priority.getUserDataString();
186 io_sd.addCallout(callout);
187
188 // Add the guard info to the service data.
Zane Shelley96d54862021-09-17 11:16:12 -0500189 // TODO: Still waiting for clock targets to be defined in the device tree.
190 // For get the processor path for the FFDC.
191 // static const std::map<callout::ClockType, std::string> m = {
192 // {callout::ClockType::OSC_REF_CLOCK_0, ""},
193 // {callout::ClockType::OSC_REF_CLOCK_1, ""},
194 // };
195 // auto target = std::string{util::pdbg::getPath(m.at(iv_clockType))};
196 // auto guardPath = util::pdbg::getPhysDevPath(target);
197 // Guard guard = io_sd.addGuard(guardPath, iv_guard);
198 auto guardPath = __getRootCauseChipPath(io_sd);
199
200 // Add the callout FFDC to the service data.
201 nlohmann::json ffdc;
202 ffdc["Callout Type"] = "Clock Callout";
203 ffdc["Clock Type"] = iv_clockType.getString();
204 ffdc["Target"] = guardPath;
205 ffdc["Priority"] = iv_priority.getRegistryString();
206 ffdc["Guard Type"] = ""; // TODO: guard.getString();
207 io_sd.addCalloutFFDC(ffdc);
Zane Shelley84721d92021-09-08 13:30:27 -0500208}
209
210//------------------------------------------------------------------------------
211
Zane Shelley0b8368c2021-03-18 17:33:41 -0500212} // namespace analyzer
213
214using namespace analyzer;
215
216TEST(Resolution, TestSet1)
217{
218 // Create a few resolutions
219 auto c1 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500220 proc_str, callout::Priority::HIGH, false);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500221
222 auto c2 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500223 omi_str, callout::Priority::MED_A, true);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500224
225 auto c3 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500226 core_str, callout::Priority::MED, true);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500227
228 auto c4 = std::make_shared<ProcedureCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500229 callout::Procedure::NEXTLVL, callout::Priority::LOW);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500230
Zane Shelley84721d92021-09-08 13:30:27 -0500231 auto c5 = std::make_shared<ClockCalloutResolution>(
232 callout::ClockType::OSC_REF_CLOCK_1, callout::Priority::LOW, false);
233
234 // l1 = (c1, c2, c5)
Zane Shelley723fa232021-08-09 12:02:06 -0500235 auto l1 = std::make_shared<ResolutionList>();
236 l1->push(c1);
237 l1->push(c2);
Zane Shelley84721d92021-09-08 13:30:27 -0500238 l1->push(c5);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500239
Zane Shelley84721d92021-09-08 13:30:27 -0500240 // l2 = (c4, c3, c1, c2, c5)
Zane Shelley723fa232021-08-09 12:02:06 -0500241 auto l2 = std::make_shared<ResolutionList>();
242 l2->push(c4);
243 l2->push(c3);
244 l2->push(l1);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500245
246 // Get some ServiceData objects
247 libhei::Chip chip{chip_str, 0xdeadbeef};
248 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
Zane Shelleyca496192021-08-09 12:05:52 -0500249 ServiceData sd1{sig, true};
250 ServiceData sd2{sig, false};
Zane Shelley0b8368c2021-03-18 17:33:41 -0500251
252 // Resolve
Zane Shelley723fa232021-08-09 12:02:06 -0500253 l1->resolve(sd1);
254 l2->resolve(sd2);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500255
256 // Start verifying
257 nlohmann::json j{};
258 std::string s{};
259
Zane Shelleyc85716c2021-08-17 10:54:06 -0500260 j = sd1.getCalloutList();
Zane Shelley0b8368c2021-03-18 17:33:41 -0500261 s = R"([
262 {
263 "LocationCode": "/proc0",
264 "Priority": "H"
265 },
266 {
Zane Shelley84721d92021-09-08 13:30:27 -0500267 "LocationCode": "P0",
268 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500269 }
270])";
Zane Shelley96d54862021-09-17 11:16:12 -0500271 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500272
Zane Shelleyc85716c2021-08-17 10:54:06 -0500273 j = sd2.getCalloutList();
Zane Shelley0b8368c2021-03-18 17:33:41 -0500274 s = R"([
275 {
276 "Priority": "L",
277 "Procedure": "NEXTLVL"
278 },
279 {
280 "LocationCode": "/proc0",
Zane Shelley0b8368c2021-03-18 17:33:41 -0500281 "Priority": "H"
282 },
283 {
Zane Shelley84721d92021-09-08 13:30:27 -0500284 "LocationCode": "P0",
285 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500286 }
287])";
Zane Shelley96d54862021-09-17 11:16:12 -0500288 EXPECT_EQ(s, j.dump(4));
289}
290
291TEST(Resolution, HardwareCallout)
292{
293 auto c1 = std::make_shared<HardwareCalloutResolution>(
294 omi_str, callout::Priority::MED_A, true);
295
296 libhei::Chip chip{chip_str, 0xdeadbeef};
297 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
298 ServiceData sd{sig, true};
299
300 c1->resolve(sd);
301
302 nlohmann::json j{};
303 std::string s{};
304
305 // Callout list
306 j = sd.getCalloutList();
307 s = R"([
308 {
309 "LocationCode": "/proc0",
310 "Priority": "A"
311 }
312])";
313 EXPECT_EQ(s, j.dump(4));
314
315 // Callout FFDC
316 j = sd.getCalloutFFDC();
317 s = R"([
318 {
319 "Callout Type": "Hardware Callout",
320 "Guard Type": "FATAL",
321 "Priority": "medium_group_A",
322 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
323 }
324])";
325 EXPECT_EQ(s, j.dump(4));
326}
327
Zane Shelley5d63cef2021-09-17 18:10:17 -0500328TEST(Resolution, ConnectedCallout)
329{
330 auto c1 = std::make_shared<ConnectedCalloutResolution>(
331 callout::BusType::SMP_BUS, iolink_str, callout::Priority::MED_A, true);
332
333 auto c2 = std::make_shared<ConnectedCalloutResolution>(
334 callout::BusType::OMI_BUS, ocmb_str, callout::Priority::MED_B, true);
335
336 auto c3 = std::make_shared<ConnectedCalloutResolution>(
337 callout::BusType::OMI_BUS, omi_str, callout::Priority::MED_C, true);
338
339 libhei::Chip chip{chip_str, 0xdeadbeef};
340 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
341 ServiceData sd{sig, true};
342
343 nlohmann::json j{};
344 std::string s{};
345
346 c1->resolve(sd);
347 c2->resolve(sd);
348 c3->resolve(sd);
349
350 // Callout list
351 j = sd.getCalloutList();
352 s = R"([
353 {
354 "LocationCode": "/proc1",
355 "Priority": "A"
356 },
357 {
358 "LocationCode": "/proc0",
359 "Priority": "B"
360 },
361 {
362 "LocationCode": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0",
363 "Priority": "C"
364 }
365])";
366 EXPECT_EQ(s, j.dump(4));
367
368 // Callout FFDC
369 j = sd.getCalloutFFDC();
370 s = R"([
371 {
372 "Bus Type": "SMP_BUS",
373 "Callout Type": "Connected Callout",
374 "Guard Type": "FATAL",
375 "Priority": "medium_group_A",
376 "Target": "/proc1/pib/perv24/pauc0/iohs0/smpgroup0"
377 },
378 {
379 "Bus Type": "OMI_BUS",
380 "Callout Type": "Connected Callout",
381 "Guard Type": "FATAL",
382 "Priority": "medium_group_B",
383 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
384 },
385 {
386 "Bus Type": "OMI_BUS",
387 "Callout Type": "Connected Callout",
388 "Guard Type": "FATAL",
389 "Priority": "medium_group_C",
390 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
391 }
392])";
393 EXPECT_EQ(s, j.dump(4));
394}
395
Zane Shelley96d54862021-09-17 11:16:12 -0500396TEST(Resolution, ClockCallout)
397{
398 auto c1 = std::make_shared<ClockCalloutResolution>(
399 callout::ClockType::OSC_REF_CLOCK_1, callout::Priority::HIGH, false);
400
401 libhei::Chip chip{chip_str, 0xdeadbeef};
402 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
403 ServiceData sd{sig, true};
404
405 c1->resolve(sd);
406
407 nlohmann::json j{};
408 std::string s{};
409
410 // Callout list
411 j = sd.getCalloutList();
412 s = R"([
413 {
414 "LocationCode": "P0",
415 "Priority": "H"
416 }
417])";
418 EXPECT_EQ(s, j.dump(4));
419
420 // Callout FFDC
421 j = sd.getCalloutFFDC();
422 s = R"([
423 {
424 "Callout Type": "Clock Callout",
425 "Clock Type": "OSC_REF_CLOCK_1",
426 "Guard Type": "",
427 "Priority": "high",
428 "Target": "/proc0"
429 }
430])";
431 EXPECT_EQ(s, j.dump(4));
432}
433
434TEST(Resolution, ProcedureCallout)
435{
436 auto c1 = std::make_shared<ProcedureCalloutResolution>(
437 callout::Procedure::NEXTLVL, callout::Priority::LOW);
438
439 libhei::Chip chip{chip_str, 0xdeadbeef};
440 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
441 ServiceData sd{sig, true};
442
443 c1->resolve(sd);
444
445 nlohmann::json j{};
446 std::string s{};
447
448 // Callout list
449 j = sd.getCalloutList();
450 s = R"([
451 {
452 "Priority": "L",
453 "Procedure": "NEXTLVL"
454 }
455])";
456 EXPECT_EQ(s, j.dump(4));
457
458 // Callout FFDC
459 j = sd.getCalloutFFDC();
460 s = R"([
461 {
462 "Callout Type": "Procedure Callout",
463 "Priority": "low",
464 "Procedure": "NEXTLVL"
465 }
466])";
467 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500468}