1 #include <fcntl.h>
2 #include <libpdbg.h>
3 
4 #include <hei_main.hpp>
5 #include <test/sim-hw-access.hpp>
6 #include <util/pdbg.hpp>
7 #include <util/trace.hpp>
8 
9 #include <limits>
10 #include <vector>
11 
12 #include "gtest/gtest.h"
13 
TEST(PDBG,PdbgDtsTest1)14 TEST(PDBG, PdbgDtsTest1)
15 {
16     const char* perv1_fapi_pos_path = "/proc0/pib/perv1";
17     const char* perv12_fapi_pos_path = "/proc0/pib/perv12";
18     const uint32_t perv1_fapi_pos = 1;
19     const uint32_t perv12_fapi_pos = 12;
20 
21     pdbg_targets_init(nullptr);
22 
23     trace::inf("retrieving fapi pos.");
24     uint32_t attr = std::numeric_limits<uint32_t>::max();
25     pdbg_target* trgt = pdbg_target_from_path(nullptr, perv1_fapi_pos_path);
26     pdbg_target_get_attribute(trgt, "ATTR_FAPI_POS", 4, 1, &attr);
27     trace::inf("perv1 fapi pos in DTS: %u", attr);
28     EXPECT_EQ(attr, perv1_fapi_pos);
29 
30     attr = std::numeric_limits<uint32_t>::max();
31     trgt = pdbg_target_from_path(nullptr, perv12_fapi_pos_path);
32     pdbg_target_get_attribute(trgt, "ATTR_FAPI_POS", 4, 1, &attr);
33     trace::inf("perv12 fapi pos in DTS: %u", attr);
34     EXPECT_EQ(attr, perv12_fapi_pos);
35 }
36 
TEST(PDBG,PdbgDtsTest2)37 TEST(PDBG, PdbgDtsTest2)
38 {
39     const char* dimm0_path =
40         "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0/mem_port0/dimm0";
41     const uint32_t index = 0;
42     const uint32_t fapi_pos = 0;
43 
44     pdbg_targets_init(nullptr);
45 
46     trace::inf("retrieving fapi pos.");
47     uint32_t attr = std::numeric_limits<uint32_t>::max();
48     pdbg_target* trgt = pdbg_target_from_path(nullptr, dimm0_path);
49     pdbg_target_get_attribute(trgt, "index", 4, 1, &attr);
50     trace::inf("index in DTS: %u", attr);
51     EXPECT_EQ(attr, index);
52 
53     attr = std::numeric_limits<uint32_t>::max();
54     pdbg_target_get_attribute(trgt, "ATTR_FAPI_POS", 4, 1, &attr);
55     trace::inf("fapi pos in DTS: %u", attr);
56     EXPECT_EQ(attr, fapi_pos);
57 }
58 
TEST(PDBG,PdbgDtsTest3)59 TEST(PDBG, PdbgDtsTest3)
60 {
61     const uint32_t chipId = 0;  // ID for proc0.
62     const uint32_t fapiPos = 0; // FAPI Position for proc0.
63 
64     pdbg_targets_init(nullptr);
65 
66     // Iterate each processor.
67     pdbg_target* procTrgt;
68     pdbg_for_each_class_target("/proc0", procTrgt)
69     {
70         // Active processors only.
71         if (PDBG_TARGET_ENABLED !=
72             pdbg_target_probe(util::pdbg::getPibTrgt(procTrgt)))
73             continue;
74 
75         // Process the PROC target.
76         uint32_t attr = std::numeric_limits<uint32_t>::max();
77         pdbg_target_get_attribute(procTrgt, "ATTR_CHIP_ID", 4, 1, &attr);
78         trace::inf("Chip ID: %u", attr);
79         EXPECT_EQ(attr, chipId);
80 
81         attr = std::numeric_limits<uint32_t>::max();
82         pdbg_target_get_attribute(procTrgt, "ATTR_FAPI_POS", 4, 1, &attr);
83         trace::inf("ATTR_FAPI_POS: %u", attr);
84         EXPECT_EQ(attr, fapiPos);
85     }
86 }
87 
TEST(PDBG,PdbgDtsTest4)88 TEST(PDBG, PdbgDtsTest4)
89 {
90     const uint32_t index = 1;
91     const uint32_t fapi_pos = 1;
92     const char* perv1_path = "/proc0/pib/perv1";
93 
94     pdbg_targets_init(nullptr);
95 
96     // Iterate each processor.
97     pdbg_target* trgt;
98     uint32_t attr;
99 
100     pdbg_for_each_class_target(perv1_path, trgt)
101     {
102         attr = std::numeric_limits<uint32_t>::max();
103         pdbg_target_get_attribute(trgt, "index", 4, 1, &attr);
104         trace::inf("index in DTS: %u", attr);
105         EXPECT_EQ(attr, index);
106 
107         attr = std::numeric_limits<uint32_t>::max();
108         pdbg_target_get_attribute(trgt, "ATTR_FAPI_POS", 4, 1, &attr);
109         trace::inf("fapi pos in DTS: %u", attr);
110         EXPECT_EQ(attr, fapi_pos);
111     }
112 }
113 
TEST(util_pdbg,getParentChip)114 TEST(util_pdbg, getParentChip)
115 {
116     using namespace util::pdbg;
117     pdbg_targets_init(nullptr);
118 
119     auto procChip = getTrgt("/proc0");
120     auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
121 
122     EXPECT_EQ(procChip, getParentChip(procChip)); // get self
123     EXPECT_EQ(procChip, getParentChip(omiUnit));  // get unit
124 
125     auto ocmbChip = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0");
126     auto memPortUnit =
127         getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0/mem_port0");
128 
129     EXPECT_EQ(ocmbChip, getParentChip(ocmbChip));    // get self
130     EXPECT_EQ(ocmbChip, getParentChip(memPortUnit)); // get unit
131 }
132 
TEST(util_pdbg,getChipUnit)133 TEST(util_pdbg, getChipUnit)
134 {
135     using namespace util::pdbg;
136     pdbg_targets_init(nullptr);
137 
138     auto procChip = getTrgt("/proc0");
139     auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
140     auto omiUnitPos = 5;
141 
142     // Get the unit and verify.
143     EXPECT_EQ(omiUnit, getChipUnit(procChip, TYPE_OMI, omiUnitPos));
144 
145     // Expect an exception when passing a unit instead of a chip.
146     EXPECT_THROW(getChipUnit(omiUnit, TYPE_OMI, omiUnitPos), std::logic_error);
147 
148     // Expect an exception when passing a chip type.
149     EXPECT_THROW(getChipUnit(procChip, TYPE_PROC, omiUnitPos),
150                  std::out_of_range);
151 
152     // Expect an exception when passing a unit type not on the target chip.
153     EXPECT_THROW(getChipUnit(procChip, TYPE_MEM_PORT, omiUnitPos),
154                  std::out_of_range);
155 
156     // Expect a nullptr if the target is not found.
157     EXPECT_EQ(nullptr, getChipUnit(procChip, TYPE_OMI, 100));
158 
159     auto ocmbChip = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0");
160     auto memPortUnit =
161         getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0/mem_port0");
162     auto memPortUnitPos = 0;
163 
164     // Get the unit and verify.
165     EXPECT_EQ(memPortUnit,
166               getChipUnit(ocmbChip, TYPE_MEM_PORT, memPortUnitPos));
167 }
168 
TEST(util_pdbg,getScom)169 TEST(util_pdbg, getScom)
170 {
171     using namespace util::pdbg;
172     pdbg_targets_init(nullptr);
173 
174     auto procChip = getTrgt("/proc0");
175     auto ocmbChip = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0");
176     auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
177 
178     sim::ScomAccess& scom = sim::ScomAccess::getSingleton();
179     scom.flush();
180     scom.add(procChip, 0x11111111, 0x0011223344556677);
181     scom.error(ocmbChip, 0x22222222);
182 
183     int rc = 0;
184     uint64_t val = 0;
185 
186     // Test good path.
187     rc = getScom(procChip, 0x11111111, val);
188     EXPECT_EQ(0, rc);
189     EXPECT_EQ(0x0011223344556677, val);
190 
191     // Test address that has not been added to ScomAccess.
192     rc = getScom(procChip, 0x33333333, val);
193     EXPECT_EQ(0, rc);
194     EXPECT_EQ(0, val);
195 
196     // Test SCOM error.
197     rc = getScom(ocmbChip, 0x22222222, val);
198     EXPECT_EQ(1, rc);
199 
200     // Test non-chip target.
201     EXPECT_DEATH({ getScom(omiUnit, 0x11111111, val); }, "");
202 }
203 
TEST(util_pdbg,getCfam)204 TEST(util_pdbg, getCfam)
205 {
206     using namespace util::pdbg;
207     pdbg_targets_init(nullptr);
208 
209     auto procChip = getTrgt("/proc0");
210     auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
211 
212     sim::CfamAccess& cfam = sim::CfamAccess::getSingleton();
213     cfam.flush();
214     cfam.add(procChip, 0x11111111, 0x00112233);
215     cfam.error(procChip, 0x22222222);
216 
217     int rc = 0;
218     uint32_t val = 0;
219 
220     // Test good path.
221     rc = getCfam(procChip, 0x11111111, val);
222     EXPECT_EQ(0, rc);
223     EXPECT_EQ(0x00112233, val);
224 
225     // Test address that has not been added to CfamAccess.
226     rc = getCfam(procChip, 0x33333333, val);
227     EXPECT_EQ(0, rc);
228     EXPECT_EQ(0, val);
229 
230     // Test CFAM error.
231     rc = getCfam(procChip, 0x22222222, val);
232     EXPECT_EQ(1, rc);
233 
234     // Test non-chip target.
235     EXPECT_DEATH({ getCfam(omiUnit, 0x11111111, val); }, "");
236 }
237 
TEST(util_pdbg,getActiveChips)238 TEST(util_pdbg, getActiveChips)
239 {
240     using namespace util::pdbg;
241     using namespace libhei;
242     pdbg_targets_init(nullptr);
243 
244     std::vector<libhei::Chip> chips;
245     getActiveChips(chips);
246 
247     trace::inf("chips size: %u", chips.size());
248     EXPECT_EQ(2, chips.size());
249 
250     /* TODO: There is an issue with the getActiveChips() function that only
251      *       seems to exist in simulation. For some reason, the OCMBs do not
252      *       show up as PDBG_TARGET_ENABLED. If we remove that check, this test
253      *       case works as expected. However, we don't want to do that in
254      *       production code.  Instead, we'll need to determine why the OCMBs
255      *       are not enabled in CI test and then reenable this test case.
256     auto proc0 = getTrgt("/proc0");
257     auto proc1 = getTrgt("/proc1");
258 
259     sim::ScomAccess& scom = sim::ScomAccess::getSingleton();
260     scom.flush();
261 
262     // Mask off proc0 mcc0 channel 1. The connected OCMB should be removed from
263     // the list.
264     scom.add(proc0, 0x0C010D03, 0x0f00000000000000);
265 
266     // Mask off one or two attentions, but not all, on proc0 mcc2. None of the
267     // connected OCMBs should be removed from the list.
268     scom.add(proc0, 0x0D010D03, 0xA500000000000000);
269 
270     // Mask off proc1 mcc7 channel 0. The connected OCMB should be removed from
271     // the list.
272     scom.add(proc1, 0x0F010D43, 0xf000000000000000);
273 
274     // Mask off proc1 mcc5 channels 0 and 1. Both the connected OCMBs should be
275     // removed from the list.
276     scom.add(proc1, 0x0E010D43, 0xff00000000000000);
277 
278     std::vector<libhei::Chip> chips;
279     getActiveChips(chips);
280 
281     // In total there should be 14 chips with 2 processors, 7 OCMBs on proc0,
282     // and 5 OCMBs on proc1.
283 
284     trace::inf("chips size: %u", chips.size());
285     EXPECT_EQ(14, chips.size());
286     */
287 }
288