perf cs-etm: Move packet queue out of decoder structure
authorMathieu Poirier <mathieu.poirier@linaro.org>
Fri, 24 May 2019 17:34:58 +0000 (11:34 -0600)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 10 Jun 2019 18:50:01 +0000 (15:50 -0300)
The decoder needs to work with more than one traceID queue if we want to
support CPU-wide scenarios with N:1 source/sink topologies.  As such
move the packet buffer and related fields out of the decoder structure
and into the cs_etm_queue structure.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: Leo Yan <leo.yan@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/20190524173508.29044-8-mathieu.poirier@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
tools/perf/util/cs-etm.c
tools/perf/util/cs-etm.h

index 5dafec421b0d47099eb3d8160870e8f5d0aa5620..3ac238e5890147bf66f9bb9a5125efbdf87208b3 100644 (file)
@@ -18,8 +18,6 @@
 #include "intlist.h"
 #include "util.h"
 
-#define MAX_BUFFER 1024
-
 /* use raw logging */
 #ifdef CS_DEBUG_RAW
 #define CS_LOG_RAW_FRAMES
 #endif
 #endif
 
-#define CS_ETM_INVAL_ADDR      0xdeadbeefdeadbeefUL
-
 struct cs_etm_decoder {
        void *data;
        void (*packet_printer)(const char *msg);
        dcd_tree_handle_t dcd_tree;
        cs_etm_mem_cb_type mem_access;
        ocsd_datapath_resp_t prev_return;
-       u32 packet_count;
-       u32 head;
-       u32 tail;
-       struct cs_etm_packet packet_buffer[MAX_BUFFER];
 };
 
 static u32
@@ -88,14 +80,14 @@ int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
        return 0;
 }
 
-int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
+int cs_etm_decoder__get_packet(struct cs_etm_packet_queue *packet_queue,
                               struct cs_etm_packet *packet)
 {
-       if (!decoder || !packet)
+       if (!packet_queue || !packet)
                return -EINVAL;
 
        /* Nothing to do, might as well just return */
-       if (decoder->packet_count == 0)
+       if (packet_queue->packet_count == 0)
                return 0;
        /*
         * The queueing process in function cs_etm_decoder__buffer_packet()
@@ -106,11 +98,12 @@ int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
         * value.  Otherwise the first element of the packet queue is not
         * used.
         */
-       decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
+       packet_queue->head = (packet_queue->head + 1) &
+                            (CS_ETM_PACKET_MAX_BUFFER - 1);
 
-       *packet = decoder->packet_buffer[decoder->head];
+       *packet = packet_queue->packet_buffer[packet_queue->head];
 
-       decoder->packet_count--;
+       packet_queue->packet_count--;
 
        return 1;
 }
@@ -276,84 +269,60 @@ cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params *t_params,
                                                     trace_config);
 }
 
-static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
-{
-       int i;
-
-       decoder->head = 0;
-       decoder->tail = 0;
-       decoder->packet_count = 0;
-       for (i = 0; i < MAX_BUFFER; i++) {
-               decoder->packet_buffer[i].isa = CS_ETM_ISA_UNKNOWN;
-               decoder->packet_buffer[i].start_addr = CS_ETM_INVAL_ADDR;
-               decoder->packet_buffer[i].end_addr = CS_ETM_INVAL_ADDR;
-               decoder->packet_buffer[i].instr_count = 0;
-               decoder->packet_buffer[i].last_instr_taken_branch = false;
-               decoder->packet_buffer[i].last_instr_size = 0;
-               decoder->packet_buffer[i].last_instr_type = 0;
-               decoder->packet_buffer[i].last_instr_subtype = 0;
-               decoder->packet_buffer[i].last_instr_cond = 0;
-               decoder->packet_buffer[i].flags = 0;
-               decoder->packet_buffer[i].exception_number = UINT32_MAX;
-               decoder->packet_buffer[i].trace_chan_id = UINT8_MAX;
-               decoder->packet_buffer[i].cpu = INT_MIN;
-       }
-}
-
 static ocsd_datapath_resp_t
-cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
+cs_etm_decoder__buffer_packet(struct cs_etm_packet_queue *packet_queue,
                              const u8 trace_chan_id,
                              enum cs_etm_sample_type sample_type)
 {
        u32 et = 0;
        int cpu;
 
-       if (decoder->packet_count >= MAX_BUFFER - 1)
+       if (packet_queue->packet_count >= CS_ETM_PACKET_MAX_BUFFER - 1)
                return OCSD_RESP_FATAL_SYS_ERR;
 
        if (cs_etm__get_cpu(trace_chan_id, &cpu) < 0)
                return OCSD_RESP_FATAL_SYS_ERR;
 
-       et = decoder->tail;
-       et = (et + 1) & (MAX_BUFFER - 1);
-       decoder->tail = et;
-       decoder->packet_count++;
-
-       decoder->packet_buffer[et].sample_type = sample_type;
-       decoder->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN;
-       decoder->packet_buffer[et].cpu = cpu;
-       decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR;
-       decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR;
-       decoder->packet_buffer[et].instr_count = 0;
-       decoder->packet_buffer[et].last_instr_taken_branch = false;
-       decoder->packet_buffer[et].last_instr_size = 0;
-       decoder->packet_buffer[et].last_instr_type = 0;
-       decoder->packet_buffer[et].last_instr_subtype = 0;
-       decoder->packet_buffer[et].last_instr_cond = 0;
-       decoder->packet_buffer[et].flags = 0;
-       decoder->packet_buffer[et].exception_number = UINT32_MAX;
-       decoder->packet_buffer[et].trace_chan_id = trace_chan_id;
-
-       if (decoder->packet_count == MAX_BUFFER - 1)
+       et = packet_queue->tail;
+       et = (et + 1) & (CS_ETM_PACKET_MAX_BUFFER - 1);
+       packet_queue->tail = et;
+       packet_queue->packet_count++;
+
+       packet_queue->packet_buffer[et].sample_type = sample_type;
+       packet_queue->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN;
+       packet_queue->packet_buffer[et].cpu = cpu;
+       packet_queue->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR;
+       packet_queue->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR;
+       packet_queue->packet_buffer[et].instr_count = 0;
+       packet_queue->packet_buffer[et].last_instr_taken_branch = false;
+       packet_queue->packet_buffer[et].last_instr_size = 0;
+       packet_queue->packet_buffer[et].last_instr_type = 0;
+       packet_queue->packet_buffer[et].last_instr_subtype = 0;
+       packet_queue->packet_buffer[et].last_instr_cond = 0;
+       packet_queue->packet_buffer[et].flags = 0;
+       packet_queue->packet_buffer[et].exception_number = UINT32_MAX;
+       packet_queue->packet_buffer[et].trace_chan_id = trace_chan_id;
+
+       if (packet_queue->packet_count == CS_ETM_PACKET_MAX_BUFFER - 1)
                return OCSD_RESP_WAIT;
 
        return OCSD_RESP_CONT;
 }
 
 static ocsd_datapath_resp_t
-cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
+cs_etm_decoder__buffer_range(struct cs_etm_packet_queue *packet_queue,
                             const ocsd_generic_trace_elem *elem,
                             const uint8_t trace_chan_id)
 {
        int ret = 0;
        struct cs_etm_packet *packet;
 
-       ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
+       ret = cs_etm_decoder__buffer_packet(packet_queue, trace_chan_id,
                                            CS_ETM_RANGE);
        if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
                return ret;
 
-       packet = &decoder->packet_buffer[decoder->tail];
+       packet = &packet_queue->packet_buffer[packet_queue->tail];
 
        switch (elem->isa) {
        case ocsd_isa_aarch64:
@@ -400,36 +369,36 @@ cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
 }
 
 static ocsd_datapath_resp_t
-cs_etm_decoder__buffer_discontinuity(struct cs_etm_decoder *decoder,
-                                          const uint8_t trace_chan_id)
+cs_etm_decoder__buffer_discontinuity(struct cs_etm_packet_queue *queue,
+                                    const uint8_t trace_chan_id)
 {
-       return cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
+       return cs_etm_decoder__buffer_packet(queue, trace_chan_id,
                                             CS_ETM_DISCONTINUITY);
 }
 
 static ocsd_datapath_resp_t
-cs_etm_decoder__buffer_exception(struct cs_etm_decoder *decoder,
+cs_etm_decoder__buffer_exception(struct cs_etm_packet_queue *queue,
                                 const ocsd_generic_trace_elem *elem,
                                 const uint8_t trace_chan_id)
 {      int ret = 0;
        struct cs_etm_packet *packet;
 
-       ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
+       ret = cs_etm_decoder__buffer_packet(queue, trace_chan_id,
                                            CS_ETM_EXCEPTION);
        if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
                return ret;
 
-       packet = &decoder->packet_buffer[decoder->tail];
+       packet = &queue->packet_buffer[queue->tail];
        packet->exception_number = elem->exception_number;
 
        return ret;
 }
 
 static ocsd_datapath_resp_t
-cs_etm_decoder__buffer_exception_ret(struct cs_etm_decoder *decoder,
+cs_etm_decoder__buffer_exception_ret(struct cs_etm_packet_queue *queue,
                                     const uint8_t trace_chan_id)
 {
-       return cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
+       return cs_etm_decoder__buffer_packet(queue, trace_chan_id,
                                             CS_ETM_EXCEPTION_RET);
 }
 
@@ -441,6 +410,13 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
 {
        ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
        struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
+       struct cs_etm_queue *etmq = decoder->data;
+       struct cs_etm_packet_queue *packet_queue;
+
+       /* First get the packet queue */
+       packet_queue = cs_etm__etmq_get_packet_queue(etmq);
+       if (!packet_queue)
+               return OCSD_RESP_FATAL_SYS_ERR;
 
        switch (elem->elem_type) {
        case OCSD_GEN_TRC_ELEM_UNKNOWN:
@@ -448,19 +424,19 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
        case OCSD_GEN_TRC_ELEM_EO_TRACE:
        case OCSD_GEN_TRC_ELEM_NO_SYNC:
        case OCSD_GEN_TRC_ELEM_TRACE_ON:
-               resp = cs_etm_decoder__buffer_discontinuity(decoder,
+               resp = cs_etm_decoder__buffer_discontinuity(packet_queue,
                                                            trace_chan_id);
                break;
        case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
-               resp = cs_etm_decoder__buffer_range(decoder, elem,
+               resp = cs_etm_decoder__buffer_range(packet_queue, elem,
                                                    trace_chan_id);
                break;
        case OCSD_GEN_TRC_ELEM_EXCEPTION:
-               resp = cs_etm_decoder__buffer_exception(decoder, elem,
+               resp = cs_etm_decoder__buffer_exception(packet_queue, elem,
                                                        trace_chan_id);
                break;
        case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
-               resp = cs_etm_decoder__buffer_exception_ret(decoder,
+               resp = cs_etm_decoder__buffer_exception_ret(packet_queue,
                                                            trace_chan_id);
                break;
        case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
@@ -554,7 +530,6 @@ cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
 
        decoder->data = d_params->data;
        decoder->prev_return = OCSD_RESP_CONT;
-       cs_etm_decoder__clear_buffer(decoder);
        format = (d_params->formatted ? OCSD_TRC_SRC_FRAME_FORMATTED :
                                         OCSD_TRC_SRC_SINGLE);
        flags = 0;
index 3ab11dfa92ae372570dc964fc18fb0744ed423f6..6ae7ab4cf5fe8448a6db684ef6a6f9dfcf07916f 100644 (file)
 #include <stdio.h>
 
 struct cs_etm_decoder;
-
-enum cs_etm_sample_type {
-       CS_ETM_EMPTY,
-       CS_ETM_RANGE,
-       CS_ETM_DISCONTINUITY,
-       CS_ETM_EXCEPTION,
-       CS_ETM_EXCEPTION_RET,
-};
-
-enum cs_etm_isa {
-       CS_ETM_ISA_UNKNOWN,
-       CS_ETM_ISA_A64,
-       CS_ETM_ISA_A32,
-       CS_ETM_ISA_T32,
-};
-
-struct cs_etm_packet {
-       enum cs_etm_sample_type sample_type;
-       enum cs_etm_isa isa;
-       u64 start_addr;
-       u64 end_addr;
-       u32 instr_count;
-       u32 last_instr_type;
-       u32 last_instr_subtype;
-       u32 flags;
-       u32 exception_number;
-       u8 last_instr_cond;
-       u8 last_instr_taken_branch;
-       u8 last_instr_size;
-       u8 trace_chan_id;
-       int cpu;
-};
+struct cs_etm_packet;
+struct cs_etm_packet_queue;
 
 struct cs_etm_queue;
 
@@ -119,7 +89,7 @@ int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder,
                                      u64 start, u64 end,
                                      cs_etm_mem_cb_type cb_func);
 
-int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
+int cs_etm_decoder__get_packet(struct cs_etm_packet_queue *packet_queue,
                               struct cs_etm_packet *packet);
 
 int cs_etm_decoder__reset(struct cs_etm_decoder *decoder);
index 5322dcaaf6542307867764e51fbc6680c59bcfe9..a74c53a45839c270ca56ea0c1c4541458182c792 100644 (file)
@@ -78,6 +78,7 @@ struct cs_etm_queue {
        struct cs_etm_packet *packet;
        const unsigned char *buf;
        size_t buf_len, buf_used;
+       struct cs_etm_packet_queue packet_queue;
 };
 
 static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
@@ -125,6 +126,36 @@ int cs_etm__get_cpu(u8 trace_chan_id, int *cpu)
        return 0;
 }
 
+static void cs_etm__clear_packet_queue(struct cs_etm_packet_queue *queue)
+{
+       int i;
+
+       queue->head = 0;
+       queue->tail = 0;
+       queue->packet_count = 0;
+       for (i = 0; i < CS_ETM_PACKET_MAX_BUFFER; i++) {
+               queue->packet_buffer[i].isa = CS_ETM_ISA_UNKNOWN;
+               queue->packet_buffer[i].start_addr = CS_ETM_INVAL_ADDR;
+               queue->packet_buffer[i].end_addr = CS_ETM_INVAL_ADDR;
+               queue->packet_buffer[i].instr_count = 0;
+               queue->packet_buffer[i].last_instr_taken_branch = false;
+               queue->packet_buffer[i].last_instr_size = 0;
+               queue->packet_buffer[i].last_instr_type = 0;
+               queue->packet_buffer[i].last_instr_subtype = 0;
+               queue->packet_buffer[i].last_instr_cond = 0;
+               queue->packet_buffer[i].flags = 0;
+               queue->packet_buffer[i].exception_number = UINT32_MAX;
+               queue->packet_buffer[i].trace_chan_id = UINT8_MAX;
+               queue->packet_buffer[i].cpu = INT_MIN;
+       }
+}
+
+struct cs_etm_packet_queue
+*cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq)
+{
+       return &etmq->packet_queue;
+}
+
 static void cs_etm__packet_dump(const char *pkt_string)
 {
        const char *color = PERF_COLOR_BLUE;
@@ -513,6 +544,7 @@ static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
        etmq->pid = -1;
        etmq->offset = 0;
        etmq->period_instructions = 0;
+       cs_etm__clear_packet_queue(&etmq->packet_queue);
 
 out:
        return ret;
@@ -1542,10 +1574,13 @@ out:
 static int cs_etm__process_decoder_queue(struct cs_etm_queue *etmq)
 {
        int ret;
+       struct cs_etm_packet_queue *packet_queue;
+
+       packet_queue = cs_etm__etmq_get_packet_queue(etmq);
 
                /* Process each packet in this chunk */
                while (1) {
-                       ret = cs_etm_decoder__get_packet(etmq->decoder,
+                       ret = cs_etm_decoder__get_packet(packet_queue,
                                                         etmq->packet);
                        if (ret <= 0)
                                /*
index 826c9eedaf5c24dd5e82beccb689c0ff4ffe45f5..75385e2fd28396863412c215e4fd0506f7dabd1a 100644 (file)
@@ -97,12 +97,57 @@ enum {
        CS_ETMV4_EXC_END = 31,
 };
 
+enum cs_etm_sample_type {
+       CS_ETM_EMPTY,
+       CS_ETM_RANGE,
+       CS_ETM_DISCONTINUITY,
+       CS_ETM_EXCEPTION,
+       CS_ETM_EXCEPTION_RET,
+};
+
+enum cs_etm_isa {
+       CS_ETM_ISA_UNKNOWN,
+       CS_ETM_ISA_A64,
+       CS_ETM_ISA_A32,
+       CS_ETM_ISA_T32,
+};
+
 /* RB tree for quick conversion between traceID and metadata pointers */
 struct intlist *traceid_list;
 
+struct cs_etm_queue;
+
+struct cs_etm_packet {
+       enum cs_etm_sample_type sample_type;
+       enum cs_etm_isa isa;
+       u64 start_addr;
+       u64 end_addr;
+       u32 instr_count;
+       u32 last_instr_type;
+       u32 last_instr_subtype;
+       u32 flags;
+       u32 exception_number;
+       u8 last_instr_cond;
+       u8 last_instr_taken_branch;
+       u8 last_instr_size;
+       u8 trace_chan_id;
+       int cpu;
+};
+
+#define CS_ETM_PACKET_MAX_BUFFER 1024
+
+struct cs_etm_packet_queue {
+       u32 packet_count;
+       u32 head;
+       u32 tail;
+       struct cs_etm_packet packet_buffer[CS_ETM_PACKET_MAX_BUFFER];
+};
+
 #define KiB(x) ((x) * 1024)
 #define MiB(x) ((x) * 1024 * 1024)
 
+#define CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL
+
 /*
  * Create a contiguous bitmask starting at bit position @l and ending at
  * position @h. For example
@@ -126,6 +171,8 @@ struct intlist *traceid_list;
 int cs_etm__process_auxtrace_info(union perf_event *event,
                                  struct perf_session *session);
 int cs_etm__get_cpu(u8 trace_chan_id, int *cpu);
+struct cs_etm_packet_queue
+*cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq);
 #else
 static inline int
 cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused,
@@ -139,6 +186,12 @@ static inline int cs_etm__get_cpu(u8 trace_chan_id __maybe_unused,
 {
        return -1;
 }
+
+static inline struct cs_etm_packet_queue *cs_etm__etmq_get_packet_queue(
+                               struct cs_etm_queue *etmq __maybe_unused)
+{
+       return NULL;
+}
 #endif
 
 #endif