Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf cs-etm: Generate branch sample for exception packet

The exception packet appears as one element with 'elem_type' ==
OCSD_GEN_TRC_ELEM_EXCEPTION or OCSD_GEN_TRC_ELEM_EXCEPTION_RET, which is
present for exception entry and exit respectively. The decoder sets the
packet fields 'packet->exc' and 'packet->exc_ret' to indicate the
exception packets; but exception packets don't have a dedicated sample
type and shares the same sample type CS_ETM_RANGE with normal
instruction packets.

As a result, the exception packets are taken as normal instruction
packets and this introduces confusion in mixing different packet types.
Furthermore, these instruction range packets will be processed for
branch samples only when 'packet->last_instr_taken_branch' is true,
otherwise they will be omitted, this can introduce a mess for exception
and exception returning due to not having the complete address range
info for context switching.

To process exception packets properly, this patch introduces two new
sample types: CS_ETM_EXCEPTION and CS_ETM_EXCEPTION_RET; these two types
of packets will be handled by cs_etm__exception(). The function
cs_etm__exception() forces setting the previous CS_ETM_RANGE packet flag
'prev_packet->last_instr_taken_branch' to true, this matches well with
the program flow when the exception is trapped from user space to kernel
space, no matter if the most recent flow has branch taken or not; this
is also safe for returning to user space after exception handling.

After exception packets have their own sample type, the packet fields
'packet->exc' and 'packet->exc_ret' aren't needed anymore, so remove
them.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Robert Walker <robert.walker@arm.com>
Cc: coresight ml <coresight@lists.linaro.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1544513908-16805-9-git-send-email-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Leo Yan and committed by
Arnaldo Carvalho de Melo
7100b12c 02e7e250

+50 -8
+20 -6
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
··· 290 290 decoder->packet_buffer[i].instr_count = 0; 291 291 decoder->packet_buffer[i].last_instr_taken_branch = false; 292 292 decoder->packet_buffer[i].last_instr_size = 0; 293 - decoder->packet_buffer[i].exc = false; 294 - decoder->packet_buffer[i].exc_ret = false; 295 293 decoder->packet_buffer[i].cpu = INT_MIN; 296 294 } 297 295 } ··· 317 319 318 320 decoder->packet_buffer[et].sample_type = sample_type; 319 321 decoder->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN; 320 - decoder->packet_buffer[et].exc = false; 321 - decoder->packet_buffer[et].exc_ret = false; 322 322 decoder->packet_buffer[et].cpu = *((int *)inode->priv); 323 323 decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; 324 324 decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; ··· 393 397 CS_ETM_DISCONTINUITY); 394 398 } 395 399 400 + static ocsd_datapath_resp_t 401 + cs_etm_decoder__buffer_exception(struct cs_etm_decoder *decoder, 402 + const uint8_t trace_chan_id) 403 + { 404 + return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, 405 + CS_ETM_EXCEPTION); 406 + } 407 + 408 + static ocsd_datapath_resp_t 409 + cs_etm_decoder__buffer_exception_ret(struct cs_etm_decoder *decoder, 410 + const uint8_t trace_chan_id) 411 + { 412 + return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, 413 + CS_ETM_EXCEPTION_RET); 414 + } 415 + 396 416 static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( 397 417 const void *context, 398 418 const ocsd_trc_index_t indx __maybe_unused, ··· 432 420 trace_chan_id); 433 421 break; 434 422 case OCSD_GEN_TRC_ELEM_EXCEPTION: 435 - decoder->packet_buffer[decoder->tail].exc = true; 423 + resp = cs_etm_decoder__buffer_exception(decoder, 424 + trace_chan_id); 436 425 break; 437 426 case OCSD_GEN_TRC_ELEM_EXCEPTION_RET: 438 - decoder->packet_buffer[decoder->tail].exc_ret = true; 427 + resp = cs_etm_decoder__buffer_exception_ret(decoder, 428 + trace_chan_id); 439 429 break; 440 430 case OCSD_GEN_TRC_ELEM_PE_CONTEXT: 441 431 case OCSD_GEN_TRC_ELEM_ADDR_NACC:
+2 -2
tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
··· 26 26 CS_ETM_EMPTY, 27 27 CS_ETM_RANGE, 28 28 CS_ETM_DISCONTINUITY, 29 + CS_ETM_EXCEPTION, 30 + CS_ETM_EXCEPTION_RET, 29 31 }; 30 32 31 33 enum cs_etm_isa { ··· 45 43 u32 instr_count; 46 44 u8 last_instr_taken_branch; 47 45 u8 last_instr_size; 48 - u8 exc; 49 - u8 exc_ret; 50 46 int cpu; 51 47 }; 52 48
+28
tools/perf/util/cs-etm.c
··· 1000 1000 return 0; 1001 1001 } 1002 1002 1003 + static int cs_etm__exception(struct cs_etm_queue *etmq) 1004 + { 1005 + /* 1006 + * When the exception packet is inserted, whether the last instruction 1007 + * in previous range packet is taken branch or not, we need to force 1008 + * to set 'prev_packet->last_instr_taken_branch' to true. This ensures 1009 + * to generate branch sample for the instruction range before the 1010 + * exception is trapped to kernel or before the exception returning. 1011 + * 1012 + * The exception packet includes the dummy address values, so don't 1013 + * swap PACKET with PREV_PACKET. This keeps PREV_PACKET to be useful 1014 + * for generating instruction and branch samples. 1015 + */ 1016 + if (etmq->prev_packet->sample_type == CS_ETM_RANGE) 1017 + etmq->prev_packet->last_instr_taken_branch = true; 1018 + 1019 + return 0; 1020 + } 1021 + 1003 1022 static int cs_etm__flush(struct cs_etm_queue *etmq) 1004 1023 { 1005 1024 int err = 0; ··· 1166 1147 * events. 1167 1148 */ 1168 1149 cs_etm__sample(etmq); 1150 + break; 1151 + case CS_ETM_EXCEPTION: 1152 + case CS_ETM_EXCEPTION_RET: 1153 + /* 1154 + * If the exception packet is coming, 1155 + * make sure the previous instruction 1156 + * range packet to be handled properly. 1157 + */ 1158 + cs_etm__exception(etmq); 1169 1159 break; 1170 1160 case CS_ETM_DISCONTINUITY: 1171 1161 /*