1c120c564SAndrew Turner /*
2c120c564SAndrew Turner * \file trc_pkt_decode_etmv4i.cpp
3c120c564SAndrew Turner * \brief OpenCSD : ETMv4 decoder
4c120c564SAndrew Turner *
5c120c564SAndrew Turner * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6c120c564SAndrew Turner */
7c120c564SAndrew Turner
8c120c564SAndrew Turner /*
9c120c564SAndrew Turner * Redistribution and use in source and binary forms, with or without modification,
10c120c564SAndrew Turner * are permitted provided that the following conditions are met:
11c120c564SAndrew Turner *
12c120c564SAndrew Turner * 1. Redistributions of source code must retain the above copyright notice,
13c120c564SAndrew Turner * this list of conditions and the following disclaimer.
14c120c564SAndrew Turner *
15c120c564SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright notice,
16c120c564SAndrew Turner * this list of conditions and the following disclaimer in the documentation
17c120c564SAndrew Turner * and/or other materials provided with the distribution.
18c120c564SAndrew Turner *
19c120c564SAndrew Turner * 3. Neither the name of the copyright holder nor the names of its contributors
20c120c564SAndrew Turner * may be used to endorse or promote products derived from this software without
21c120c564SAndrew Turner * specific prior written permission.
22c120c564SAndrew Turner *
23c120c564SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24c120c564SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25c120c564SAndrew Turner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26c120c564SAndrew Turner * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27c120c564SAndrew Turner * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28c120c564SAndrew Turner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29c120c564SAndrew Turner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30c120c564SAndrew Turner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31c120c564SAndrew Turner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32c120c564SAndrew Turner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33c120c564SAndrew Turner */
34c120c564SAndrew Turner
35c120c564SAndrew Turner #include "opencsd/etmv4/trc_pkt_decode_etmv4i.h"
36c120c564SAndrew Turner
37c120c564SAndrew Turner #include "common/trc_gen_elem.h"
38c120c564SAndrew Turner
39c120c564SAndrew Turner
40c120c564SAndrew Turner #define DCD_NAME "DCD_ETMV4"
41c120c564SAndrew Turner
42*46e6e290SRuslan Bukin static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON |
43*46e6e290SRuslan Bukin ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS;
44c120c564SAndrew Turner
TrcPktDecodeEtmV4I()45c120c564SAndrew Turner TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I()
46c120c564SAndrew Turner : TrcPktDecodeBase(DCD_NAME)
47c120c564SAndrew Turner {
48c120c564SAndrew Turner initDecoder();
49c120c564SAndrew Turner }
50c120c564SAndrew Turner
TrcPktDecodeEtmV4I(int instIDNum)51c120c564SAndrew Turner TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I(int instIDNum)
52c120c564SAndrew Turner : TrcPktDecodeBase(DCD_NAME,instIDNum)
53c120c564SAndrew Turner {
54c120c564SAndrew Turner initDecoder();
55c120c564SAndrew Turner }
56c120c564SAndrew Turner
~TrcPktDecodeEtmV4I()57c120c564SAndrew Turner TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I()
58c120c564SAndrew Turner {
59c120c564SAndrew Turner }
60c120c564SAndrew Turner
61c120c564SAndrew Turner /*********************** implementation packet decoding interface */
62c120c564SAndrew Turner
processPacket()63c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()
64c120c564SAndrew Turner {
65c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
66b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
67c120c564SAndrew Turner bool bPktDone = false;
68c120c564SAndrew Turner
69c120c564SAndrew Turner while(!bPktDone)
70c120c564SAndrew Turner {
71c120c564SAndrew Turner switch (m_curr_state)
72c120c564SAndrew Turner {
73c120c564SAndrew Turner case NO_SYNC:
74c120c564SAndrew Turner // output the initial not synced packet to the sink
75b6aadd18SAndrew Turner err = m_out_elem.resetElemStack();
76b6aadd18SAndrew Turner if (!err)
77b6aadd18SAndrew Turner err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC);
78b6aadd18SAndrew Turner if (!err)
79b6aadd18SAndrew Turner {
80b6aadd18SAndrew Turner outElem().setUnSyncEOTReason(m_unsync_eot_info);
81b6aadd18SAndrew Turner resp = m_out_elem.sendElements();
82c120c564SAndrew Turner m_curr_state = WAIT_SYNC;
83b6aadd18SAndrew Turner }
84b6aadd18SAndrew Turner else
85b6aadd18SAndrew Turner resp = OCSD_RESP_FATAL_SYS_ERR;
86b6aadd18SAndrew Turner
87c120c564SAndrew Turner // fall through to check if the current packet is the async we are waiting for.
88c120c564SAndrew Turner break;
89c120c564SAndrew Turner
90c120c564SAndrew Turner case WAIT_SYNC:
91c120c564SAndrew Turner if(m_curr_packet_in->getType() == ETM4_PKT_I_ASYNC)
92c120c564SAndrew Turner m_curr_state = WAIT_TINFO;
93c120c564SAndrew Turner bPktDone = true;
94c120c564SAndrew Turner break;
95c120c564SAndrew Turner
96c120c564SAndrew Turner case WAIT_TINFO:
97c120c564SAndrew Turner m_need_ctxt = true;
98c120c564SAndrew Turner m_need_addr = true;
99c120c564SAndrew Turner if(m_curr_packet_in->getType() == ETM4_PKT_I_TRACE_INFO)
100c120c564SAndrew Turner {
101c120c564SAndrew Turner doTraceInfoPacket();
102c120c564SAndrew Turner m_curr_state = DECODE_PKTS;
103c120c564SAndrew Turner m_return_stack.flush();
104c120c564SAndrew Turner }
105*46e6e290SRuslan Bukin /* ETE spec allows early event packets. */
106*46e6e290SRuslan Bukin else if ((m_config->MajVersion() >= 0x5) &&
107*46e6e290SRuslan Bukin (m_curr_packet_in->getType() == ETM4_PKT_I_EVENT))
108*46e6e290SRuslan Bukin {
109*46e6e290SRuslan Bukin err = decodePacket();
110*46e6e290SRuslan Bukin if (err)
111*46e6e290SRuslan Bukin resp = OCSD_RESP_FATAL_INVALID_DATA;
112*46e6e290SRuslan Bukin }
113c120c564SAndrew Turner bPktDone = true;
114c120c564SAndrew Turner break;
115c120c564SAndrew Turner
116c120c564SAndrew Turner case DECODE_PKTS:
117b6aadd18SAndrew Turner // this may change the state to RESOLVE_ELEM if required;
118b6aadd18SAndrew Turner err = decodePacket();
119b6aadd18SAndrew Turner if (err)
120b6aadd18SAndrew Turner {
121b6aadd18SAndrew Turner #ifdef OCSD_WARN_UNSUPPORTED
122b6aadd18SAndrew Turner if (err == OCSD_ERR_UNSUPP_DECODE_PKT)
123b6aadd18SAndrew Turner resp = OCSD_RESP_WARN_CONT;
124b6aadd18SAndrew Turner else
125b6aadd18SAndrew Turner #else
126b6aadd18SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
127b6aadd18SAndrew Turner #endif
128b6aadd18SAndrew Turner
129b6aadd18SAndrew Turner bPktDone = true;
130b6aadd18SAndrew Turner }
131b6aadd18SAndrew Turner else if (m_curr_state != RESOLVE_ELEM)
132b6aadd18SAndrew Turner bPktDone = true;
133c120c564SAndrew Turner break;
134c120c564SAndrew Turner
135b6aadd18SAndrew Turner case RESOLVE_ELEM:
136b6aadd18SAndrew Turner // this will change the state to DECODE_PKTS once required elem resolved &
137b6aadd18SAndrew Turner // needed generic packets output
138b6aadd18SAndrew Turner resp = resolveElements();
139b6aadd18SAndrew Turner if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp)))
140b6aadd18SAndrew Turner bPktDone = true;
141c120c564SAndrew Turner break;
142c120c564SAndrew Turner }
143c120c564SAndrew Turner }
144c120c564SAndrew Turner return resp;
145c120c564SAndrew Turner }
146c120c564SAndrew Turner
onEOT()147c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()
148c120c564SAndrew Turner {
149c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
150b6aadd18SAndrew Turner ocsd_err_t err;
151b6aadd18SAndrew Turner if ((err = commitElemOnEOT()) != OCSD_OK)
152b6aadd18SAndrew Turner {
153b6aadd18SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
154b6aadd18SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data."));
155b6aadd18SAndrew Turner }
156b6aadd18SAndrew Turner else
157b6aadd18SAndrew Turner resp = m_out_elem.sendElements();
158c120c564SAndrew Turner return resp;
159c120c564SAndrew Turner }
160c120c564SAndrew Turner
onReset()161c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()
162c120c564SAndrew Turner {
163c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
164b6aadd18SAndrew Turner m_unsync_eot_info = UNSYNC_RESET_DECODER;
165c120c564SAndrew Turner resetDecoder();
166c120c564SAndrew Turner return resp;
167c120c564SAndrew Turner }
168c120c564SAndrew Turner
onFlush()169c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush()
170c120c564SAndrew Turner {
171c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
172c120c564SAndrew Turner
173b6aadd18SAndrew Turner if (m_curr_state == RESOLVE_ELEM)
174b6aadd18SAndrew Turner resp = resolveElements();
175b6aadd18SAndrew Turner else
176b6aadd18SAndrew Turner resp = m_out_elem.sendElements();
177c120c564SAndrew Turner return resp;
178c120c564SAndrew Turner }
179c120c564SAndrew Turner
onProtocolConfig()180c120c564SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()
181c120c564SAndrew Turner {
182c120c564SAndrew Turner ocsd_err_t err = OCSD_OK;
183c120c564SAndrew Turner
184c120c564SAndrew Turner // set some static config elements
185c120c564SAndrew Turner m_CSID = m_config->getTraceID();
186c120c564SAndrew Turner m_max_spec_depth = m_config->MaxSpecDepth();
187b6aadd18SAndrew Turner
188b6aadd18SAndrew Turner // elements associated with data trace
189b6aadd18SAndrew Turner #ifdef DATA_TRACE_SUPPORTED
190c120c564SAndrew Turner m_p0_key_max = m_config->P0_Key_Max();
191c120c564SAndrew Turner m_cond_key_max_incr = m_config->CondKeyMaxIncr();
192b6aadd18SAndrew Turner #endif
193b6aadd18SAndrew Turner
194b6aadd18SAndrew Turner m_out_elem.initCSID(m_CSID);
195c120c564SAndrew Turner
196c120c564SAndrew Turner // set up static trace instruction decode elements
197c120c564SAndrew Turner m_instr_info.dsb_dmb_waypoints = 0;
198c120c564SAndrew Turner m_instr_info.wfi_wfe_branch = m_config->wfiwfeBranch() ? 1 : 0;
199c120c564SAndrew Turner m_instr_info.pe_type.arch = m_config->archVersion();
200c120c564SAndrew Turner m_instr_info.pe_type.profile = m_config->coreProfile();
201c120c564SAndrew Turner
202c120c564SAndrew Turner m_IASize64 = (m_config->iaSizeMax() == 64);
203c120c564SAndrew Turner
204c120c564SAndrew Turner if (m_config->enabledRetStack())
205c120c564SAndrew Turner {
206c120c564SAndrew Turner m_return_stack.set_active(true);
207c120c564SAndrew Turner #ifdef TRC_RET_STACK_DEBUG
208c120c564SAndrew Turner m_return_stack.set_dbg_logger(this);
209c120c564SAndrew Turner #endif
210c120c564SAndrew Turner }
211c120c564SAndrew Turner
212c120c564SAndrew Turner // check config compatible with current decoder support level.
213c120c564SAndrew Turner // at present no data trace, no spec depth, no return stack, no QE
214c120c564SAndrew Turner // Remove these checks as support is added.
215b6aadd18SAndrew Turner if(m_config->enabledDataTrace())
216c120c564SAndrew Turner {
217c120c564SAndrew Turner err = OCSD_ERR_HW_CFG_UNSUPP;
218c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported"));
219c120c564SAndrew Turner }
220c120c564SAndrew Turner else if(m_config->enabledLSP0Trace())
221c120c564SAndrew Turner {
222c120c564SAndrew Turner err = OCSD_ERR_HW_CFG_UNSUPP;
223c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : LSP0 elements not supported."));
224c120c564SAndrew Turner }
225c120c564SAndrew Turner else if(m_config->enabledCondITrace() != EtmV4Config::COND_TR_DIS)
226c120c564SAndrew Turner {
227c120c564SAndrew Turner err = OCSD_ERR_HW_CFG_UNSUPP;
228c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported."));
229c120c564SAndrew Turner }
230c120c564SAndrew Turner return err;
231c120c564SAndrew Turner }
232c120c564SAndrew Turner
233c120c564SAndrew Turner /************* local decode methods */
initDecoder()234c120c564SAndrew Turner void TrcPktDecodeEtmV4I::initDecoder()
235c120c564SAndrew Turner {
236c120c564SAndrew Turner // set the operational modes supported.
237c120c564SAndrew Turner m_supported_op_flags = ETMV4_SUPPORTED_DECODE_OP_FLAGS;
238c120c564SAndrew Turner
239c120c564SAndrew Turner /* init elements that get set by config */
240c120c564SAndrew Turner m_max_spec_depth = 0;
241c120c564SAndrew Turner m_CSID = 0;
242c120c564SAndrew Turner m_IASize64 = false;
243c120c564SAndrew Turner
244b6aadd18SAndrew Turner // elements associated with data trace
245b6aadd18SAndrew Turner #ifdef DATA_TRACE_SUPPORTED
246b6aadd18SAndrew Turner m_p0_key_max = 0;
247b6aadd18SAndrew Turner m_cond_key_max_incr = 0;
248b6aadd18SAndrew Turner #endif
249b6aadd18SAndrew Turner
250c120c564SAndrew Turner // reset decoder state to unsynced
251b6aadd18SAndrew Turner m_unsync_eot_info = UNSYNC_INIT_DECODER;
252c120c564SAndrew Turner resetDecoder();
253c120c564SAndrew Turner }
254c120c564SAndrew Turner
resetDecoder()255c120c564SAndrew Turner void TrcPktDecodeEtmV4I::resetDecoder()
256c120c564SAndrew Turner {
257c120c564SAndrew Turner m_curr_state = NO_SYNC;
258c120c564SAndrew Turner m_timestamp = 0;
259c120c564SAndrew Turner m_context_id = 0;
260c120c564SAndrew Turner m_vmid_id = 0;
261c120c564SAndrew Turner m_is_secure = true;
262c120c564SAndrew Turner m_is_64bit = false;
263c120c564SAndrew Turner m_cc_threshold = 0;
264c120c564SAndrew Turner m_curr_spec_depth = 0;
265b6aadd18SAndrew Turner m_need_ctxt = true;
266b6aadd18SAndrew Turner m_need_addr = true;
267b6aadd18SAndrew Turner m_elem_pending_addr = false;
268b6aadd18SAndrew Turner m_prev_overflow = false;
269b6aadd18SAndrew Turner m_P0_stack.delete_all();
270b6aadd18SAndrew Turner m_out_elem.resetElemStack();
271b6aadd18SAndrew Turner m_last_IS = 0;
272b6aadd18SAndrew Turner clearElemRes();
273*46e6e290SRuslan Bukin m_ete_first_ts_marker = false;
274b6aadd18SAndrew Turner
275b6aadd18SAndrew Turner // elements associated with data trace
276b6aadd18SAndrew Turner #ifdef DATA_TRACE_SUPPORTED
277c120c564SAndrew Turner m_p0_key = 0;
278c120c564SAndrew Turner m_cond_c_key = 0;
279c120c564SAndrew Turner m_cond_r_key = 0;
280b6aadd18SAndrew Turner #endif
281c120c564SAndrew Turner }
282c120c564SAndrew Turner
onFirstInitOK()283b6aadd18SAndrew Turner void TrcPktDecodeEtmV4I::onFirstInitOK()
284c120c564SAndrew Turner {
285b6aadd18SAndrew Turner // once init, set the output element interface to the out elem list.
286b6aadd18SAndrew Turner m_out_elem.initSendIf(this->getTraceElemOutAttachPt());
287b6aadd18SAndrew Turner }
288b6aadd18SAndrew Turner
289b6aadd18SAndrew Turner // Changes a packet into stack of trace elements - these will be resolved and output later
decodePacket()290b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()
291b6aadd18SAndrew Turner {
292b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
293c120c564SAndrew Turner bool bAllocErr = false;
294c120c564SAndrew Turner bool is_addr = false;
295c120c564SAndrew Turner
296c120c564SAndrew Turner switch(m_curr_packet_in->getType())
297c120c564SAndrew Turner {
298c120c564SAndrew Turner case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
299c120c564SAndrew Turner case ETM4_PKT_I_IGNORE: // or this one.
300c120c564SAndrew Turner break;
301c120c564SAndrew Turner
302c120c564SAndrew Turner case ETM4_PKT_I_TRACE_INFO:
303c120c564SAndrew Turner // skip subsequent TInfo packets.
304c120c564SAndrew Turner m_return_stack.flush();
305c120c564SAndrew Turner break;
306c120c564SAndrew Turner
307c120c564SAndrew Turner case ETM4_PKT_I_TRACE_ON:
308c120c564SAndrew Turner {
309c120c564SAndrew Turner if (m_P0_stack.createParamElemNoParam(P0_TRC_ON, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
310c120c564SAndrew Turner bAllocErr = true;
311c120c564SAndrew Turner }
312c120c564SAndrew Turner break;
313c120c564SAndrew Turner
314c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F1:
315c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F2:
316c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F3:
317c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F4:
318c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F5:
319c120c564SAndrew Turner case ETM4_PKT_I_ATOM_F6:
320c120c564SAndrew Turner {
321c120c564SAndrew Turner if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
322c120c564SAndrew Turner bAllocErr = true;
323c120c564SAndrew Turner else
324c120c564SAndrew Turner m_curr_spec_depth += m_curr_packet_in->getAtom().num;
325c120c564SAndrew Turner }
326c120c564SAndrew Turner break;
327c120c564SAndrew Turner
328c120c564SAndrew Turner case ETM4_PKT_I_CTXT:
329c120c564SAndrew Turner {
330b6aadd18SAndrew Turner if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
331c120c564SAndrew Turner bAllocErr = true;
332c120c564SAndrew Turner }
333c120c564SAndrew Turner break;
334c120c564SAndrew Turner
335c120c564SAndrew Turner case ETM4_PKT_I_ADDR_MATCH:
336c120c564SAndrew Turner {
337c120c564SAndrew Turner etmv4_addr_val_t addr;
338c120c564SAndrew Turner
339c120c564SAndrew Turner addr.val = m_curr_packet_in->getAddrVal();
340b6aadd18SAndrew Turner addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
341b6aadd18SAndrew Turner
342c120c564SAndrew Turner if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
343c120c564SAndrew Turner bAllocErr = true;
344c120c564SAndrew Turner is_addr = true;
345c120c564SAndrew Turner }
346c120c564SAndrew Turner break;
347c120c564SAndrew Turner
348c120c564SAndrew Turner case ETM4_PKT_I_ADDR_CTXT_L_64IS0:
349c120c564SAndrew Turner case ETM4_PKT_I_ADDR_CTXT_L_64IS1:
350c120c564SAndrew Turner case ETM4_PKT_I_ADDR_CTXT_L_32IS0:
351c120c564SAndrew Turner case ETM4_PKT_I_ADDR_CTXT_L_32IS1:
352c120c564SAndrew Turner {
353b6aadd18SAndrew Turner m_last_IS = m_curr_packet_in->getAddrIS();
354b6aadd18SAndrew Turner if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
355c120c564SAndrew Turner bAllocErr = true;
356c120c564SAndrew Turner }
357c120c564SAndrew Turner case ETM4_PKT_I_ADDR_L_32IS0:
358c120c564SAndrew Turner case ETM4_PKT_I_ADDR_L_32IS1:
359c120c564SAndrew Turner case ETM4_PKT_I_ADDR_L_64IS0:
360c120c564SAndrew Turner case ETM4_PKT_I_ADDR_L_64IS1:
361c120c564SAndrew Turner case ETM4_PKT_I_ADDR_S_IS0:
362c120c564SAndrew Turner case ETM4_PKT_I_ADDR_S_IS1:
363c120c564SAndrew Turner {
364c120c564SAndrew Turner etmv4_addr_val_t addr;
365c120c564SAndrew Turner
366c120c564SAndrew Turner addr.val = m_curr_packet_in->getAddrVal();
367b6aadd18SAndrew Turner addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
368b6aadd18SAndrew Turner
369c120c564SAndrew Turner if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
370c120c564SAndrew Turner bAllocErr = true;
371*46e6e290SRuslan Bukin is_addr = true; // may be waiting for target address from indirect branch
372*46e6e290SRuslan Bukin }
373*46e6e290SRuslan Bukin break;
374*46e6e290SRuslan Bukin
375*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_MATCH:
376*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_S_IS0:
377*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_S_IS1:
378*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_L_32IS0:
379*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_L_32IS1:
380*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_L_64IS0:
381*46e6e290SRuslan Bukin case ETE_PKT_I_SRC_ADDR_L_64IS1:
382*46e6e290SRuslan Bukin {
383*46e6e290SRuslan Bukin etmv4_addr_val_t addr;
384*46e6e290SRuslan Bukin
385*46e6e290SRuslan Bukin addr.val = m_curr_packet_in->getAddrVal();
386*46e6e290SRuslan Bukin addr.isa = m_curr_packet_in->getAddrIS();
387*46e6e290SRuslan Bukin if (m_P0_stack.createSrcAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
388*46e6e290SRuslan Bukin bAllocErr = true;
389*46e6e290SRuslan Bukin m_curr_spec_depth++;
390c120c564SAndrew Turner }
391c120c564SAndrew Turner break;
392c120c564SAndrew Turner
393c120c564SAndrew Turner // Exceptions
394c120c564SAndrew Turner case ETM4_PKT_I_EXCEPT:
395c120c564SAndrew Turner {
396c120c564SAndrew Turner if (m_P0_stack.createExceptElem(m_curr_packet_in->getType(), m_index_curr_pkt,
397c120c564SAndrew Turner (m_curr_packet_in->exception_info.addr_interp == 0x2),
398c120c564SAndrew Turner m_curr_packet_in->exception_info.exceptionType) == 0)
399c120c564SAndrew Turner bAllocErr = true;
400c120c564SAndrew Turner else
401b6aadd18SAndrew Turner m_elem_pending_addr = true; // wait for following packets before marking for commit.
402c120c564SAndrew Turner }
403c120c564SAndrew Turner break;
404c120c564SAndrew Turner
405c120c564SAndrew Turner case ETM4_PKT_I_EXCEPT_RTN:
406c120c564SAndrew Turner {
407c120c564SAndrew Turner // P0 element if V7M profile.
408c120c564SAndrew Turner bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM);
409c120c564SAndrew Turner if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
410c120c564SAndrew Turner bAllocErr = true;
411c120c564SAndrew Turner else if (bV7MProfile)
412c120c564SAndrew Turner m_curr_spec_depth++;
413c120c564SAndrew Turner }
414c120c564SAndrew Turner break;
415c120c564SAndrew Turner
416c120c564SAndrew Turner case ETM4_PKT_I_FUNC_RET:
417c120c564SAndrew Turner {
418c120c564SAndrew Turner // P0 element iff V8M profile, otherwise ignore
419c120c564SAndrew Turner if (OCSD_IS_V8_ARCH(m_config->archVersion()) && (m_config->coreProfile() == profile_CortexM))
420c120c564SAndrew Turner {
421c120c564SAndrew Turner if (m_P0_stack.createParamElemNoParam(P0_FUNC_RET, true, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
422c120c564SAndrew Turner bAllocErr = true;
423c120c564SAndrew Turner else
424c120c564SAndrew Turner m_curr_spec_depth++;
425c120c564SAndrew Turner }
426c120c564SAndrew Turner }
427c120c564SAndrew Turner break;
428c120c564SAndrew Turner
429c120c564SAndrew Turner // event trace
430c120c564SAndrew Turner case ETM4_PKT_I_EVENT:
431c120c564SAndrew Turner {
432c120c564SAndrew Turner std::vector<uint32_t> params = { 0 };
433c120c564SAndrew Turner params[0] = (uint32_t)m_curr_packet_in->event_val;
434c120c564SAndrew Turner if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
435c120c564SAndrew Turner bAllocErr = true;
436c120c564SAndrew Turner
437c120c564SAndrew Turner }
438c120c564SAndrew Turner break;
439c120c564SAndrew Turner
440c120c564SAndrew Turner /* cycle count packets */
441c120c564SAndrew Turner case ETM4_PKT_I_CCNT_F1:
442c120c564SAndrew Turner case ETM4_PKT_I_CCNT_F2:
443c120c564SAndrew Turner case ETM4_PKT_I_CCNT_F3:
444c120c564SAndrew Turner {
445c120c564SAndrew Turner std::vector<uint32_t> params = { 0 };
446c120c564SAndrew Turner params[0] = m_curr_packet_in->getCC();
447c120c564SAndrew Turner if (m_P0_stack.createParamElem(P0_CC, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
448c120c564SAndrew Turner bAllocErr = true;
449c120c564SAndrew Turner
450c120c564SAndrew Turner }
451c120c564SAndrew Turner break;
452c120c564SAndrew Turner
453c120c564SAndrew Turner // timestamp
454c120c564SAndrew Turner case ETM4_PKT_I_TIMESTAMP:
455c120c564SAndrew Turner {
456c120c564SAndrew Turner bool bTSwithCC = m_config->enabledCCI();
457c120c564SAndrew Turner uint64_t ts = m_curr_packet_in->getTS();
458c120c564SAndrew Turner std::vector<uint32_t> params = { 0, 0, 0 };
459c120c564SAndrew Turner params[0] = (uint32_t)(ts & 0xFFFFFFFF);
460c120c564SAndrew Turner params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF);
461c120c564SAndrew Turner if (bTSwithCC)
462c120c564SAndrew Turner params[2] = m_curr_packet_in->getCC();
463c120c564SAndrew Turner if (m_P0_stack.createParamElem(bTSwithCC ? P0_TS_CC : P0_TS, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
464c120c564SAndrew Turner bAllocErr = true;
465c120c564SAndrew Turner
466c120c564SAndrew Turner }
467c120c564SAndrew Turner break;
468c120c564SAndrew Turner
469*46e6e290SRuslan Bukin case ETE_PKT_I_TS_MARKER:
470*46e6e290SRuslan Bukin {
471*46e6e290SRuslan Bukin trace_marker_payload_t marker;
472*46e6e290SRuslan Bukin marker.type = ELEM_MARKER_TS;
473*46e6e290SRuslan Bukin marker.value = 0;
474*46e6e290SRuslan Bukin if (m_P0_stack.createMarkerElem(m_curr_packet_in->getType(), m_index_curr_pkt, marker) == 0)
475*46e6e290SRuslan Bukin bAllocErr = true;
476*46e6e290SRuslan Bukin }
477*46e6e290SRuslan Bukin break;
478*46e6e290SRuslan Bukin
479c120c564SAndrew Turner case ETM4_PKT_I_BAD_SEQUENCE:
480*46e6e290SRuslan Bukin err = handleBadPacket("Bad byte sequence in packet.", m_index_curr_pkt);
481c120c564SAndrew Turner break;
482c120c564SAndrew Turner
483c120c564SAndrew Turner case ETM4_PKT_I_BAD_TRACEMODE:
484*46e6e290SRuslan Bukin err = handleBadPacket("Invalid packet type for trace mode.", m_index_curr_pkt);
485c120c564SAndrew Turner break;
486c120c564SAndrew Turner
487c120c564SAndrew Turner case ETM4_PKT_I_RESERVED:
488*46e6e290SRuslan Bukin err = handleBadPacket("Reserved packet header", m_index_curr_pkt);
489b6aadd18SAndrew Turner break;
490b6aadd18SAndrew Turner
491b6aadd18SAndrew Turner // speculation
492b6aadd18SAndrew Turner case ETM4_PKT_I_MISPREDICT:
493b6aadd18SAndrew Turner case ETM4_PKT_I_CANCEL_F1_MISPRED:
494b6aadd18SAndrew Turner case ETM4_PKT_I_CANCEL_F2:
495b6aadd18SAndrew Turner case ETM4_PKT_I_CANCEL_F3:
496b6aadd18SAndrew Turner m_elem_res.mispredict = true;
497b6aadd18SAndrew Turner if (m_curr_packet_in->getNumAtoms())
498b6aadd18SAndrew Turner {
499b6aadd18SAndrew Turner if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
500b6aadd18SAndrew Turner bAllocErr = true;
501b6aadd18SAndrew Turner else
502b6aadd18SAndrew Turner m_curr_spec_depth += m_curr_packet_in->getNumAtoms();
503b6aadd18SAndrew Turner }
504b6aadd18SAndrew Turner
505b6aadd18SAndrew Turner case ETM4_PKT_I_CANCEL_F1:
506b6aadd18SAndrew Turner m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem();
507b6aadd18SAndrew Turner break;
508b6aadd18SAndrew Turner
509b6aadd18SAndrew Turner case ETM4_PKT_I_COMMIT:
510b6aadd18SAndrew Turner m_elem_res.P0_commit = m_curr_packet_in->getCommitElem();
511b6aadd18SAndrew Turner break;
512b6aadd18SAndrew Turner
513b6aadd18SAndrew Turner case ETM4_PKT_I_OVERFLOW:
514b6aadd18SAndrew Turner m_prev_overflow = true;
515b6aadd18SAndrew Turner case ETM4_PKT_I_DISCARD:
516b6aadd18SAndrew Turner m_curr_spec_depth = 0;
517b6aadd18SAndrew Turner m_elem_res.discard = true;
518b6aadd18SAndrew Turner break;
519b6aadd18SAndrew Turner
520b6aadd18SAndrew Turner /* Q packets */
521b6aadd18SAndrew Turner case ETM4_PKT_I_Q:
522b6aadd18SAndrew Turner {
523b6aadd18SAndrew Turner TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count);
524b6aadd18SAndrew Turner if (pQElem)
525b6aadd18SAndrew Turner {
526b6aadd18SAndrew Turner if (m_curr_packet_in->Q_pkt.addr_present)
527b6aadd18SAndrew Turner {
528b6aadd18SAndrew Turner etmv4_addr_val_t addr;
529b6aadd18SAndrew Turner
530b6aadd18SAndrew Turner addr.val = m_curr_packet_in->getAddrVal();
531b6aadd18SAndrew Turner addr.isa = m_curr_packet_in->getAddrIS();
532b6aadd18SAndrew Turner pQElem->setAddr(addr);
533b6aadd18SAndrew Turner m_curr_spec_depth++;
534b6aadd18SAndrew Turner }
535b6aadd18SAndrew Turner else
536b6aadd18SAndrew Turner m_elem_pending_addr = true;
537b6aadd18SAndrew Turner }
538b6aadd18SAndrew Turner else
539b6aadd18SAndrew Turner bAllocErr = true;
540b6aadd18SAndrew Turner }
541c120c564SAndrew Turner break;
542c120c564SAndrew Turner
543*46e6e290SRuslan Bukin /* transactional memory packets */
544*46e6e290SRuslan Bukin case ETE_PKT_I_TRANS_ST:
545*46e6e290SRuslan Bukin {
546*46e6e290SRuslan Bukin if (m_P0_stack.createParamElemNoParam(P0_TRANS_START, m_config->commTransP0(), m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
547*46e6e290SRuslan Bukin bAllocErr = true;
548*46e6e290SRuslan Bukin if (m_config->commTransP0())
549*46e6e290SRuslan Bukin m_curr_spec_depth++;
550*46e6e290SRuslan Bukin }
551*46e6e290SRuslan Bukin break;
552*46e6e290SRuslan Bukin
553*46e6e290SRuslan Bukin case ETE_PKT_I_TRANS_COMMIT:
554*46e6e290SRuslan Bukin {
555*46e6e290SRuslan Bukin if (m_P0_stack.createParamElemNoParam(P0_TRANS_COMMIT, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
556*46e6e290SRuslan Bukin bAllocErr = true;
557*46e6e290SRuslan Bukin }
558*46e6e290SRuslan Bukin break;
559*46e6e290SRuslan Bukin
560*46e6e290SRuslan Bukin case ETE_PKT_I_TRANS_FAIL:
561*46e6e290SRuslan Bukin {
562*46e6e290SRuslan Bukin if (m_P0_stack.createParamElemNoParam(P0_TRANS_FAIL, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
563*46e6e290SRuslan Bukin bAllocErr = true;
564*46e6e290SRuslan Bukin }
565*46e6e290SRuslan Bukin break;
566*46e6e290SRuslan Bukin
567*46e6e290SRuslan Bukin /* PE Instrumentation packet */
568*46e6e290SRuslan Bukin case ETE_PKT_I_ITE:
569*46e6e290SRuslan Bukin {
570*46e6e290SRuslan Bukin trace_sw_ite_t ite_pkt;
571*46e6e290SRuslan Bukin
572*46e6e290SRuslan Bukin ite_pkt.el = m_curr_packet_in->getITE_EL();
573*46e6e290SRuslan Bukin ite_pkt.value = m_curr_packet_in->getITE_value();
574*46e6e290SRuslan Bukin if (m_P0_stack.createITEElem(m_curr_packet_in->getType(), m_index_curr_pkt, ite_pkt) == 0)
575*46e6e290SRuslan Bukin bAllocErr = true;
576*46e6e290SRuslan Bukin }
577*46e6e290SRuslan Bukin break;
578*46e6e290SRuslan Bukin
579c120c564SAndrew Turner /*** presently unsupported packets ***/
580c120c564SAndrew Turner /* conditional instruction tracing */
581c120c564SAndrew Turner case ETM4_PKT_I_COND_FLUSH:
582c120c564SAndrew Turner case ETM4_PKT_I_COND_I_F1:
583c120c564SAndrew Turner case ETM4_PKT_I_COND_I_F2:
584c120c564SAndrew Turner case ETM4_PKT_I_COND_I_F3:
585c120c564SAndrew Turner case ETM4_PKT_I_COND_RES_F1:
586c120c564SAndrew Turner case ETM4_PKT_I_COND_RES_F2:
587c120c564SAndrew Turner case ETM4_PKT_I_COND_RES_F3:
588c120c564SAndrew Turner case ETM4_PKT_I_COND_RES_F4:
589c120c564SAndrew Turner // data synchronisation markers
590c120c564SAndrew Turner case ETM4_PKT_I_NUM_DS_MKR:
591c120c564SAndrew Turner case ETM4_PKT_I_UNNUM_DS_MKR:
592b6aadd18SAndrew Turner // all currently unsupported
593b6aadd18SAndrew Turner {
594b6aadd18SAndrew Turner ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR;
595b6aadd18SAndrew Turner #ifdef OCSD_WARN_UNSUPPORTED
596b6aadd18SAndrew Turner sev = OCSD_ERR_SEV_WARN;
597b6aadd18SAndrew Turner //resp = OCSD_RESP_WARN_CONT;
598b6aadd18SAndrew Turner #else
599b6aadd18SAndrew Turner //resp = OCSD_RESP_FATAL_INVALID_DATA;
600b6aadd18SAndrew Turner #endif
601b6aadd18SAndrew Turner err = OCSD_ERR_UNSUPP_DECODE_PKT;
602*46e6e290SRuslan Bukin if (sev == OCSD_ERR_SEV_WARN)
603*46e6e290SRuslan Bukin LogError(ocsdError(sev, err, "Data trace related, unsupported packet type."));
604*46e6e290SRuslan Bukin else
605*46e6e290SRuslan Bukin err = handlePacketSeqErr(err, m_index_curr_pkt, "Data trace related, unsupported packet type.");
606b6aadd18SAndrew Turner }
607c120c564SAndrew Turner break;
608c120c564SAndrew Turner
609c120c564SAndrew Turner default:
610c120c564SAndrew Turner // any other packet - bad packet error
611*46e6e290SRuslan Bukin err = handleBadPacket("Unknown packet type.", m_index_curr_pkt);
612c120c564SAndrew Turner break;
613c120c564SAndrew Turner }
614c120c564SAndrew Turner
615b6aadd18SAndrew Turner // we need to wait for following address after certain packets
616c120c564SAndrew Turner // - work out if we have seen enough here...
617b6aadd18SAndrew Turner if (is_addr && m_elem_pending_addr)
618c120c564SAndrew Turner {
619b6aadd18SAndrew Turner m_curr_spec_depth++; // increase spec depth for element waiting on address.
620b6aadd18SAndrew Turner m_elem_pending_addr = false; // can't be waiting on both
621c120c564SAndrew Turner }
622c120c564SAndrew Turner
623c120c564SAndrew Turner if(bAllocErr)
624c120c564SAndrew Turner {
625b6aadd18SAndrew Turner err = OCSD_ERR_MEM;
626c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));
627c120c564SAndrew Turner }
628c120c564SAndrew Turner else if(m_curr_spec_depth > m_max_spec_depth)
629c120c564SAndrew Turner {
630c120c564SAndrew Turner // auto commit anything above max spec depth
631c120c564SAndrew Turner // (this will auto commit anything if spec depth not supported!)
632b6aadd18SAndrew Turner m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;
633c120c564SAndrew Turner }
634b6aadd18SAndrew Turner
635b6aadd18SAndrew Turner if (!err && isElemForRes())
636b6aadd18SAndrew Turner m_curr_state = RESOLVE_ELEM;
637b6aadd18SAndrew Turner return err;
638c120c564SAndrew Turner }
639c120c564SAndrew Turner
doTraceInfoPacket()640c120c564SAndrew Turner void TrcPktDecodeEtmV4I::doTraceInfoPacket()
641c120c564SAndrew Turner {
642c120c564SAndrew Turner m_trace_info = m_curr_packet_in->getTraceInfo();
643c120c564SAndrew Turner m_cc_threshold = m_curr_packet_in->getCCThreshold();
644c120c564SAndrew Turner m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
645*46e6e290SRuslan Bukin /* put a trans marker in stack if started in trans state */
646*46e6e290SRuslan Bukin if (m_trace_info.bits.in_trans_state)
647*46e6e290SRuslan Bukin m_P0_stack.createParamElemNoParam(P0_TRANS_TRACE_INIT, false, m_curr_packet_in->getType(), m_index_curr_pkt);
648b6aadd18SAndrew Turner
649b6aadd18SAndrew Turner // elements associated with data trace
650b6aadd18SAndrew Turner #ifdef DATA_TRACE_SUPPORTED
651b6aadd18SAndrew Turner m_p0_key = m_curr_packet_in->getP0Key();
652b6aadd18SAndrew Turner #endif
653b6aadd18SAndrew Turner }
654b6aadd18SAndrew Turner
655b6aadd18SAndrew Turner /* Element resolution
656b6aadd18SAndrew Turner * Commit or cancel elements as required
657b6aadd18SAndrew Turner * Send any buffered output packets.
658b6aadd18SAndrew Turner */
resolveElements()659b6aadd18SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()
660b6aadd18SAndrew Turner {
661b6aadd18SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
662b6aadd18SAndrew Turner bool Complete = false;
663b6aadd18SAndrew Turner
664b6aadd18SAndrew Turner while (!Complete)
665b6aadd18SAndrew Turner {
666b6aadd18SAndrew Turner if (m_out_elem.numElemToSend())
667b6aadd18SAndrew Turner resp = m_out_elem.sendElements();
668b6aadd18SAndrew Turner else if (isElemForRes())
669b6aadd18SAndrew Turner {
670b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
671b6aadd18SAndrew Turner if (m_elem_res.P0_commit)
672b6aadd18SAndrew Turner err = commitElements();
673b6aadd18SAndrew Turner
674*46e6e290SRuslan Bukin // allow for early flush on context element
675*46e6e290SRuslan Bukin if (!m_elem_res.P0_commit) {
676*46e6e290SRuslan Bukin
677b6aadd18SAndrew Turner if (!err && m_elem_res.P0_cancel)
678b6aadd18SAndrew Turner err = cancelElements();
679b6aadd18SAndrew Turner
680b6aadd18SAndrew Turner if (!err && m_elem_res.mispredict)
681b6aadd18SAndrew Turner err = mispredictAtom();
682b6aadd18SAndrew Turner
683b6aadd18SAndrew Turner if (!err && m_elem_res.discard)
684b6aadd18SAndrew Turner err = discardElements();
685*46e6e290SRuslan Bukin }
686b6aadd18SAndrew Turner
687b6aadd18SAndrew Turner if (err != OCSD_OK)
688b6aadd18SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
689b6aadd18SAndrew Turner }
690b6aadd18SAndrew Turner
691b6aadd18SAndrew Turner // break out on error or wait request.
692b6aadd18SAndrew Turner if (!OCSD_DATA_RESP_IS_CONT(resp))
693b6aadd18SAndrew Turner break;
694b6aadd18SAndrew Turner
695b6aadd18SAndrew Turner // completion is nothing to send and nothing to commit
696b6aadd18SAndrew Turner Complete = !m_out_elem.numElemToSend() && !isElemForRes();
697b6aadd18SAndrew Turner
698b6aadd18SAndrew Turner // done all elements - need more packets.
699b6aadd18SAndrew Turner if (Complete) {
700b6aadd18SAndrew Turner // if we are still in resolve, the goto decode.
701b6aadd18SAndrew Turner if (m_curr_state == RESOLVE_ELEM)
702b6aadd18SAndrew Turner m_curr_state = DECODE_PKTS;
703b6aadd18SAndrew Turner }
704b6aadd18SAndrew Turner }
705b6aadd18SAndrew Turner return resp;
706c120c564SAndrew Turner }
707c120c564SAndrew Turner
708c120c564SAndrew Turner /*
709c120c564SAndrew Turner * Walks through the element stack, processing from oldest element to the newest,
710c120c564SAndrew Turner according to the number of P0 elements that need committing.
711b6aadd18SAndrew Turner Build a stack of output elements in the process.
712c120c564SAndrew Turner */
commitElements()713b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::commitElements()
714c120c564SAndrew Turner {
715b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
716c120c564SAndrew Turner bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!)
717b6aadd18SAndrew Turner int num_commit_req = m_elem_res.P0_commit;
718c120c564SAndrew Turner ocsd_trc_index_t err_idx = 0;
719c120c564SAndrew Turner TrcStackElem *pElem = 0; // stacked element pointer
720*46e6e290SRuslan Bukin bool contextFlush = false;
721c120c564SAndrew Turner
722b6aadd18SAndrew Turner err = m_out_elem.resetElemStack();
723b6aadd18SAndrew Turner
724*46e6e290SRuslan Bukin while(m_elem_res.P0_commit && !err && !contextFlush)
725c120c564SAndrew Turner {
726c120c564SAndrew Turner if (m_P0_stack.size() > 0)
727c120c564SAndrew Turner {
728c120c564SAndrew Turner pElem = m_P0_stack.back(); // get oldest element
729c120c564SAndrew Turner err_idx = pElem->getRootIndex(); // save index in case of error.
730c120c564SAndrew Turner
731c120c564SAndrew Turner switch (pElem->getP0Type())
732c120c564SAndrew Turner {
733c120c564SAndrew Turner // indicates a trace restart - beginning of trace or discontinuiuty
734c120c564SAndrew Turner case P0_TRC_ON:
735b6aadd18SAndrew Turner err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);
736b6aadd18SAndrew Turner if (!err)
737b6aadd18SAndrew Turner {
738b6aadd18SAndrew Turner m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
739c120c564SAndrew Turner m_prev_overflow = false;
740c120c564SAndrew Turner m_return_stack.flush();
741b6aadd18SAndrew Turner }
742c120c564SAndrew Turner break;
743c120c564SAndrew Turner
744c120c564SAndrew Turner case P0_ADDR:
745c120c564SAndrew Turner {
746c120c564SAndrew Turner TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);
747c120c564SAndrew Turner m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack
748c120c564SAndrew Turner if (pAddrElem)
749c120c564SAndrew Turner {
750c120c564SAndrew Turner SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);
751c120c564SAndrew Turner m_need_addr = false;
752c120c564SAndrew Turner }
753c120c564SAndrew Turner }
754c120c564SAndrew Turner break;
755c120c564SAndrew Turner
756c120c564SAndrew Turner case P0_CTXT:
757c120c564SAndrew Turner {
758c120c564SAndrew Turner TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
759c120c564SAndrew Turner if (pCtxtElem)
760c120c564SAndrew Turner {
761c120c564SAndrew Turner etmv4_context_t ctxt = pCtxtElem->getContext();
762c120c564SAndrew Turner // check this is an updated context
763c120c564SAndrew Turner if(ctxt.updated)
764c120c564SAndrew Turner {
765b6aadd18SAndrew Turner err = m_out_elem.addElem(pElem->getRootIndex());
766*46e6e290SRuslan Bukin if (!err) {
767b6aadd18SAndrew Turner updateContext(pCtxtElem, outElem());
768*46e6e290SRuslan Bukin
769*46e6e290SRuslan Bukin // updated context - need to force this to be output to the client so correct memory
770*46e6e290SRuslan Bukin // context can be used.
771*46e6e290SRuslan Bukin contextFlush = true;
772*46e6e290SRuslan Bukin
773*46e6e290SRuslan Bukin // invalidate memory accessor cacheing - force next memory access out to client to
774*46e6e290SRuslan Bukin // ensure that the correct memory context is in play when decoding subsequent atoms.
775*46e6e290SRuslan Bukin invalidateMemAccCache();
776*46e6e290SRuslan Bukin }
777c120c564SAndrew Turner }
778c120c564SAndrew Turner }
779c120c564SAndrew Turner }
780c120c564SAndrew Turner break;
781c120c564SAndrew Turner
782c120c564SAndrew Turner case P0_EVENT:
783c120c564SAndrew Turner case P0_TS:
784c120c564SAndrew Turner case P0_CC:
785c120c564SAndrew Turner case P0_TS_CC:
786b6aadd18SAndrew Turner err = processTS_CC_EventElem(pElem);
787c120c564SAndrew Turner break;
788c120c564SAndrew Turner
789*46e6e290SRuslan Bukin case P0_MARKER:
790*46e6e290SRuslan Bukin err = processMarkerElem(pElem);
791*46e6e290SRuslan Bukin break;
792*46e6e290SRuslan Bukin
793c120c564SAndrew Turner case P0_ATOM:
794c120c564SAndrew Turner {
795c120c564SAndrew Turner TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
796c120c564SAndrew Turner
797c120c564SAndrew Turner if (pAtomElem)
798c120c564SAndrew Turner {
799b6aadd18SAndrew Turner while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)
800c120c564SAndrew Turner {
801c120c564SAndrew Turner ocsd_atm_val atom = pAtomElem->commitOldest();
802c120c564SAndrew Turner
803c120c564SAndrew Turner // check if prev atom left us an indirect address target on the return stack
804b6aadd18SAndrew Turner if ((err = returnStackPop()) != OCSD_OK)
805c120c564SAndrew Turner break;
806c120c564SAndrew Turner
807c120c564SAndrew Turner // if address and context do instruction trace follower.
808c120c564SAndrew Turner // otherwise skip atom and reduce committed elements
809c120c564SAndrew Turner if (!m_need_ctxt && !m_need_addr)
810c120c564SAndrew Turner {
811b6aadd18SAndrew Turner err = processAtom(atom);
812c120c564SAndrew Turner }
813b6aadd18SAndrew Turner m_elem_res.P0_commit--; // mark committed
814c120c564SAndrew Turner }
815c120c564SAndrew Turner if (!pAtomElem->isEmpty())
816c120c564SAndrew Turner bPopElem = false; // don't remove if still atoms to process.
817c120c564SAndrew Turner }
818c120c564SAndrew Turner }
819c120c564SAndrew Turner break;
820c120c564SAndrew Turner
821c120c564SAndrew Turner case P0_EXCEP:
822c120c564SAndrew Turner // check if prev atom left us an indirect address target on the return stack
823b6aadd18SAndrew Turner if ((err = returnStackPop()) != OCSD_OK)
824c120c564SAndrew Turner break;
825c120c564SAndrew Turner
826b6aadd18SAndrew Turner err = processException(); // output trace + exception elements.
827b6aadd18SAndrew Turner m_elem_res.P0_commit--;
828c120c564SAndrew Turner break;
829c120c564SAndrew Turner
830c120c564SAndrew Turner case P0_EXCEP_RET:
831b6aadd18SAndrew Turner err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
832b6aadd18SAndrew Turner if (!err)
833b6aadd18SAndrew Turner {
834c120c564SAndrew Turner if (pElem->isP0()) // are we on a core that counts ERET as P0?
835b6aadd18SAndrew Turner m_elem_res.P0_commit--;
836b6aadd18SAndrew Turner }
837c120c564SAndrew Turner break;
838c120c564SAndrew Turner
839c120c564SAndrew Turner case P0_FUNC_RET:
840c120c564SAndrew Turner // func ret is V8M - data trace only - hint that data has been popped off the stack.
841c120c564SAndrew Turner // at this point nothing to do till the decoder starts handling data trace.
842c120c564SAndrew Turner if (pElem->isP0())
843b6aadd18SAndrew Turner m_elem_res.P0_commit--;
844b6aadd18SAndrew Turner break;
845b6aadd18SAndrew Turner
846*46e6e290SRuslan Bukin case P0_SRC_ADDR:
847*46e6e290SRuslan Bukin err = processSourceAddress();
848*46e6e290SRuslan Bukin m_elem_res.P0_commit--;
849*46e6e290SRuslan Bukin break;
850*46e6e290SRuslan Bukin
851b6aadd18SAndrew Turner case P0_Q:
852b6aadd18SAndrew Turner err = processQElement();
853b6aadd18SAndrew Turner m_elem_res.P0_commit--;
854c120c564SAndrew Turner break;
855*46e6e290SRuslan Bukin
856*46e6e290SRuslan Bukin case P0_TRANS_START:
857*46e6e290SRuslan Bukin if (m_config->commTransP0())
858*46e6e290SRuslan Bukin m_elem_res.P0_commit--;
859*46e6e290SRuslan Bukin case P0_TRANS_COMMIT:
860*46e6e290SRuslan Bukin case P0_TRANS_FAIL:
861*46e6e290SRuslan Bukin case P0_TRANS_TRACE_INIT:
862*46e6e290SRuslan Bukin err = processTransElem(pElem);
863*46e6e290SRuslan Bukin break;
864*46e6e290SRuslan Bukin
865*46e6e290SRuslan Bukin case P0_ITE:
866*46e6e290SRuslan Bukin err = processITEElem(pElem);
867*46e6e290SRuslan Bukin break;
868c120c564SAndrew Turner }
869c120c564SAndrew Turner
870c120c564SAndrew Turner if(bPopElem)
871c120c564SAndrew Turner m_P0_stack.delete_back(); // remove element from stack;
872c120c564SAndrew Turner }
873c120c564SAndrew Turner else
874c120c564SAndrew Turner {
875c120c564SAndrew Turner // too few elements for commit operation - decode error.
876*46e6e290SRuslan Bukin err = handlePacketSeqErr(OCSD_ERR_COMMIT_PKT_OVERRUN, err_idx, "Not enough elements to commit");
877c120c564SAndrew Turner }
878c120c564SAndrew Turner }
879c120c564SAndrew Turner
880c120c564SAndrew Turner // reduce the spec depth by number of comitted elements
881b6aadd18SAndrew Turner m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit);
882b6aadd18SAndrew Turner return err;
883c120c564SAndrew Turner }
884c120c564SAndrew Turner
returnStackPop()885b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()
886c120c564SAndrew Turner {
887b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
888c120c564SAndrew Turner ocsd_isa nextISA;
889c120c564SAndrew Turner
890c120c564SAndrew Turner if (m_return_stack.pop_pending())
891c120c564SAndrew Turner {
892c120c564SAndrew Turner ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
893c120c564SAndrew Turner if (m_return_stack.overflow())
894c120c564SAndrew Turner {
895b6aadd18SAndrew Turner err = OCSD_ERR_RET_STACK_OVERFLOW;
896*46e6e290SRuslan Bukin err = handlePacketSeqErr(err, OCSD_BAD_TRC_INDEX, "Trace Return Stack Overflow.");
897c120c564SAndrew Turner }
898c120c564SAndrew Turner else
899c120c564SAndrew Turner {
900c120c564SAndrew Turner m_instr_info.instr_addr = popAddr;
901c120c564SAndrew Turner m_instr_info.isa = nextISA;
902c120c564SAndrew Turner m_need_addr = false;
903c120c564SAndrew Turner }
904c120c564SAndrew Turner }
905b6aadd18SAndrew Turner return err;
906c120c564SAndrew Turner }
907c120c564SAndrew Turner
commitElemOnEOT()908b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()
909c120c564SAndrew Turner {
910b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
911c120c564SAndrew Turner TrcStackElem *pElem = 0;
912b6aadd18SAndrew Turner
913b6aadd18SAndrew Turner // nothing outstanding - reset the stack before we add more
914b6aadd18SAndrew Turner if (!m_out_elem.numElemToSend())
915b6aadd18SAndrew Turner m_out_elem.resetElemStack();
916b6aadd18SAndrew Turner
917b6aadd18SAndrew Turner while((m_P0_stack.size() > 0) && !err)
918c120c564SAndrew Turner {
919b6aadd18SAndrew Turner // scan for outstanding events, TS and CC, that appear before any outstanding
920b6aadd18SAndrew Turner // uncommited P0 element.
921c120c564SAndrew Turner pElem = m_P0_stack.back();
922c120c564SAndrew Turner
923c120c564SAndrew Turner switch(pElem->getP0Type())
924c120c564SAndrew Turner {
925c120c564SAndrew Turner // clear stack and stop
926c120c564SAndrew Turner case P0_UNKNOWN:
927c120c564SAndrew Turner case P0_ATOM:
928c120c564SAndrew Turner case P0_TRC_ON:
929c120c564SAndrew Turner case P0_EXCEP:
930c120c564SAndrew Turner case P0_EXCEP_RET:
931c120c564SAndrew Turner case P0_OVERFLOW:
932b6aadd18SAndrew Turner case P0_Q:
933c120c564SAndrew Turner m_P0_stack.delete_all();
934c120c564SAndrew Turner break;
935c120c564SAndrew Turner
936c120c564SAndrew Turner //skip
937c120c564SAndrew Turner case P0_ADDR:
938c120c564SAndrew Turner case P0_CTXT:
939c120c564SAndrew Turner break;
940c120c564SAndrew Turner
941*46e6e290SRuslan Bukin // trans
942*46e6e290SRuslan Bukin // P0 trans - clear and stop, otherwise skip
943*46e6e290SRuslan Bukin case P0_TRANS_START:
944*46e6e290SRuslan Bukin if (m_config->commTransP0())
945*46e6e290SRuslan Bukin m_P0_stack.delete_all();
946*46e6e290SRuslan Bukin break;
947*46e6e290SRuslan Bukin
948*46e6e290SRuslan Bukin // non-speculative trans fail / commit - could appear at EoT after valid trace
949*46e6e290SRuslan Bukin // but without a subsequent P0 that would force output.
950*46e6e290SRuslan Bukin case P0_TRANS_FAIL:
951*46e6e290SRuslan Bukin case P0_TRANS_COMMIT:
952*46e6e290SRuslan Bukin if (m_max_spec_depth == 0 || m_curr_spec_depth == 0)
953*46e6e290SRuslan Bukin err = processTransElem(pElem);
954*46e6e290SRuslan Bukin break;
955*46e6e290SRuslan Bukin
956*46e6e290SRuslan Bukin // others - skip non P0
957*46e6e290SRuslan Bukin case P0_TRANS_TRACE_INIT:
958*46e6e290SRuslan Bukin break;
959*46e6e290SRuslan Bukin
960c120c564SAndrew Turner // output
961c120c564SAndrew Turner case P0_EVENT:
962b6aadd18SAndrew Turner case P0_TS:
963b6aadd18SAndrew Turner case P0_CC:
964b6aadd18SAndrew Turner case P0_TS_CC:
965b6aadd18SAndrew Turner err = processTS_CC_EventElem(pElem);
966b6aadd18SAndrew Turner break;
967*46e6e290SRuslan Bukin
968*46e6e290SRuslan Bukin case P0_MARKER:
969*46e6e290SRuslan Bukin err = processMarkerElem(pElem);
970*46e6e290SRuslan Bukin break;
971*46e6e290SRuslan Bukin
972*46e6e290SRuslan Bukin case P0_ITE:
973*46e6e290SRuslan Bukin err = processITEElem(pElem);
974*46e6e290SRuslan Bukin break;
975b6aadd18SAndrew Turner }
976b6aadd18SAndrew Turner m_P0_stack.delete_back();
977b6aadd18SAndrew Turner }
978b6aadd18SAndrew Turner
979b6aadd18SAndrew Turner if(!err)
980b6aadd18SAndrew Turner {
981b6aadd18SAndrew Turner err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE);
982b6aadd18SAndrew Turner outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT);
983b6aadd18SAndrew Turner }
984b6aadd18SAndrew Turner return err;
985b6aadd18SAndrew Turner }
986b6aadd18SAndrew Turner
987b6aadd18SAndrew Turner // cancel elements. These not output
cancelElements()988b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()
989b6aadd18SAndrew Turner {
990b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
991b6aadd18SAndrew Turner bool P0StackDone = false; // checked all P0 elements on the stack
992b6aadd18SAndrew Turner TrcStackElem *pElem = 0; // stacked element pointer
993b6aadd18SAndrew Turner EtmV4P0Stack temp;
994b6aadd18SAndrew Turner int num_cancel_req = m_elem_res.P0_cancel;
995b6aadd18SAndrew Turner
996b6aadd18SAndrew Turner while (m_elem_res.P0_cancel)
997b6aadd18SAndrew Turner {
998b6aadd18SAndrew Turner //search the stack for the newest elements
999b6aadd18SAndrew Turner if (!P0StackDone)
1000b6aadd18SAndrew Turner {
1001b6aadd18SAndrew Turner if (m_P0_stack.size() == 0)
1002b6aadd18SAndrew Turner P0StackDone = true;
1003b6aadd18SAndrew Turner else
1004b6aadd18SAndrew Turner {
1005b6aadd18SAndrew Turner // get the newest element
1006b6aadd18SAndrew Turner pElem = m_P0_stack.front();
1007b6aadd18SAndrew Turner if (pElem->isP0()) {
1008b6aadd18SAndrew Turner if (pElem->getP0Type() == P0_ATOM)
1009b6aadd18SAndrew Turner {
1010b6aadd18SAndrew Turner TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem;
1011b6aadd18SAndrew Turner // atom - cancel N atoms
1012b6aadd18SAndrew Turner m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel);
1013b6aadd18SAndrew Turner if (pAtomElem->isEmpty())
1014b6aadd18SAndrew Turner m_P0_stack.delete_front(); // remove the element
1015b6aadd18SAndrew Turner }
1016b6aadd18SAndrew Turner else
1017b6aadd18SAndrew Turner {
1018b6aadd18SAndrew Turner m_elem_res.P0_cancel--;
1019b6aadd18SAndrew Turner m_P0_stack.delete_front(); // remove the element
1020b6aadd18SAndrew Turner }
1021b6aadd18SAndrew Turner } else {
1022b6aadd18SAndrew Turner // not P0, make a keep / remove decision
1023b6aadd18SAndrew Turner switch (pElem->getP0Type())
1024b6aadd18SAndrew Turner {
1025b6aadd18SAndrew Turner // keep these
1026b6aadd18SAndrew Turner case P0_EVENT:
1027b6aadd18SAndrew Turner case P0_TS:
1028b6aadd18SAndrew Turner case P0_CC:
1029b6aadd18SAndrew Turner case P0_TS_CC:
1030*46e6e290SRuslan Bukin case P0_MARKER:
1031*46e6e290SRuslan Bukin case P0_ITE:
1032b6aadd18SAndrew Turner m_P0_stack.pop_front(false);
1033b6aadd18SAndrew Turner temp.push_back(pElem);
1034b6aadd18SAndrew Turner break;
1035b6aadd18SAndrew Turner
1036b6aadd18SAndrew Turner default:
1037b6aadd18SAndrew Turner m_P0_stack.delete_front();
1038b6aadd18SAndrew Turner break;
1039b6aadd18SAndrew Turner }
1040b6aadd18SAndrew Turner }
1041*46e6e290SRuslan Bukin if (m_P0_stack.size() == 0)
1042*46e6e290SRuslan Bukin P0StackDone = true;
1043b6aadd18SAndrew Turner }
1044b6aadd18SAndrew Turner }
1045b6aadd18SAndrew Turner // may have some unseen elements
1046b6aadd18SAndrew Turner else if (m_unseen_spec_elem)
1047b6aadd18SAndrew Turner {
1048b6aadd18SAndrew Turner m_unseen_spec_elem--;
1049b6aadd18SAndrew Turner m_elem_res.P0_cancel--;
1050b6aadd18SAndrew Turner }
1051b6aadd18SAndrew Turner // otherwise we have some sort of overrun
1052b6aadd18SAndrew Turner else
1053b6aadd18SAndrew Turner {
1054b6aadd18SAndrew Turner // too few elements for commit operation - decode error.
1055b6aadd18SAndrew Turner err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1056*46e6e290SRuslan Bukin err = handlePacketSeqErr(err, m_index_curr_pkt, "Not enough elements to cancel");
1057b6aadd18SAndrew Turner m_elem_res.P0_cancel = 0;
1058b6aadd18SAndrew Turner break;
1059b6aadd18SAndrew Turner }
1060*46e6e290SRuslan Bukin }
1061b6aadd18SAndrew Turner
1062*46e6e290SRuslan Bukin /* restore any saved elements that are unaffected by cancel. */
1063b6aadd18SAndrew Turner if (temp.size())
1064b6aadd18SAndrew Turner {
1065b6aadd18SAndrew Turner while (temp.size())
1066b6aadd18SAndrew Turner {
1067b6aadd18SAndrew Turner pElem = temp.back();
1068b6aadd18SAndrew Turner m_P0_stack.push_front(pElem);
1069b6aadd18SAndrew Turner temp.pop_back(false);
1070b6aadd18SAndrew Turner }
1071b6aadd18SAndrew Turner }
1072*46e6e290SRuslan Bukin
1073b6aadd18SAndrew Turner m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;
1074b6aadd18SAndrew Turner return err;
1075b6aadd18SAndrew Turner }
1076b6aadd18SAndrew Turner
1077b6aadd18SAndrew Turner // mispredict an atom
mispredictAtom()1078b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()
1079b6aadd18SAndrew Turner {
1080b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1081b6aadd18SAndrew Turner bool bFoundAtom = false, bDone = false;
1082b6aadd18SAndrew Turner TrcStackElem *pElem = 0;
1083b6aadd18SAndrew Turner
1084b6aadd18SAndrew Turner m_P0_stack.from_front_init(); // init iterator at front.
1085b6aadd18SAndrew Turner while (!bDone)
1086b6aadd18SAndrew Turner {
1087b6aadd18SAndrew Turner pElem = m_P0_stack.from_front_next();
1088b6aadd18SAndrew Turner if (pElem)
1089b6aadd18SAndrew Turner {
1090b6aadd18SAndrew Turner if (pElem->getP0Type() == P0_ATOM)
1091b6aadd18SAndrew Turner {
1092b6aadd18SAndrew Turner TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
1093b6aadd18SAndrew Turner if (pAtomElem)
1094b6aadd18SAndrew Turner {
1095b6aadd18SAndrew Turner pAtomElem->mispredictNewest();
1096b6aadd18SAndrew Turner bFoundAtom = true;
1097b6aadd18SAndrew Turner }
1098b6aadd18SAndrew Turner bDone = true;
1099b6aadd18SAndrew Turner }
1100b6aadd18SAndrew Turner else if (pElem->getP0Type() == P0_ADDR)
1101b6aadd18SAndrew Turner {
1102b6aadd18SAndrew Turner // need to disregard any addresses that appear between mispredict and the atom in question
1103b6aadd18SAndrew Turner m_P0_stack.erase_curr_from_front();
1104b6aadd18SAndrew Turner }
1105b6aadd18SAndrew Turner }
1106b6aadd18SAndrew Turner else
1107b6aadd18SAndrew Turner bDone = true;
1108b6aadd18SAndrew Turner }
1109b6aadd18SAndrew Turner
1110b6aadd18SAndrew Turner // if missed atom then either overrun error or mispredict on unseen element
1111b6aadd18SAndrew Turner if (!bFoundAtom && !m_unseen_spec_elem)
1112b6aadd18SAndrew Turner {
1113b6aadd18SAndrew Turner err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1114*46e6e290SRuslan Bukin err = handlePacketSeqErr(err, m_index_curr_pkt, "Not found mispredict atom");
1115*46e6e290SRuslan Bukin //LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));
1116b6aadd18SAndrew Turner }
1117b6aadd18SAndrew Turner m_elem_res.mispredict = false;
1118b6aadd18SAndrew Turner return err;
1119b6aadd18SAndrew Turner }
1120b6aadd18SAndrew Turner
1121b6aadd18SAndrew Turner // discard elements and flush
discardElements()1122b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::discardElements()
1123b6aadd18SAndrew Turner {
1124b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1125b6aadd18SAndrew Turner TrcStackElem *pElem = 0; // stacked element pointer
1126b6aadd18SAndrew Turner
1127b6aadd18SAndrew Turner // dump P0, elemnts - output remaining CC / TS
1128b6aadd18SAndrew Turner while ((m_P0_stack.size() > 0) && !err)
1129b6aadd18SAndrew Turner {
1130b6aadd18SAndrew Turner pElem = m_P0_stack.back();
1131*46e6e290SRuslan Bukin if (pElem->getP0Type() == P0_MARKER)
1132*46e6e290SRuslan Bukin err = processMarkerElem(pElem);
1133*46e6e290SRuslan Bukin else if (pElem->getP0Type() == P0_MARKER)
1134*46e6e290SRuslan Bukin err = processITEElem(pElem);
1135*46e6e290SRuslan Bukin else
1136b6aadd18SAndrew Turner err = processTS_CC_EventElem(pElem);
1137b6aadd18SAndrew Turner m_P0_stack.delete_back();
1138b6aadd18SAndrew Turner }
1139b6aadd18SAndrew Turner
1140b6aadd18SAndrew Turner // clear all speculation info
1141b6aadd18SAndrew Turner clearElemRes();
1142b6aadd18SAndrew Turner m_curr_spec_depth = 0;
1143b6aadd18SAndrew Turner
1144b6aadd18SAndrew Turner // set decode state
1145b6aadd18SAndrew Turner m_curr_state = NO_SYNC;
1146b6aadd18SAndrew Turner m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD;
1147b6aadd18SAndrew Turner
1148b6aadd18SAndrew Turner // unsync so need context & address.
1149b6aadd18SAndrew Turner m_need_ctxt = true;
1150b6aadd18SAndrew Turner m_need_addr = true;
1151b6aadd18SAndrew Turner m_elem_pending_addr = false;
1152b6aadd18SAndrew Turner return err;
1153b6aadd18SAndrew Turner }
1154b6aadd18SAndrew Turner
processTS_CC_EventElem(TrcStackElem * pElem)1155b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)
1156b6aadd18SAndrew Turner {
1157b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1158*46e6e290SRuslan Bukin // ignore ts for ETE if not seen first TS marker on systems that use this.
1159*46e6e290SRuslan Bukin bool bPermitTS = !m_config->eteHasTSMarker() || m_ete_first_ts_marker;
1160b6aadd18SAndrew Turner
1161b6aadd18SAndrew Turner switch (pElem->getP0Type())
1162b6aadd18SAndrew Turner {
1163b6aadd18SAndrew Turner case P0_EVENT:
1164c120c564SAndrew Turner {
1165c120c564SAndrew Turner TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1166c120c564SAndrew Turner if (pParamElem)
1167b6aadd18SAndrew Turner err = addElemEvent(pParamElem);
1168c120c564SAndrew Turner }
1169c120c564SAndrew Turner break;
1170c120c564SAndrew Turner
1171c120c564SAndrew Turner case P0_TS:
1172c120c564SAndrew Turner {
1173c120c564SAndrew Turner TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1174*46e6e290SRuslan Bukin if (pParamElem && bPermitTS)
1175b6aadd18SAndrew Turner err = addElemTS(pParamElem, false);
1176c120c564SAndrew Turner }
1177c120c564SAndrew Turner break;
1178c120c564SAndrew Turner
1179c120c564SAndrew Turner case P0_CC:
1180c120c564SAndrew Turner {
1181c120c564SAndrew Turner TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1182c120c564SAndrew Turner if (pParamElem)
1183b6aadd18SAndrew Turner err = addElemCC(pParamElem);
1184c120c564SAndrew Turner }
1185c120c564SAndrew Turner break;
1186c120c564SAndrew Turner
1187c120c564SAndrew Turner case P0_TS_CC:
1188c120c564SAndrew Turner {
1189c120c564SAndrew Turner TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1190*46e6e290SRuslan Bukin if (pParamElem && bPermitTS)
1191b6aadd18SAndrew Turner err = addElemTS(pParamElem, true);
1192c120c564SAndrew Turner }
1193c120c564SAndrew Turner break;
1194c120c564SAndrew Turner }
1195b6aadd18SAndrew Turner return err;
1196b6aadd18SAndrew Turner
1197c120c564SAndrew Turner }
1198c120c564SAndrew Turner
processMarkerElem(TrcStackElem * pElem)1199*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::processMarkerElem(TrcStackElem *pElem)
1200*46e6e290SRuslan Bukin {
1201*46e6e290SRuslan Bukin ocsd_err_t err = OCSD_OK;
1202*46e6e290SRuslan Bukin TrcStackElemMarker *pMarkerElem = dynamic_cast<TrcStackElemMarker *>(pElem);
1203*46e6e290SRuslan Bukin
1204*46e6e290SRuslan Bukin if (m_config->eteHasTSMarker() && (pMarkerElem->getMarker().type == ELEM_MARKER_TS))
1205*46e6e290SRuslan Bukin m_ete_first_ts_marker = true;
1206*46e6e290SRuslan Bukin
1207*46e6e290SRuslan Bukin if (!err)
1208*46e6e290SRuslan Bukin {
1209*46e6e290SRuslan Bukin err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_SYNC_MARKER);
1210*46e6e290SRuslan Bukin if (!err)
1211*46e6e290SRuslan Bukin m_out_elem.getCurrElem().setSyncMarker(pMarkerElem->getMarker());
1212*46e6e290SRuslan Bukin }
1213*46e6e290SRuslan Bukin return err;
1214*46e6e290SRuslan Bukin }
1215*46e6e290SRuslan Bukin
processTransElem(TrcStackElem * pElem)1216*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::processTransElem(TrcStackElem *pElem)
1217*46e6e290SRuslan Bukin {
1218*46e6e290SRuslan Bukin ocsd_err_t err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_MEMTRANS);
1219*46e6e290SRuslan Bukin if (!err)
1220*46e6e290SRuslan Bukin {
1221*46e6e290SRuslan Bukin outElem().setTransactionType((trace_memtrans_t)((int)OCSD_MEM_TRANS_FAIL -
1222*46e6e290SRuslan Bukin ((int)P0_TRANS_FAIL - (int)pElem->getP0Type())));
1223*46e6e290SRuslan Bukin }
1224*46e6e290SRuslan Bukin return err;
1225*46e6e290SRuslan Bukin }
1226*46e6e290SRuslan Bukin
processITEElem(TrcStackElem * pElem)1227*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::processITEElem(TrcStackElem *pElem)
1228*46e6e290SRuslan Bukin {
1229*46e6e290SRuslan Bukin ocsd_err_t err = OCSD_OK;
1230*46e6e290SRuslan Bukin TrcStackElemITE *pITEElem = dynamic_cast<TrcStackElemITE *>(pElem);
1231*46e6e290SRuslan Bukin
1232*46e6e290SRuslan Bukin err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_INSTRUMENTATION);
1233*46e6e290SRuslan Bukin if (!err) {
1234*46e6e290SRuslan Bukin outElem().setITEInfo(pITEElem->getITE());
1235*46e6e290SRuslan Bukin }
1236*46e6e290SRuslan Bukin return err;
1237*46e6e290SRuslan Bukin }
1238*46e6e290SRuslan Bukin
addElemCC(TrcStackElemParam * pParamElem)1239b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)
1240c120c564SAndrew Turner {
1241b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1242b6aadd18SAndrew Turner
1243b6aadd18SAndrew Turner err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
1244b6aadd18SAndrew Turner if (!err)
1245b6aadd18SAndrew Turner outElem().setCycleCount(pParamElem->getParam(0));
1246b6aadd18SAndrew Turner return err;
1247c120c564SAndrew Turner }
1248c120c564SAndrew Turner
addElemTS(TrcStackElemParam * pParamElem,bool withCC)1249b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)
1250c120c564SAndrew Turner {
1251b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1252c120c564SAndrew Turner
1253b6aadd18SAndrew Turner err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP);
1254b6aadd18SAndrew Turner if (!err)
1255c120c564SAndrew Turner {
1256b6aadd18SAndrew Turner outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
1257c120c564SAndrew Turner if (withCC)
1258b6aadd18SAndrew Turner outElem().setCycleCount(pParamElem->getParam(2));
1259b6aadd18SAndrew Turner }
1260b6aadd18SAndrew Turner return err;
1261c120c564SAndrew Turner }
1262c120c564SAndrew Turner
addElemEvent(TrcStackElemParam * pParamElem)1263b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)
1264c120c564SAndrew Turner {
1265b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1266b6aadd18SAndrew Turner
1267b6aadd18SAndrew Turner err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT);
1268b6aadd18SAndrew Turner if (!err)
1269b6aadd18SAndrew Turner {
1270b6aadd18SAndrew Turner outElem().trace_event.ev_type = EVENT_NUMBERED;
1271b6aadd18SAndrew Turner outElem().trace_event.ev_number = pParamElem->getParam(0);
1272b6aadd18SAndrew Turner }
1273b6aadd18SAndrew Turner return err;
1274c120c564SAndrew Turner }
1275c120c564SAndrew Turner
setElemTraceRange(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index)1276b6aadd18SAndrew Turner void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1277b6aadd18SAndrew Turner const bool executed, ocsd_trc_index_t index)
1278c120c564SAndrew Turner {
1279*46e6e290SRuslan Bukin setElemTraceRangeInstr(elemIn, addr_range, executed, index, m_instr_info);
1280*46e6e290SRuslan Bukin }
1281*46e6e290SRuslan Bukin
setElemTraceRangeInstr(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index,ocsd_instr_info & instr)1282*46e6e290SRuslan Bukin void TrcPktDecodeEtmV4I::setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1283*46e6e290SRuslan Bukin const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr)
1284*46e6e290SRuslan Bukin {
1285b6aadd18SAndrew Turner elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
1286*46e6e290SRuslan Bukin elemIn.setLastInstrInfo(executed, instr.type, instr.sub_type, instr.instr_size);
1287*46e6e290SRuslan Bukin elemIn.setISA(instr.isa);
1288*46e6e290SRuslan Bukin elemIn.setLastInstrCond(instr.is_conditional);
1289b6aadd18SAndrew Turner elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1290c120c564SAndrew Turner if (executed)
1291*46e6e290SRuslan Bukin instr.isa = instr.next_isa;
1292c120c564SAndrew Turner }
1293c120c564SAndrew Turner
processAtom(const ocsd_atm_val atom)1294b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)
1295c120c564SAndrew Turner {
1296c120c564SAndrew Turner ocsd_err_t err;
1297b6aadd18SAndrew Turner TrcStackElem *pElem = m_P0_stack.back(); // get the atom element
1298b6aadd18SAndrew Turner WP_res_t WPRes;
1299b6aadd18SAndrew Turner instr_range_t addr_range;
1300*46e6e290SRuslan Bukin bool ETE_ERET = false;
1301c120c564SAndrew Turner
1302b6aadd18SAndrew Turner // new element for this processed atom
1303b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK)
1304b6aadd18SAndrew Turner return err;
1305b6aadd18SAndrew Turner
1306b6aadd18SAndrew Turner err = traceInstrToWP(addr_range, WPRes);
1307c120c564SAndrew Turner if(err != OCSD_OK)
1308c120c564SAndrew Turner {
1309c120c564SAndrew Turner if(err == OCSD_ERR_UNSUPPORTED_ISA)
1310c120c564SAndrew Turner {
1311c120c564SAndrew Turner m_need_addr = true;
1312c120c564SAndrew Turner m_need_ctxt = true;
1313c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));
1314c120c564SAndrew Turner // wait for next context
1315b6aadd18SAndrew Turner return OCSD_OK;
1316c120c564SAndrew Turner }
1317c120c564SAndrew Turner else
1318c120c564SAndrew Turner {
1319*46e6e290SRuslan Bukin err = handlePacketSeqErr(err, pElem->getRootIndex(), "Error processing atom packet.");
1320*46e6e290SRuslan Bukin //LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));
1321b6aadd18SAndrew Turner return err;
1322c120c564SAndrew Turner }
1323c120c564SAndrew Turner }
1324c120c564SAndrew Turner
1325b6aadd18SAndrew Turner if(WPFound(WPRes))
1326c120c564SAndrew Turner {
1327c120c564SAndrew Turner // save recorded next instuction address
1328c120c564SAndrew Turner ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
1329c120c564SAndrew Turner
1330c120c564SAndrew Turner // action according to waypoint type and atom value
1331c120c564SAndrew Turner switch(m_instr_info.type)
1332c120c564SAndrew Turner {
1333c120c564SAndrew Turner case OCSD_INSTR_BR:
1334c120c564SAndrew Turner if (atom == ATOM_E)
1335c120c564SAndrew Turner {
1336c120c564SAndrew Turner m_instr_info.instr_addr = m_instr_info.branch_addr;
1337c120c564SAndrew Turner if (m_instr_info.is_link)
1338c120c564SAndrew Turner m_return_stack.push(nextAddr, m_instr_info.isa);
1339c120c564SAndrew Turner
1340c120c564SAndrew Turner }
1341c120c564SAndrew Turner break;
1342c120c564SAndrew Turner
1343c120c564SAndrew Turner case OCSD_INSTR_BR_INDIRECT:
1344c120c564SAndrew Turner if (atom == ATOM_E)
1345c120c564SAndrew Turner {
1346c120c564SAndrew Turner m_need_addr = true; // indirect branch taken - need new address.
1347c120c564SAndrew Turner if (m_instr_info.is_link)
1348c120c564SAndrew Turner m_return_stack.push(nextAddr,m_instr_info.isa);
1349c120c564SAndrew Turner m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen
1350*46e6e290SRuslan Bukin
1351*46e6e290SRuslan Bukin /* ETE does not have ERET trace packets - however to maintain the illusion if we see an ERET
1352*46e6e290SRuslan Bukin output a gen elem ERET packet */
1353*46e6e290SRuslan Bukin if (isETEConfig() && (m_instr_info.sub_type == OCSD_S_INSTR_V8_ERET))
1354*46e6e290SRuslan Bukin ETE_ERET = true;
1355c120c564SAndrew Turner }
1356c120c564SAndrew Turner break;
1357c120c564SAndrew Turner }
1358b6aadd18SAndrew Turner setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());
1359*46e6e290SRuslan Bukin
1360*46e6e290SRuslan Bukin if (ETE_ERET)
1361*46e6e290SRuslan Bukin {
1362*46e6e290SRuslan Bukin err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
1363*46e6e290SRuslan Bukin if (err)
1364*46e6e290SRuslan Bukin return err;
1365*46e6e290SRuslan Bukin }
1366c120c564SAndrew Turner }
1367c120c564SAndrew Turner else
1368c120c564SAndrew Turner {
1369c120c564SAndrew Turner // no waypoint - likely inaccessible memory range.
1370c120c564SAndrew Turner m_need_addr = true; // need an address update
1371c120c564SAndrew Turner
1372b6aadd18SAndrew Turner if(addr_range.st_addr != addr_range.en_addr)
1373c120c564SAndrew Turner {
1374c120c564SAndrew Turner // some trace before we were out of memory access range
1375b6aadd18SAndrew Turner setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex());
1376b6aadd18SAndrew Turner
1377b6aadd18SAndrew Turner // another element for the nacc...
1378b6aadd18SAndrew Turner if (WPNacc(WPRes))
1379b6aadd18SAndrew Turner err = m_out_elem.addElem(pElem->getRootIndex());
1380c120c564SAndrew Turner }
1381c120c564SAndrew Turner
1382b6aadd18SAndrew Turner if(WPNacc(WPRes) && !err)
1383c120c564SAndrew Turner {
1384b6aadd18SAndrew Turner outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1385b6aadd18SAndrew Turner outElem().st_addr = m_instr_info.instr_addr;
1386c120c564SAndrew Turner }
1387c120c564SAndrew Turner }
1388b6aadd18SAndrew Turner return err;
1389c120c564SAndrew Turner }
1390c120c564SAndrew Turner
1391c120c564SAndrew Turner // Exception processor
processException()1392b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::processException()
1393c120c564SAndrew Turner {
1394b6aadd18SAndrew Turner ocsd_err_t err;
1395b6aadd18SAndrew Turner TrcStackElem *pElem = 0;
1396b6aadd18SAndrew Turner TrcStackElemExcept *pExceptElem = 0;
1397c120c564SAndrew Turner TrcStackElemAddr *pAddressElem = 0;
1398c120c564SAndrew Turner TrcStackElemCtxt *pCtxtElem = 0;
1399b6aadd18SAndrew Turner bool branch_target = false; // exception address implies prior branch target address
1400*46e6e290SRuslan Bukin ocsd_vaddr_t excep_ret_addr = 0;
1401b6aadd18SAndrew Turner ocsd_trc_index_t excep_pkt_index;
1402b6aadd18SAndrew Turner WP_res_t WPRes = WP_NOT_FOUND;
1403*46e6e290SRuslan Bukin bool ETE_resetPkt = false;
1404c120c564SAndrew Turner
1405b6aadd18SAndrew Turner // grab the exception element off the stack
1406b6aadd18SAndrew Turner pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element
1407b6aadd18SAndrew Turner excep_pkt_index = pExceptElem->getRootIndex();
1408b6aadd18SAndrew Turner branch_target = pExceptElem->getPrevSame();
1409*46e6e290SRuslan Bukin if (pExceptElem->getRootPkt() == ETE_PKT_I_PE_RESET)
1410*46e6e290SRuslan Bukin ETE_resetPkt = true;
1411c120c564SAndrew Turner m_P0_stack.pop_back(); // remove the exception element
1412b6aadd18SAndrew Turner
1413*46e6e290SRuslan Bukin // ETE reset has no follow up address, the rest of the exceptions do....
1414*46e6e290SRuslan Bukin if (!ETE_resetPkt)
1415*46e6e290SRuslan Bukin {
1416c120c564SAndrew Turner pElem = m_P0_stack.back(); // look at next element.
1417c120c564SAndrew Turner if (pElem->getP0Type() == P0_CTXT)
1418c120c564SAndrew Turner {
1419c120c564SAndrew Turner pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1420c120c564SAndrew Turner m_P0_stack.pop_back(); // remove the context element
1421c120c564SAndrew Turner pElem = m_P0_stack.back(); // next one should be an address element
1422c120c564SAndrew Turner }
1423c120c564SAndrew Turner
1424c120c564SAndrew Turner if (pElem->getP0Type() != P0_ADDR)
1425c120c564SAndrew Turner {
1426c120c564SAndrew Turner // no following address element - indicate processing error.
1427*46e6e290SRuslan Bukin
1428*46e6e290SRuslan Bukin err = handlePacketSeqErr(OCSD_ERR_BAD_PACKET_SEQ, m_index_curr_pkt, "Address missing in exception packet.");
1429*46e6e290SRuslan Bukin //LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index, m_CSID, "Address missing in exception packet."));
1430*46e6e290SRuslan Bukin return err;
1431c120c564SAndrew Turner }
1432c120c564SAndrew Turner else
1433c120c564SAndrew Turner {
1434c120c564SAndrew Turner // extract address
1435c120c564SAndrew Turner pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
1436b6aadd18SAndrew Turner excep_ret_addr = pAddressElem->getAddr().val;
1437c120c564SAndrew Turner
1438c120c564SAndrew Turner // see if there is an address + optional context element implied
1439c120c564SAndrew Turner // prior to the exception.
1440b6aadd18SAndrew Turner if (branch_target)
1441c120c564SAndrew Turner {
1442c120c564SAndrew Turner // this was a branch target address - update current setting
1443c120c564SAndrew Turner bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
1444c120c564SAndrew Turner if (pCtxtElem) {
1445c120c564SAndrew Turner b64bit = pCtxtElem->getContext().SF;
1446c120c564SAndrew Turner }
1447b6aadd18SAndrew Turner
1448b6aadd18SAndrew Turner // as the exception address was also a branch target address then update the
1449b6aadd18SAndrew Turner // current maintained address value. This also means that there is no range to
1450b6aadd18SAndrew Turner // output before the exception packet.
1451b6aadd18SAndrew Turner m_instr_info.instr_addr = excep_ret_addr;
1452b6aadd18SAndrew Turner m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?
1453c120c564SAndrew Turner (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
1454c120c564SAndrew Turner m_need_addr = false;
1455c120c564SAndrew Turner }
1456c120c564SAndrew Turner }
1457*46e6e290SRuslan Bukin }
1458c120c564SAndrew Turner
1459b6aadd18SAndrew Turner // need to output something - set up an element
1460b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(excep_pkt_index)))
1461b6aadd18SAndrew Turner return err;
1462b6aadd18SAndrew Turner
1463b6aadd18SAndrew Turner // output a context element if present
1464b6aadd18SAndrew Turner if (pCtxtElem)
1465c120c564SAndrew Turner {
1466b6aadd18SAndrew Turner updateContext(pCtxtElem, outElem());
1467b6aadd18SAndrew Turner
1468b6aadd18SAndrew Turner // used the element - need another for later stages
1469b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(excep_pkt_index)))
1470b6aadd18SAndrew Turner return err;
1471c120c564SAndrew Turner }
1472c120c564SAndrew Turner
1473*46e6e290SRuslan Bukin if (!ETE_resetPkt)
1474*46e6e290SRuslan Bukin {
1475b6aadd18SAndrew Turner // if the preferred return address is not the end of the last output range...
1476b6aadd18SAndrew Turner if (m_instr_info.instr_addr != excep_ret_addr)
1477c120c564SAndrew Turner {
1478b6aadd18SAndrew Turner bool range_out = false;
1479b6aadd18SAndrew Turner instr_range_t addr_range;
1480c120c564SAndrew Turner
1481c120c564SAndrew Turner // look for match to return address.
1482b6aadd18SAndrew Turner err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);
1483c120c564SAndrew Turner
1484c120c564SAndrew Turner if (err != OCSD_OK)
1485c120c564SAndrew Turner {
1486c120c564SAndrew Turner if (err == OCSD_ERR_UNSUPPORTED_ISA)
1487c120c564SAndrew Turner {
1488c120c564SAndrew Turner m_need_addr = true;
1489c120c564SAndrew Turner m_need_ctxt = true;
1490b6aadd18SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_WARN, err, excep_pkt_index, m_CSID, "Warning: unsupported instruction set processing exception packet."));
1491c120c564SAndrew Turner }
1492c120c564SAndrew Turner else
1493c120c564SAndrew Turner {
1494b6aadd18SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, excep_pkt_index, m_CSID, "Error processing exception packet."));
1495c120c564SAndrew Turner }
1496b6aadd18SAndrew Turner return err;
1497c120c564SAndrew Turner }
1498c120c564SAndrew Turner
1499b6aadd18SAndrew Turner if (WPFound(WPRes))
1500c120c564SAndrew Turner {
1501c120c564SAndrew Turner // waypoint address found - output range
1502b6aadd18SAndrew Turner setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1503b6aadd18SAndrew Turner range_out = true;
1504c120c564SAndrew Turner }
1505c120c564SAndrew Turner else
1506c120c564SAndrew Turner {
1507c120c564SAndrew Turner // no waypoint - likely inaccessible memory range.
1508c120c564SAndrew Turner m_need_addr = true; // need an address update
1509c120c564SAndrew Turner
1510b6aadd18SAndrew Turner if (addr_range.st_addr != addr_range.en_addr)
1511c120c564SAndrew Turner {
1512c120c564SAndrew Turner // some trace before we were out of memory access range
1513b6aadd18SAndrew Turner setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1514b6aadd18SAndrew Turner range_out = true;
1515c120c564SAndrew Turner }
1516c120c564SAndrew Turner }
1517c120c564SAndrew Turner
1518b6aadd18SAndrew Turner // used the element need another for NACC or EXCEP.
1519b6aadd18SAndrew Turner if (range_out)
1520c120c564SAndrew Turner {
1521b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(excep_pkt_index)))
1522b6aadd18SAndrew Turner return err;
1523b6aadd18SAndrew Turner }
1524c120c564SAndrew Turner }
1525c120c564SAndrew Turner
1526b6aadd18SAndrew Turner // watchpoint walk resulted in inaccessible memory call...
1527b6aadd18SAndrew Turner if (WPNacc(WPRes))
1528c120c564SAndrew Turner {
1529b6aadd18SAndrew Turner
1530b6aadd18SAndrew Turner outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1531b6aadd18SAndrew Turner outElem().st_addr = m_instr_info.instr_addr;
1532b6aadd18SAndrew Turner
1533b6aadd18SAndrew Turner // used the element - need another for the final exception packet.
1534b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(excep_pkt_index)))
1535b6aadd18SAndrew Turner return err;
1536b6aadd18SAndrew Turner }
1537*46e6e290SRuslan Bukin }
1538b6aadd18SAndrew Turner
1539b6aadd18SAndrew Turner // output exception element.
1540b6aadd18SAndrew Turner outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
1541b6aadd18SAndrew Turner
1542c120c564SAndrew Turner // add end address as preferred return address to end addr in element
1543b6aadd18SAndrew Turner outElem().en_addr = excep_ret_addr;
1544b6aadd18SAndrew Turner outElem().excep_ret_addr = 1;
1545b6aadd18SAndrew Turner outElem().excep_ret_addr_br_tgt = branch_target;
1546b6aadd18SAndrew Turner outElem().exception_number = pExceptElem->getExcepNum();
1547b6aadd18SAndrew Turner
1548b6aadd18SAndrew Turner m_P0_stack.delete_popped(); // clear the used elements from the stack
1549b6aadd18SAndrew Turner return err;
1550c120c564SAndrew Turner }
1551c120c564SAndrew Turner
processQElement()1552b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::processQElement()
1553c120c564SAndrew Turner {
1554b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1555b6aadd18SAndrew Turner TrcStackQElem *pQElem;
1556b6aadd18SAndrew Turner etmv4_addr_val_t QAddr; // address where trace restarts
1557b6aadd18SAndrew Turner int iCount = 0;
1558b6aadd18SAndrew Turner
1559b6aadd18SAndrew Turner pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back()); // get the exception element
1560b6aadd18SAndrew Turner m_P0_stack.pop_back(); // remove the Q element.
1561b6aadd18SAndrew Turner
1562b6aadd18SAndrew Turner if (!pQElem->hasAddr()) // no address - it must be next on the stack....
1563b6aadd18SAndrew Turner {
1564b6aadd18SAndrew Turner TrcStackElemAddr *pAddressElem = 0;
1565b6aadd18SAndrew Turner TrcStackElemCtxt *pCtxtElem = 0;
1566b6aadd18SAndrew Turner TrcStackElem *pElem = 0;
1567b6aadd18SAndrew Turner
1568b6aadd18SAndrew Turner pElem = m_P0_stack.back(); // look at next element.
1569b6aadd18SAndrew Turner if (pElem->getP0Type() == P0_CTXT)
1570b6aadd18SAndrew Turner {
1571b6aadd18SAndrew Turner pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1572b6aadd18SAndrew Turner m_P0_stack.pop_back(); // remove the context element
1573b6aadd18SAndrew Turner pElem = m_P0_stack.back(); // next one should be an address element
1574c120c564SAndrew Turner }
1575c120c564SAndrew Turner
1576b6aadd18SAndrew Turner if (pElem->getP0Type() != P0_ADDR)
1577b6aadd18SAndrew Turner {
1578b6aadd18SAndrew Turner // no following address element - indicate processing error.
1579b6aadd18SAndrew Turner err = OCSD_ERR_BAD_PACKET_SEQ;
1580b6aadd18SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet."));
1581b6aadd18SAndrew Turner m_P0_stack.delete_popped();
1582b6aadd18SAndrew Turner return err;
1583b6aadd18SAndrew Turner }
1584b6aadd18SAndrew Turner pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem);
1585b6aadd18SAndrew Turner QAddr = pAddressElem->getAddr();
1586b6aadd18SAndrew Turner m_P0_stack.pop_back(); // remove the address element
1587b6aadd18SAndrew Turner m_P0_stack.delete_popped(); // clear used elements
1588b6aadd18SAndrew Turner
1589b6aadd18SAndrew Turner // return the context element for processing next time.
1590b6aadd18SAndrew Turner if (pCtxtElem)
1591b6aadd18SAndrew Turner {
1592b6aadd18SAndrew Turner // need a new copy at the back - old one will be deleted as popped.
1593b6aadd18SAndrew Turner m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true);
1594b6aadd18SAndrew Turner }
1595b6aadd18SAndrew Turner }
1596b6aadd18SAndrew Turner else
1597b6aadd18SAndrew Turner QAddr = pQElem->getAddr();
1598b6aadd18SAndrew Turner
1599b6aadd18SAndrew Turner // process the Q element with address.
1600b6aadd18SAndrew Turner iCount = pQElem->getInstrCount();
1601b6aadd18SAndrew Turner
1602b6aadd18SAndrew Turner bool isBranch = false;
1603b6aadd18SAndrew Turner
1604b6aadd18SAndrew Turner // need to output something - set up an element
1605b6aadd18SAndrew Turner if ((err = m_out_elem.addElem(pQElem->getRootIndex())))
1606b6aadd18SAndrew Turner return err;
1607b6aadd18SAndrew Turner
1608b6aadd18SAndrew Turner instr_range_t addr_range;
1609b6aadd18SAndrew Turner addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr;
1610b6aadd18SAndrew Turner addr_range.num_instr = 0;
1611b6aadd18SAndrew Turner
1612b6aadd18SAndrew Turner // walk iCount instructions
1613b6aadd18SAndrew Turner for (int i = 0; i < iCount; i++)
1614c120c564SAndrew Turner {
1615c120c564SAndrew Turner uint32_t opcode;
1616b6aadd18SAndrew Turner uint32_t bytesReq = 4;
1617c120c564SAndrew Turner
1618b6aadd18SAndrew Turner err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1619c120c564SAndrew Turner if (err != OCSD_OK) break;
1620c120c564SAndrew Turner
1621c120c564SAndrew Turner if (bytesReq == 4) // got data back
1622c120c564SAndrew Turner {
1623c120c564SAndrew Turner m_instr_info.opcode = opcode;
1624c120c564SAndrew Turner err = instrDecode(&m_instr_info);
1625c120c564SAndrew Turner if (err != OCSD_OK) break;
1626c120c564SAndrew Turner
1627c120c564SAndrew Turner // increment address - may be adjusted by direct branch value later
1628c120c564SAndrew Turner m_instr_info.instr_addr += m_instr_info.instr_size;
1629b6aadd18SAndrew Turner addr_range.num_instr++;
1630c120c564SAndrew Turner
1631b6aadd18SAndrew Turner isBranch = (m_instr_info.type == OCSD_INSTR_BR) ||
1632b6aadd18SAndrew Turner (m_instr_info.type == OCSD_INSTR_BR_INDIRECT);
1633b6aadd18SAndrew Turner
1634b6aadd18SAndrew Turner // on a branch no way of knowing if taken - bail out
1635b6aadd18SAndrew Turner if (isBranch)
1636b6aadd18SAndrew Turner break;
1637b6aadd18SAndrew Turner }
1638b6aadd18SAndrew Turner else
1639b6aadd18SAndrew Turner break; // missing memory
1640b6aadd18SAndrew Turner
1641b6aadd18SAndrew Turner }
1642b6aadd18SAndrew Turner
1643b6aadd18SAndrew Turner if (err == OCSD_OK)
1644b6aadd18SAndrew Turner {
1645b6aadd18SAndrew Turner bool inCompleteRange = true;
1646b6aadd18SAndrew Turner if (iCount && (addr_range.num_instr == (unsigned)iCount))
1647b6aadd18SAndrew Turner {
1648b6aadd18SAndrew Turner if ((m_instr_info.instr_addr == QAddr.val) || // complete range
1649b6aadd18SAndrew Turner (isBranch)) // or ends on branch - only way we know if branch taken.
1650b6aadd18SAndrew Turner {
1651b6aadd18SAndrew Turner // output a range and continue
1652b6aadd18SAndrew Turner inCompleteRange = false;
1653c120c564SAndrew Turner // update the range decoded address in the output packet.
1654b6aadd18SAndrew Turner addr_range.en_addr = m_instr_info.instr_addr;
1655b6aadd18SAndrew Turner setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex());
1656b6aadd18SAndrew Turner }
1657b6aadd18SAndrew Turner }
1658b6aadd18SAndrew Turner
1659b6aadd18SAndrew Turner if (inCompleteRange)
1660b6aadd18SAndrew Turner {
1661b6aadd18SAndrew Turner // unknown instructions executed.
1662b6aadd18SAndrew Turner addr_range.en_addr = QAddr.val;
1663b6aadd18SAndrew Turner addr_range.num_instr = iCount;
1664b6aadd18SAndrew Turner
1665b6aadd18SAndrew Turner outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH);
1666b6aadd18SAndrew Turner outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1667b6aadd18SAndrew Turner outElem().setISA(calcISA(m_is_64bit, QAddr.isa));
1668b6aadd18SAndrew Turner }
1669b6aadd18SAndrew Turner
1670b6aadd18SAndrew Turner // after the Q element, tracing resumes at the address supplied
1671b6aadd18SAndrew Turner SetInstrInfoInAddrISA(QAddr.val, QAddr.isa);
1672b6aadd18SAndrew Turner m_need_addr = false;
1673b6aadd18SAndrew Turner }
1674b6aadd18SAndrew Turner else
1675b6aadd18SAndrew Turner {
1676b6aadd18SAndrew Turner // output error and halt decode.
1677b6aadd18SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet"));
1678b6aadd18SAndrew Turner }
1679b6aadd18SAndrew Turner m_P0_stack.delete_popped();
1680b6aadd18SAndrew Turner return err;
1681b6aadd18SAndrew Turner }
1682b6aadd18SAndrew Turner
processSourceAddress()1683*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::processSourceAddress()
1684*46e6e290SRuslan Bukin {
1685*46e6e290SRuslan Bukin ocsd_err_t err = OCSD_OK;
1686*46e6e290SRuslan Bukin TrcStackElemAddr *pElem = dynamic_cast<TrcStackElemAddr *>(m_P0_stack.back()); // get the address element
1687*46e6e290SRuslan Bukin etmv4_addr_val_t srcAddr = pElem->getAddr();
1688*46e6e290SRuslan Bukin uint32_t opcode, bytesReq = 4;
1689*46e6e290SRuslan Bukin ocsd_vaddr_t currAddr = m_instr_info.instr_addr; // get the latest decoded address.
1690*46e6e290SRuslan Bukin instr_range_t out_range;
1691*46e6e290SRuslan Bukin bool bSplitRangeOnN = getComponentOpMode() & ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS ? true : false;
1692*46e6e290SRuslan Bukin
1693*46e6e290SRuslan Bukin // check we can read instruction @ source address
1694*46e6e290SRuslan Bukin err = accessMemory(srcAddr.val, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1695*46e6e290SRuslan Bukin if (err != OCSD_OK)
1696*46e6e290SRuslan Bukin {
1697*46e6e290SRuslan Bukin LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1698*46e6e290SRuslan Bukin return err;
1699*46e6e290SRuslan Bukin }
1700*46e6e290SRuslan Bukin
1701*46e6e290SRuslan Bukin if (bytesReq != 4)
1702*46e6e290SRuslan Bukin {
1703*46e6e290SRuslan Bukin // can't access - no bytes returned - output nacc.
1704*46e6e290SRuslan Bukin err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1705*46e6e290SRuslan Bukin outElem().setAddrStart(srcAddr.val);
1706*46e6e290SRuslan Bukin return err;
1707*46e6e290SRuslan Bukin }
1708*46e6e290SRuslan Bukin
1709*46e6e290SRuslan Bukin // analyze opcode @ source address.
1710*46e6e290SRuslan Bukin m_instr_info.opcode = opcode;
1711*46e6e290SRuslan Bukin m_instr_info.instr_addr = srcAddr.val;
1712*46e6e290SRuslan Bukin err = instrDecode(&m_instr_info);
1713*46e6e290SRuslan Bukin if (err != OCSD_OK)
1714*46e6e290SRuslan Bukin {
1715*46e6e290SRuslan Bukin LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1716*46e6e290SRuslan Bukin return err;
1717*46e6e290SRuslan Bukin }
1718*46e6e290SRuslan Bukin m_instr_info.instr_addr += m_instr_info.instr_size;
1719*46e6e290SRuslan Bukin
1720*46e6e290SRuslan Bukin // initial instruction count for the range.
1721*46e6e290SRuslan Bukin out_range.num_instr = 1;
1722*46e6e290SRuslan Bukin
1723*46e6e290SRuslan Bukin // calculate range traced...
1724*46e6e290SRuslan Bukin if (m_need_addr || (currAddr > srcAddr.val))
1725*46e6e290SRuslan Bukin {
1726*46e6e290SRuslan Bukin // we were waiting for a target address, or missing trace
1727*46e6e290SRuslan Bukin // that indicates how we got to the source address.
1728*46e6e290SRuslan Bukin m_need_addr = false;
1729*46e6e290SRuslan Bukin out_range.st_addr = srcAddr.val;
1730*46e6e290SRuslan Bukin }
1731*46e6e290SRuslan Bukin else
1732*46e6e290SRuslan Bukin out_range.st_addr = currAddr;
1733*46e6e290SRuslan Bukin out_range.en_addr = m_instr_info.instr_addr;
1734*46e6e290SRuslan Bukin
1735*46e6e290SRuslan Bukin // count instructions
1736*46e6e290SRuslan Bukin if (out_range.en_addr - out_range.st_addr > m_instr_info.instr_size)
1737*46e6e290SRuslan Bukin {
1738*46e6e290SRuslan Bukin if ((m_instr_info.isa != ocsd_isa_thumb2) && !bSplitRangeOnN)
1739*46e6e290SRuslan Bukin {
1740*46e6e290SRuslan Bukin // all 4 byte instructions - just calculate...
1741*46e6e290SRuslan Bukin out_range.num_instr = (uint32_t)(out_range.en_addr - out_range.st_addr) / 4;
1742*46e6e290SRuslan Bukin }
1743*46e6e290SRuslan Bukin else
1744*46e6e290SRuslan Bukin {
1745*46e6e290SRuslan Bukin // need to count T32 - 2 or 4 byte instructions or we are spotting N atoms
1746*46e6e290SRuslan Bukin ocsd_instr_info instr; // going back to start of range so make a copy of info.
1747*46e6e290SRuslan Bukin bool bMemAccErr = false;
1748*46e6e290SRuslan Bukin
1749*46e6e290SRuslan Bukin instr.instr_addr = out_range.st_addr;
1750*46e6e290SRuslan Bukin instr.isa = m_instr_info.isa;
1751*46e6e290SRuslan Bukin instr.pe_type = m_instr_info.pe_type;
1752*46e6e290SRuslan Bukin instr.dsb_dmb_waypoints = m_instr_info.dsb_dmb_waypoints;
1753*46e6e290SRuslan Bukin instr.wfi_wfe_branch = m_instr_info.wfi_wfe_branch;
1754*46e6e290SRuslan Bukin out_range.num_instr = 0;
1755*46e6e290SRuslan Bukin
1756*46e6e290SRuslan Bukin while ((instr.instr_addr < out_range.en_addr) && !bMemAccErr)
1757*46e6e290SRuslan Bukin {
1758*46e6e290SRuslan Bukin bytesReq = 4;
1759*46e6e290SRuslan Bukin err = accessMemory(instr.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1760*46e6e290SRuslan Bukin if (err != OCSD_OK)
1761*46e6e290SRuslan Bukin {
1762*46e6e290SRuslan Bukin LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1763*46e6e290SRuslan Bukin return err;
1764*46e6e290SRuslan Bukin }
1765*46e6e290SRuslan Bukin
1766*46e6e290SRuslan Bukin if (bytesReq == 4)
1767*46e6e290SRuslan Bukin {
1768*46e6e290SRuslan Bukin instr.opcode = opcode;
1769*46e6e290SRuslan Bukin err = instrDecode(&instr);
1770*46e6e290SRuslan Bukin if (err != OCSD_OK)
1771*46e6e290SRuslan Bukin {
1772*46e6e290SRuslan Bukin LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1773*46e6e290SRuslan Bukin return err;
1774*46e6e290SRuslan Bukin }
1775*46e6e290SRuslan Bukin
1776*46e6e290SRuslan Bukin instr.instr_addr += instr.instr_size;
1777*46e6e290SRuslan Bukin out_range.num_instr++;
1778*46e6e290SRuslan Bukin
1779*46e6e290SRuslan Bukin /* if we are doing N atom ranges ...*/
1780*46e6e290SRuslan Bukin if (bSplitRangeOnN && (instr.instr_addr < out_range.en_addr))
1781*46e6e290SRuslan Bukin {
1782*46e6e290SRuslan Bukin if (instr.type != OCSD_INSTR_OTHER)
1783*46e6e290SRuslan Bukin {
1784*46e6e290SRuslan Bukin instr_range_t mid_range = out_range;
1785*46e6e290SRuslan Bukin mid_range.en_addr = instr.instr_addr;
1786*46e6e290SRuslan Bukin
1787*46e6e290SRuslan Bukin err = m_out_elem.addElem(pElem->getRootIndex());
1788*46e6e290SRuslan Bukin if (err)
1789*46e6e290SRuslan Bukin return err;
1790*46e6e290SRuslan Bukin setElemTraceRangeInstr(outElem(), mid_range, false, pElem->getRootIndex(), instr);
1791*46e6e290SRuslan Bukin
1792*46e6e290SRuslan Bukin out_range.st_addr = mid_range.en_addr;
1793*46e6e290SRuslan Bukin out_range.num_instr = 0;
1794*46e6e290SRuslan Bukin }
1795*46e6e290SRuslan Bukin }
1796*46e6e290SRuslan Bukin }
1797*46e6e290SRuslan Bukin else
1798*46e6e290SRuslan Bukin {
1799*46e6e290SRuslan Bukin // something inaccessible between last and current...
1800*46e6e290SRuslan Bukin bMemAccErr = true;
1801*46e6e290SRuslan Bukin
1802*46e6e290SRuslan Bukin err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1803*46e6e290SRuslan Bukin if (err)
1804*46e6e290SRuslan Bukin return err;
1805*46e6e290SRuslan Bukin outElem().setAddrStart(srcAddr.val);
1806*46e6e290SRuslan Bukin
1807*46e6e290SRuslan Bukin // force range to the one instruction
1808*46e6e290SRuslan Bukin out_range.num_instr = 1;
1809*46e6e290SRuslan Bukin out_range.st_addr = srcAddr.val;
1810*46e6e290SRuslan Bukin out_range.en_addr = m_instr_info.instr_addr; // instr after the decoded instruction @ srcAddr.
1811*46e6e290SRuslan Bukin }
1812*46e6e290SRuslan Bukin }
1813*46e6e290SRuslan Bukin }
1814*46e6e290SRuslan Bukin }
1815*46e6e290SRuslan Bukin
1816*46e6e290SRuslan Bukin // got to the source address - output trace range, and instruction as E atom.
1817*46e6e290SRuslan Bukin switch (m_instr_info.type)
1818*46e6e290SRuslan Bukin {
1819*46e6e290SRuslan Bukin case OCSD_INSTR_BR:
1820*46e6e290SRuslan Bukin if (m_instr_info.is_link)
1821*46e6e290SRuslan Bukin m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1822*46e6e290SRuslan Bukin m_instr_info.instr_addr = m_instr_info.branch_addr;
1823*46e6e290SRuslan Bukin break;
1824*46e6e290SRuslan Bukin
1825*46e6e290SRuslan Bukin case OCSD_INSTR_BR_INDIRECT:
1826*46e6e290SRuslan Bukin m_need_addr = true; // indirect branch taken - need new address.
1827*46e6e290SRuslan Bukin if (m_instr_info.is_link)
1828*46e6e290SRuslan Bukin m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1829*46e6e290SRuslan Bukin m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen
1830*46e6e290SRuslan Bukin break;
1831*46e6e290SRuslan Bukin }
1832*46e6e290SRuslan Bukin m_instr_info.isa = m_instr_info.next_isa;
1833*46e6e290SRuslan Bukin
1834*46e6e290SRuslan Bukin // set the trace range element.
1835*46e6e290SRuslan Bukin m_out_elem.addElem(pElem->getRootIndex());
1836*46e6e290SRuslan Bukin setElemTraceRange(outElem(), out_range, true, pElem->getRootIndex());
1837*46e6e290SRuslan Bukin return err;
1838*46e6e290SRuslan Bukin }
1839*46e6e290SRuslan Bukin
SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val,const uint8_t isa)1840b6aadd18SAndrew Turner void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
1841b6aadd18SAndrew Turner {
1842b6aadd18SAndrew Turner m_instr_info.instr_addr = addr_val;
1843b6aadd18SAndrew Turner m_instr_info.isa = calcISA(m_is_64bit, isa);
1844b6aadd18SAndrew Turner }
1845b6aadd18SAndrew Turner
1846b6aadd18SAndrew Turner // trace an instruction range to a waypoint - and set next address to restart from.
traceInstrToWP(instr_range_t & range,WP_res_t & WPRes,const bool traceToAddrNext,const ocsd_vaddr_t nextAddrMatch)1847b6aadd18SAndrew Turner ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
1848b6aadd18SAndrew Turner {
1849b6aadd18SAndrew Turner uint32_t opcode;
1850b6aadd18SAndrew Turner uint32_t bytesReq;
1851b6aadd18SAndrew Turner ocsd_err_t err = OCSD_OK;
1852b6aadd18SAndrew Turner
1853b6aadd18SAndrew Turner range.st_addr = range.en_addr = m_instr_info.instr_addr;
1854b6aadd18SAndrew Turner range.num_instr = 0;
1855b6aadd18SAndrew Turner
1856b6aadd18SAndrew Turner WPRes = WP_NOT_FOUND;
1857b6aadd18SAndrew Turner
1858b6aadd18SAndrew Turner while(WPRes == WP_NOT_FOUND)
1859b6aadd18SAndrew Turner {
1860b6aadd18SAndrew Turner // start off by reading next opcode;
1861b6aadd18SAndrew Turner bytesReq = 4;
1862b6aadd18SAndrew Turner err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);
1863b6aadd18SAndrew Turner if(err != OCSD_OK) break;
1864b6aadd18SAndrew Turner
1865b6aadd18SAndrew Turner if(bytesReq == 4) // got data back
1866b6aadd18SAndrew Turner {
1867b6aadd18SAndrew Turner m_instr_info.opcode = opcode;
1868b6aadd18SAndrew Turner err = instrDecode(&m_instr_info);
1869b6aadd18SAndrew Turner if(err != OCSD_OK) break;
1870b6aadd18SAndrew Turner
1871b6aadd18SAndrew Turner // increment address - may be adjusted by direct branch value later
1872b6aadd18SAndrew Turner m_instr_info.instr_addr += m_instr_info.instr_size;
1873b6aadd18SAndrew Turner range.num_instr++;
1874c120c564SAndrew Turner
1875c120c564SAndrew Turner // either walking to match the next instruction address or a real watchpoint
1876c120c564SAndrew Turner if (traceToAddrNext)
1877b6aadd18SAndrew Turner {
1878b6aadd18SAndrew Turner if (m_instr_info.instr_addr == nextAddrMatch)
1879b6aadd18SAndrew Turner WPRes = WP_FOUND;
1880b6aadd18SAndrew Turner }
1881b6aadd18SAndrew Turner else if (m_instr_info.type != OCSD_INSTR_OTHER)
1882b6aadd18SAndrew Turner WPRes = WP_FOUND;
1883c120c564SAndrew Turner }
1884c120c564SAndrew Turner else
1885c120c564SAndrew Turner {
1886c120c564SAndrew Turner // not enough memory accessible.
1887b6aadd18SAndrew Turner WPRes = WP_NACC;
1888c120c564SAndrew Turner }
1889c120c564SAndrew Turner }
1890b6aadd18SAndrew Turner // update the range decoded address in the output packet.
1891b6aadd18SAndrew Turner range.en_addr = m_instr_info.instr_addr;
1892b6aadd18SAndrew Turner return err;
1893b6aadd18SAndrew Turner }
1894b6aadd18SAndrew Turner
updateContext(TrcStackElemCtxt * pCtxtElem,OcsdTraceElement & elem)1895b6aadd18SAndrew Turner void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)
1896b6aadd18SAndrew Turner {
1897b6aadd18SAndrew Turner etmv4_context_t ctxt = pCtxtElem->getContext();
1898b6aadd18SAndrew Turner
1899b6aadd18SAndrew Turner elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
1900b6aadd18SAndrew Turner
1901b6aadd18SAndrew Turner // map to output element and local saved state.
1902b6aadd18SAndrew Turner m_is_64bit = (ctxt.SF != 0);
1903b6aadd18SAndrew Turner elem.context.bits64 = ctxt.SF;
1904b6aadd18SAndrew Turner m_is_secure = (ctxt.NS == 0);
1905*46e6e290SRuslan Bukin if (ctxt.NSE)
1906*46e6e290SRuslan Bukin elem.context.security_level = ctxt.NS ? ocsd_sec_realm : ocsd_sec_root;
1907*46e6e290SRuslan Bukin else
1908b6aadd18SAndrew Turner elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
1909b6aadd18SAndrew Turner elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
1910b6aadd18SAndrew Turner elem.context.el_valid = 1;
1911b6aadd18SAndrew Turner if(ctxt.updated_c)
1912b6aadd18SAndrew Turner {
1913b6aadd18SAndrew Turner elem.context.ctxt_id_valid = 1;
1914b6aadd18SAndrew Turner m_context_id = elem.context.context_id = ctxt.ctxtID;
1915b6aadd18SAndrew Turner }
1916b6aadd18SAndrew Turner if(ctxt.updated_v)
1917b6aadd18SAndrew Turner {
1918b6aadd18SAndrew Turner elem.context.vmid_valid = 1;
1919b6aadd18SAndrew Turner m_vmid_id = elem.context.vmid = ctxt.VMID;
1920b6aadd18SAndrew Turner }
1921b6aadd18SAndrew Turner
1922b6aadd18SAndrew Turner // need to update ISA in case context follows address.
1923b6aadd18SAndrew Turner elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
1924b6aadd18SAndrew Turner m_need_ctxt = false;
1925b6aadd18SAndrew Turner }
1926b6aadd18SAndrew Turner
handleBadPacket(const char * reason,ocsd_trc_index_t index)1927*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason, ocsd_trc_index_t index /* = OCSD_BAD_TRC_INDEX */)
1928b6aadd18SAndrew Turner {
1929*46e6e290SRuslan Bukin ocsd_err_severity_t sev = OCSD_ERR_SEV_WARN;
1930b6aadd18SAndrew Turner if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
1931*46e6e290SRuslan Bukin sev = OCSD_ERR_SEV_ERROR;
1932*46e6e290SRuslan Bukin
1933*46e6e290SRuslan Bukin return handlePacketErr(OCSD_ERR_BAD_DECODE_PKT, sev, index, reason);
1934b6aadd18SAndrew Turner }
1935*46e6e290SRuslan Bukin
handlePacketSeqErr(ocsd_err_t err,ocsd_trc_index_t index,const char * reason)1936*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason)
1937b6aadd18SAndrew Turner {
1938*46e6e290SRuslan Bukin return handlePacketErr(err, OCSD_ERR_SEV_ERROR, index, reason);
1939*46e6e290SRuslan Bukin }
1940*46e6e290SRuslan Bukin
handlePacketErr(ocsd_err_t err,ocsd_err_severity_t sev,ocsd_trc_index_t index,const char * reason)1941*46e6e290SRuslan Bukin ocsd_err_t TrcPktDecodeEtmV4I::handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason)
1942*46e6e290SRuslan Bukin {
1943*46e6e290SRuslan Bukin bool resetOnBadPackets = true;
1944*46e6e290SRuslan Bukin
1945*46e6e290SRuslan Bukin if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS)
1946*46e6e290SRuslan Bukin resetOnBadPackets = false;
1947*46e6e290SRuslan Bukin
1948*46e6e290SRuslan Bukin LogError(ocsdError(sev, err, index, getCoreSightTraceID(), reason));
1949*46e6e290SRuslan Bukin
1950*46e6e290SRuslan Bukin if (resetOnBadPackets)
1951*46e6e290SRuslan Bukin {
1952b6aadd18SAndrew Turner // switch to unsync - clear decode state
1953b6aadd18SAndrew Turner resetDecoder();
1954b6aadd18SAndrew Turner m_curr_state = NO_SYNC;
1955b6aadd18SAndrew Turner m_unsync_eot_info = UNSYNC_BAD_PACKET;
1956*46e6e290SRuslan Bukin err = OCSD_OK;
1957b6aadd18SAndrew Turner }
1958c120c564SAndrew Turner return err;
1959*46e6e290SRuslan Bukin
1960c120c564SAndrew Turner }
1961c120c564SAndrew Turner
1962*46e6e290SRuslan Bukin
getCurrMemSpace()1963b6aadd18SAndrew Turner inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()
1964c120c564SAndrew Turner {
1965b6aadd18SAndrew Turner static ocsd_mem_space_acc_t SMemSpace[] = {
1966b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL1S,
1967b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL1S,
1968b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL2S,
1969b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL3
1970b6aadd18SAndrew Turner };
1971c120c564SAndrew Turner
1972b6aadd18SAndrew Turner static ocsd_mem_space_acc_t NSMemSpace[] = {
1973b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL1N,
1974b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL1N,
1975b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL2,
1976b6aadd18SAndrew Turner OCSD_MEM_SPACE_EL3
1977b6aadd18SAndrew Turner };
1978c120c564SAndrew Turner
1979b6aadd18SAndrew Turner /* if no valid EL value - just use S/NS */
1980b6aadd18SAndrew Turner if (!outElem().context.el_valid)
1981b6aadd18SAndrew Turner return m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
1982c120c564SAndrew Turner
1983b6aadd18SAndrew Turner /* mem space according to EL + S/NS */
1984b6aadd18SAndrew Turner int el = (int)(outElem().context.exception_level) & 0x3;
1985b6aadd18SAndrew Turner return m_is_secure ? SMemSpace[el] : NSMemSpace[el];
1986b6aadd18SAndrew Turner }
1987c120c564SAndrew Turner /* End of File trc_pkt_decode_etmv4i.cpp */
1988