|
@@ -200,6 +200,121 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static ocsd_datapath_resp_t
|
|
|
|
+cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
|
|
|
|
+ const ocsd_generic_trace_elem *elem,
|
|
|
|
+ const u8 trace_chan_id,
|
|
|
|
+ enum cs_etm_sample_type sample_type)
|
|
|
|
+{
|
|
|
|
+ u32 et = 0;
|
|
|
|
+ struct int_node *inode = NULL;
|
|
|
|
+
|
|
|
|
+ if (decoder->packet_count >= MAX_BUFFER - 1)
|
|
|
|
+ return OCSD_RESP_FATAL_SYS_ERR;
|
|
|
|
+
|
|
|
|
+ /* Search the RB tree for the cpu associated with this traceID */
|
|
|
|
+ inode = intlist__find(traceid_list, trace_chan_id);
|
|
|
|
+ if (!inode)
|
|
|
|
+ return OCSD_RESP_FATAL_SYS_ERR;
|
|
|
|
+
|
|
|
|
+ et = decoder->tail;
|
|
|
|
+ decoder->packet_buffer[et].sample_type = sample_type;
|
|
|
|
+ decoder->packet_buffer[et].start_addr = elem->st_addr;
|
|
|
|
+ decoder->packet_buffer[et].end_addr = elem->en_addr;
|
|
|
|
+ decoder->packet_buffer[et].exc = false;
|
|
|
|
+ decoder->packet_buffer[et].exc_ret = false;
|
|
|
|
+ decoder->packet_buffer[et].cpu = *((int *)inode->priv);
|
|
|
|
+
|
|
|
|
+ /* Wrap around if need be */
|
|
|
|
+ et = (et + 1) & (MAX_BUFFER - 1);
|
|
|
|
+
|
|
|
|
+ decoder->tail = et;
|
|
|
|
+ decoder->packet_count++;
|
|
|
|
+
|
|
|
|
+ if (decoder->packet_count == MAX_BUFFER - 1)
|
|
|
|
+ return OCSD_RESP_WAIT;
|
|
|
|
+
|
|
|
|
+ return OCSD_RESP_CONT;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
|
|
|
|
+ const void *context,
|
|
|
|
+ const ocsd_trc_index_t indx __maybe_unused,
|
|
|
|
+ const u8 trace_chan_id __maybe_unused,
|
|
|
|
+ const ocsd_generic_trace_elem *elem)
|
|
|
|
+{
|
|
|
|
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
|
|
|
|
+ struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
|
|
|
|
+
|
|
|
|
+ switch (elem->elem_type) {
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_UNKNOWN:
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_NO_SYNC:
|
|
|
|
+ decoder->trace_on = false;
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_TRACE_ON:
|
|
|
|
+ decoder->trace_on = true;
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
|
|
|
|
+ resp = cs_etm_decoder__buffer_packet(decoder, elem,
|
|
|
|
+ trace_chan_id,
|
|
|
|
+ CS_ETM_RANGE);
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_EXCEPTION:
|
|
|
|
+ decoder->packet_buffer[decoder->tail].exc = true;
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
|
|
|
|
+ decoder->packet_buffer[decoder->tail].exc_ret = true;
|
|
|
|
+ break;
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_EO_TRACE:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_ADDR_NACC:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_TIMESTAMP:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_EVENT:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_SWTRACE:
|
|
|
|
+ case OCSD_GEN_TRC_ELEM_CUSTOM:
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return resp;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int cs_etm_decoder__create_etm_packet_decoder(
|
|
|
|
+ struct cs_etm_trace_params *t_params,
|
|
|
|
+ struct cs_etm_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ const char *decoder_name;
|
|
|
|
+ ocsd_etmv4_cfg trace_config_etmv4;
|
|
|
|
+ void *trace_config;
|
|
|
|
+ u8 csid;
|
|
|
|
+
|
|
|
|
+ switch (t_params->protocol) {
|
|
|
|
+ case CS_ETM_PROTO_ETMV4i:
|
|
|
|
+ cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
|
|
|
|
+ decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
|
|
|
|
+ trace_config = &trace_config_etmv4;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ocsd_dt_create_decoder(decoder->dcd_tree,
|
|
|
|
+ decoder_name,
|
|
|
|
+ OCSD_CREATE_FLG_FULL_DECODER,
|
|
|
|
+ trace_config, &csid))
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
|
|
|
|
+ cs_etm_decoder__gen_trace_elem_printer,
|
|
|
|
+ decoder))
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int
|
|
static int
|
|
cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
|
|
cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
|
|
struct cs_etm_trace_params *t_params,
|
|
struct cs_etm_trace_params *t_params,
|
|
@@ -208,6 +323,10 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
|
|
if (d_params->operation == CS_ETM_OPERATION_PRINT)
|
|
if (d_params->operation == CS_ETM_OPERATION_PRINT)
|
|
return cs_etm_decoder__create_etm_packet_printer(t_params,
|
|
return cs_etm_decoder__create_etm_packet_printer(t_params,
|
|
decoder);
|
|
decoder);
|
|
|
|
+ else if (d_params->operation == CS_ETM_OPERATION_DECODE)
|
|
|
|
+ return cs_etm_decoder__create_etm_packet_decoder(t_params,
|
|
|
|
+ decoder);
|
|
|
|
+
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|