Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16 172 lines 4.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <errno.h> 3#include "util/kvm-stat.h" 4#include "util/parse-events.h" 5#include "util/debug.h" 6 7#include "book3s_hv_exits.h" 8#include "book3s_hcalls.h" 9 10#define NR_TPS 4 11 12const char *vcpu_id_str = "vcpu_id"; 13const int decode_str_len = 40; 14const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter"; 15const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit"; 16 17define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit); 18define_exit_reasons_table(hcall_reasons, kvm_trace_symbol_hcall); 19 20/* Tracepoints specific to ppc_book3s_hv */ 21const char *ppc_book3s_hv_kvm_tp[] = { 22 "kvm_hv:kvm_guest_enter", 23 "kvm_hv:kvm_guest_exit", 24 "kvm_hv:kvm_hcall_enter", 25 "kvm_hv:kvm_hcall_exit", 26 NULL, 27}; 28 29/* 1 extra placeholder for NULL */ 30const char *kvm_events_tp[NR_TPS + 1]; 31const char *kvm_exit_reason; 32 33static void hcall_event_get_key(struct perf_evsel *evsel, 34 struct perf_sample *sample, 35 struct event_key *key) 36{ 37 key->info = 0; 38 key->key = perf_evsel__intval(evsel, sample, "req"); 39} 40 41static const char *get_hcall_exit_reason(u64 exit_code) 42{ 43 struct exit_reasons_table *tbl = hcall_reasons; 44 45 while (tbl->reason != NULL) { 46 if (tbl->exit_code == exit_code) 47 return tbl->reason; 48 tbl++; 49 } 50 51 pr_debug("Unknown hcall code: %lld\n", 52 (unsigned long long)exit_code); 53 return "UNKNOWN"; 54} 55 56static bool hcall_event_end(struct perf_evsel *evsel, 57 struct perf_sample *sample __maybe_unused, 58 struct event_key *key __maybe_unused) 59{ 60 return (!strcmp(evsel->name, kvm_events_tp[3])); 61} 62 63static bool hcall_event_begin(struct perf_evsel *evsel, 64 struct perf_sample *sample, struct event_key *key) 65{ 66 if (!strcmp(evsel->name, kvm_events_tp[2])) { 67 hcall_event_get_key(evsel, sample, key); 68 return true; 69 } 70 71 return false; 72} 73static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, 74 struct event_key *key, 75 char *decode) 76{ 77 const char *hcall_reason = get_hcall_exit_reason(key->key); 78 79 scnprintf(decode, decode_str_len, "%s", hcall_reason); 80} 81 82static struct kvm_events_ops hcall_events = { 83 .is_begin_event = hcall_event_begin, 84 .is_end_event = hcall_event_end, 85 .decode_key = hcall_event_decode_key, 86 .name = "HCALL-EVENT", 87}; 88 89static struct kvm_events_ops exit_events = { 90 .is_begin_event = exit_event_begin, 91 .is_end_event = exit_event_end, 92 .decode_key = exit_event_decode_key, 93 .name = "VM-EXIT" 94}; 95 96struct kvm_reg_events_ops kvm_reg_events_ops[] = { 97 { .name = "vmexit", .ops = &exit_events }, 98 { .name = "hcall", .ops = &hcall_events }, 99 { NULL, NULL }, 100}; 101 102const char * const kvm_skip_events[] = { 103 NULL, 104}; 105 106 107static int is_tracepoint_available(const char *str, struct perf_evlist *evlist) 108{ 109 struct parse_events_error err; 110 int ret; 111 112 err.str = NULL; 113 ret = parse_events(evlist, str, &err); 114 if (err.str) 115 pr_err("%s : %s\n", str, err.str); 116 return ret; 117} 118 119static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, 120 struct perf_evlist *evlist) 121{ 122 const char **events_ptr; 123 int i, nr_tp = 0, err = -1; 124 125 /* Check for book3s_hv tracepoints */ 126 for (events_ptr = ppc_book3s_hv_kvm_tp; *events_ptr; events_ptr++) { 127 err = is_tracepoint_available(*events_ptr, evlist); 128 if (err) 129 return -1; 130 nr_tp++; 131 } 132 133 for (i = 0; i < nr_tp; i++) 134 kvm_events_tp[i] = ppc_book3s_hv_kvm_tp[i]; 135 136 kvm_events_tp[i] = NULL; 137 kvm_exit_reason = "trap"; 138 kvm->exit_reasons = hv_exit_reasons; 139 kvm->exit_reasons_isa = "HV"; 140 141 return 0; 142} 143 144/* Wrapper to setup kvm tracepoints */ 145static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm) 146{ 147 struct perf_evlist *evlist = perf_evlist__new(); 148 149 if (evlist == NULL) 150 return -ENOMEM; 151 152 /* Right now, only supported on book3s_hv */ 153 return ppc__setup_book3s_hv(kvm, evlist); 154} 155 156int setup_kvm_events_tp(struct perf_kvm_stat *kvm) 157{ 158 return ppc__setup_kvm_tp(kvm); 159} 160 161int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused) 162{ 163 int ret; 164 165 ret = ppc__setup_kvm_tp(kvm); 166 if (ret) { 167 kvm->exit_reasons = NULL; 168 kvm->exit_reasons_isa = NULL; 169 } 170 171 return ret; 172}