xref: /openbmc/openpower-hw-diags/util/pdbg.cpp (revision 5183af30)
1 #include <assert.h>
2 
3 #include <hei_main.hpp>
4 #include <util/pdbg.hpp>
5 #include <util/trace.hpp>
6 
7 namespace util
8 {
9 
10 namespace pdbg
11 {
12 
13 //------------------------------------------------------------------------------
14 
15 pdbg_target* getTrgt(const libhei::Chip& i_chip)
16 {
17     return (pdbg_target*)i_chip.getChip();
18 }
19 
20 //------------------------------------------------------------------------------
21 
22 const char* getPath(pdbg_target* i_trgt)
23 {
24     return pdbg_target_path(i_trgt);
25 }
26 
27 const char* getPath(const libhei::Chip& i_chip)
28 {
29     return getPath(getTrgt(i_chip));
30 }
31 
32 //------------------------------------------------------------------------------
33 
34 uint32_t getChipPos(pdbg_target* i_trgt)
35 {
36     uint32_t attr = 0;
37     pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
38     return attr;
39 }
40 
41 uint32_t getChipPos(const libhei::Chip& i_chip)
42 {
43     return getChipPos(getTrgt(i_chip));
44 }
45 
46 //------------------------------------------------------------------------------
47 
48 uint8_t getTrgtType(pdbg_target* i_trgt)
49 {
50     uint8_t attr = 0;
51     pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
52     return attr;
53 }
54 
55 uint8_t getTrgtType(const libhei::Chip& i_chip)
56 {
57     return getTrgtType(getTrgt(i_chip));
58 }
59 
60 //------------------------------------------------------------------------------
61 
62 pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
63 {
64     // The input target must be a processor.
65     assert(0x05 == getTrgtType(i_procTrgt));
66 
67     // Get the pib path.
68     char path[16];
69     sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
70 
71     // Return the pib target.
72     pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
73     assert(nullptr != pibTrgt);
74 
75     return pibTrgt;
76 }
77 
78 //------------------------------------------------------------------------------
79 
80 pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
81 {
82     // The input target must be a processor.
83     assert(0x05 == getTrgtType(i_procTrgt));
84 
85     // Get the fsi path.
86     char path[16];
87     sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
88 
89     // Return the fsi target.
90     pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
91     assert(nullptr != fsiTrgt);
92 
93     return fsiTrgt;
94 }
95 
96 //------------------------------------------------------------------------------
97 
98 uint32_t __getChipId(pdbg_target* i_trgt)
99 {
100     uint32_t attr = 0;
101     pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
102     return attr;
103 }
104 
105 uint8_t __getChipEc(pdbg_target* i_trgt)
106 {
107     uint8_t attr = 0;
108     pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
109     return attr;
110 }
111 
112 uint32_t __getChipIdEc(pdbg_target* i_trgt)
113 {
114     return ((__getChipId(i_trgt) & 0xffff) << 16) | __getChipEc(i_trgt);
115 }
116 
117 void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
118                libhei::ChipType_t i_type)
119 {
120     // Trace each chip for debug. It is important to show the type just in case
121     // the model/EC does not exist. See note below.
122     trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
123                getPath(i_trgt));
124 
125     if (0 == i_type)
126     {
127         // There is a special case where the model/level attributes have not
128         // been initialized in the devtree. This is possible on the epoch IPL
129         // where an attention occurs before Hostboot is able to update the
130         // devtree information on the BMC. For now, just ignore the chip.
131     }
132     else
133     {
134         o_chips.emplace_back(i_trgt, i_type);
135     }
136 }
137 
138 void getActiveChips(std::vector<libhei::Chip>& o_chips)
139 {
140     o_chips.clear();
141 
142     // Iterate each processor.
143     pdbg_target* procTrgt;
144     pdbg_for_each_class_target("proc", procTrgt)
145     {
146         // We cannot use the proc target to determine if the chip is active.
147         // There is some design limitation in pdbg that requires the proc
148         // targets to always be active. Instead, we must get the associated pib
149         // target and check if it is active.
150 
151         // Active processors only.
152         if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
153             continue;
154 
155         // Add the processor to the list.
156         __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
157 
158         // Iterate the connected OCMBs, if they exist.
159         pdbg_target* ocmbTrgt;
160         pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
161         {
162             // Active OCMBs only.
163             if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
164                 continue;
165 
166             // Add the OCMB to the list.
167             __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
168         }
169     }
170 }
171 
172 //------------------------------------------------------------------------------
173 
174 bool queryHardwareAnalysisSupported()
175 {
176     // Hardware analysis is only supported on P10 systems and up.
177     return (PDBG_PROC_P9 < pdbg_get_proc());
178 }
179 
180 //------------------------------------------------------------------------------
181 
182 } // namespace pdbg
183 
184 } // namespace util
185