forked from Minki/linux
7eeb9855c1
It is generally more useful to show the symbol with an address. In this case, the print function requires the 'machine' which means changing callers to provide it as a parameter. It is optional because most events do not need it and the callers that matter can provide it. Committer notes: Made 'union perf_event' continue to be the first parameter to the perf_event__fprintf() and perf_event__fprintf_text_poke() events. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Borislav Petkov <bp@alien8.de> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt (VMware) <rostedt@goodmis.org> Cc: x86@kernel.org Link: http://lore.kernel.org/lkml/20200512121922.8997-16-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
412 lines
10 KiB
C
412 lines
10 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PERF_RECORD_H
|
|
#define __PERF_RECORD_H
|
|
/*
|
|
* The linux/stddef.h isn't need here, but is needed for __always_inline used
|
|
* in files included from uapi/linux/perf_event.h such as
|
|
* /usr/include/linux/swab.h and /usr/include/linux/byteorder/little_endian.h,
|
|
* detected in at least musl libc, used in Alpine Linux. -acme
|
|
*/
|
|
#include <stdio.h>
|
|
#include <linux/stddef.h>
|
|
#include <perf/event.h>
|
|
#include <linux/types.h>
|
|
|
|
#include "perf_regs.h"
|
|
|
|
struct dso;
|
|
struct machine;
|
|
struct perf_event_attr;
|
|
|
|
#ifdef __LP64__
|
|
/*
|
|
* /usr/include/inttypes.h uses just 'lu' for PRIu64, but we end up defining
|
|
* __u64 as long long unsigned int, and then -Werror=format= kicks in and
|
|
* complains of the mismatched types, so use these two special extra PRI
|
|
* macros to overcome that.
|
|
*/
|
|
#define PRI_lu64 "l" PRIu64
|
|
#define PRI_lx64 "l" PRIx64
|
|
#define PRI_ld64 "l" PRId64
|
|
#else
|
|
#define PRI_lu64 PRIu64
|
|
#define PRI_lx64 PRIx64
|
|
#define PRI_ld64 PRId64
|
|
#endif
|
|
|
|
#define PERF_SAMPLE_MASK \
|
|
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
|
|
PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
|
|
PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
|
|
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
|
|
PERF_SAMPLE_IDENTIFIER)
|
|
|
|
/* perf sample has 16 bits size limit */
|
|
#define PERF_SAMPLE_MAX_SIZE (1 << 16)
|
|
|
|
struct regs_dump {
|
|
u64 abi;
|
|
u64 mask;
|
|
u64 *regs;
|
|
|
|
/* Cached values/mask filled by first register access. */
|
|
u64 cache_regs[PERF_REGS_MAX];
|
|
u64 cache_mask;
|
|
};
|
|
|
|
struct stack_dump {
|
|
u16 offset;
|
|
u64 size;
|
|
char *data;
|
|
};
|
|
|
|
struct sample_read_value {
|
|
u64 value;
|
|
u64 id;
|
|
};
|
|
|
|
struct sample_read {
|
|
u64 time_enabled;
|
|
u64 time_running;
|
|
union {
|
|
struct {
|
|
u64 nr;
|
|
struct sample_read_value *values;
|
|
} group;
|
|
struct sample_read_value one;
|
|
};
|
|
};
|
|
|
|
struct ip_callchain {
|
|
u64 nr;
|
|
u64 ips[];
|
|
};
|
|
|
|
struct branch_stack;
|
|
|
|
enum {
|
|
PERF_IP_FLAG_BRANCH = 1ULL << 0,
|
|
PERF_IP_FLAG_CALL = 1ULL << 1,
|
|
PERF_IP_FLAG_RETURN = 1ULL << 2,
|
|
PERF_IP_FLAG_CONDITIONAL = 1ULL << 3,
|
|
PERF_IP_FLAG_SYSCALLRET = 1ULL << 4,
|
|
PERF_IP_FLAG_ASYNC = 1ULL << 5,
|
|
PERF_IP_FLAG_INTERRUPT = 1ULL << 6,
|
|
PERF_IP_FLAG_TX_ABORT = 1ULL << 7,
|
|
PERF_IP_FLAG_TRACE_BEGIN = 1ULL << 8,
|
|
PERF_IP_FLAG_TRACE_END = 1ULL << 9,
|
|
PERF_IP_FLAG_IN_TX = 1ULL << 10,
|
|
};
|
|
|
|
#define PERF_IP_FLAG_CHARS "bcrosyiABEx"
|
|
|
|
#define PERF_BRANCH_MASK (\
|
|
PERF_IP_FLAG_BRANCH |\
|
|
PERF_IP_FLAG_CALL |\
|
|
PERF_IP_FLAG_RETURN |\
|
|
PERF_IP_FLAG_CONDITIONAL |\
|
|
PERF_IP_FLAG_SYSCALLRET |\
|
|
PERF_IP_FLAG_ASYNC |\
|
|
PERF_IP_FLAG_INTERRUPT |\
|
|
PERF_IP_FLAG_TX_ABORT |\
|
|
PERF_IP_FLAG_TRACE_BEGIN |\
|
|
PERF_IP_FLAG_TRACE_END)
|
|
|
|
#define MAX_INSN 16
|
|
|
|
struct aux_sample {
|
|
u64 size;
|
|
void *data;
|
|
};
|
|
|
|
struct perf_sample {
|
|
u64 ip;
|
|
u32 pid, tid;
|
|
u64 time;
|
|
u64 addr;
|
|
u64 id;
|
|
u64 stream_id;
|
|
u64 period;
|
|
u64 weight;
|
|
u64 transaction;
|
|
u64 insn_cnt;
|
|
u64 cyc_cnt;
|
|
u32 cpu;
|
|
u32 raw_size;
|
|
u64 data_src;
|
|
u64 phys_addr;
|
|
u64 cgroup;
|
|
u32 flags;
|
|
u16 insn_len;
|
|
u8 cpumode;
|
|
u16 misc;
|
|
bool no_hw_idx; /* No hw_idx collected in branch_stack */
|
|
char insn[MAX_INSN];
|
|
void *raw_data;
|
|
struct ip_callchain *callchain;
|
|
struct branch_stack *branch_stack;
|
|
struct regs_dump user_regs;
|
|
struct regs_dump intr_regs;
|
|
struct stack_dump user_stack;
|
|
struct sample_read read;
|
|
struct aux_sample aux_sample;
|
|
};
|
|
|
|
#define PERF_MEM_DATA_SRC_NONE \
|
|
(PERF_MEM_S(OP, NA) |\
|
|
PERF_MEM_S(LVL, NA) |\
|
|
PERF_MEM_S(SNOOP, NA) |\
|
|
PERF_MEM_S(LOCK, NA) |\
|
|
PERF_MEM_S(TLB, NA))
|
|
|
|
/* Attribute type for custom synthesized events */
|
|
#define PERF_TYPE_SYNTH (INT_MAX + 1U)
|
|
|
|
/* Attribute config for custom synthesized events */
|
|
enum perf_synth_id {
|
|
PERF_SYNTH_INTEL_PTWRITE,
|
|
PERF_SYNTH_INTEL_MWAIT,
|
|
PERF_SYNTH_INTEL_PWRE,
|
|
PERF_SYNTH_INTEL_EXSTOP,
|
|
PERF_SYNTH_INTEL_PWRX,
|
|
PERF_SYNTH_INTEL_CBR,
|
|
};
|
|
|
|
/*
|
|
* Raw data formats for synthesized events. Note that 4 bytes of padding are
|
|
* present to match the 'size' member of PERF_SAMPLE_RAW data which is always
|
|
* 8-byte aligned. That means we must dereference raw_data with an offset of 4.
|
|
* Refer perf_sample__synth_ptr() and perf_synth__raw_data(). It also means the
|
|
* structure sizes are 4 bytes bigger than the raw_size, refer
|
|
* perf_synth__raw_size().
|
|
*/
|
|
|
|
struct perf_synth_intel_ptwrite {
|
|
u32 padding;
|
|
union {
|
|
struct {
|
|
u32 ip : 1,
|
|
reserved : 31;
|
|
};
|
|
u32 flags;
|
|
};
|
|
u64 payload;
|
|
};
|
|
|
|
struct perf_synth_intel_mwait {
|
|
u32 padding;
|
|
u32 reserved;
|
|
union {
|
|
struct {
|
|
u64 hints : 8,
|
|
reserved1 : 24,
|
|
extensions : 2,
|
|
reserved2 : 30;
|
|
};
|
|
u64 payload;
|
|
};
|
|
};
|
|
|
|
struct perf_synth_intel_pwre {
|
|
u32 padding;
|
|
u32 reserved;
|
|
union {
|
|
struct {
|
|
u64 reserved1 : 7,
|
|
hw : 1,
|
|
subcstate : 4,
|
|
cstate : 4,
|
|
reserved2 : 48;
|
|
};
|
|
u64 payload;
|
|
};
|
|
};
|
|
|
|
struct perf_synth_intel_exstop {
|
|
u32 padding;
|
|
union {
|
|
struct {
|
|
u32 ip : 1,
|
|
reserved : 31;
|
|
};
|
|
u32 flags;
|
|
};
|
|
};
|
|
|
|
struct perf_synth_intel_pwrx {
|
|
u32 padding;
|
|
u32 reserved;
|
|
union {
|
|
struct {
|
|
u64 deepest_cstate : 4,
|
|
last_cstate : 4,
|
|
wake_reason : 4,
|
|
reserved1 : 52;
|
|
};
|
|
u64 payload;
|
|
};
|
|
};
|
|
|
|
struct perf_synth_intel_cbr {
|
|
u32 padding;
|
|
union {
|
|
struct {
|
|
u32 cbr : 8,
|
|
reserved1 : 8,
|
|
max_nonturbo : 8,
|
|
reserved2 : 8;
|
|
};
|
|
u32 flags;
|
|
};
|
|
u32 freq;
|
|
u32 reserved3;
|
|
};
|
|
|
|
/*
|
|
* raw_data is always 4 bytes from an 8-byte boundary, so subtract 4 to get
|
|
* 8-byte alignment.
|
|
*/
|
|
static inline void *perf_sample__synth_ptr(struct perf_sample *sample)
|
|
{
|
|
return sample->raw_data - 4;
|
|
}
|
|
|
|
static inline void *perf_synth__raw_data(void *p)
|
|
{
|
|
return p + 4;
|
|
}
|
|
|
|
#define perf_synth__raw_size(d) (sizeof(d) - 4)
|
|
|
|
#define perf_sample__bad_synth_size(s, d) ((s)->raw_size < sizeof(d) - 4)
|
|
|
|
enum {
|
|
PERF_STAT_ROUND_TYPE__INTERVAL = 0,
|
|
PERF_STAT_ROUND_TYPE__FINAL = 1,
|
|
};
|
|
|
|
void perf_event__print_totals(void);
|
|
|
|
struct perf_cpu_map;
|
|
struct perf_record_stat_config;
|
|
struct perf_stat_config;
|
|
struct perf_tool;
|
|
|
|
void perf_event__read_stat_config(struct perf_stat_config *config,
|
|
struct perf_record_stat_config *event);
|
|
|
|
int perf_event__process_comm(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_lost(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_lost_samples(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_aux(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_itrace_start(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_switch(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_namespaces(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_cgroup(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_mmap(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_mmap2(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_fork(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_exit(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_ksymbol(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_bpf(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process_text_poke(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
int perf_event__process(struct perf_tool *tool,
|
|
union perf_event *event,
|
|
struct perf_sample *sample,
|
|
struct machine *machine);
|
|
|
|
struct addr_location;
|
|
|
|
int machine__resolve(struct machine *machine, struct addr_location *al,
|
|
struct perf_sample *sample);
|
|
|
|
void addr_location__put(struct addr_location *al);
|
|
|
|
struct thread;
|
|
|
|
bool is_bts_event(struct perf_event_attr *attr);
|
|
bool sample_addr_correlates_sym(struct perf_event_attr *attr);
|
|
void thread__resolve(struct thread *thread, struct addr_location *al,
|
|
struct perf_sample *sample);
|
|
|
|
const char *perf_event__name(unsigned int id);
|
|
|
|
size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_cgroup(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp);
|
|
size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *machine,FILE *fp);
|
|
size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FILE *fp);
|
|
|
|
int kallsyms__get_function_start(const char *kallsyms_filename,
|
|
const char *symbol_name, u64 *addr);
|
|
|
|
void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max);
|
|
void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
|
|
u16 type, int max);
|
|
|
|
void event_attr_init(struct perf_event_attr *attr);
|
|
|
|
int perf_event_paranoid(void);
|
|
bool perf_event_paranoid_check(int max_level);
|
|
|
|
extern int sysctl_perf_event_max_stack;
|
|
extern int sysctl_perf_event_max_contexts_per_stack;
|
|
extern unsigned int proc_map_timeout;
|
|
|
|
#endif /* __PERF_RECORD_H */
|