blob: d233d3e02a28a86d5a1c9de834a1c19465097aee [file] [log] [blame]
Zane Shelleyd84ed6e2020-06-08 13:41:48 -05001#include <assert.h>
Ben Tyner87eabc62020-05-14 17:56:54 -05002#include <libpdbg.h>
3
Ben Tyner0205f3b2020-02-24 10:24:47 -06004#include <hei_main.hpp>
Zane Shelleyd84ed6e2020-06-08 13:41:48 -05005#include <util/trace.hpp>
Ben Tyner0205f3b2020-02-24 10:24:47 -06006
Zane Shelleyd84ed6e2020-06-08 13:41:48 -05007#include <algorithm>
Ben Tyner87eabc62020-05-14 17:56:54 -05008#include <fstream>
9#include <iostream>
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050010#include <map>
11#include <string>
12
Ben Tyner0205f3b2020-02-24 10:24:47 -060013namespace analyzer
14{
15
Ben Tyner87eabc62020-05-14 17:56:54 -050016/** @brief Chip types that coorelate device tree nodes to chip data files */
17static constexpr uint8_t chipTypeOcmb[4] = {0x00, 0x20, 0x0d, 0x16};
18static constexpr uint8_t chipTypeProc[4] = {0x49, 0xa0, 0x0d, 0x12};
19
20/**
21 * @brief send chip data file to isolator
22 *
23 * Read a chip data file into memory and then send it to the isolator via
24 * the initialize interface.
25 *
26 * @param i_filePath The file path and name to read into memory
27 *
28 * @return Returns true if the isolator was successfully initialized with
29 * a single chip data file. Returns false otherwise.
30 *
31 */
32bool initWithFile(const char* i_filePath)
Ben Tyner0205f3b2020-02-24 10:24:47 -060033{
Ben Tynerb859d792020-05-06 21:29:47 -050034 using namespace libhei;
35
Ben Tyner87eabc62020-05-14 17:56:54 -050036 bool rc = true; // assume success
Ben Tynerb859d792020-05-06 21:29:47 -050037
Ben Tyner87eabc62020-05-14 17:56:54 -050038 // open the file and seek to the end to get length
39 std::ifstream fileStream(i_filePath, std::ios::binary | std::ios::ate);
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050040
Ben Tyner87eabc62020-05-14 17:56:54 -050041 if (!fileStream)
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050042 {
Ben Tyner87eabc62020-05-14 17:56:54 -050043 std::cout << "could not open file" << std::endl;
44 rc = false;
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050045 }
46 else
47 {
Ben Tyner87eabc62020-05-14 17:56:54 -050048 // get file size based on seek position
49 std::ifstream::pos_type fileSize = fileStream.tellg();
50
51 // create a buffer large enough to hold the entire file
52 std::vector<char> fileBuffer(fileSize);
53
54 // seek to the beginning of the file
55 fileStream.seekg(0, std::ios::beg);
56
57 // read the entire file into the buffer
58 fileStream.read(fileBuffer.data(), fileSize);
59
60 // done with the file
61 fileStream.close();
62
63 // intialize the isolator with the chip data
64 initialize(fileBuffer.data(), fileSize); // hei initialize
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050065 }
Ben Tynerb859d792020-05-06 21:29:47 -050066
Ben Tyner87eabc62020-05-14 17:56:54 -050067 return rc;
68}
Ben Tynerb1ebfcb2020-05-08 18:52:48 -050069
Zane Shelleyd84ed6e2020-06-08 13:41:48 -050070//------------------------------------------------------------------------------
71
72// Returns the chip model/level of the given target. Also, adds the chip
73// model/level to the list of type types needed to initialize the isolator.
74libhei::ChipType_t __getChipType(pdbg_target* i_trgt,
75 std::vector<libhei::ChipType_t>& o_types)
76{
77 libhei::ChipType_t type;
78
79 // START WORKAROUND
80 // TODO: Will need to grab the model/level from the target attributes when
81 // they are available. For now, use ATTR_TYPE to determine which
82 // currently supported value to use supported.
83 char* attrType = new char[1];
84
85 pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, attrType);
86
87 switch (attrType[0])
88 {
89 case 0x05: // PROC
90 type = 0x120DA049;
91 break;
92
93 case 0x4b: // OCMB_CHIP
94 type = 0x160D2000;
95 break;
96
97 default:
98 trace::err("Unsupported ATTR_TYPE value: 0x%02x", attrType[0]);
99 assert(0);
100 }
101
102 delete[] attrType;
103 // END WORKAROUND
104
105 o_types.push_back(type);
106
107 return type;
108}
109
110//------------------------------------------------------------------------------
111
112// Gathers list of active chips to analyze. Also, returns the list of chip types
113// needed to initialize the isolator.
114void __getActiveChips(std::vector<libhei::Chip>& o_chips,
115 std::vector<libhei::ChipType_t>& o_types)
116{
117 // Iterate each processor.
118 pdbg_target* procTrgt;
119 pdbg_for_each_class_target("proc", procTrgt)
120 {
121 // Active processors only.
122 if (PDBG_TARGET_ENABLED != pdbg_target_probe(procTrgt))
123 continue;
124
125 // Add the processor to the list.
126 o_chips.emplace_back(procTrgt, __getChipType(procTrgt, o_types));
127
128 // Iterate the connected OCMBs, if they exist.
129 pdbg_target* ocmbTrgt;
130 pdbg_for_each_target("ocmb_chip", procTrgt, ocmbTrgt)
131 {
132 // Active OCMBs only.
133 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
134 continue;
135
136 // Add the OCMB to the list.
137 o_chips.emplace_back(ocmbTrgt, __getChipType(ocmbTrgt, o_types));
138 }
139 }
140
141 // Make sure the model/level list is of unique values only.
142 auto itr = std::unique(o_types.begin(), o_types.end());
143 o_types.resize(std::distance(o_types.begin(), itr));
144}
145
146//------------------------------------------------------------------------------
147
Ben Tyner87eabc62020-05-14 17:56:54 -0500148/**
149 * @brief Analyze using the hardware error isolator
150 *
151 * Query the hardware for each active chip that is a valid candidate for
152 * error analyses. Based on the list of active chips initialize the
153 * isolator with the associated chip data files. Finally request analyses
154 * from the hardware error isolator and log the results.
155 *
156 * @param o_errors A map for storing information about erros that were
157 * detected by the hardware error isolator.
158 *
159 * @return True if hardware error analyses was successful, false otherwise
160 */
161bool analyzeHardware(std::map<std::string, std::string>& o_errors)
162{
163 using namespace libhei;
Ben Tynerb1ebfcb2020-05-08 18:52:48 -0500164
Ben Tyner87eabc62020-05-14 17:56:54 -0500165 bool rc = true;
166
Zane Shelleyd84ed6e2020-06-08 13:41:48 -0500167 // Get the active chips to be analyzed and their types.
168 std::vector<libhei::Chip> chipList;
169 std::vector<libhei::ChipType_t> chipTypes;
170 __getActiveChips(chipList, chipTypes);
Ben Tyner87eabc62020-05-14 17:56:54 -0500171
172 IsolationData isoData{}; // data from isolato
173
Ben Tyner87eabc62020-05-14 17:56:54 -0500174 // TODO select chip data files based on chip types detected
175 do
176 {
177 // TODO for now chip data files are local
178 // hei initialize
179 if (false ==
180 initWithFile("/usr/share/openpower-hw-diags/chip_data_ocmb.cdb"))
181 {
182 rc = false;
183 break;
184 }
185
186 // TODO for now chip data files are local
187 // hei initialize
188 if (false ==
189 initWithFile("/usr/share/openpower-hw-diags/chip_data_proc.cdb"))
190 {
191 rc = false;
192 break;
193 }
194
195 // hei isolate
196 isolate(chipList, isoData);
197
198 if (!(isoData.getSignatureList().empty()))
199 {
200 // TODO parse signature list
201 int numErrors = isoData.getSignatureList().size();
202
203 std::cout << "isolated: " << numErrors << std::endl;
204 }
205
206 // hei uninitialize
207 uninitialize();
208
209 } while (0);
210
211 return rc;
Ben Tyner0205f3b2020-02-24 10:24:47 -0600212}
213
214} // namespace analyzer