| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #ifndef __PERF_KVM_STAT_H |
| 3 | #define __PERF_KVM_STAT_H |
| 4 | |
| 5 | #ifdef HAVE_KVM_STAT_SUPPORT |
| 6 | |
| 7 | #include "tool.h" |
| 8 | #include "sort.h" |
| 9 | #include "stat.h" |
| 10 | #include "symbol.h" |
| 11 | #include "record.h" |
| 12 | |
| 13 | #include <errno.h> |
| 14 | #include <stdlib.h> |
| 15 | #include <linux/zalloc.h> |
| 16 | |
| 17 | #define KVM_EVENT_NAME_LEN 40 |
| 18 | |
| 19 | struct evsel; |
| 20 | struct evlist; |
| 21 | struct perf_session; |
| 22 | |
| 23 | struct event_key { |
| 24 | #define INVALID_KEY (~0ULL) |
| 25 | u64 key; |
| 26 | int info; |
| 27 | struct exit_reasons_table *exit_reasons; |
| 28 | }; |
| 29 | |
| 30 | struct kvm_info { |
| 31 | char name[KVM_EVENT_NAME_LEN]; |
| 32 | refcount_t refcnt; |
| 33 | }; |
| 34 | |
| 35 | struct kvm_event_stats { |
| 36 | u64 time; |
| 37 | struct stats stats; |
| 38 | }; |
| 39 | |
| 40 | struct perf_kvm_stat; |
| 41 | |
| 42 | struct kvm_event { |
| 43 | struct list_head hash_entry; |
| 44 | |
| 45 | struct perf_kvm_stat *perf_kvm; |
| 46 | struct event_key key; |
| 47 | |
| 48 | struct kvm_event_stats total; |
| 49 | |
| 50 | #define DEFAULT_VCPU_NUM 8 |
| 51 | int max_vcpu; |
| 52 | struct kvm_event_stats *vcpu; |
| 53 | |
| 54 | struct hist_entry he; |
| 55 | }; |
| 56 | |
| 57 | struct child_event_ops { |
| 58 | void (*get_key)(struct evsel *evsel, |
| 59 | struct perf_sample *sample, |
| 60 | struct event_key *key); |
| 61 | const char *name; |
| 62 | }; |
| 63 | |
| 64 | struct kvm_events_ops { |
| 65 | bool (*is_begin_event)(struct evsel *evsel, |
| 66 | struct perf_sample *sample, |
| 67 | struct event_key *key); |
| 68 | bool (*is_end_event)(struct evsel *evsel, |
| 69 | struct perf_sample *sample, struct event_key *key); |
| 70 | struct child_event_ops *child_ops; |
| 71 | void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, |
| 72 | char *decode); |
| 73 | const char *name; |
| 74 | }; |
| 75 | |
| 76 | struct exit_reasons_table { |
| 77 | unsigned long exit_code; |
| 78 | const char *reason; |
| 79 | }; |
| 80 | |
| 81 | struct perf_kvm_stat { |
| 82 | struct perf_tool tool; |
| 83 | struct record_opts opts; |
| 84 | struct evlist *evlist; |
| 85 | struct perf_session *session; |
| 86 | |
| 87 | const char *file_name; |
| 88 | const char *report_event; |
| 89 | const char *sort_key; |
| 90 | int trace_vcpu; |
| 91 | |
| 92 | /* Used when process events */ |
| 93 | struct addr_location al; |
| 94 | |
| 95 | struct exit_reasons_table *exit_reasons; |
| 96 | const char *exit_reasons_isa; |
| 97 | |
| 98 | struct kvm_events_ops *events_ops; |
| 99 | |
| 100 | u64 total_time; |
| 101 | u64 total_count; |
| 102 | u64 lost_events; |
| 103 | u64 duration; |
| 104 | |
| 105 | struct intlist *pid_list; |
| 106 | |
| 107 | int timerfd; |
| 108 | unsigned int display_time; |
| 109 | bool live; |
| 110 | bool force; |
| 111 | bool use_stdio; |
| 112 | }; |
| 113 | |
| 114 | struct kvm_reg_events_ops { |
| 115 | const char *name; |
| 116 | struct kvm_events_ops *ops; |
| 117 | }; |
| 118 | |
| 119 | #if defined(HAVE_KVM_STAT_SUPPORT) && defined(HAVE_LIBTRACEEVENT) |
| 120 | |
| 121 | void exit_event_get_key(struct evsel *evsel, |
| 122 | struct perf_sample *sample, |
| 123 | struct event_key *key); |
| 124 | bool exit_event_begin(struct evsel *evsel, |
| 125 | struct perf_sample *sample, |
| 126 | struct event_key *key); |
| 127 | bool exit_event_end(struct evsel *evsel, |
| 128 | struct perf_sample *sample, |
| 129 | struct event_key *key); |
| 130 | void exit_event_decode_key(struct perf_kvm_stat *kvm, |
| 131 | struct event_key *key, |
| 132 | char *decode); |
| 133 | #endif |
| 134 | |
| 135 | bool kvm_exit_event(struct evsel *evsel); |
| 136 | bool kvm_entry_event(struct evsel *evsel); |
| 137 | int setup_kvm_events_tp(struct perf_kvm_stat *kvm); |
| 138 | |
| 139 | #define define_exit_reasons_table(name, symbols) \ |
| 140 | static struct exit_reasons_table name[] = { \ |
| 141 | symbols, { -1, NULL } \ |
| 142 | } |
| 143 | |
| 144 | /* |
| 145 | * arch specific callbacks and data structures |
| 146 | */ |
| 147 | int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid); |
| 148 | |
| 149 | extern const char *kvm_events_tp[]; |
| 150 | extern struct kvm_reg_events_ops kvm_reg_events_ops[]; |
| 151 | extern const char * const kvm_skip_events[]; |
| 152 | extern const char *vcpu_id_str; |
| 153 | extern const char *kvm_exit_reason; |
| 154 | extern const char *kvm_entry_trace; |
| 155 | extern const char *kvm_exit_trace; |
| 156 | |
| 157 | static inline struct kvm_info *kvm_info__get(struct kvm_info *ki) |
| 158 | { |
| 159 | if (ki) |
| 160 | refcount_inc(&ki->refcnt); |
| 161 | return ki; |
| 162 | } |
| 163 | |
| 164 | static inline void kvm_info__put(struct kvm_info *ki) |
| 165 | { |
| 166 | if (ki && refcount_dec_and_test(&ki->refcnt)) |
| 167 | free(ki); |
| 168 | } |
| 169 | |
| 170 | static inline void __kvm_info__zput(struct kvm_info **ki) |
| 171 | { |
| 172 | kvm_info__put(*ki); |
| 173 | *ki = NULL; |
| 174 | } |
| 175 | |
| 176 | #define kvm_info__zput(ki) __kvm_info__zput(&ki) |
| 177 | |
| 178 | static inline struct kvm_info *kvm_info__new(void) |
| 179 | { |
| 180 | struct kvm_info *ki; |
| 181 | |
| 182 | ki = zalloc(sizeof(*ki)); |
| 183 | if (ki) |
| 184 | refcount_set(&ki->refcnt, 1); |
| 185 | |
| 186 | return ki; |
| 187 | } |
| 188 | |
| 189 | #else /* HAVE_KVM_STAT_SUPPORT */ |
| 190 | // We use this unconditionally in hists__findnew_entry() and hist_entry__delete() |
| 191 | #define kvm_info__zput(ki) do { } while (0) |
| 192 | #endif /* HAVE_KVM_STAT_SUPPORT */ |
| 193 | |
| 194 | #define STRDUP_FAIL_EXIT(s) \ |
| 195 | ({ char *_p; \ |
| 196 | _p = strdup(s); \ |
| 197 | if (!_p) { \ |
| 198 | ret = -ENOMEM; \ |
| 199 | goto EXIT; \ |
| 200 | } \ |
| 201 | _p; \ |
| 202 | }) |
| 203 | |
| 204 | extern int kvm_add_default_arch_event(int *argc, const char **argv); |
| 205 | #endif /* __PERF_KVM_STAT_H */ |
| 206 | |