diff options
Diffstat (limited to 'tools/perf/util/auxtrace.h')
-rw-r--r-- | tools/perf/util/auxtrace.h | 185 |
1 files changed, 138 insertions, 47 deletions
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 142ccf7d34df..55702215a82d 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -15,6 +15,7 @@ #include <linux/list.h> #include <linux/perf_event.h> #include <linux/types.h> +#include <perf/cpumap.h> #include <asm/bitsperlong.h> #include <asm/barrier.h> @@ -47,6 +48,7 @@ enum auxtrace_type { PERF_AUXTRACE_CS_ETM, PERF_AUXTRACE_ARM_SPE, PERF_AUXTRACE_S390_CPUMSF, + PERF_AUXTRACE_HISI_PTT, }; enum itrace_period_type { @@ -55,6 +57,13 @@ enum itrace_period_type { PERF_ITRACE_PERIOD_NANOSECS, }; +#define AUXTRACE_ERR_FLG_OVERFLOW (1 << ('o' - 'a')) +#define AUXTRACE_ERR_FLG_DATA_LOST (1 << ('l' - 'a')) + +#define AUXTRACE_LOG_FLG_ALL_PERF_EVTS (1 << ('a' - 'a')) +#define AUXTRACE_LOG_FLG_ON_ERROR (1 << ('e' - 'a')) +#define AUXTRACE_LOG_FLG_USE_STDOUT (1 << ('o' - 'a')) + /** * struct itrace_synth_opts - AUX area tracing synthesis options. * @set: indicates whether or not options have been set @@ -62,6 +71,9 @@ enum itrace_period_type { * @inject: indicates the event (not just the sample) must be fully synthesized * because 'perf inject' will write it out * @instructions: whether to synthesize 'instructions' events + * @cycles: whether to synthesize 'cycles' events + * (not fully accurate, since CYC packets are only emitted + * together with other events, such as branches) * @branches: whether to synthesize 'branches' events * (branch misses only for Arm SPE) * @transactions: whether to synthesize events for transactions @@ -69,6 +81,7 @@ enum itrace_period_type { * @pwr_events: whether to synthesize power events * @other_events: whether to synthesize other events recorded due to the use of * aux_output + * @intr_events: whether to synthesize interrupt events * @errors: whether to synthesize decoder error events * @dont_decode: whether to skip decoding entirely * @log: write a decoding log @@ -79,10 +92,17 @@ enum itrace_period_type { * @thread_stack: feed branches to the thread_stack * @last_branch: add branch context to 'instruction' events * @add_last_branch: add branch context to existing event records + * @approx_ipc: approximate IPC * @flc: whether to synthesize first level cache events * @llc: whether to synthesize last level cache events * @tlb: whether to synthesize TLB events * @remote_access: whether to synthesize remote access events + * @mem: whether to synthesize memory events + * @timeless_decoding: prefer "timeless" decoding i.e. ignore timestamps + * @use_timestamp: use the timestamp trace as kernel time + * @vm_time_correlation: perform VM Time Correlation + * @vm_tm_corr_dry_run: VM Time Correlation dry-run + * @vm_tm_corr_args: VM Time Correlation implementation-specific arguments * @callchain_sz: maximum callchain size * @last_branch_sz: branch context size * @period: 'instructions' events period @@ -91,17 +111,25 @@ enum itrace_period_type { * @cpu_bitmap: CPUs for which to synthesize events, or NULL for all * @ptime_range: time intervals to trace or NULL * @range_num: number of time intervals to trace + * @error_plus_flags: flags to affect what errors are reported + * @error_minus_flags: flags to affect what errors are reported + * @log_plus_flags: flags to affect what is logged + * @log_minus_flags: flags to affect what is logged + * @quick: quicker (less detailed) decoding + * @log_on_error_size: size of log to keep for outputting log only on errors */ struct itrace_synth_opts { bool set; bool default_no_sample; bool inject; bool instructions; + bool cycles; bool branches; bool transactions; bool ptwrites; bool pwr_events; bool other_events; + bool intr_events; bool errors; bool dont_decode; bool log; @@ -112,10 +140,17 @@ struct itrace_synth_opts { bool thread_stack; bool last_branch; bool add_last_branch; + bool approx_ipc; bool flc; bool llc; bool tlb; bool remote_access; + bool mem; + bool timeless_decoding; + bool use_timestamp; + bool vm_time_correlation; + bool vm_tm_corr_dry_run; + char *vm_tm_corr_args; unsigned int callchain_sz; unsigned int last_branch_sz; unsigned long long period; @@ -124,6 +159,12 @@ struct itrace_synth_opts { unsigned long *cpu_bitmap; struct perf_time_interval *ptime_range; int range_num; + unsigned int error_plus_flags; + unsigned int error_minus_flags; + unsigned int log_plus_flags; + unsigned int log_minus_flags; + unsigned int quick; + unsigned int log_on_error_size; }; /** @@ -212,7 +253,7 @@ struct auxtrace_buffer { size_t size; pid_t pid; pid_t tid; - int cpu; + struct perf_cpu cpu; void *data; off_t data_offset; void *mmap_addr; @@ -313,6 +354,10 @@ struct auxtrace_mmap { * @idx: index of this mmap * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu * mmap) otherwise %0 + * @mmap_needed: set to %false for non-auxtrace events. This is needed because + * auxtrace mmapping is done in the same code path as non-auxtrace + * mmapping but not every evsel that needs non-auxtrace mmapping + * also needs auxtrace mmapping. * @cpu: cpu number for a per-cpu mmap otherwise %-1 */ struct auxtrace_mmap_params { @@ -322,7 +367,8 @@ struct auxtrace_mmap_params { int prot; int idx; pid_t tid; - int cpu; + bool mmap_needed; + struct perf_cpu cpu; }; /** @@ -415,52 +461,39 @@ struct auxtrace_cache; #ifdef HAVE_AUXTRACE_SUPPORT -/* - * In snapshot mode the mmapped page is read-only which makes using - * __sync_val_compare_and_swap() problematic. However, snapshot mode expects - * the buffer is not updated while the snapshot is made (e.g. Intel PT disables - * the event) so there is not a race anyway. - */ -static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm) -{ - struct perf_event_mmap_page *pc = mm->userpg; - u64 head = READ_ONCE(pc->aux_head); - - /* Ensure all reads are done after we read the head */ - rmb(); - return head; -} +u64 compat_auxtrace_mmap__read_head(struct auxtrace_mmap *mm); +int compat_auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail); -static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm) +static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm, + int kernel_is_64_bit __maybe_unused) { struct perf_event_mmap_page *pc = mm->userpg; -#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT) - u64 head = READ_ONCE(pc->aux_head); -#else - u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0); + u64 head; + +#if BITS_PER_LONG == 32 + if (kernel_is_64_bit) + return compat_auxtrace_mmap__read_head(mm); #endif + head = READ_ONCE(pc->aux_head); /* Ensure all reads are done after we read the head */ - rmb(); + smp_rmb(); return head; } -static inline void auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail) +static inline int auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail, + int kernel_is_64_bit __maybe_unused) { struct perf_event_mmap_page *pc = mm->userpg; -#if BITS_PER_LONG != 64 && defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT) - u64 old_tail; -#endif - /* Ensure all reads are done before we write the tail out */ - mb(); -#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT) - pc->aux_tail = tail; -#else - do { - old_tail = __sync_val_compare_and_swap(&pc->aux_tail, 0, 0); - } while (!__sync_bool_compare_and_swap(&pc->aux_tail, old_tail, tail)); +#if BITS_PER_LONG == 32 + if (kernel_is_64_bit) + return compat_auxtrace_mmap__write_tail(mm, tail); #endif + /* Ensure all reads are done before we write the tail out */ + smp_mb(); + WRITE_ONCE(pc->aux_tail, tail); + return 0; } int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, @@ -472,8 +505,8 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, int idx, - bool per_cpu); + struct evlist *evlist, + struct evsel *evsel, int idx); typedef int (*process_auxtrace_t)(struct perf_tool *tool, struct mmap *map, @@ -508,7 +541,11 @@ int auxtrace_queue_data(struct perf_session *session, bool samples, bool events); struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue, struct auxtrace_buffer *buffer); -void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd); +void *auxtrace_buffer__get_data_rw(struct auxtrace_buffer *buffer, int fd, bool rw); +static inline void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd) +{ + return auxtrace_buffer__get_data_rw(buffer, fd, false); +} void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer); void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer); void auxtrace_buffer__free(struct auxtrace_buffer *buffer); @@ -542,6 +579,7 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, int auxtrace_parse_sample_options(struct auxtrace_record *itr, struct evlist *evlist, struct record_opts *opts, const char *str); +void auxtrace_regroup_aux_output(struct evlist *evlist); int auxtrace_record__options(struct auxtrace_record *itr, struct evlist *evlist, struct record_opts *opts); @@ -567,6 +605,10 @@ int auxtrace_index__process(int fd, u64 size, struct perf_session *session, bool needs_swap); void auxtrace_index__free(struct list_head *head); +void auxtrace_synth_guest_error(struct perf_record_auxtrace_error *auxtrace_error, int type, + int code, int cpu, pid_t pid, pid_t tid, u64 ip, + const char *msg, u64 timestamp, + pid_t machine_pid, int vcpu); void auxtrace_synth_error(struct perf_record_auxtrace_error *auxtrace_error, int type, int code, int cpu, pid_t pid, pid_t tid, u64 ip, const char *msg, u64 timestamp); @@ -577,6 +619,8 @@ s64 perf_event__process_auxtrace(struct perf_session *session, union perf_event *event); int perf_event__process_auxtrace_error(struct perf_session *session, union perf_event *event); +int itrace_do_parse_synth_opts(struct itrace_synth_opts *synth_opts, + const char *str, int unset); int itrace_parse_synth_opts(const struct option *opt, const char *str, int unset); void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts, @@ -604,24 +648,41 @@ bool auxtrace__evsel_is_auxtrace(struct perf_session *session, struct evsel *evsel); #define ITRACE_HELP \ -" i: synthesize instructions events\n" \ +" i[period]: synthesize instructions events\n" \ +" y[period]: synthesize cycles events (same period as i)\n" \ " b: synthesize branches events (branch misses for Arm SPE)\n" \ " c: synthesize branches events (calls only)\n" \ " r: synthesize branches events (returns only)\n" \ " x: synthesize transactions events\n" \ " w: synthesize ptwrite events\n" \ " p: synthesize power events\n" \ -" e: synthesize error events\n" \ -" d: create a debug log\n" \ +" o: synthesize other events recorded due to the use\n" \ +" of aux-output (refer to perf record)\n" \ +" I: synthesize interrupt or similar (asynchronous) events\n" \ +" (e.g. Intel PT Event Trace)\n" \ +" e[flags]: synthesize error events\n" \ +" each flag must be preceded by + or -\n" \ +" error flags are: o (overflow)\n" \ +" l (data lost)\n" \ +" d[flags]: create a debug log\n" \ +" each flag must be preceded by + or -\n" \ +" log flags are: a (all perf events)\n" \ +" o (output to stdout)\n" \ " f: synthesize first level cache events\n" \ " m: synthesize last level cache events\n" \ " t: synthesize TLB events\n" \ " a: synthesize remote access events\n" \ " g[len]: synthesize a call chain (use with i or x)\n" \ +" G[len]: synthesize a call chain on existing event records\n" \ " l[len]: synthesize last branch entries (use with i or x)\n" \ +" L[len]: synthesize last branch entries on existing event records\n" \ " sNUMBER: skip initial number of events\n" \ +" q: quicker (less detailed) decoding\n" \ +" A: approximate IPC\n" \ +" Z: prefer to ignore timestamps (so-called \"timeless\" decoding)\n" \ +" T: use the timestamp trace as kernel time\n" \ " PERIOD[ns|us|ms|i|t]: specify period to sample stream\n" \ -" concatenate multiple options. Default is ibxwpe or cewp\n" +" concatenate multiple options. Default is iybxwpe or cewp\n" static inline void itrace_synth_opts__set_time_range(struct itrace_synth_opts *opts, @@ -663,9 +724,26 @@ int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused, return 0; } -#define perf_event__process_auxtrace_info 0 -#define perf_event__process_auxtrace 0 -#define perf_event__process_auxtrace_error 0 +static inline +int perf_event__process_auxtrace_info(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} + +static inline +s64 perf_event__process_auxtrace(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} + +static inline +int perf_event__process_auxtrace_error(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} static inline void perf_session__auxtrace_error_inc(struct perf_session *session @@ -682,6 +760,14 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats } static inline +int itrace_do_parse_synth_opts(struct itrace_synth_opts *synth_opts __maybe_unused, + const char *str __maybe_unused, int unset __maybe_unused) +{ + pr_err("AUX area tracing not supported\n"); + return -EINVAL; +} + +static inline int itrace_parse_synth_opts(const struct option *opt __maybe_unused, const char *str __maybe_unused, int unset __maybe_unused) @@ -714,6 +800,11 @@ int auxtrace_parse_sample_options(struct auxtrace_record *itr __maybe_unused, } static inline +void auxtrace_regroup_aux_output(struct evlist *evlist __maybe_unused) +{ +} + +static inline int auxtrace__process_event(struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, @@ -793,8 +884,8 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, int idx, - bool per_cpu); + struct evlist *evlist, + struct evsel *evsel, int idx); #define ITRACE_HELP "" |