blob: 605df77e037da73ea97c34c22844d3fe1240998a [file] [log] [blame]
Zane Shelley171a2e02020-11-13 13:56:13 -06001#include <assert.h>
2
Zane Shelley7ae9c8c2020-12-02 20:10:31 -06003#include <hei_main.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -06004#include <util/pdbg.hpp>
Zane Shelley171a2e02020-11-13 13:56:13 -06005#include <util/trace.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -06006
7namespace util
8{
9
10namespace pdbg
11{
12
13//------------------------------------------------------------------------------
14
Zane Shelleya0299852020-11-13 13:38:04 -060015pdbg_target* getTrgt(const libhei::Chip& i_chip)
16{
17 return (pdbg_target*)i_chip.getChip();
18}
19
20//------------------------------------------------------------------------------
21
22const char* getPath(pdbg_target* i_trgt)
23{
24 return pdbg_target_path(i_trgt);
25}
26
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060027const char* getPath(const libhei::Chip& i_chip)
28{
Zane Shelleya0299852020-11-13 13:38:04 -060029 return getPath(getTrgt(i_chip));
30}
31
32//------------------------------------------------------------------------------
33
34uint32_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
41uint32_t getChipPos(const libhei::Chip& i_chip)
42{
43 return getChipPos(getTrgt(i_chip));
44}
45
46//------------------------------------------------------------------------------
47
48uint8_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
55uint8_t getTrgtType(const libhei::Chip& i_chip)
56{
57 return getTrgtType(getTrgt(i_chip));
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060058}
59
60//------------------------------------------------------------------------------
61
Zane Shelley171a2e02020-11-13 13:56:13 -060062pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
63{
64 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -060065 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelley171a2e02020-11-13 13:56:13 -060066
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
Zane Shelleyff76b6b2020-11-18 13:54:26 -060080pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
81{
82 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -060083 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelleyff76b6b2020-11-18 13:54:26 -060084
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
Zane Shelley35171d92020-12-03 13:31:13 -060098int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
99{
100 // Only processor targets are supported.
101 assert(TYPE_PROC == getTrgtType(i_trgt));
102
103 auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
104
105 int rc = fsi_read(fsiTrgt, i_addr, &o_val);
106
107 if (0 != rc)
108 {
109 trace::err("fsi_read failure: trgt=%s addr=0x%08x",
110 util::pdbg::getPath(fsiTrgt), i_addr);
111 }
112
113 return rc;
114}
115
116//------------------------------------------------------------------------------
117
118// IMPORTANT:
119// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
120// point during the IPL. It is possible that this information is needed before
121// the sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600122uint32_t __getChipId(pdbg_target* i_trgt)
123{
124 uint32_t attr = 0;
125 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
126 return attr;
127}
128
Zane Shelley35171d92020-12-03 13:31:13 -0600129// IMPORTANT:
130// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
131// during the IPL. It is possible that this information is needed before the
132// sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600133uint8_t __getChipEc(pdbg_target* i_trgt)
134{
135 uint8_t attr = 0;
136 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
137 return attr;
138}
139
140uint32_t __getChipIdEc(pdbg_target* i_trgt)
141{
Zane Shelley35171d92020-12-03 13:31:13 -0600142 auto chipId = __getChipId(i_trgt);
143 auto chipEc = __getChipEc(i_trgt);
144
145 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
146 {
147 // There is a special case where the model/level attributes have not
148 // been initialized in the devtree. This is possible on the epoch IPL
149 // where an attention occurs before Hostboot is able to update the
150 // devtree information on the BMC. It may is still possible to get this
151 // information from chips with CFAM access (i.e. a processor) via the
152 // CFAM chip ID register.
153
154 uint32_t val = 0;
155 if (0 == getCfam(i_trgt, 0x100a, val))
156 {
157 chipId = ((val & 0x0F0FF000) >> 12);
158 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
159 }
160 }
161
162 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
Zane Shelley171a2e02020-11-13 13:56:13 -0600163}
164
165void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
166 libhei::ChipType_t i_type)
167{
168 // Trace each chip for debug. It is important to show the type just in case
169 // the model/EC does not exist. See note below.
170 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
171 getPath(i_trgt));
172
173 if (0 == i_type)
174 {
Zane Shelley35171d92020-12-03 13:31:13 -0600175 // This is a special case. See the details in __getChipIdEC(). There is
176 // nothing more we can do with this chip since we don't know what it is.
177 // So ignore the chip for now.
Zane Shelley171a2e02020-11-13 13:56:13 -0600178 }
179 else
180 {
181 o_chips.emplace_back(i_trgt, i_type);
182 }
183}
184
185void getActiveChips(std::vector<libhei::Chip>& o_chips)
186{
187 o_chips.clear();
188
189 // Iterate each processor.
190 pdbg_target* procTrgt;
191 pdbg_for_each_class_target("proc", procTrgt)
192 {
193 // We cannot use the proc target to determine if the chip is active.
194 // There is some design limitation in pdbg that requires the proc
195 // targets to always be active. Instead, we must get the associated pib
196 // target and check if it is active.
197
198 // Active processors only.
199 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
200 continue;
201
202 // Add the processor to the list.
203 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
204
205 // Iterate the connected OCMBs, if they exist.
206 pdbg_target* ocmbTrgt;
207 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
208 {
209 // Active OCMBs only.
210 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
211 continue;
212
213 // Add the OCMB to the list.
214 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
215 }
216 }
217}
218
219//------------------------------------------------------------------------------
220
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600221bool queryHardwareAnalysisSupported()
222{
223 // Hardware analysis is only supported on P10 systems and up.
Zane Shelley5183af32020-12-07 14:49:03 -0600224 return (PDBG_PROC_P9 < pdbg_get_proc());
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600225}
226
227//------------------------------------------------------------------------------
228
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -0600229} // namespace pdbg
230
231} // namespace util