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