20 #include <linux/kernel.h> 21 #include <linux/types.h> 22 #include <linux/bitops.h> 23 #include <linux/log2.h> 40 #define MAX_TIMESTAMP (~0ULL) 42 #define INTEL_BTS_ERR_NOINSN 5 43 #define INTEL_BTS_ERR_LOST 9 45 #if __BYTE_ORDER == __BIG_ENDIAN 46 #define le64_to_cpu bswap_64 94 unsigned char *buf,
size_t len)
97 size_t i, pos = 0, br_sz =
sizeof(
struct branch), sz;
101 ". ... Intel BTS data: size %zu bytes\n",
111 for (i = 0; i < sz; i++)
113 for (; i < br_sz; i++)
116 branch = (
struct branch *)buf;
145 sample->
tid, 0,
"Lost trace data");
149 pr_err(
"Intel BTS: failed to deliver error event, error %d\n",
179 if (list_empty(&queue->
head))
188 if (queue->
cpu != -1)
237 unsigned char *buf_b,
size_t len_b)
242 offs = len_a - len_b;
246 for (; offs < len_a; offs +=
sizeof(
struct branch)) {
248 if (!memcmp(buf_a + offs, buf_b, len))
284 event.sample.header.type = PERF_RECORD_SAMPLE;
285 event.sample.header.misc = PERF_RECORD_MISC_USER;
286 event.sample.header.size =
sizeof(
struct perf_event_header);
288 sample.
cpumode = PERF_RECORD_MISC_USER;
312 pr_err(
"Intel BTS: failed to deliver branch event, error %d\n",
330 cpumode = PERF_RECORD_MISC_KERNEL;
332 cpumode = PERF_RECORD_MISC_USER;
368 "Failed to get instruction");
372 pr_err(
"Intel BTS: failed to deliver error event, error %d\n",
390 }
else if (!branch->
to) {
427 size_t sz, bsz =
sizeof(
struct branch);
436 branch = buffer->
data;
442 for (; sz > bsz; branch += 1, sz -= bsz) {
443 if (!branch->
from && !branch->
to)
471 if (btsq->
pid == -1) {
558 for (i = 0; i < queues->
nr_queues; i++) {
562 if (btsq && btsq->
tid == tid)
621 pr_err(
"Intel BTS requires ordered events\n");
625 if (sample->
time && sample->
time != (u64)-1)
637 if (event->
header.type == PERF_RECORD_EXIT) {
643 if (event->
header.type == PERF_RECORD_AUX &&
644 (event->
aux.
flags & PERF_AUX_FLAG_TRUNCATED) &&
670 data_offset = lseek(fd, 0, SEEK_CUR);
671 if (data_offset == -1)
676 data_offset, &buffer);
729 for (i = 0; i < queues->
nr_queues; i++) {
758 container_of(tool,
struct intel_bts_synth,
dummy_tool);
765 struct perf_event_attr *
attr, u64
id)
769 memset(&intel_bts_synth, 0,
sizeof(
struct intel_bts_synth));
781 struct perf_event_attr attr;
794 pr_debug(
"There are no selected events with Intel BTS data\n");
798 memset(&attr, 0,
sizeof(
struct perf_event_attr));
799 attr.size =
sizeof(
struct perf_event_attr);
800 attr.type = PERF_TYPE_HARDWARE;
802 attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
804 attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
805 attr.sample_type &= ~(u64)PERF_SAMPLE_CPU;
806 attr.exclude_user = evsel->
attr.exclude_user;
807 attr.exclude_kernel = evsel->
attr.exclude_kernel;
808 attr.exclude_hv = evsel->
attr.exclude_hv;
809 attr.exclude_host = evsel->
attr.exclude_host;
810 attr.exclude_guest = evsel->
attr.exclude_guest;
811 attr.sample_id_all = evsel->
attr.sample_id_all;
812 attr.read_format = evsel->
attr.read_format;
814 id = evsel->
id[0] + 1000000000;
819 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
820 attr.sample_period = 1;
821 attr.sample_type |= PERF_SAMPLE_ADDR;
822 pr_debug(
"Synthesizing 'branches' event with id %" PRIu64
" sample type %#" PRIx64
"\n",
823 id, (u64)attr.sample_type);
826 pr_err(
"%s: failed to synthesize 'branches' event type\n",
838 __perf_evsel__sample_size(attr.sample_type);
860 for (i = start; i <= finish; i++)
928 goto err_free_queues;
932 goto err_free_queues;
int color_fprintf(FILE *fp, const char *color, const char *fmt,...)
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_event_header header
int auxtrace_queues__process_index(struct auxtrace_queues *queues, struct perf_session *session)
static int intel_bts_get_branch_type(struct intel_bts_queue *btsq, struct branch *branch)
void * auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd)
struct auxtrace_queue * queue_array
struct intel_pt_insn intel_pt_insn
struct auxtrace * auxtrace
static struct intel_bts_queue * intel_bts_alloc_queue(struct intel_bts *bts, unsigned int queue_nr)
#define INTEL_PT_INSN_BUF_SZ
static unsigned char * intel_bts_find_overlap(unsigned char *buf_a, size_t len_a, unsigned char *buf_b, size_t len_b)
struct auxtrace_heap_item * heap_array
static int intel_bts_do_fix_overlap(struct auxtrace_queue *queue, struct auxtrace_buffer *b)
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)
int intel_pt_insn_type(enum intel_pt_insn_op op)
size_t branches_event_size
static int intel_bts_synth_event(struct perf_session *session, struct perf_event_attr *attr, u64 id)
struct auxtrace_buffer * auxtrace_buffer__next(struct auxtrace_queue *queue, struct auxtrace_buffer *buffer)
struct itrace_synth_opts synth_opts
static int intel_bts_update_queues(struct intel_bts *bts)
struct itrace_synth_opts * itrace_synth_opts
static int intel_bts_synth_events(struct intel_bts *bts, struct perf_session *session)
void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type, int code, int cpu, pid_t pid, pid_t tid, u64 ip, const char *msg)
int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, u64 to_ip, u16 insn_len, u64 trace_nr)
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 void intel_bts_free_queue(void *priv)
static int intel_bts_event_synth(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused)
static void intel_bts_free(struct perf_session *session)
static int intel_bts_process_auxtrace_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool __maybe_unused)
static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
int intel_bts_process_auxtrace_info(union perf_event *event, struct perf_session *session)
struct perf_tool dummy_tool
unsigned char buf[INTEL_PT_INSN_BUF_SZ]
ssize_t dso__data_read_addr(struct dso *dso, struct map *map, struct machine *machine, u64 addr, u8 *data, ssize_t size)
struct thread * machine__find_thread(struct machine *machine, pid_t pid, pid_t tid)
static int intel_bts_process_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample, struct perf_tool *tool)
int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, const struct perf_sample *sample)
static int intel_bts_flush(struct perf_session *session, struct perf_tool *tool __maybe_unused)
struct auxtrace_queues queues
#define pr_debug(fmt,...)
struct auxtrace_buffer * buffer
#define evlist__for_each_entry(evlist, evsel)
void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer)
struct perf_tsc_conversion tc
u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
static int intel_bts_process_tid_exit(struct intel_bts *bts, pid_t tid)
static void intel_bts_dump_event(struct intel_bts *bts, unsigned char *buf, size_t len)
static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
static int intel_bts_lost(struct intel_bts *bts, struct perf_sample *sample)
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
static struct perf_tool tool
static bool machine__kernel_ip(struct machine *machine, u64 ip)
static int intel_bts_process_queues(struct intel_bts *bts, u64 timestamp)
int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64, struct intel_pt_insn *intel_pt_insn)
void auxtrace_heap__free(struct auxtrace_heap *heap)
static void intel_bts_free_events(struct perf_session *session)
void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer)
static int intel_bts_process_buffer(struct intel_bts_queue *btsq, struct auxtrace_buffer *buffer, struct thread *thread)
static int perf_data__fd(struct perf_data *data)
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
static void intel_bts_print_info(u64 *arr, int start, int finish)
struct perf_event_header header
unsigned long initial_skip
struct auxtrace_error_event auxtrace_error
static int perf_data__is_pipe(struct perf_data *data)
struct strfilter * filter
struct auxtrace_heap heap
void(* free_events)(struct perf_session *session)
int(* flush_events)(struct perf_session *session, struct perf_tool *tool)
void thread__put(struct thread *thread)
void auxtrace_heap__pop(struct auxtrace_heap *heap)
void auxtrace_queues__free(struct auxtrace_queues *queues)
static int intel_bts_setup_queue(struct intel_bts *bts, struct auxtrace_queue *queue, unsigned int queue_nr)
static int intel_bts_synth_error(struct intel_bts *bts, int cpu, pid_t pid, pid_t tid, u64 ip)
int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr, u64 ordinal)
#define INTEL_BTS_ERR_LOST
static int intel_bts_setup_queues(struct intel_bts *bts)
static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, struct branch *branch)
void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
void(* free)(struct perf_session *session)
int auxtrace_queues__init(struct auxtrace_queues *queues)
int map__load(struct map *map)
#define INTEL_BTS_ERR_NOINSN
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
struct perf_event_attr attr
static void intel_bts_dump(struct intel_bts *bts __maybe_unused, unsigned char *buf, size_t len)
static const char *const intel_bts_info_fmts[]
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 int intel_bts_flush_queue(struct intel_bts_queue *btsq)
struct perf_session * session