Linux Perf
kvm-stat.c
Go to the documentation of this file.
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 
12 const char *vcpu_id_str = "vcpu_id";
13 const int decode_str_len = 40;
14 const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter";
15 const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit";
16 
19 
20 /* Tracepoints specific to ppc_book3s_hv */
21 const 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 */
30 const char *kvm_events_tp[NR_TPS + 1];
31 const char *kvm_exit_reason;
32 
33 static 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 
41 static 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 
56 static 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 
63 static 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 }
73 static 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 
82 static struct kvm_events_ops hcall_events = {
84  .is_end_event = hcall_event_end,
85  .decode_key = hcall_event_decode_key,
86  .name = "HCALL-EVENT",
87 };
88 
89 static struct kvm_events_ops exit_events = {
91  .is_end_event = exit_event_end,
92  .decode_key = exit_event_decode_key,
93  .name = "VM-EXIT"
94 };
95 
97  { .name = "vmexit", .ops = &exit_events },
98  { .name = "hcall", .ops = &hcall_events },
99  { NULL, NULL },
100 };
101 
102 const char * const kvm_skip_events[] = {
103  NULL,
104 };
105 
106 
107 static 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 
119 static 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++)
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 */
145 static 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 
157 {
158  return ppc__setup_kvm_tp(kvm);
159 }
160 
161 int 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 }
const char * ppc_book3s_hv_kvm_tp[]
Definition: kvm-stat.c:21
define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit)
const int decode_str_len
Definition: kvm-stat.c:13
static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, struct event_key *key, char *decode)
Definition: kvm-stat.c:73
struct exit_reasons_table * exit_reasons
Definition: kvm-stat.h:84
#define kvm_trace_symbol_hcall
Definition: book3s_hcalls.h:8
int int err
Definition: 5sec.c:44
static bool hcall_event_end(struct perf_evsel *evsel, struct perf_sample *sample __maybe_unused, struct event_key *key __maybe_unused)
Definition: kvm-stat.c:56
const char * kvm_events_tp[NR_TPS+1]
Definition: kvm-stat.c:30
int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
Definition: kvm-stat.c:156
#define pr_err(fmt,...)
Definition: json.h:21
const char * vcpu_id_str
Definition: kvm-stat.c:12
int info
Definition: kvm-stat.h:15
int parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *err)
#define NR_TPS
Definition: kvm-stat.c:10
const char * key
Definition: bpf-loader.c:196
#define pr_debug(fmt,...)
Definition: json.h:27
int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
Definition: kvm-stat.c:161
static bool hcall_event_begin(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.c:63
const char *const kvm_skip_events[]
Definition: kvm-stat.c:102
static int str(yyscan_t scanner, int token)
u64 key
Definition: kvm-stat.h:14
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
Definition: evsel.c:2722
const char * reason
Definition: kvm-stat.h:67
const char * name
Definition: kvm-stat.h:107
unsigned long exit_code
Definition: kvm-stat.h:66
#define kvm_trace_symbol_exit
bool exit_event_begin(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
static struct kvm_events_ops exit_events
Definition: kvm-stat.c:89
void exit_event_decode_key(struct perf_kvm_stat *kvm, struct event_key *key, char *decode)
bool(* is_begin_event)(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.h:54
static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm)
Definition: kvm-stat.c:145
const char * kvm_exit_reason
Definition: kvm-stat.c:31
static struct kvm_events_ops hcall_events
Definition: kvm-stat.c:82
static void cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
Definition: header.c:11
const char * exit_reasons_isa
Definition: kvm-stat.h:85
static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, struct perf_evlist *evlist)
Definition: kvm-stat.c:119
const char * kvm_exit_trace
Definition: kvm-stat.c:15
static const char * get_hcall_exit_reason(u64 exit_code)
Definition: kvm-stat.c:41
char * name
Definition: evsel.h:102
const char * kvm_entry_trace
Definition: kvm-stat.c:14
const char * name
Definition: kvm-stat.h:62
struct perf_evlist * perf_evlist__new(void)
Definition: evlist.c:54
bool exit_event_end(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
static void hcall_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.c:33
static int is_tracepoint_available(const char *str, struct perf_evlist *evlist)
Definition: kvm-stat.c:107