forked from Minki/linux
perf tools: Add support for decoding CoreSight trace data
Adding functionality to create a CoreSight trace decoder capable of decoding trace data pushed by a client application. Co-authored-by: Tor Jeremiassen <tor@ti.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Kim Phillips <kim.phillips@arm.com> Cc: Mike Leach <mike.leach@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1516211539-5166-6-git-send-email-mathieu.poirier@linaro.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
68ffe39028
commit
c9a01a11df
@ -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
|
||||
cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_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)
|
||||
return cs_etm_decoder__create_etm_packet_printer(t_params,
|
||||
decoder);
|
||||
else if (d_params->operation == CS_ETM_OPERATION_DECODE)
|
||||
return cs_etm_decoder__create_etm_packet_decoder(t_params,
|
||||
decoder);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user