9 #include <linux/bitops.h> 10 #include <linux/err.h> 11 #include <linux/kernel.h> 12 #include <linux/log2.h> 13 #include <linux/types.h> 32 #define MAX_TIMESTAMP (~0ULL) 40 #define A64_INSTR_SIZE 4 74 const struct cs_etm_state *
state;
92 pid_t tid, u64 time_);
97 int len = strlen(pkt_string);
99 if (len && (pkt_string[len-1] ==
'\n'))
115 size_t buffer_used = 0;
117 fprintf(stdout,
"\n");
119 ". ... CoreSight ETM Trace data: size %zu bytes\n",
124 for (i = 0; i < etm->
num_cpu; i++) {
155 &((u8 *)buffer->
data)[buffer_used],
156 buffer->
size - buffer_used, &consumed);
160 buffer_used += consumed;
161 }
while (buffer_used < buffer->
size);
215 for (i = 0; i < queues->
nr_queues; i++) {
239 for (i = 0; i < aux->
num_cpu; i++)
248 size_t size, u8 *buffer)
262 cpumode = PERF_RECORD_MISC_KERNEL;
264 cpumode = PERF_RECORD_MISC_USER;
268 if (cpumode != PERF_RECORD_MISC_KERNEL)
301 etmq =
zalloc(
sizeof(*etmq));
344 for (i = 0; i < etm->
num_cpu; i++) {
363 d_params.
data = etmq;
379 goto out_free_decoder;
401 unsigned int queue_nr)
405 if (list_empty(&queue->
head) || etmq)
415 if (queue->
cpu != -1)
457 bs_dst->
nr = bs_src->
nr;
589 etmq->
buffer = aux_buffer;
592 if (!aux_buffer->
data) {
597 if (!aux_buffer->
data)
620 if (queue->
tid == -1)
623 if ((!etmq->
thread) && (etmq->
tid != -1))
629 if (queue->
cpu == -1)
635 u64 addr, u64 period)
642 event->sample.header.type = PERF_RECORD_SAMPLE;
643 event->sample.header.misc = PERF_RECORD_MISC_USER;
644 event->sample.header.size =
sizeof(
struct perf_event_header);
655 sample.
cpumode =
event->header.misc;
673 "CS ETM Trace: failed to deliver instruction event, error %d\n",
692 struct dummy_branch_stack {
697 event->sample.header.type = PERF_RECORD_SAMPLE;
698 event->sample.header.misc = PERF_RECORD_MISC_USER;
699 event->sample.header.size =
sizeof(
struct perf_event_header);
710 sample.
cpumode = PERF_RECORD_MISC_USER;
716 dummy_bs = (
struct dummy_branch_stack){
737 "CS ETM Trace: failed to deliver instruction event, error %d\n",
754 container_of(tool,
struct cs_etm_synth,
dummy_tool);
761 struct perf_event_attr *
attr, u64
id)
765 memset(&cs_etm_synth, 0,
sizeof(
struct cs_etm_synth));
777 struct perf_event_attr attr;
790 pr_debug(
"No selected events with CoreSight Trace data\n");
794 memset(&attr, 0,
sizeof(
struct perf_event_attr));
795 attr.size =
sizeof(
struct perf_event_attr);
796 attr.type = PERF_TYPE_HARDWARE;
798 attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
801 attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
803 attr.sample_type |= PERF_SAMPLE_TIME;
805 attr.exclude_user = evsel->
attr.exclude_user;
806 attr.exclude_kernel = evsel->
attr.exclude_kernel;
807 attr.exclude_hv = evsel->
attr.exclude_hv;
808 attr.exclude_host = evsel->
attr.exclude_host;
809 attr.exclude_guest = evsel->
attr.exclude_guest;
810 attr.sample_id_all = evsel->
attr.sample_id_all;
811 attr.read_format = evsel->
attr.read_format;
814 id = evsel->
id[0] + 1000000000;
820 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
821 attr.sample_period = 1;
822 attr.sample_type |= PERF_SAMPLE_ADDR;
830 attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
834 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
837 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
888 u64 offset = (instrs_executed - instrs_over - 1);
960 size_t buffer_used, processed;
969 memset(&buffer, 0,
sizeof(buffer));
987 &buffer.
buf[buffer_used],
988 buffer.
len - buffer_used,
993 etmq->
offset += processed;
994 buffer_used += processed;
1027 }
while (buffer.
len > buffer_used);
1038 pid_t tid, u64 time_)
1043 for (i = 0; i < queues->
nr_queues; i++) {
1047 if (etmq && ((tid == -1) || (etmq->
tid == tid))) {
1072 pr_err(
"CoreSight ETM Trace requires ordered events\n");
1079 if (sample->
time && (sample->
time != (u64) -1))
1080 timestamp = sample->
time;
1090 if (event->
header.type == PERF_RECORD_EXIT)
1115 data_offset = lseek(fd, 0, SEEK_CUR);
1116 if (data_offset == -1)
1121 event, data_offset, &buffer);
1146 if ((evsel->
attr.sample_type & PERF_SAMPLE_TIME))
1147 timeless_decoding =
false;
1187 for (i = CS_HEADER_VERSION_0_MAX; cpu < num; cpu++) {
1207 int event_header_size =
sizeof(
struct perf_event_header);
1208 int info_header_size;
1209 int total_size = auxtrace_info->
header.size;
1212 int err = 0, idx = -1;
1214 u64 *ptr, *hdr = NULL;
1221 info_header_size = 8;
1223 if (total_size < (event_header_size + info_header_size))
1226 priv_size = total_size - event_header_size - info_header_size;
1229 ptr = (u64 *) auxtrace_info->
priv;
1257 metadata =
zalloc(
sizeof(*metadata) * num_cpu);
1260 goto err_free_traceid_list;
1269 for (j = 0; j <
num_cpu; j++) {
1271 metadata[j] =
zalloc(
sizeof(*metadata[j]) *
1275 goto err_free_metadata;
1278 metadata[j][k] = ptr[i + k];
1284 metadata[j] =
zalloc(
sizeof(*metadata[j]) *
1288 goto err_free_metadata;
1291 metadata[j][k] = ptr[i + k];
1303 err = PTR_ERR(inode);
1304 goto err_free_metadata;
1313 goto err_free_metadata;
1326 if (i * 8 != priv_size) {
1328 goto err_free_metadata;
1331 etm =
zalloc(
sizeof(*etm));
1335 goto err_free_metadata;
1361 goto err_free_queues;
1371 goto err_delete_thread;
1374 goto err_delete_thread;
1390 goto err_delete_thread;
1394 goto err_delete_thread;
1412 err_free_traceid_list:
int color_fprintf(FILE *fp, const char *color, const char *fmt,...)
u64(* map_ip)(struct map *, u64)
static int cs_etm__flush(struct cs_etm_queue *etmq)
struct perf_evlist * evlist
int(* process_event)(struct perf_session *session, union perf_event *event, struct perf_sample *sample, struct perf_tool *tool)
struct perf_tool dummy_tool
void(* packet_printer)(const char *msg)
static u64 cs_etm__instr_addr(const struct cs_etm_packet *packet, u64 offset)
#define intlist__for_each_entry_safe(pos, n, ilist)
struct perf_event_header header
static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
static const u64 __perf_cs_etmv3_magic
static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
int auxtrace_queues__process_index(struct auxtrace_queues *queues, struct perf_session *session)
struct perf_session * session
void * auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd)
struct auxtrace_queue * queue_array
struct itrace_synth_opts synth_opts
struct auxtrace * auxtrace
#define thread__zput(thread)
void intlist__delete(struct intlist *ilist)
static void cs_etm__free_queue(void *priv)
static int cs_etm__process_auxtrace_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool __maybe_unused)
static int cs_etm__sample(struct cs_etm_queue *etmq)
static int cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, u64 addr, u64 period)
int perf_session__deliver_synth_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample)
struct map * thread__find_map(struct thread *thread, u8 cpumode, u64 addr, struct addr_location *al)
struct perf_session * session
struct auxtrace_buffer * auxtrace_buffer__next(struct auxtrace_queue *queue, struct auxtrace_buffer *buffer)
static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
struct itrace_synth_opts * itrace_synth_opts
u64 instructions_sample_period
int auxtrace_queues__add_event(struct auxtrace_queues *queues, struct perf_session *session, union perf_event *event, off_t data_offset, struct auxtrace_buffer **buffer_ptr)
static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
enum cs_etm_sample_type sample_type
struct auxtrace_buffer * buffer
static int cs_etm__event_synth(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused)
struct cs_etmv4_trace_params etmv4
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
int thread__init_map_groups(struct thread *thread, struct machine *machine)
static u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
static const u64 __perf_cs_etmv4_magic
struct branch_entry entries[0]
struct thread * machine__find_thread(struct machine *machine, pid_t pid, pid_t tid)
static void cs_etm__free(struct perf_session *session)
static void cs_etm__print_auxtrace_info(u64 *val, int num)
struct cs_etm_packet * packet
int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, const struct perf_sample *sample)
static void cs_etm__packet_dump(const char *pkt_string)
#define pr_debug(fmt,...)
static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm, pid_t tid, u64 time_)
void intlist__remove(struct intlist *ilist, struct int_node *node)
static const char *const cs_etm_global_header_fmts[]
#define evlist__for_each_entry(evlist, evsel)
int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer)
struct int_node * intlist__findnew(struct intlist *ilist, int i)
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, struct perf_session *session)
static struct perf_tool tool
static int cs_etm__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, u64 start, u64 end, cs_etm_mem_cb_type cb_func)
unsigned long long period
static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
u8 last_instr_taken_branch
static const char *const cs_etmv4_priv_fmts[]
void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer)
struct cs_etm_decoder * cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params t_params[])
struct branch_stack * branch_stack
struct cs_etm_decoder * decoder
static int perf_data__fd(struct perf_data *data)
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
int cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder, u64 indx, const u8 *buf, size_t len, size_t *consumed)
union perf_event * event_buf
unsigned int last_branch_sz
const struct cs_etm_state * state
static int cs_etm__process_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample, struct perf_tool *tool)
struct perf_event_header header
static int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp)
struct intlist * intlist__new(const char *slist)
static int perf_data__is_pipe(struct perf_data *data)
struct auxtrace_heap heap
void(* free_events)(struct perf_session *session)
struct auxtrace_queues queues
int(* flush_events)(struct perf_session *session, struct perf_tool *tool)
static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, struct auxtrace_queue *queue, unsigned int queue_nr)
struct branch_stack * last_branch
u64 instructions_sample_type
static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
static const char *const cs_etm_priv_fmts[]
struct thread * thread__new(pid_t pid, pid_t tid)
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format)
#define PERF_SAMPLE_MAX_SIZE
static u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
void auxtrace_queues__free(struct auxtrace_queues *queues)
static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, size_t size, u8 *buffer)
static int cs_etm__flush_events(struct perf_session *session, struct perf_tool *tool)
struct intlist * traceid_list
ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size)
struct cs_etm_auxtrace * etm
void(* free)(struct perf_session *session)
int auxtrace_queues__init(struct auxtrace_queues *queues)
void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
int map__load(struct map *map)
static u64 machine__kernel_start(struct machine *machine)
int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_session *session)
int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder, struct cs_etm_packet *packet)
static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm, struct auxtrace_queue *queue)
static void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq)
struct perf_event_attr attr
struct cs_etm_packet * prev_packet
static struct cs_etm_queue * cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, unsigned int queue_nr)
const unsigned char * buf
static int cs_etm__synth_event(struct perf_session *session, struct perf_event_attr *attr, u64 id)
struct branch_flags flags
static void cs_etm__dump_event(struct cs_etm_auxtrace *etm, struct auxtrace_buffer *buffer)
struct branch_stack * last_branch_rb
bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
static void cs_etm__free_events(struct perf_session *session)
int(* process_auxtrace_event)(struct perf_session *session, union perf_event *event, struct perf_tool *tool)
void static void * zalloc(size_t size)
static void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
struct thread * unknown_thread