162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __PERF_KVM_STAT_H
362306a36Sopenharmony_ci#define __PERF_KVM_STAT_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifdef HAVE_KVM_STAT_SUPPORT
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "tool.h"
862306a36Sopenharmony_ci#include "sort.h"
962306a36Sopenharmony_ci#include "stat.h"
1062306a36Sopenharmony_ci#include "symbol.h"
1162306a36Sopenharmony_ci#include "record.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <stdlib.h>
1462306a36Sopenharmony_ci#include <linux/zalloc.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define KVM_EVENT_NAME_LEN	40
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct evsel;
1962306a36Sopenharmony_cistruct evlist;
2062306a36Sopenharmony_cistruct perf_session;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct event_key {
2362306a36Sopenharmony_ci	#define INVALID_KEY     (~0ULL)
2462306a36Sopenharmony_ci	u64 key;
2562306a36Sopenharmony_ci	int info;
2662306a36Sopenharmony_ci	struct exit_reasons_table *exit_reasons;
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct kvm_info {
3062306a36Sopenharmony_ci	char name[KVM_EVENT_NAME_LEN];
3162306a36Sopenharmony_ci	refcount_t refcnt;
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct kvm_event_stats {
3562306a36Sopenharmony_ci	u64 time;
3662306a36Sopenharmony_ci	struct stats stats;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistruct perf_kvm_stat;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct kvm_event {
4262306a36Sopenharmony_ci	struct list_head hash_entry;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	struct perf_kvm_stat *perf_kvm;
4562306a36Sopenharmony_ci	struct event_key key;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	struct kvm_event_stats total;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	#define DEFAULT_VCPU_NUM 8
5062306a36Sopenharmony_ci	int max_vcpu;
5162306a36Sopenharmony_ci	struct kvm_event_stats *vcpu;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	struct hist_entry he;
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistruct child_event_ops {
5762306a36Sopenharmony_ci	void (*get_key)(struct evsel *evsel,
5862306a36Sopenharmony_ci			struct perf_sample *sample,
5962306a36Sopenharmony_ci			struct event_key *key);
6062306a36Sopenharmony_ci	const char *name;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct kvm_events_ops {
6462306a36Sopenharmony_ci	bool (*is_begin_event)(struct evsel *evsel,
6562306a36Sopenharmony_ci			       struct perf_sample *sample,
6662306a36Sopenharmony_ci			       struct event_key *key);
6762306a36Sopenharmony_ci	bool (*is_end_event)(struct evsel *evsel,
6862306a36Sopenharmony_ci			     struct perf_sample *sample, struct event_key *key);
6962306a36Sopenharmony_ci	struct child_event_ops *child_ops;
7062306a36Sopenharmony_ci	void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
7162306a36Sopenharmony_ci			   char *decode);
7262306a36Sopenharmony_ci	const char *name;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistruct exit_reasons_table {
7662306a36Sopenharmony_ci	unsigned long exit_code;
7762306a36Sopenharmony_ci	const char *reason;
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct perf_kvm_stat {
8162306a36Sopenharmony_ci	struct perf_tool    tool;
8262306a36Sopenharmony_ci	struct record_opts  opts;
8362306a36Sopenharmony_ci	struct evlist  *evlist;
8462306a36Sopenharmony_ci	struct perf_session *session;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	const char *file_name;
8762306a36Sopenharmony_ci	const char *report_event;
8862306a36Sopenharmony_ci	const char *sort_key;
8962306a36Sopenharmony_ci	int trace_vcpu;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/* Used when process events */
9262306a36Sopenharmony_ci	struct addr_location al;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	struct exit_reasons_table *exit_reasons;
9562306a36Sopenharmony_ci	const char *exit_reasons_isa;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	struct kvm_events_ops *events_ops;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	u64 total_time;
10062306a36Sopenharmony_ci	u64 total_count;
10162306a36Sopenharmony_ci	u64 lost_events;
10262306a36Sopenharmony_ci	u64 duration;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	struct intlist *pid_list;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	int timerfd;
10762306a36Sopenharmony_ci	unsigned int display_time;
10862306a36Sopenharmony_ci	bool live;
10962306a36Sopenharmony_ci	bool force;
11062306a36Sopenharmony_ci	bool use_stdio;
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistruct kvm_reg_events_ops {
11462306a36Sopenharmony_ci	const char *name;
11562306a36Sopenharmony_ci	struct kvm_events_ops *ops;
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_civoid exit_event_get_key(struct evsel *evsel,
11962306a36Sopenharmony_ci			struct perf_sample *sample,
12062306a36Sopenharmony_ci			struct event_key *key);
12162306a36Sopenharmony_cibool exit_event_begin(struct evsel *evsel,
12262306a36Sopenharmony_ci		      struct perf_sample *sample,
12362306a36Sopenharmony_ci		      struct event_key *key);
12462306a36Sopenharmony_cibool exit_event_end(struct evsel *evsel,
12562306a36Sopenharmony_ci		    struct perf_sample *sample,
12662306a36Sopenharmony_ci		    struct event_key *key);
12762306a36Sopenharmony_civoid exit_event_decode_key(struct perf_kvm_stat *kvm,
12862306a36Sopenharmony_ci			   struct event_key *key,
12962306a36Sopenharmony_ci			   char *decode);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cibool kvm_exit_event(struct evsel *evsel);
13262306a36Sopenharmony_cibool kvm_entry_event(struct evsel *evsel);
13362306a36Sopenharmony_ciint setup_kvm_events_tp(struct perf_kvm_stat *kvm);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci#define define_exit_reasons_table(name, symbols)	\
13662306a36Sopenharmony_ci	static struct exit_reasons_table name[] = {	\
13762306a36Sopenharmony_ci		symbols, { -1, NULL }			\
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/*
14162306a36Sopenharmony_ci * arch specific callbacks and data structures
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_ciint cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ciextern const char *kvm_events_tp[];
14662306a36Sopenharmony_ciextern struct kvm_reg_events_ops kvm_reg_events_ops[];
14762306a36Sopenharmony_ciextern const char * const kvm_skip_events[];
14862306a36Sopenharmony_ciextern const char *vcpu_id_str;
14962306a36Sopenharmony_ciextern const char *kvm_exit_reason;
15062306a36Sopenharmony_ciextern const char *kvm_entry_trace;
15162306a36Sopenharmony_ciextern const char *kvm_exit_trace;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic inline struct kvm_info *kvm_info__get(struct kvm_info *ki)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	if (ki)
15662306a36Sopenharmony_ci		refcount_inc(&ki->refcnt);
15762306a36Sopenharmony_ci	return ki;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic inline void kvm_info__put(struct kvm_info *ki)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	if (ki && refcount_dec_and_test(&ki->refcnt))
16362306a36Sopenharmony_ci		free(ki);
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic inline void __kvm_info__zput(struct kvm_info **ki)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	kvm_info__put(*ki);
16962306a36Sopenharmony_ci	*ki = NULL;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#define kvm_info__zput(ki) __kvm_info__zput(&ki)
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic inline struct kvm_info *kvm_info__new(void)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	struct kvm_info *ki;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	ki = zalloc(sizeof(*ki));
17962306a36Sopenharmony_ci	if (ki)
18062306a36Sopenharmony_ci		refcount_set(&ki->refcnt, 1);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return ki;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#else /* HAVE_KVM_STAT_SUPPORT */
18662306a36Sopenharmony_ci// We use this unconditionally in hists__findnew_entry() and hist_entry__delete()
18762306a36Sopenharmony_ci#define kvm_info__zput(ki) do { } while (0)
18862306a36Sopenharmony_ci#endif /* HAVE_KVM_STAT_SUPPORT */
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ciextern int kvm_add_default_arch_event(int *argc, const char **argv);
19162306a36Sopenharmony_ci#endif /* __PERF_KVM_STAT_H */
192