blob: a984f246510317c7066439ad616e40410a28b931 [file] [log] [blame]
Zane Shelleydd156ad2019-10-25 20:59:55 -05001// clang-format off
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05002/* IBM_PROLOG_BEGIN_TAG */
3/* This is an automatically generated prolog. */
4/* */
5/* $Source: src/usr/diag/prdf/common/framework/register/prdfCaptureData.C $ */
6/* */
7/* OpenPOWER HostBoot Project */
8/* */
9/* Contributors Listed Below - COPYRIGHT 2012,2019 */
10/* [+] International Business Machines Corp. */
11/* */
12/* */
13/* Licensed under the Apache License, Version 2.0 (the "License"); */
14/* you may not use this file except in compliance with the License. */
15/* You may obtain a copy of the License at */
16/* */
17/* http://www.apache.org/licenses/LICENSE-2.0 */
18/* */
19/* Unless required by applicable law or agreed to in writing, software */
20/* distributed under the License is distributed on an "AS IS" BASIS, */
21/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
22/* implied. See the License for the specific language governing */
23/* permissions and limitations under the License. */
24/* */
25/* IBM_PROLOG_END_TAG */
26
27/**
28 @file prdfCaptureData.C
29 @brief Squadrons implementation of capture data
30*/
31//----------------------------------------------------------------------
32// Includes
33//----------------------------------------------------------------------
34
Ben Tyner032bf9e2020-05-06 21:27:54 -050035#include <hei_macros.hpp>
Zane Shelley52cb1a92019-08-21 14:38:31 -050036#include <register/hei_hardware_register.hpp>
37#include <util/hei_bit_string.hpp>
38
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050039#include <iipchip.h>
40#include <iipCaptureData.h>
41#include <string.h>
42#include <algorithm> // @jl04 a Add this for the Drop function.
43
44using namespace TARGETING;
45
Zane Shelleyfd275a22019-09-05 23:13:59 -050046namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050047{
48
49//---------------------------------------------------------------------
50// Member Function Specifications
51//---------------------------------------------------------------------
52
53CaptureData::CaptureData(void):data()
54{
55// data.reserve(INITIAL_DATA_COUNT);
56}
57
58// dg05d CaptureData::~CaptureData(void)
59// dg05d {
60// dg05d if(!data.empty())
61// dg05d {
62// dg05d Clear();
63// dg05d }
64// dg05d }
65
66void CaptureData::Clear(void)
67{
68
69 if(!data.empty())
70 {
71// dg05d for(DataContainerType::iterator i = data.begin();i != data.end();i++)
72// dg05d {
73// dg05d delete [] (*i).dataPtr;
74// dg05d }
75
76 data.erase(data.begin(), data.end());
77
78 } /* if not empty */
79}
80
81//------------------------------------------------------------------------------
82
83void CaptureData::AddDataElement( TargetHandle_t i_trgt, int i_scomId,
84 const BitString * i_bs,
85 Place i_place, RegType i_type )
86{
87 // Initial values of the bit string buffer if i_bs has a zero value.
88 uint8_t * buf = nullptr;
89 size_t sz_buf = 0;
90
91 // Add buffer only if the value is non-zero.
92 if ( !i_bs->isZero() )
93 {
94 // Get the size of i_bs and ensure byte alignment.
95 sz_buf = (i_bs->getBitLen() + 8-1) / 8;
96
97 // Since we are using a BitString below, which does everything on a
98 // CPU_WORD boundary, we must make sure the buffer is CPU_WORD aligned.
99 const size_t sz_word = sizeof(CPU_WORD);
100 sz_buf = ((sz_buf + sz_word-1) / sz_word) * sz_word;
101
102 // Allocate memory for the buffer.
103 buf = new uint8_t[sz_buf];
104 memset( buf, 0x00, sz_buf );
105
106 // Use a BitString to copy i_bs to the buffer.
107 BitString bs ( i_bs->getBitLen(), (CPU_WORD *)buf );
108 bs.setString( *i_bs );
109
110 // Create the new data element.
111 Data element( i_trgt, i_scomId, sz_buf, buf );
112 element.registerType = i_type;
113
114 // Add the new element to the data.
115 if ( FRONT == i_place )
116 data.insert( data.begin(), element );
117 else
118 data.push_back( element );
119 }
120}
121
122//------------------------------------------------------------------------------
123
124void CaptureData::Add( TargetHandle_t i_trgt, int32_t i_scomId,
Zane Shelley23244cb2019-08-30 21:12:12 -0500125 Register & io_scr,
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500126 Place i_place, RegType i_type )
127{
128 if ( SUCCESS == io_scr.Read() )
129 {
130 AddDataElement( i_trgt, i_scomId, io_scr.GetBitString(),
131 i_place, i_type );
132 }
133}
134
135//------------------------------------------------------------------------------
136
137void CaptureData::Add( TargetHandle_t i_trgt, int i_scomId,
138 const BitString & i_bs, Place i_place )
139{
140 AddDataElement( i_trgt, i_scomId, &i_bs, i_place );
141}
142
143//------------------------------------------------------------------------------
144
145// start jl04a
146void CaptureData::Drop(RegType i_type)
147{
148 // Function below requires a predicate function above to Drop
149 // a data element from the capture data if it is
150 // defined as secondary data instead of primary data in the rule files.
151 // This predicate has to exist within the CaptureData Class because the
152 // class "Data" is defined within CaptureData class.
153 data.erase( std::remove_if(data.begin(),data.end(),
154 prdfCompareCaptureDataType(i_type)), data.end() );
155}
156// end jl04a
157
158//------------------------------------------------------------------------------
159
160template <class T>
161void __bufferAdd( uint8_t* & i_idx, T i_val )
162{
163 memcpy( i_idx, &i_val, sizeof(i_val) );
164 i_idx += sizeof(i_val);
165}
166
167bool __bufferFull( uint8_t * i_buf, size_t i_bufSize,
168 uint8_t * i_idx, size_t i_idxSize )
169{
170 if ( (i_buf + i_bufSize) < (i_idx + i_idxSize) )
171 {
Zane Shelley5d432bf2019-09-02 20:58:51 -0500172 HEI_ERR( "[CaptureData::Copy] Buffer is full. Some data may have "
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500173 "been lost" );
174 return true;
175 }
176
177 return false;
178}
179
180/* CaptureData Format:
181 * capture data -> ( <chip header> <registers> )*
182 * chip header -> ( <chip id:32> <# registers:32> )
183 * registers -> ( <reg id:16> <reg byte len:16> <bytes>+ )
184 */
185uint32_t CaptureData::Copy( uint8_t * i_buffer, uint32_t i_bufferSize ) const
186{
187 TargetHandle_t curTrgt = nullptr;
188
189 uint32_t * regCntPtr = nullptr;
190
191 uint8_t * curIdx = i_buffer;
192
193 for ( auto & entry : data )
194 {
195 // We only need the target data when the target for this entry does not
196 // match the previous entry.
197 if ( entry.chipHandle != curTrgt )
198 {
199 // Ensure we have enough space for the entry header.
200 if ( __bufferFull( i_buffer, i_bufferSize, curIdx,
201 (sizeof(HUID) + sizeof(uint32_t)) ) )
202 {
203 break;
204 }
205
206 // Update current target.
207 curTrgt = entry.chipHandle;
208
209 // Add HUID to buffer.
210 __bufferAdd( curIdx, htonl(PlatServices::getHuid(curTrgt)) );
211
212 // Update the current count pointer.
213 regCntPtr = (uint32_t *)curIdx;
214
215 // Zero out the register count.
216 __bufferAdd( curIdx, htonl(0) );
217 }
218
219 // Go to next entry if the data byte length is 0.
220 if ( 0 == entry.dataByteLength )
221 continue;
222
223 // Ensure we have enough space for the entry header.
224 if ( __bufferFull( i_buffer, i_bufferSize, curIdx,
225 (2 * sizeof(uint16_t) + entry.dataByteLength) ) )
226 {
227 break;
228 }
229
230 // Write register ID.
231 __bufferAdd( curIdx, htons(entry.address) );
232
233 // Write data length.
234 __bufferAdd( curIdx, htons(entry.dataByteLength) );
235
236 // Write the data.
237 // >>> TODO: RTC 199045 The data should already be in network format.
238 // However, that is not the case. Instead, the data is
239 // converted here, which would be is fine if we were only
240 // adding registers, but we have additional capture data,
241 // especially in the memory subsytem, that are actually stored
242 // in the network format, but swizzled before adding to the
243 // capture data. Which means we are doing too much.
244 // Unfortunately, it currently works and will take some time
245 // to actually do it right. Therefore, we will leave this
246 // as-is and try to make the appropriate fix later.
247 uint32_t l_dataWritten = 0;
248 while ((l_dataWritten + 4) <= entry.dataByteLength)
249 {
250 uint32_t l_temp32;
251 memcpy(&l_temp32, &entry.dataPtr[l_dataWritten], sizeof(l_temp32));
252 l_temp32 = htonl(l_temp32);
253 memcpy(curIdx, &l_temp32, 4);
254 l_dataWritten += 4; curIdx += 4;
255 }
256 if (l_dataWritten != entry.dataByteLength)
257 {
258 // TODO: RTC 199045 This is actually pretty bad because it will read
259 // four bytes of memory, sizzle the four bytes, then write
260 // less than four bytes to the buffer. This could cause a
261 // buffer overrun exception if we were at the end of memory.
262 // Also, how can we trust the right most bytes to be correct
263 // since they technically should not be part of the entry
264 // data? Again, we don't seem to be hitting this bug and it
265 // will take time to fix it (see note above). Therefore, we
266 // will leave it for now and fix it when we have time.
267 uint32_t l_temp32;
268 memcpy(&l_temp32, &entry.dataPtr[l_dataWritten], sizeof(l_temp32));
269 l_temp32 = htonl(l_temp32);
270 memcpy(curIdx, &l_temp32, entry.dataByteLength - l_dataWritten);
271 curIdx += entry.dataByteLength - l_dataWritten;
272 }
273 // <<< TODO: RTC 199045
274
275 // Update entry count. It is important to update the buffer just in
276 // case we happen to run out of room in the buffer and need to exit
277 // early.
278 *regCntPtr = htonl( ntohl(*regCntPtr) + 1 );
279 }
280
281 return curIdx - i_buffer;
282}
283
284// dg08a -->
285CaptureData & CaptureData::operator=(const uint8_t *i_flatdata)
286{
287 uint32_t l_tmp32 = 0;
288 uint16_t l_tmp16 = 0;
289
290 HUID l_chipHuid = INVALID_HUID;
291 const size_t l_huidSize = sizeof(l_chipHuid);
292
293 // Read size.
294 memcpy(&l_tmp32, i_flatdata, sizeof(uint32_t));
295 uint32_t size = ntohl(l_tmp32);
296 i_flatdata += sizeof(uint32_t);
297
298 Clear();
299
300 // Calculate end of buffer.
301 const uint8_t *eptr = i_flatdata + size;
302
303 while(i_flatdata < eptr)
304 {
305 // Read chip Handle.
306 memcpy(&l_chipHuid , i_flatdata,l_huidSize );
307 i_flatdata += l_huidSize ;
Zane Shelley05bac982019-09-02 20:57:42 -0500308 TargetHandle_t l_pchipHandle =nullptr;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500309 l_chipHuid = ntohl(l_chipHuid);
310 l_pchipHandle = PlatServices::getTarget(l_chipHuid );
Zane Shelley05bac982019-09-02 20:57:42 -0500311 if(nullptr ==l_pchipHandle)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500312 {
313 continue;
314 }
315
316 // Read # of entries.
317 memcpy(&l_tmp32, i_flatdata, sizeof(uint32_t));
318 i_flatdata += sizeof(l_tmp32);
319 uint32_t entries = ntohl(l_tmp32);
320
321 // Input each entry.
322 for(uint32_t i = 0; i < entries; ++i)
323 {
324 // Read register id.
325 memcpy(&l_tmp16, i_flatdata, sizeof(uint16_t));
326 i_flatdata += sizeof(uint16_t);
327 int regid = ntohs(l_tmp16);
328
329 // Read byte count.
330 memcpy(&l_tmp16, i_flatdata, sizeof(uint16_t));
331 i_flatdata += sizeof(uint16_t);
332 uint32_t bytecount = ntohs(l_tmp16);
333
334 // Read data for register.
335 BitStringBuffer bs(bytecount * 8);
336 for(uint32_t bc = 0; bc < bytecount; ++bc)
337 {
338 bs.setFieldJustify(bc*8,8,(CPU_WORD)(*(i_flatdata+bc))); //mp01a
339 }
340 i_flatdata += bytecount;
341
342 // Add to capture data.
343 Add(l_pchipHandle, regid, bs);
344 }
345 }
346
347 return *this;
348}
349
350// <-- dg08a
351
352void CaptureData::mergeData(CaptureData & i_cd)
353{
354 DataContainerType l_data = *(i_cd.getData());
355
356 if( !l_data.empty() )
357 {
358 // Remove duplicate entries from secondary capture data
359 for (ConstDataIterator i = data.begin(); i != data.end(); i++)
360 {
361 l_data.remove_if(prdfCompareCaptureDataEntry(i->chipHandle,
362 i->address) );
363 }
364
365 // Add secondary capture data to primary one
366 data.insert( data.end(),
367 l_data.begin(),
368 l_data.end() );
369 }
370}
371
372
373// copy ctor for Data class
374CaptureData::Data::Data(const Data & d):
375chipHandle(d.chipHandle), address(d.address),
Zane Shelley05bac982019-09-02 20:57:42 -0500376dataByteLength(d.dataByteLength), dataPtr(nullptr)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500377{
Zane Shelley05bac982019-09-02 20:57:42 -0500378 if(d.dataPtr != nullptr)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500379 {
380 dataPtr = new uint8_t[dataByteLength];
381
382 memcpy(dataPtr, d.dataPtr, dataByteLength);
383 }
384}
385
386CaptureData::Data & CaptureData::Data::operator=(const Data & d)
387{
388 chipHandle = d.chipHandle;
389 address = d.address;
390 dataByteLength = d.dataByteLength;
Zane Shelley05bac982019-09-02 20:57:42 -0500391 if(dataPtr != nullptr)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500392 {
393 delete[]dataPtr;
Zane Shelley05bac982019-09-02 20:57:42 -0500394 dataPtr = nullptr;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500395 }
Zane Shelley05bac982019-09-02 20:57:42 -0500396 if(d.dataPtr != nullptr)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500397 {
398 dataPtr = new uint8_t[dataByteLength];
399 memcpy(dataPtr, d.dataPtr, dataByteLength);
400 }
401
402 return *this;
403}
404
Zane Shelleyfd275a22019-09-05 23:13:59 -0500405} // end namespace libhei
Zane Shelleydd156ad2019-10-25 20:59:55 -0500406// clang-format on