blob: ddca989825c2060d99c1685db4cff66ef2a4e020 [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 {
267 "LocationCode": "/proc0",
268 "Priority": "A"
Zane Shelley84721d92021-09-08 13:30:27 -0500269 },
270 {
271 "LocationCode": "P0",
272 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500273 }
274])";
Zane Shelley96d54862021-09-17 11:16:12 -0500275 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500276
Zane Shelleyc85716c2021-08-17 10:54:06 -0500277 j = sd2.getCalloutList();
Zane Shelley0b8368c2021-03-18 17:33:41 -0500278 s = R"([
279 {
280 "Priority": "L",
281 "Procedure": "NEXTLVL"
282 },
283 {
284 "LocationCode": "/proc0",
285 "Priority": "M"
286 },
287 {
288 "LocationCode": "/proc0",
289 "Priority": "H"
290 },
291 {
292 "LocationCode": "/proc0",
293 "Priority": "A"
Zane Shelley84721d92021-09-08 13:30:27 -0500294 },
295 {
296 "LocationCode": "P0",
297 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500298 }
299])";
Zane Shelley96d54862021-09-17 11:16:12 -0500300 EXPECT_EQ(s, j.dump(4));
301}
302
303TEST(Resolution, HardwareCallout)
304{
305 auto c1 = std::make_shared<HardwareCalloutResolution>(
306 omi_str, callout::Priority::MED_A, true);
307
308 libhei::Chip chip{chip_str, 0xdeadbeef};
309 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
310 ServiceData sd{sig, true};
311
312 c1->resolve(sd);
313
314 nlohmann::json j{};
315 std::string s{};
316
317 // Callout list
318 j = sd.getCalloutList();
319 s = R"([
320 {
321 "LocationCode": "/proc0",
322 "Priority": "A"
323 }
324])";
325 EXPECT_EQ(s, j.dump(4));
326
327 // Callout FFDC
328 j = sd.getCalloutFFDC();
329 s = R"([
330 {
331 "Callout Type": "Hardware Callout",
332 "Guard Type": "FATAL",
333 "Priority": "medium_group_A",
334 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
335 }
336])";
337 EXPECT_EQ(s, j.dump(4));
338}
339
Zane Shelley5d63cef2021-09-17 18:10:17 -0500340TEST(Resolution, ConnectedCallout)
341{
342 auto c1 = std::make_shared<ConnectedCalloutResolution>(
343 callout::BusType::SMP_BUS, iolink_str, callout::Priority::MED_A, true);
344
345 auto c2 = std::make_shared<ConnectedCalloutResolution>(
346 callout::BusType::OMI_BUS, ocmb_str, callout::Priority::MED_B, true);
347
348 auto c3 = std::make_shared<ConnectedCalloutResolution>(
349 callout::BusType::OMI_BUS, omi_str, callout::Priority::MED_C, true);
350
351 libhei::Chip chip{chip_str, 0xdeadbeef};
352 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
353 ServiceData sd{sig, true};
354
355 nlohmann::json j{};
356 std::string s{};
357
358 c1->resolve(sd);
359 c2->resolve(sd);
360 c3->resolve(sd);
361
362 // Callout list
363 j = sd.getCalloutList();
364 s = R"([
365 {
366 "LocationCode": "/proc1",
367 "Priority": "A"
368 },
369 {
370 "LocationCode": "/proc0",
371 "Priority": "B"
372 },
373 {
374 "LocationCode": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0",
375 "Priority": "C"
376 }
377])";
378 EXPECT_EQ(s, j.dump(4));
379
380 // Callout FFDC
381 j = sd.getCalloutFFDC();
382 s = R"([
383 {
384 "Bus Type": "SMP_BUS",
385 "Callout Type": "Connected Callout",
386 "Guard Type": "FATAL",
387 "Priority": "medium_group_A",
388 "Target": "/proc1/pib/perv24/pauc0/iohs0/smpgroup0"
389 },
390 {
391 "Bus Type": "OMI_BUS",
392 "Callout Type": "Connected Callout",
393 "Guard Type": "FATAL",
394 "Priority": "medium_group_B",
395 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
396 },
397 {
398 "Bus Type": "OMI_BUS",
399 "Callout Type": "Connected Callout",
400 "Guard Type": "FATAL",
401 "Priority": "medium_group_C",
402 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
403 }
404])";
405 EXPECT_EQ(s, j.dump(4));
406}
407
Zane Shelley96d54862021-09-17 11:16:12 -0500408TEST(Resolution, ClockCallout)
409{
410 auto c1 = std::make_shared<ClockCalloutResolution>(
411 callout::ClockType::OSC_REF_CLOCK_1, callout::Priority::HIGH, false);
412
413 libhei::Chip chip{chip_str, 0xdeadbeef};
414 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
415 ServiceData sd{sig, true};
416
417 c1->resolve(sd);
418
419 nlohmann::json j{};
420 std::string s{};
421
422 // Callout list
423 j = sd.getCalloutList();
424 s = R"([
425 {
426 "LocationCode": "P0",
427 "Priority": "H"
428 }
429])";
430 EXPECT_EQ(s, j.dump(4));
431
432 // Callout FFDC
433 j = sd.getCalloutFFDC();
434 s = R"([
435 {
436 "Callout Type": "Clock Callout",
437 "Clock Type": "OSC_REF_CLOCK_1",
438 "Guard Type": "",
439 "Priority": "high",
440 "Target": "/proc0"
441 }
442])";
443 EXPECT_EQ(s, j.dump(4));
444}
445
446TEST(Resolution, ProcedureCallout)
447{
448 auto c1 = std::make_shared<ProcedureCalloutResolution>(
449 callout::Procedure::NEXTLVL, callout::Priority::LOW);
450
451 libhei::Chip chip{chip_str, 0xdeadbeef};
452 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
453 ServiceData sd{sig, true};
454
455 c1->resolve(sd);
456
457 nlohmann::json j{};
458 std::string s{};
459
460 // Callout list
461 j = sd.getCalloutList();
462 s = R"([
463 {
464 "Priority": "L",
465 "Procedure": "NEXTLVL"
466 }
467])";
468 EXPECT_EQ(s, j.dump(4));
469
470 // Callout FFDC
471 j = sd.getCalloutFFDC();
472 s = R"([
473 {
474 "Callout Type": "Procedure Callout",
475 "Priority": "low",
476 "Procedure": "NEXTLVL"
477 }
478])";
479 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500480}