1 /*
2 * \file trc_pkt_proc_etmv4i.cpp
3 * \brief OpenCSD : Packet processor for ETMv4
4 *
5 * \copyright Copyright (c) 2015, 2019, ARM Limited. All Rights Reserved.
6 */
7
8 /*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include "opencsd/etmv4/trc_pkt_proc_etmv4.h"
36 #include "common/ocsd_error.h"
37
38 #ifdef __GNUC__
39 // G++ doesn't like the ## pasting
40 #define ETMV4I_PKTS_NAME "PKTP_ETMV4I"
41 #else
42 // VC++ is fine
43 #define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I"
44 #endif
45
46 static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;
47
48 /* trace etmv4 packet processing class */
TrcPktProcEtmV4I()49 TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),
50 m_isInit(false),
51 m_first_trace_info(false)
52 {
53 m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
54 }
55
TrcPktProcEtmV4I(int instIDNum)56 TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum),
57 m_isInit(false),
58 m_first_trace_info(false)
59 {
60 m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
61 }
62
63
~TrcPktProcEtmV4I()64 TrcPktProcEtmV4I::~TrcPktProcEtmV4I()
65 {
66 }
67
onProtocolConfig()68 ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()
69 {
70 InitProcessorState();
71 m_config = *TrcPktProcBase::getProtocolConfig();
72 BuildIPacketTable(); // packet table based on config
73 m_isInit = true;
74 return OCSD_OK;
75 }
76
processData(const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)77 ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t index,
78 const uint32_t dataBlockSize,
79 const uint8_t *pDataBlock,
80 uint32_t *numBytesProcessed)
81 {
82 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
83
84 if (!m_isInit)
85 return OCSD_RESP_FATAL_NOT_INIT;
86
87 m_trcIn.init(dataBlockSize, pDataBlock, &m_currPacketData);
88 m_blockIndex = index;
89 bool done = false;
90 uint8_t nextByte;
91
92 do
93 {
94 try
95 {
96 while ( (!m_trcIn.empty() || (m_process_state == SEND_PKT)) &&
97 OCSD_DATA_RESP_IS_CONT(resp)
98 )
99 {
100 switch (m_process_state)
101 {
102 case PROC_HDR:
103 m_packet_index = m_blockIndex + m_trcIn.processed();
104 if (m_is_sync)
105 {
106 nextByte = m_trcIn.peekNextByte();
107 m_pIPktFn = m_i_table[nextByte].pptkFn;
108 m_curr_packet.type = m_i_table[nextByte].pkt_type;
109 }
110 else
111 {
112 // unsynced - process data until we see a sync point
113 m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
114 m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
115 }
116 m_process_state = PROC_DATA;
117
118 case PROC_DATA:
119 // loop till full packet or no more data...
120 while (!m_trcIn.empty() && (m_process_state == PROC_DATA))
121 {
122 nextByte = m_trcIn.peekNextByte();
123 m_trcIn.copyByteToPkt(); // move next byte into the packet
124 (this->*m_pIPktFn)(nextByte);
125 }
126 break;
127
128 case SEND_PKT:
129 resp = outputPacket();
130 InitPacketState();
131 m_process_state = PROC_HDR;
132 break;
133
134 case SEND_UNSYNCED:
135 resp = outputUnsyncedRawPacket();
136 if (m_update_on_unsync_packet_index != 0)
137 {
138 m_packet_index = m_update_on_unsync_packet_index;
139 m_update_on_unsync_packet_index = 0;
140 }
141 m_process_state = PROC_DATA; // after dumping unsynced data, still in data mode.
142 break;
143 }
144 }
145 done = true;
146 }
147 catch(ocsdError &err)
148 {
149 done = true;
150 LogError(err);
151 if( (err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) ||
152 (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR))
153 {
154 // send invalid packets up the pipe to let the next stage decide what to do.
155 m_process_state = SEND_PKT;
156 done = false;
157 }
158 else
159 {
160 // bail out on any other error.
161 resp = OCSD_RESP_FATAL_INVALID_DATA;
162 }
163 }
164 catch(...)
165 {
166 done = true;
167 /// vv bad at this point.
168 resp = OCSD_RESP_FATAL_SYS_ERR;
169 const ocsdError &fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_config.getTraceID(),"Unknown System Error decoding trace.");
170 LogError(fatal);
171 }
172 } while (!done);
173
174 *numBytesProcessed = m_trcIn.processed();
175 return resp;
176 }
177
onEOT()178 ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT()
179 {
180 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
181 if (!m_isInit)
182 return OCSD_RESP_FATAL_NOT_INIT;
183
184 // if we have a partial packet then send to attached sinks
185 if(m_currPacketData.size() != 0)
186 {
187 m_curr_packet.updateErrType(ETM4_PKT_I_INCOMPLETE_EOT);
188 resp = outputPacket();
189 InitPacketState();
190 }
191 return resp;
192 }
193
onReset()194 ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset()
195 {
196 if (!m_isInit)
197 return OCSD_RESP_FATAL_NOT_INIT;
198
199 // prepare for new decoding session
200 InitProcessorState();
201 return OCSD_RESP_CONT;
202 }
203
onFlush()204 ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush()
205 {
206 if (!m_isInit)
207 return OCSD_RESP_FATAL_NOT_INIT;
208
209 // packet processor never holds on to flushable data (may have partial packet,
210 // but any full packets are immediately sent)
211 return OCSD_RESP_CONT;
212 }
213
InitPacketState()214 void TrcPktProcEtmV4I::InitPacketState()
215 {
216 m_currPacketData.clear();
217 m_curr_packet.initNextPacket(); // clear for next packet.
218 m_update_on_unsync_packet_index = 0;
219 }
220
InitProcessorState()221 void TrcPktProcEtmV4I::InitProcessorState()
222 {
223 InitPacketState();
224 m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
225 m_packet_index = 0;
226 m_is_sync = false;
227 m_first_trace_info = false;
228 m_sent_notsync_packet = false;
229 m_process_state = PROC_HDR;
230 m_curr_packet.initStartState();
231 }
232
outputPacket()233 ocsd_datapath_resp_t TrcPktProcEtmV4I::outputPacket()
234 {
235 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
236 resp = outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData);
237 return resp;
238 }
239
outputUnsyncedRawPacket()240 ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket()
241 {
242 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
243
244
245 outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
246
247 if(!m_sent_notsync_packet)
248 {
249 resp = outputDecodedPacket(m_packet_index,&m_curr_packet);
250 m_sent_notsync_packet = true;
251 }
252
253 if(m_currPacketData.size() <= m_dump_unsynced_bytes)
254 m_currPacketData.clear();
255 else
256 m_currPacketData.erase(m_currPacketData.begin(),m_currPacketData.begin()+m_dump_unsynced_bytes);
257
258 return resp;
259 }
260
iNotSync(const uint8_t lastByte)261 void TrcPktProcEtmV4I::iNotSync(const uint8_t lastByte)
262 {
263 // is it an extension byte?
264 if (lastByte == 0x00) // TBD : add check for forced sync in here?
265 {
266 if (m_currPacketData.size() > 1)
267 {
268 m_dump_unsynced_bytes = m_currPacketData.size() - 1;
269 m_process_state = SEND_UNSYNCED;
270 // outputting some data then update packet index after so output indexes accurate
271 m_update_on_unsync_packet_index = m_blockIndex + m_trcIn.processed() - 1;
272 }
273 else
274 m_packet_index = m_blockIndex + m_trcIn.processed() - 1; // set it up now otherwise.
275
276 m_pIPktFn = m_i_table[lastByte].pptkFn;
277 }
278 else if (m_currPacketData.size() >= 8)
279 {
280 m_dump_unsynced_bytes = m_currPacketData.size();
281 m_process_state = SEND_UNSYNCED;
282 // outputting some data then update packet index after so output indexes accurate
283 m_update_on_unsync_packet_index = m_blockIndex + m_trcIn.processed();
284 }
285 }
286
iPktNoPayload(const uint8_t lastByte)287 void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)
288 {
289 // some expansion may be required...
290 switch(m_curr_packet.type)
291 {
292 case ETM4_PKT_I_ADDR_MATCH:
293 m_curr_packet.setAddressExactMatch(lastByte & 0x3);
294 break;
295
296 case ETM4_PKT_I_EVENT:
297 m_curr_packet.setEvent(lastByte & 0xF);
298 break;
299
300 case ETM4_PKT_I_NUM_DS_MKR:
301 case ETM4_PKT_I_UNNUM_DS_MKR:
302 m_curr_packet.setDataSyncMarker(lastByte & 0x7);
303 break;
304
305 // these just need the packet type - no processing required.
306 case ETM4_PKT_I_COND_FLUSH:
307 case ETM4_PKT_I_EXCEPT_RTN:
308 case ETM4_PKT_I_TRACE_ON:
309 case ETM4_PKT_I_FUNC_RET:
310 case ETM4_PKT_I_IGNORE:
311 default: break;
312 }
313 m_process_state = SEND_PKT; // now just send it....
314 }
315
iPktReserved(const uint8_t lastByte)316 void TrcPktProcEtmV4I::iPktReserved(const uint8_t lastByte)
317 {
318 m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED, lastByte); // swap type for err type
319 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR,m_packet_index,m_config.getTraceID());
320 }
321
iPktInvalidCfg(const uint8_t lastByte)322 void TrcPktProcEtmV4I::iPktInvalidCfg(const uint8_t lastByte)
323 {
324 m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED_CFG, lastByte); // swap type for err type
325 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR, m_packet_index, m_config.getTraceID());
326 }
327
iPktExtension(const uint8_t lastByte)328 void TrcPktProcEtmV4I::iPktExtension(const uint8_t lastByte)
329 {
330 if(m_currPacketData.size() == 2)
331 {
332 // not sync and not next by 0x00 - not sync sequence
333 if(!m_is_sync && (lastByte != 0x00))
334 {
335 m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
336 m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
337 return;
338 }
339
340 switch(lastByte)
341 {
342 case 0x03: // discard packet.
343 m_curr_packet.type = ETM4_PKT_I_DISCARD;
344 m_process_state = SEND_PKT;
345 break;
346
347 case 0x05:
348 m_curr_packet.type = ETM4_PKT_I_OVERFLOW;
349 m_process_state = SEND_PKT;
350 break;
351
352 case 0x00:
353 m_curr_packet.type = ETM4_PKT_I_ASYNC;
354 m_pIPktFn = &TrcPktProcEtmV4I::iPktASync; // handle subsequent bytes as async
355 break;
356
357 default:
358 m_curr_packet.err_type = m_curr_packet.type;
359 m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE;
360 m_process_state = SEND_PKT;
361 break;
362 }
363 }
364 }
365
iPktASync(const uint8_t lastByte)366 void TrcPktProcEtmV4I::iPktASync(const uint8_t lastByte)
367 {
368 if(lastByte != 0x00)
369 {
370 // not sync and not next by 0x00 - not sync sequence if < 12
371 if(!m_is_sync && m_currPacketData.size() != 12)
372 {
373 m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
374 m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
375 return;
376 }
377
378 // 12 bytes and not valid sync sequence - not possible even if not synced
379 m_process_state = SEND_PKT;
380 if((m_currPacketData.size() != 12) || (lastByte != 0x80))
381 {
382 m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE;
383 m_curr_packet.err_type = ETM4_PKT_I_ASYNC;
384 }
385 else
386 m_is_sync = true; // found a sync packet, mark decoder as synchronised.
387 }
388 else if(m_currPacketData.size() == 12)
389 {
390 if(!m_is_sync)
391 {
392 // if we are not yet synced then ignore extra leading 0x00.
393 m_dump_unsynced_bytes = 1;
394 m_process_state = SEND_UNSYNCED;
395 }
396 else
397 {
398 // bad periodic ASYNC sequence.
399 m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE;
400 m_curr_packet.err_type = ETM4_PKT_I_ASYNC;
401 m_process_state = SEND_PKT;
402 }
403 }
404 }
405
iPktTraceInfo(const uint8_t lastByte)406 void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)
407 {
408 if(m_currPacketData.size() == 1) // header
409 {
410 //clear flags
411 m_tinfo_sections.sectFlags = 0; // mark all sections as incomplete.
412 m_tinfo_sections.ctrlBytes = 1; // assume only a single control section byte for now
413
414 }
415 else if(m_currPacketData.size() == 2) // first payload control byte
416 {
417 // figure out which sections are absent and set to true - opposite of bitfeild in byte;
418 m_tinfo_sections.sectFlags = (~lastByte) & TINFO_ALL_SECT;
419
420 // see if there is an extended control section, otherwise this byte is it.
421 if((lastByte & 0x80) == 0x0)
422 m_tinfo_sections.sectFlags |= TINFO_CTRL;
423
424 }
425 else
426 {
427 if(!(m_tinfo_sections.sectFlags & TINFO_CTRL))
428 {
429 m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_CTRL;
430 m_tinfo_sections.ctrlBytes++;
431 }
432 else if(!(m_tinfo_sections.sectFlags & TINFO_INFO_SECT))
433 m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_INFO_SECT;
434 else if(!(m_tinfo_sections.sectFlags & TINFO_KEY_SECT))
435 m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_KEY_SECT;
436 else if(!(m_tinfo_sections.sectFlags & TINFO_SPEC_SECT))
437 m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_SPEC_SECT;
438 else if(!(m_tinfo_sections.sectFlags & TINFO_CYCT_SECT))
439 m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_CYCT_SECT;
440 }
441
442 // all sections accounted for?
443 if(m_tinfo_sections.sectFlags == TINFO_ALL)
444 {
445 // index of first section is number of payload control bytes + 1 for header byte
446 unsigned idx = m_tinfo_sections.ctrlBytes + 1;
447 uint32_t fieldVal = 0;
448 uint8_t presSect = m_currPacketData[1] & TINFO_ALL_SECT; // first payload control byte
449
450 m_curr_packet.clearTraceInfo();
451
452 if((presSect & TINFO_INFO_SECT) && (idx < m_currPacketData.size()))
453 {
454 idx += extractContField(m_currPacketData,idx,fieldVal);
455 m_curr_packet.setTraceInfo(fieldVal);
456 }
457 if((presSect & TINFO_KEY_SECT) && (idx < m_currPacketData.size()))
458 {
459 idx += extractContField(m_currPacketData,idx,fieldVal);
460 m_curr_packet.setTraceInfoKey(fieldVal);
461 }
462 if((presSect & TINFO_SPEC_SECT) && (idx < m_currPacketData.size()))
463 {
464 idx += extractContField(m_currPacketData,idx,fieldVal);
465 m_curr_packet.setTraceInfoSpec(fieldVal);
466 }
467 if((presSect & TINFO_CYCT_SECT) && (idx < m_currPacketData.size()))
468 {
469 idx += extractContField(m_currPacketData,idx,fieldVal);
470 m_curr_packet.setTraceInfoCyct(fieldVal);
471 }
472 m_process_state = SEND_PKT;
473 m_first_trace_info = true;
474 }
475
476 }
477
iPktTimestamp(const uint8_t lastByte)478 void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte)
479 {
480 // process the header byte
481 if(m_currPacketData.size() == 1)
482 {
483 m_ccount_done = (bool)((lastByte & 0x1) == 0); // 0 = not present
484 m_ts_done = false;
485 m_ts_bytes = 0;
486 }
487 else
488 {
489 if(!m_ts_done)
490 {
491 m_ts_bytes++;
492 m_ts_done = (m_ts_bytes == 9) || ((lastByte & 0x80) == 0);
493 }
494 else if(!m_ccount_done)
495 {
496 m_ccount_done = (bool)((lastByte & 0x80) == 0);
497 // TBD: check for oorange ccount - bad packet.
498 }
499 }
500
501 if(m_ts_done && m_ccount_done)
502 {
503 int idx = 1;
504 uint64_t tsVal;
505 int ts_bytes = extractContField64(m_currPacketData, idx, tsVal);
506 int ts_bits = ts_bytes < 7 ? ts_bytes * 7 : 64;
507
508 if(!m_curr_packet.pkt_valid.bits.ts_valid && m_first_trace_info)
509 ts_bits = 64; // after trace info, missing bits are all 0.
510
511 m_curr_packet.setTS(tsVal,(uint8_t)ts_bits);
512
513 if((m_currPacketData[0] & 0x1) == 0x1)
514 {
515 uint32_t countVal, countMask;
516
517 idx += ts_bytes;
518 extractContField(m_currPacketData, idx, countVal, 3); // only 3 possible count bytes.
519 countMask = (((uint32_t)1UL << m_config.ccSize()) - 1); // mask of the CC size
520 countVal &= countMask;
521 m_curr_packet.setCycleCount(countVal);
522 }
523
524 m_process_state = SEND_PKT;
525 }
526 }
527
iPktException(const uint8_t lastByte)528 void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)
529 {
530 uint16_t excep_type = 0;
531
532 switch(m_currPacketData.size())
533 {
534 case 1: m_excep_size = 3; break;
535 case 2: if((lastByte & 0x80) == 0x00)
536 m_excep_size = 2;
537 break;
538 }
539
540 if(m_currPacketData.size() == (unsigned)m_excep_size)
541 {
542 excep_type = (m_currPacketData[1] >> 1) & 0x1F;
543 uint8_t addr_interp = (m_currPacketData[1] & 0x40) >> 5 | (m_currPacketData[1] & 0x1);
544 uint8_t m_fault_pending = 0;
545 uint8_t m_type = (m_config.coreProfile() == profile_CortexM) ? 1 : 0;
546
547 // extended exception packet (probably M class);
548 if(m_currPacketData[1] & 0x80)
549 {
550 excep_type |= ((uint16_t)m_currPacketData[2] & 0x1F) << 5;
551 m_fault_pending = (m_currPacketData[2] >> 5) & 0x1;
552 }
553 m_curr_packet.setExceptionInfo(excep_type,addr_interp,m_fault_pending, m_type);
554 m_process_state = SEND_PKT;
555
556 // allow the standard address packet handlers to process the address packet field for the exception.
557 }
558 }
559
iPktCycleCntF123(const uint8_t lastByte)560 void TrcPktProcEtmV4I::iPktCycleCntF123(const uint8_t lastByte)
561 {
562 ocsd_etmv4_i_pkt_type format = m_curr_packet.type;
563
564 if( m_currPacketData.size() == 1)
565 {
566 m_count_done = m_commit_done = false;
567 m_has_count = true;
568
569 if(format == ETM4_PKT_I_CCNT_F3)
570 {
571 // no commit section for TRCIDR0.COMMOPT == 1
572 if(!m_config.commitOpt1())
573 {
574 m_curr_packet.setCommitElements(((lastByte >> 2) & 0x3) + 1);
575 }
576 // TBD: warning of non-valid CC threshold here?
577 m_curr_packet.setCycleCount(m_curr_packet.getCCThreshold() + (lastByte & 0x3));
578 m_process_state = SEND_PKT;
579 }
580 else if(format == ETM4_PKT_I_CCNT_F1)
581 {
582 if((lastByte & 0x1) == 0x1)
583 {
584 m_has_count = false;
585 m_count_done = true;
586 }
587
588 // no commit section for TRCIDR0.COMMOPT == 1
589 if(m_config.commitOpt1())
590 m_commit_done = true;
591 }
592 }
593 else if((format == ETM4_PKT_I_CCNT_F2) && ( m_currPacketData.size() == 2))
594 {
595 int commit_offset = ((lastByte & 0x1) == 0x1) ? ((int)m_config.MaxSpecDepth() - 15) : 1;
596 int commit_elements = ((lastByte >> 4) & 0xF);
597 commit_elements += commit_offset;
598
599 // TBD: warning if commit elements < 0?
600
601 m_curr_packet.setCycleCount(m_curr_packet.getCCThreshold() + (lastByte & 0xF));
602 m_curr_packet.setCommitElements(commit_elements);
603 m_process_state = SEND_PKT;
604 }
605 else
606 {
607 // F1 and size 2 or more
608 if(!m_commit_done)
609 m_commit_done = ((lastByte & 0x80) == 0x00);
610 else if(!m_count_done)
611 m_count_done = ((lastByte & 0x80) == 0x00);
612 }
613
614 if((format == ETM4_PKT_I_CCNT_F1) && m_commit_done && m_count_done)
615 {
616 int idx = 1; // index into buffer for payload data.
617 uint32_t field_value = 0;
618 // no commit section for TRCIDR0.COMMOPT == 1
619 if(!m_config.commitOpt1())
620 {
621 idx += extractContField(m_currPacketData,idx,field_value);
622 m_curr_packet.setCommitElements(field_value);
623 }
624 if (m_has_count)
625 {
626 extractContField(m_currPacketData, idx, field_value, 3);
627 m_curr_packet.setCycleCount(field_value + m_curr_packet.getCCThreshold());
628 }
629 else
630 m_curr_packet.setCycleCount(0); /* unknown CC marked as 0 after overflow */
631 m_process_state = SEND_PKT;
632 }
633 }
634
iPktSpeclRes(const uint8_t lastByte)635 void TrcPktProcEtmV4I::iPktSpeclRes(const uint8_t lastByte)
636 {
637 if(m_currPacketData.size() == 1)
638 {
639 switch(m_curr_packet.getType())
640 {
641 case ETM4_PKT_I_MISPREDICT:
642 case ETM4_PKT_I_CANCEL_F2:
643 switch(lastByte & 0x3)
644 {
645 case 0x1: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x1, 1); break; // E
646 case 0x2: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x3, 2); break; // EE
647 case 0x3: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x0, 1); break; // N
648 }
649 if (m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2)
650 m_curr_packet.setCancelElements(1);
651 else
652 m_curr_packet.setCancelElements(0);
653 m_process_state = SEND_PKT;
654 break;
655
656 case ETM4_PKT_I_CANCEL_F3:
657 if(lastByte & 0x1)
658 m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x1, 1); // E
659 m_curr_packet.setCancelElements(((lastByte >> 1) & 0x3) + 2);
660 m_process_state = SEND_PKT;
661 break;
662 }
663 }
664 else
665 {
666 if((lastByte & 0x80) == 0x00)
667 {
668 uint32_t field_val = 0;
669 extractContField(m_currPacketData,1,field_val);
670 if(m_curr_packet.getType() == ETM4_PKT_I_COMMIT)
671 m_curr_packet.setCommitElements(field_val);
672 else
673 m_curr_packet.setCancelElements(field_val);
674 m_process_state = SEND_PKT;
675 }
676 }
677 }
678
iPktCondInstr(const uint8_t lastByte)679 void TrcPktProcEtmV4I::iPktCondInstr(const uint8_t lastByte)
680 {
681 bool bF1Done = false;
682
683 if(m_currPacketData.size() == 1)
684 {
685 if(m_curr_packet.getType() == ETM4_PKT_I_COND_I_F2)
686 {
687 m_curr_packet.setCondIF2(lastByte & 0x3);
688 m_process_state = SEND_PKT;
689 }
690
691 }
692 else if(m_currPacketData.size() == 2)
693 {
694 if(m_curr_packet.getType() == ETM4_PKT_I_COND_I_F3) // f3 two bytes long
695 {
696 uint8_t num_c_elem = ((lastByte >> 1) & 0x3F) + (lastByte & 0x1);
697 m_curr_packet.setCondIF3(num_c_elem,(bool)((lastByte & 0x1) == 0x1));
698 // TBD: check for 0 num_c_elem in here.
699 m_process_state = SEND_PKT;
700 }
701 else
702 {
703 bF1Done = ((lastByte & 0x80) == 0x00);
704 }
705 }
706 else
707 {
708 bF1Done = ((lastByte & 0x80) == 0x00);
709 }
710
711 if(bF1Done)
712 {
713 uint32_t cond_key = 0;
714 extractContField(m_currPacketData, 1, cond_key);
715 m_process_state = SEND_PKT;
716 }
717 }
718
iPktCondResult(const uint8_t lastByte)719 void TrcPktProcEtmV4I::iPktCondResult(const uint8_t lastByte)
720 {
721 if(m_currPacketData.size() == 1)
722 {
723 m_F1P1_done = false; // F1 payload 1 done
724 m_F1P2_done = false; // F1 payload 2 done
725 m_F1has_P2 = false; // F1 has a payload 2
726
727 switch(m_curr_packet.getType())
728 {
729 case ETM4_PKT_I_COND_RES_F1:
730
731 m_F1has_P2 = true;
732 if((lastByte & 0xFC) == 0x6C)// only one payload set
733 {
734 m_F1P2_done = true;
735 m_F1has_P2 = false;
736 }
737 break;
738
739 case ETM4_PKT_I_COND_RES_F2:
740 m_curr_packet.setCondRF2((lastByte & 0x4) ? 2 : 1, lastByte & 0x3);
741 m_process_state = SEND_PKT;
742 break;
743
744 case ETM4_PKT_I_COND_RES_F3:
745 break;
746
747 case ETM4_PKT_I_COND_RES_F4:
748 m_curr_packet.setCondRF4(lastByte & 0x3);
749 m_process_state = SEND_PKT;
750 break;
751 }
752 }
753 else if((m_curr_packet.getType() == ETM4_PKT_I_COND_RES_F3) && (m_currPacketData.size() == 2))
754 {
755 // 2nd F3 packet
756 uint16_t f3_tokens = 0;
757 f3_tokens = (uint16_t)m_currPacketData[1];
758 f3_tokens |= ((uint16_t)m_currPacketData[0] & 0xf) << 8;
759 m_curr_packet.setCondRF3(f3_tokens);
760 m_process_state = SEND_PKT;
761 }
762 else // !first packet - F1
763 {
764 if(!m_F1P1_done)
765 m_F1P1_done = ((lastByte & 0x80) == 0x00);
766 else if(!m_F1P2_done)
767 m_F1P2_done = ((lastByte & 0x80) == 0x00);
768
769 if(m_F1P1_done && m_F1P2_done)
770 {
771 int st_idx = 1;
772 uint32_t key[2];
773 uint8_t result[2];
774 uint8_t CI[2];
775
776 st_idx+= extractCondResult(m_currPacketData,st_idx,key[0],result[0]);
777 CI[0] = m_currPacketData[0] & 0x1;
778 if(m_F1has_P2) // 2nd payload?
779 {
780 extractCondResult(m_currPacketData,st_idx,key[1],result[1]);
781 CI[1] = (m_currPacketData[0] >> 1) & 0x1;
782 }
783 m_curr_packet.setCondRF1(key,result,CI,m_F1has_P2);
784 m_process_state = SEND_PKT;
785 }
786 }
787 }
788
iPktContext(const uint8_t lastByte)789 void TrcPktProcEtmV4I::iPktContext(const uint8_t lastByte)
790 {
791 bool bSendPacket = false;
792
793 if(m_currPacketData.size() == 1)
794 {
795 if((lastByte & 0x1) == 0)
796 {
797 m_curr_packet.setContextInfo(false); // no update context packet (ctxt same as last time).
798 m_process_state = SEND_PKT;
799 }
800 }
801 else if(m_currPacketData.size() == 2)
802 {
803 if((lastByte & 0xC0) == 0) // no VMID or CID
804 {
805 bSendPacket = true;
806 }
807 else
808 {
809 m_vmidBytes = ((lastByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0;
810 m_ctxtidBytes = ((lastByte & 0x80) == 0x80) ? (m_config.cidSize()/8) : 0;
811 }
812 }
813 else // 3rd byte onwards
814 {
815 if(m_vmidBytes > 0)
816 m_vmidBytes--;
817 else if(m_ctxtidBytes > 0)
818 m_ctxtidBytes--;
819
820 if((m_ctxtidBytes == 0) && (m_vmidBytes == 0))
821 bSendPacket = true;
822 }
823
824 if(bSendPacket)
825 {
826 extractAndSetContextInfo(m_currPacketData,1);
827 m_process_state = SEND_PKT;
828 }
829 }
830
extractAndSetContextInfo(const std::vector<uint8_t> & buffer,const int st_idx)831 void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx)
832 {
833 // on input, buffer index points at the info byte - always present
834 uint8_t infoByte = m_currPacketData[st_idx];
835
836 m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1);
837
838 // see if there are VMID and CID bytes, and how many.
839 int nVMID_bytes = ((infoByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0;
840 int nCtxtID_bytes = ((infoByte & 0x80) == 0x80) ? (m_config.cidSize()/8) : 0;
841
842 // extract any VMID and CID
843 int payload_idx = st_idx+1;
844 if(nVMID_bytes)
845 {
846 uint32_t VMID = 0;
847 for(int i = 0; i < nVMID_bytes; i++)
848 {
849 VMID |= ((uint32_t)m_currPacketData[i+payload_idx] << i*8);
850 }
851 payload_idx += nVMID_bytes;
852 m_curr_packet.setContextVMID(VMID);
853 }
854
855 if(nCtxtID_bytes)
856 {
857 uint32_t CID = 0;
858 for(int i = 0; i < nCtxtID_bytes; i++)
859 {
860 CID |= ((uint32_t)m_currPacketData[i+payload_idx] << i*8);
861 }
862 m_curr_packet.setContextCID(CID);
863 }
864 }
865
iPktAddrCtxt(const uint8_t lastByte)866 void TrcPktProcEtmV4I::iPktAddrCtxt(const uint8_t lastByte)
867 {
868 if( m_currPacketData.size() == 1)
869 {
870 m_addrIS = 0;
871 m_addrBytes = 4;
872 m_bAddr64bit = false;
873 m_vmidBytes = 0;
874 m_ctxtidBytes = 0;
875 m_bCtxtInfoDone = false;
876
877 switch(m_curr_packet.type)
878 {
879 case ETM4_PKT_I_ADDR_CTXT_L_32IS1:
880 m_addrIS = 1;
881 case ETM4_PKT_I_ADDR_CTXT_L_32IS0:
882 break;
883
884 case ETM4_PKT_I_ADDR_CTXT_L_64IS1:
885 m_addrIS = 1;
886 case ETM4_PKT_I_ADDR_CTXT_L_64IS0:
887 m_addrBytes = 8;
888 m_bAddr64bit = true;
889 break;
890 }
891 }
892 else
893 {
894 if(m_addrBytes == 0)
895 {
896 if(m_bCtxtInfoDone == false)
897 {
898 m_bCtxtInfoDone = true;
899 m_vmidBytes = ((lastByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0;
900 m_ctxtidBytes = ((lastByte & 0x80) == 0x80) ? (m_config.cidSize()/8) : 0;
901 }
902 else
903 {
904 if( m_vmidBytes > 0)
905 m_vmidBytes--;
906 else if(m_ctxtidBytes > 0)
907 m_ctxtidBytes--;
908 }
909 }
910 else
911 m_addrBytes--;
912
913 if((m_addrBytes == 0) && m_bCtxtInfoDone && (m_vmidBytes == 0) && (m_ctxtidBytes == 0))
914 {
915 int st_idx = 1;
916 if(m_bAddr64bit)
917 {
918 uint64_t val64;
919 st_idx+=extract64BitLongAddr(m_currPacketData,st_idx,m_addrIS,val64);
920 m_curr_packet.set64BitAddress(val64,m_addrIS);
921 }
922 else
923 {
924 uint32_t val32;
925 st_idx+=extract32BitLongAddr(m_currPacketData,st_idx,m_addrIS,val32);
926 m_curr_packet.set32BitAddress(val32,m_addrIS);
927 }
928 extractAndSetContextInfo(m_currPacketData,st_idx);
929 m_process_state = SEND_PKT;
930 }
931 }
932 }
933
iPktShortAddr(const uint8_t lastByte)934 void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte)
935 {
936 if (m_currPacketData.size() == 1)
937 {
938 m_addr_done = false;
939 m_addrIS = 0;
940 if (lastByte == ETM4_PKT_I_ADDR_S_IS1)
941 m_addrIS = 1;
942 }
943 else if(!m_addr_done)
944 {
945 m_addr_done = (m_currPacketData.size() == 3) || ((lastByte & 0x80) == 0x00);
946 }
947
948 if(m_addr_done)
949 {
950 uint32_t addr_val = 0;
951 int bits = 0;
952
953 extractShortAddr(m_currPacketData,1,m_addrIS,addr_val,bits);
954 m_curr_packet.updateShortAddress(addr_val,m_addrIS,(uint8_t)bits);
955 m_process_state = SEND_PKT;
956 }
957 }
958
extractShortAddr(const std::vector<uint8_t> & buffer,const int st_idx,const uint8_t IS,uint32_t & value,int & bits)959 int TrcPktProcEtmV4I::extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits)
960 {
961 int IS_shift = (IS == 0) ? 2 : 1;
962 int idx = 0;
963
964 bits = 7; // at least 7 bits
965 value = 0;
966 value |= ((uint32_t)(buffer[st_idx+idx] & 0x7F)) << IS_shift;
967
968 if(m_currPacketData[st_idx+idx] & 0x80)
969 {
970 idx++;
971 value |= ((uint32_t)m_currPacketData[st_idx+idx]) << (7 + IS_shift);
972 bits += 8;
973 }
974 idx++;
975 bits += IS_shift;
976 return idx;
977 }
978
iPktLongAddr(const uint8_t lastByte)979 void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte)
980 {
981 if(m_currPacketData.size() == 1)
982 {
983 // init the intra-byte data
984 m_addrIS = 0;
985 m_bAddr64bit = false;
986 m_addrBytes = 4;
987
988 switch(m_curr_packet.type)
989 {
990 case ETM4_PKT_I_ADDR_L_32IS1:
991 m_addrIS = 1;
992 case ETM4_PKT_I_ADDR_L_32IS0:
993 m_addrBytes = 4;
994 break;
995
996 case ETM4_PKT_I_ADDR_L_64IS1:
997 m_addrIS = 1;
998 case ETM4_PKT_I_ADDR_L_64IS0:
999 m_addrBytes = 8;
1000 m_bAddr64bit = true;
1001 break;
1002 }
1003 }
1004 if(m_currPacketData.size() == (unsigned)(1+m_addrBytes))
1005 {
1006 int st_idx = 1;
1007 if(m_bAddr64bit)
1008 {
1009 uint64_t val64;
1010 st_idx+=extract64BitLongAddr(m_currPacketData,st_idx,m_addrIS,val64);
1011 m_curr_packet.set64BitAddress(val64,m_addrIS);
1012 }
1013 else
1014 {
1015 uint32_t val32;
1016 st_idx+=extract32BitLongAddr(m_currPacketData,st_idx,m_addrIS,val32);
1017 m_curr_packet.set32BitAddress(val32,m_addrIS);
1018 }
1019 m_process_state = SEND_PKT;
1020 }
1021 }
1022
iPktQ(const uint8_t lastByte)1023 void TrcPktProcEtmV4I::iPktQ(const uint8_t lastByte)
1024 {
1025 if(m_currPacketData.size() == 1)
1026 {
1027 m_Q_type = lastByte & 0xF;
1028
1029 m_addrBytes = 0;
1030 m_count_done = false;
1031 m_has_addr = false;
1032 m_addr_short = true;
1033 m_addr_match = false;
1034 m_addrIS = 1;
1035 m_QE = 0;
1036
1037 switch(m_Q_type)
1038 {
1039 // count only - implied address.
1040 case 0x0:
1041 case 0x1:
1042 case 0x2:
1043 m_addr_match = true;
1044 m_has_addr = true;
1045 m_QE = m_Q_type & 0x3;
1046 case 0xC:
1047 break;
1048
1049 // count + short address
1050 case 0x5:
1051 m_addrIS = 0;
1052 case 0x6:
1053 m_has_addr = true;
1054 m_addrBytes = 2; // short IS0/1
1055 break;
1056
1057 // count + long address
1058 case 0xA:
1059 m_addrIS = 0;
1060 case 0xB:
1061 m_has_addr = true;
1062 m_addr_short = false;
1063 m_addrBytes = 4; // long IS0/1
1064 break;
1065
1066 // no count, no address
1067 case 0xF:
1068 m_count_done = true;
1069 break;
1070
1071 // reserved values 0x3, 0x4, 0x7, 0x8, 0x9, 0xD, 0xE
1072 default:
1073 m_curr_packet.err_type = m_curr_packet.type;
1074 m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE;
1075 //SendBadIPacket( PKT_BAD_SEQUENCE, "ERROR: Bad Q packet type", PKT_Q );
1076 break;
1077 }
1078 }
1079 else
1080 {
1081 if(m_addrBytes > 0)
1082 {
1083 if(m_addr_short && m_addrBytes == 2) // short
1084 {
1085 if((lastByte & 0x80) == 0x00)
1086 m_addrBytes--; // short version can have just single byte.
1087 }
1088 m_addrBytes--;
1089 }
1090 else if(!m_count_done)
1091 {
1092 m_count_done = ((lastByte & 0x80) == 0x00);
1093 }
1094 }
1095
1096 if(((m_addrBytes == 0) && m_count_done))
1097 {
1098 int idx = 1; // move past the header
1099 int bits = 0;
1100 uint32_t q_addr;
1101 uint32_t q_count;
1102
1103 if(m_has_addr)
1104 {
1105 if(m_addr_match)
1106 {
1107 m_curr_packet.setAddressExactMatch(m_QE);
1108 }
1109 else if(m_addr_short)
1110 {
1111 idx+=extractShortAddr(m_currPacketData,idx,m_addrIS,q_addr,bits);
1112 m_curr_packet.updateShortAddress(q_addr,m_addrIS,(uint8_t)bits);
1113 }
1114 else
1115 {
1116 idx+=extract32BitLongAddr(m_currPacketData,idx,m_addrIS,q_addr);
1117 m_curr_packet.set32BitAddress(q_addr,m_addrIS);
1118 }
1119 }
1120
1121 if(m_Q_type != 0xF)
1122 {
1123 extractContField(m_currPacketData,idx,q_count);
1124 m_curr_packet.setQType(true,q_count,m_has_addr,m_addr_match,m_Q_type);
1125 }
1126 else
1127 {
1128 m_curr_packet.setQType(false,0,false,false,0xF);
1129 }
1130 m_process_state = SEND_PKT;
1131 }
1132
1133 }
1134
iAtom(const uint8_t lastByte)1135 void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte)
1136 {
1137 // patterns lsbit = oldest atom, ms bit = newest.
1138 static const uint32_t f4_patterns[] = {
1139 0xE, // EEEN
1140 0x0, // NNNN
1141 0xA, // ENEN
1142 0x5 // NENE
1143 };
1144
1145 uint8_t pattIdx = 0, pattCount = 0;
1146 uint32_t pattern;
1147
1148 // atom packets are single byte, no payload.
1149 switch(m_curr_packet.type)
1150 {
1151 case ETM4_PKT_I_ATOM_F1:
1152 m_curr_packet.setAtomPacket(ATOM_PATTERN,(lastByte & 0x1), 1); // 1xE or N
1153 break;
1154
1155 case ETM4_PKT_I_ATOM_F2:
1156 m_curr_packet.setAtomPacket(ATOM_PATTERN,(lastByte & 0x3), 2); // 2x (E or N)
1157 break;
1158
1159 case ETM4_PKT_I_ATOM_F3:
1160 m_curr_packet.setAtomPacket(ATOM_PATTERN,(lastByte & 0x7), 3); // 3x (E or N)
1161 break;
1162
1163 case ETM4_PKT_I_ATOM_F4:
1164 m_curr_packet.setAtomPacket(ATOM_PATTERN,f4_patterns[(lastByte & 0x3)], 4); // 4 atom pattern
1165 break;
1166
1167 case ETM4_PKT_I_ATOM_F5:
1168 pattIdx = ((lastByte & 0x20) >> 3) | (lastByte & 0x3);
1169 switch(pattIdx)
1170 {
1171 case 5: // 0b101
1172 m_curr_packet.setAtomPacket(ATOM_PATTERN,0x1E, 5); // 5 atom pattern EEEEN
1173 break;
1174
1175 case 1: // 0b001
1176 m_curr_packet.setAtomPacket(ATOM_PATTERN,0x00, 5); // 5 atom pattern NNNNN
1177 break;
1178
1179 case 2: //0b010
1180 m_curr_packet.setAtomPacket(ATOM_PATTERN,0x0A, 5); // 5 atom pattern NENEN
1181 break;
1182
1183 case 3: //0b011
1184 m_curr_packet.setAtomPacket(ATOM_PATTERN,0x15, 5); // 5 atom pattern ENENE
1185 break;
1186
1187 default:
1188 // TBD: warn about invalid pattern in here.
1189 break;
1190 }
1191 break;
1192
1193 case ETM4_PKT_I_ATOM_F6:
1194 pattCount = (lastByte & 0x1F) + 3; // count of E's
1195 // TBD: check 23 or less at this point?
1196 pattern = ((uint32_t)0x1 << pattCount) - 1; // set pattern to string of E's
1197 if((lastByte & 0x20) == 0x00) // last atom is E?
1198 pattern |= ((uint32_t)0x1 << pattCount);
1199 m_curr_packet.setAtomPacket(ATOM_PATTERN,pattern, pattCount+1);
1200 break;
1201 }
1202
1203 m_process_state = SEND_PKT;
1204 }
1205
1206 // header byte processing is table driven.
BuildIPacketTable()1207 void TrcPktProcEtmV4I::BuildIPacketTable()
1208 {
1209 // initialise everything as reserved.
1210 for(int i = 0; i < 256; i++)
1211 {
1212 m_i_table[i].pkt_type = ETM4_PKT_I_RESERVED;
1213 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iPktReserved;
1214 }
1215
1216 // 0x00 - extension
1217 m_i_table[0x00].pkt_type = ETM4_PKT_I_EXTENSION;
1218 m_i_table[0x00].pptkFn = &TrcPktProcEtmV4I::iPktExtension;
1219
1220 // 0x01 - Trace info
1221 m_i_table[0x01].pkt_type = ETM4_PKT_I_TRACE_INFO;
1222 m_i_table[0x01].pptkFn = &TrcPktProcEtmV4I::iPktTraceInfo;
1223
1224 // b0000001x - timestamp
1225 m_i_table[0x02].pkt_type = ETM4_PKT_I_TIMESTAMP;
1226 m_i_table[0x02].pptkFn = &TrcPktProcEtmV4I::iPktTimestamp;
1227 m_i_table[0x03].pkt_type = ETM4_PKT_I_TIMESTAMP;
1228 m_i_table[0x03].pptkFn = &TrcPktProcEtmV4I::iPktTimestamp;
1229
1230 // b0000 0100 - trace on
1231 m_i_table[0x04].pkt_type = ETM4_PKT_I_TRACE_ON;
1232 m_i_table[0x04].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1233
1234
1235 // b0000 0101 - Funct ret V8M
1236 m_i_table[0x05].pkt_type = ETM4_PKT_I_FUNC_RET;
1237 if ((m_config.coreProfile() == profile_CortexM) &&
1238 (OCSD_IS_V8_ARCH(m_config.archVersion())) &&
1239 (m_config.FullVersion() >= 0x42))
1240 {
1241 m_i_table[0x05].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1242 }
1243
1244 // b0000 0110 - exception
1245 m_i_table[0x06].pkt_type = ETM4_PKT_I_EXCEPT;
1246 m_i_table[0x06].pptkFn = &TrcPktProcEtmV4I::iPktException;
1247
1248 // b0000 0111 - exception return
1249 m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN;
1250 m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1251
1252 // b0000 110x - cycle count f2
1253 // b0000 111x - cycle count f1
1254 for(int i = 0; i < 4; i++)
1255 {
1256 m_i_table[0x0C+i].pkt_type = (i >= 2) ? ETM4_PKT_I_CCNT_F1 : ETM4_PKT_I_CCNT_F2;
1257 m_i_table[0x0C+i].pptkFn = &TrcPktProcEtmV4I::iPktCycleCntF123;
1258 }
1259
1260 // b0001 xxxx - cycle count f3
1261 for(int i = 0; i < 16; i++)
1262 {
1263 m_i_table[0x10+i].pkt_type = ETM4_PKT_I_CCNT_F3;
1264 m_i_table[0x10+i].pptkFn = &TrcPktProcEtmV4I::iPktCycleCntF123;
1265 }
1266
1267 // b0010 0xxx - NDSM
1268 for(int i = 0; i < 8; i++)
1269 {
1270 m_i_table[0x20 + i].pkt_type = ETM4_PKT_I_NUM_DS_MKR;
1271 if (m_config.enabledDataTrace())
1272 m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1273 else
1274 m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1275 }
1276
1277 // b0010 10xx, b0010 1100 - UDSM
1278 for(int i = 0; i < 5; i++)
1279 {
1280 m_i_table[0x28+i].pkt_type = ETM4_PKT_I_UNNUM_DS_MKR;
1281 if (m_config.enabledDataTrace())
1282 m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1283 else
1284 m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1285 }
1286
1287 // b0010 1101 - commit
1288 m_i_table[0x2D].pkt_type = ETM4_PKT_I_COMMIT;
1289 m_i_table[0x2D].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1290
1291 // b0010 111x - cancel f1 (mis pred)
1292 m_i_table[0x2E].pkt_type = ETM4_PKT_I_CANCEL_F1;
1293 m_i_table[0x2E].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1294 m_i_table[0x2F].pkt_type = ETM4_PKT_I_CANCEL_F1_MISPRED;
1295 m_i_table[0x2F].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1296
1297 // b0011 00xx - mis predict
1298 for(int i = 0; i < 4; i++)
1299 {
1300 m_i_table[0x30+i].pkt_type = ETM4_PKT_I_MISPREDICT;
1301 m_i_table[0x30+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1302 }
1303
1304 // b0011 01xx - cancel f2
1305 for(int i = 0; i < 4; i++)
1306 {
1307 m_i_table[0x34+i].pkt_type = ETM4_PKT_I_CANCEL_F2;
1308 m_i_table[0x34+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1309 }
1310
1311 // b0011 1xxx - cancel f3
1312 for(int i = 0; i < 8; i++)
1313 {
1314 m_i_table[0x38+i].pkt_type = ETM4_PKT_I_CANCEL_F3;
1315 m_i_table[0x38+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
1316 }
1317
1318 bool bCondValid = m_config.hasCondTrace() && m_config.enabledCondITrace();
1319
1320 // b0100 000x, b0100 0010 - cond I f2
1321 for (int i = 0; i < 3; i++)
1322 {
1323 m_i_table[0x40 + i].pkt_type = ETM4_PKT_I_COND_I_F2;
1324 if (bCondValid)
1325 m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
1326 else
1327 m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1328 }
1329
1330 // b0100 0011 - cond flush
1331 m_i_table[0x43].pkt_type = ETM4_PKT_I_COND_FLUSH;
1332 if (bCondValid)
1333 m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1334 else
1335 m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1336
1337 // b0100 010x, b0100 0110 - cond res f4
1338 for (int i = 0; i < 3; i++)
1339 {
1340 m_i_table[0x44 + i].pkt_type = ETM4_PKT_I_COND_RES_F4;
1341 if (bCondValid)
1342 m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1343 else
1344 m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1345 }
1346
1347 // b0100 100x, b0100 0110 - cond res f2
1348 // b0100 110x, b0100 1110 - cond res f2
1349 for (int i = 0; i < 3; i++)
1350 {
1351 m_i_table[0x48 + i].pkt_type = ETM4_PKT_I_COND_RES_F2;
1352 if (bCondValid)
1353 m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1354 else
1355 m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1356 }
1357 for (int i = 0; i < 3; i++)
1358 {
1359 m_i_table[0x4C + i].pkt_type = ETM4_PKT_I_COND_RES_F2;
1360 if (bCondValid)
1361 m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1362 else
1363 m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1364 }
1365
1366 // b0101xxxx - cond res f3
1367 for (int i = 0; i < 16; i++)
1368 {
1369 m_i_table[0x50 + i].pkt_type = ETM4_PKT_I_COND_RES_F3;
1370 if (bCondValid)
1371 m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1372 else
1373 m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1374 }
1375
1376 // b011010xx - cond res f1
1377 for (int i = 0; i < 4; i++)
1378 {
1379 m_i_table[0x68 + i].pkt_type = ETM4_PKT_I_COND_RES_F1;
1380 if (bCondValid)
1381 m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1382 else
1383 m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1384 }
1385
1386 // b0110 1100 - cond instr f1
1387 m_i_table[0x6C].pkt_type = ETM4_PKT_I_COND_I_F1;
1388 if (bCondValid)
1389 m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
1390 else
1391 m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1392
1393 // b0110 1101 - cond instr f3
1394 m_i_table[0x6D].pkt_type = ETM4_PKT_I_COND_I_F3;
1395 if (bCondValid)
1396 m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
1397 else
1398 m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1399
1400 // b0110111x - cond res f1
1401 for (int i = 0; i < 2; i++)
1402 {
1403 // G++ cannot understand [0x6E+i] so change these round
1404 m_i_table[i + 0x6E].pkt_type = ETM4_PKT_I_COND_RES_F1;
1405 if (bCondValid)
1406 m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
1407 else
1408 m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
1409 }
1410
1411 // ETM 4.3 introduces ignore packets
1412 if (m_config.FullVersion() >= 0x43)
1413 {
1414 m_i_table[0x70].pkt_type = ETM4_PKT_I_IGNORE;
1415 m_i_table[0x70].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1416 }
1417
1418 // b01110001 - b01111111 - event trace
1419 for(int i = 0; i < 15; i++)
1420 {
1421 m_i_table[0x71+i].pkt_type = ETM4_PKT_I_EVENT;
1422 m_i_table[0x71+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1423 }
1424
1425 // 0b1000 000x - context
1426 for(int i = 0; i < 2; i++)
1427 {
1428 m_i_table[0x80+i].pkt_type = ETM4_PKT_I_CTXT;
1429 m_i_table[0x80+i].pptkFn = &TrcPktProcEtmV4I::iPktContext;
1430 }
1431
1432 // 0b1000 0010 to b1000 0011 - addr with ctxt
1433 // 0b1000 0101 to b1000 0110 - addr with ctxt
1434 for(int i = 0; i < 2; i++)
1435 {
1436 m_i_table[0x82+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_32IS0 : ETM4_PKT_I_ADDR_CTXT_L_32IS1;
1437 m_i_table[0x82+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt;
1438 }
1439
1440 for(int i = 0; i < 2; i++)
1441 {
1442 m_i_table[0x85+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_64IS0 : ETM4_PKT_I_ADDR_CTXT_L_64IS1;
1443 m_i_table[0x85+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt;
1444 }
1445
1446 // 0b1001 0000 to b1001 0010 - exact match addr
1447 for(int i = 0; i < 3; i++)
1448 {
1449 m_i_table[0x90+i].pkt_type = ETM4_PKT_I_ADDR_MATCH;
1450 m_i_table[0x90+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
1451 }
1452
1453 // b1001 0101 - b1001 0110 - addr short address
1454 for(int i = 0; i < 2; i++)
1455 {
1456 m_i_table[0x95+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_S_IS0 : ETM4_PKT_I_ADDR_S_IS1;
1457 m_i_table[0x95+i].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr;
1458 }
1459
1460 // b10011010 - b10011011 - addr long address
1461 // b10011101 - b10011110 - addr long address
1462 for(int i = 0; i < 2; i++)
1463 {
1464 m_i_table[0x9A+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_L_32IS0 : ETM4_PKT_I_ADDR_L_32IS1;
1465 m_i_table[0x9A+i].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
1466 }
1467 for(int i = 0; i < 2; i++)
1468 {
1469 m_i_table[0x9D+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_L_64IS0 : ETM4_PKT_I_ADDR_L_64IS1;
1470 m_i_table[0x9D+i].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
1471 }
1472
1473 // b1010xxxx - Q packet
1474 for (int i = 0; i < 16; i++)
1475 {
1476 m_i_table[0xA0 + i].pkt_type = ETM4_PKT_I_Q;
1477 // certain Q type codes are reserved.
1478 switch (i) {
1479 case 0x3:
1480 case 0x4:
1481 case 0x7:
1482 case 0x8:
1483 case 0x9:
1484 case 0xD:
1485 case 0xE:
1486 // don't update pkt fn - leave at default reserved.
1487 break;
1488 default:
1489 // if this config supports Q elem - otherwise reserved again.
1490 if (m_config.hasQElem())
1491 m_i_table[0xA0 + i].pptkFn = &TrcPktProcEtmV4I::iPktQ;
1492 }
1493 }
1494
1495 // Atom Packets - all no payload but have specific pattern generation fn
1496 for(int i = 0xC0; i <= 0xD4; i++) // atom f6
1497 {
1498 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6;
1499 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1500 }
1501 for(int i = 0xD5; i <= 0xD7; i++) // atom f5
1502 {
1503 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F5;
1504 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1505 }
1506 for(int i = 0xD8; i <= 0xDB; i++) // atom f2
1507 {
1508 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F2;
1509 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1510 }
1511 for(int i = 0xDC; i <= 0xDF; i++) // atom f4
1512 {
1513 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F4;
1514 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1515 }
1516 for(int i = 0xE0; i <= 0xF4; i++) // atom f6
1517 {
1518 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6;
1519 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1520 }
1521
1522 // atom f5
1523 m_i_table[0xF5].pkt_type = ETM4_PKT_I_ATOM_F5;
1524 m_i_table[0xF5].pptkFn = &TrcPktProcEtmV4I::iAtom;
1525
1526 for(int i = 0xF6; i <= 0xF7; i++) // atom f1
1527 {
1528 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F1;
1529 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1530 }
1531 for(int i = 0xF8; i <= 0xFF; i++) // atom f3
1532 {
1533 m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F3;
1534 m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom;
1535 }
1536 }
1537
extractContField(const std::vector<uint8_t> & buffer,const unsigned st_idx,uint32_t & value,const unsigned byte_limit)1538 unsigned TrcPktProcEtmV4I::extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/)
1539 {
1540 unsigned idx = 0;
1541 bool lastByte = false;
1542 uint8_t byteVal;
1543 value = 0;
1544 while(!lastByte && (idx < byte_limit)) // max 5 bytes for 32 bit value;
1545 {
1546 if(buffer.size() > (st_idx + idx))
1547 {
1548 // each byte has seven bits + cont bit
1549 byteVal = buffer[(st_idx + idx)];
1550 lastByte = (byteVal & 0x80) != 0x80;
1551 value |= ((uint32_t)(byteVal & 0x7F)) << (idx * 7);
1552 idx++;
1553 }
1554 else
1555 {
1556 throwBadSequenceError("Invalid 32 bit continuation fields in packet");
1557 }
1558 }
1559 return idx;
1560 }
1561
extractContField64(const std::vector<uint8_t> & buffer,const unsigned st_idx,uint64_t & value,const unsigned byte_limit)1562 unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/)
1563 {
1564 unsigned idx = 0;
1565 bool lastByte = false;
1566 uint8_t byteVal;
1567 value = 0;
1568 while(!lastByte && (idx < byte_limit)) // max 9 bytes for 64 bit value;
1569 {
1570 if(buffer.size() > (st_idx + idx))
1571 {
1572 // each byte has seven bits + cont bit
1573 byteVal = buffer[(st_idx + idx)];
1574 lastByte = (byteVal & 0x80) != 0x80;
1575 value |= ((uint64_t)(byteVal & 0x7F)) << (idx * 7);
1576 idx++;
1577 }
1578 else
1579 {
1580 throwBadSequenceError("Invalid 64 bit continuation fields in packet");
1581 }
1582 }
1583 return idx;
1584 }
1585
extractCondResult(const std::vector<uint8_t> & buffer,const unsigned st_idx,uint32_t & key,uint8_t & result)1586 unsigned TrcPktProcEtmV4I::extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result)
1587 {
1588 unsigned idx = 0;
1589 bool lastByte = false;
1590 int incr = 0;
1591
1592 key = 0;
1593
1594 while(!lastByte && (idx < 6)) // cannot be more than 6 bytes for res + 32 bit key
1595 {
1596 if(buffer.size() > (st_idx + idx))
1597 {
1598 if(idx == 0)
1599 {
1600 result = buffer[st_idx+idx];
1601 key = (buffer[st_idx+idx] >> 4) & 0x7;
1602 incr+=3;
1603 }
1604 else
1605 {
1606 key |= ((uint32_t)(buffer[st_idx+idx] & 0x7F)) << incr;
1607 incr+=7;
1608 }
1609 lastByte = (bool)((buffer[st_idx+idx] & 0x80) == 0);
1610 idx++;
1611 }
1612 else
1613 {
1614 throwBadSequenceError("Invalid continuation fields in packet");
1615 }
1616 }
1617 return idx;
1618 }
1619
extract64BitLongAddr(const std::vector<uint8_t> & buffer,const int st_idx,const uint8_t IS,uint64_t & value)1620 int TrcPktProcEtmV4I::extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value)
1621 {
1622 value = 0;
1623 if(IS == 0)
1624 {
1625 value |= ((uint64_t)(buffer[st_idx+0] & 0x7F)) << 2;
1626 value |= ((uint64_t)(buffer[st_idx+1] & 0x7F)) << 9;
1627 }
1628 else
1629 {
1630 value |= ((uint64_t)(buffer[st_idx+0] & 0x7F)) << 1;
1631 value |= ((uint64_t)buffer[st_idx+1]) << 8;
1632 }
1633 value |= ((uint64_t)buffer[st_idx+2]) << 16;
1634 value |= ((uint64_t)buffer[st_idx+3]) << 24;
1635 value |= ((uint64_t)buffer[st_idx+4]) << 32;
1636 value |= ((uint64_t)buffer[st_idx+5]) << 40;
1637 value |= ((uint64_t)buffer[st_idx+6]) << 48;
1638 value |= ((uint64_t)buffer[st_idx+7]) << 56;
1639 return 8;
1640 }
1641
extract32BitLongAddr(const std::vector<uint8_t> & buffer,const int st_idx,const uint8_t IS,uint32_t & value)1642 int TrcPktProcEtmV4I::extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value)
1643 {
1644 value = 0;
1645 if(IS == 0)
1646 {
1647 value |= ((uint32_t)(buffer[st_idx+0] & 0x7F)) << 2;
1648 value |= ((uint32_t)(buffer[st_idx+1] & 0x7F)) << 9;
1649 }
1650 else
1651 {
1652 value |= ((uint32_t)(buffer[st_idx+0] & 0x7F)) << 1;
1653 value |= ((uint32_t)buffer[st_idx+1]) << 8;
1654 }
1655 value |= ((uint32_t)buffer[st_idx+2]) << 16;
1656 value |= ((uint32_t)buffer[st_idx+3]) << 24;
1657 return 4;
1658 }
1659
throwBadSequenceError(const char * pszExtMsg)1660 void TrcPktProcEtmV4I::throwBadSequenceError(const char *pszExtMsg)
1661 {
1662 m_curr_packet.updateErrType(ETM4_PKT_I_BAD_SEQUENCE); // swap type for err type
1663 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ,m_packet_index,m_config.getTraceID(),pszExtMsg);
1664 }
1665
1666
1667 /* End of File trc_pkt_proc_etmv4i.cpp */
1668