blob: d4170a71c5f8af8018909f340df38b62e7e44203 [file] [log] [blame]
Zane Shelley171a2e02020-11-13 13:56:13 -06001#include <assert.h>
Zane Shelleye4bfb472021-08-10 12:47:32 -05002#include <config.h>
Zane Shelley171a2e02020-11-13 13:56:13 -06003
Zane Shelley7ae9c8c2020-12-02 20:10:31 -06004#include <hei_main.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -06005#include <util/pdbg.hpp>
Zane Shelley171a2e02020-11-13 13:56:13 -06006#include <util/trace.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -06007
Zane Shelley3a851082021-03-23 16:45:28 -05008#ifdef CONFIG_PHAL_API
Zane Shelleye4bfb472021-08-10 12:47:32 -05009#include <attributes_info.H>
Zane Shelley3a851082021-03-23 16:45:28 -050010#endif
11
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060012namespace util
13{
14
15namespace pdbg
16{
17
18//------------------------------------------------------------------------------
19
Zane Shelleya0299852020-11-13 13:38:04 -060020pdbg_target* getTrgt(const libhei::Chip& i_chip)
21{
22 return (pdbg_target*)i_chip.getChip();
23}
24
25//------------------------------------------------------------------------------
26
Zane Shelley236bb732021-03-24 17:07:46 -050027pdbg_target* getTrgt(const std::string& i_path)
28{
29 return pdbg_target_from_path(nullptr, i_path.c_str());
30}
31
32//------------------------------------------------------------------------------
33
Zane Shelleya0299852020-11-13 13:38:04 -060034const char* getPath(pdbg_target* i_trgt)
35{
36 return pdbg_target_path(i_trgt);
37}
38
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060039const char* getPath(const libhei::Chip& i_chip)
40{
Zane Shelleya0299852020-11-13 13:38:04 -060041 return getPath(getTrgt(i_chip));
42}
43
44//------------------------------------------------------------------------------
45
46uint32_t getChipPos(pdbg_target* i_trgt)
47{
48 uint32_t attr = 0;
49 pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
50 return attr;
51}
52
53uint32_t getChipPos(const libhei::Chip& i_chip)
54{
55 return getChipPos(getTrgt(i_chip));
56}
57
58//------------------------------------------------------------------------------
59
60uint8_t getTrgtType(pdbg_target* i_trgt)
61{
62 uint8_t attr = 0;
63 pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
64 return attr;
65}
66
67uint8_t getTrgtType(const libhei::Chip& i_chip)
68{
69 return getTrgtType(getTrgt(i_chip));
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060070}
71
72//------------------------------------------------------------------------------
73
Zane Shelley171a2e02020-11-13 13:56:13 -060074pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
75{
76 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -060077 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelley171a2e02020-11-13 13:56:13 -060078
79 // Get the pib path.
80 char path[16];
81 sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
82
83 // Return the pib target.
84 pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
85 assert(nullptr != pibTrgt);
86
87 return pibTrgt;
88}
89
90//------------------------------------------------------------------------------
91
Zane Shelleyff76b6b2020-11-18 13:54:26 -060092pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
93{
94 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -060095 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelleyff76b6b2020-11-18 13:54:26 -060096
97 // Get the fsi path.
98 char path[16];
99 sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
100
101 // Return the fsi target.
102 pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
103 assert(nullptr != fsiTrgt);
104
105 return fsiTrgt;
106}
107
108//------------------------------------------------------------------------------
109
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600110int getScom(pdbg_target* i_trgt, uint64_t i_addr, uint64_t& o_val)
111{
112 // Only processor targets are supported.
113 // TODO: Will need to add OCMB support later.
114 assert(TYPE_PROC == getTrgtType(i_trgt));
115
116 auto pibTrgt = util::pdbg::getPibTrgt(i_trgt);
117
118 int rc = pib_read(pibTrgt, i_addr, &o_val);
119
120 if (0 != rc)
121 {
122 trace::err("pib_read failure: target=%s addr=0x%0" PRIx64,
123 util::pdbg::getPath(pibTrgt), i_addr);
124 }
125
126 return rc;
127}
128
129//------------------------------------------------------------------------------
130
Zane Shelley35171d92020-12-03 13:31:13 -0600131int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
132{
133 // Only processor targets are supported.
134 assert(TYPE_PROC == getTrgtType(i_trgt));
135
136 auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
137
138 int rc = fsi_read(fsiTrgt, i_addr, &o_val);
139
140 if (0 != rc)
141 {
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600142 trace::err("fsi_read failure: target=%s addr=0x%08x",
Zane Shelley35171d92020-12-03 13:31:13 -0600143 util::pdbg::getPath(fsiTrgt), i_addr);
144 }
145
146 return rc;
147}
148
149//------------------------------------------------------------------------------
150
151// IMPORTANT:
152// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
153// point during the IPL. It is possible that this information is needed before
154// the sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600155uint32_t __getChipId(pdbg_target* i_trgt)
156{
157 uint32_t attr = 0;
158 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
159 return attr;
160}
161
Zane Shelley35171d92020-12-03 13:31:13 -0600162// IMPORTANT:
163// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
164// during the IPL. It is possible that this information is needed before the
165// sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600166uint8_t __getChipEc(pdbg_target* i_trgt)
167{
168 uint8_t attr = 0;
169 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
170 return attr;
171}
172
173uint32_t __getChipIdEc(pdbg_target* i_trgt)
174{
Zane Shelley35171d92020-12-03 13:31:13 -0600175 auto chipId = __getChipId(i_trgt);
176 auto chipEc = __getChipEc(i_trgt);
177
178 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
179 {
180 // There is a special case where the model/level attributes have not
181 // been initialized in the devtree. This is possible on the epoch IPL
182 // where an attention occurs before Hostboot is able to update the
183 // devtree information on the BMC. It may is still possible to get this
184 // information from chips with CFAM access (i.e. a processor) via the
185 // CFAM chip ID register.
186
187 uint32_t val = 0;
188 if (0 == getCfam(i_trgt, 0x100a, val))
189 {
190 chipId = ((val & 0x0F0FF000) >> 12);
191 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
192 }
193 }
194
195 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
Zane Shelley171a2e02020-11-13 13:56:13 -0600196}
197
198void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
199 libhei::ChipType_t i_type)
200{
201 // Trace each chip for debug. It is important to show the type just in case
202 // the model/EC does not exist. See note below.
203 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
204 getPath(i_trgt));
205
206 if (0 == i_type)
207 {
Zane Shelley35171d92020-12-03 13:31:13 -0600208 // This is a special case. See the details in __getChipIdEC(). There is
209 // nothing more we can do with this chip since we don't know what it is.
210 // So ignore the chip for now.
Zane Shelley171a2e02020-11-13 13:56:13 -0600211 }
212 else
213 {
214 o_chips.emplace_back(i_trgt, i_type);
215 }
216}
217
218void getActiveChips(std::vector<libhei::Chip>& o_chips)
219{
220 o_chips.clear();
221
222 // Iterate each processor.
223 pdbg_target* procTrgt;
224 pdbg_for_each_class_target("proc", procTrgt)
225 {
226 // We cannot use the proc target to determine if the chip is active.
227 // There is some design limitation in pdbg that requires the proc
228 // targets to always be active. Instead, we must get the associated pib
229 // target and check if it is active.
230
231 // Active processors only.
232 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
233 continue;
234
235 // Add the processor to the list.
236 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
237
238 // Iterate the connected OCMBs, if they exist.
239 pdbg_target* ocmbTrgt;
240 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
241 {
242 // Active OCMBs only.
243 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
244 continue;
245
246 // Add the OCMB to the list.
247 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
248 }
249 }
250}
251
252//------------------------------------------------------------------------------
253
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600254pdbg_target* getPrimaryProcessor()
255{
256 // TODO: For at least P10, the primary processor (the one connected directly
257 // to the BMC), will always be PROC 0. We will need to update this
258 // later if we ever support an alternate primary processor.
259 return getTrgt("/proc0");
260}
261
262//------------------------------------------------------------------------------
263
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600264bool queryHardwareAnalysisSupported()
265{
266 // Hardware analysis is only supported on P10 systems and up.
Zane Shelley5183af32020-12-07 14:49:03 -0600267 return (PDBG_PROC_P9 < pdbg_get_proc());
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600268}
269
270//------------------------------------------------------------------------------
271
Zane Shelley3a851082021-03-23 16:45:28 -0500272std::string getLocationCode(pdbg_target* trgt)
273{
274 if (nullptr == trgt)
275 {
276 // Either the path is wrong or the attribute doesn't exist.
277 return std::string{};
278 }
279
280#ifdef CONFIG_PHAL_API
281
282 ATTR_LOCATION_CODE_Type val;
283 if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val))
284 {
285 // Get the immediate parent in the devtree path and try again.
286 return getLocationCode(pdbg_target_parent(nullptr, trgt));
287 }
288
289 // Attribute found.
290 return std::string{val};
291
292#else
293
294 return std::string{getPath(trgt)};
295
296#endif
297}
298
299//------------------------------------------------------------------------------
300
301std::string getPhysDevPath(pdbg_target* trgt)
302{
303 if (nullptr == trgt)
304 {
305 // Either the path is wrong or the attribute doesn't exist.
306 return std::string{};
307 }
308
309#ifdef CONFIG_PHAL_API
310
311 ATTR_PHYS_DEV_PATH_Type val;
312 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val))
313 {
314 // Get the immediate parent in the devtree path and try again.
315 return getPhysDevPath(pdbg_target_parent(nullptr, trgt));
316 }
317
318 // Attribute found.
319 return std::string{val};
320
321#else
322
323 return std::string{getPath(trgt)};
324
325#endif
326}
327
328//------------------------------------------------------------------------------
329
Zane Shelleybf3326f2021-11-12 13:41:39 -0600330std::vector<uint8_t> getPhysBinPath(pdbg_target* target)
331{
332 std::vector<uint8_t> binPath;
333
334 if (nullptr != target)
335 {
336#ifdef CONFIG_PHAL_API
337
338 ATTR_PHYS_BIN_PATH_Type value;
339 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
340 {
341 // The attrirbute for this target does not exist. Get the immediate
342 // parent in the devtree path and try again. Note that if there is
343 // no parent target, nullptr will be returned and that will be
344 // checked above.
345 return getPhysBinPath(pdbg_target_parent(nullptr, target));
346 }
347
348 // Attribute was found. Copy the attribute array to the returned
349 // vector. Note that the reason we return the vector instead of just
350 // returning the array is because the array type and details only
351 // exists in this specific configuration.
352 binPath.insert(binPath.end(), value, value + sizeof(value));
353
354#endif
355 }
356
357 return binPath;
358}
359
360//------------------------------------------------------------------------------
361
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -0600362} // namespace pdbg
363
364} // namespace util