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