2014-07-03 18:29:05 +04:00
# ifndef __PERF_KVM_STAT_H
# define __PERF_KVM_STAT_H
# include "../perf.h"
# include "evsel.h"
# include "evlist.h"
# include "session.h"
# include "tool.h"
# include "stat.h"
struct event_key {
# define INVALID_KEY (~0ULL)
u64 key ;
int info ;
2014-07-03 18:29:07 +04:00
struct exit_reasons_table * exit_reasons ;
2014-07-03 18:29:05 +04:00
} ;
struct kvm_event_stats {
u64 time ;
struct stats stats ;
} ;
struct kvm_event {
struct list_head hash_entry ;
struct rb_node rb ;
struct event_key key ;
struct kvm_event_stats total ;
# define DEFAULT_VCPU_NUM 8
int max_vcpu ;
struct kvm_event_stats * vcpu ;
} ;
typedef int ( * key_cmp_fun ) ( struct kvm_event * , struct kvm_event * , int ) ;
struct kvm_event_key {
const char * name ;
key_cmp_fun key ;
} ;
struct perf_kvm_stat ;
2014-07-03 18:29:07 +04:00
struct child_event_ops {
void ( * get_key ) ( struct perf_evsel * evsel ,
struct perf_sample * sample ,
struct event_key * key ) ;
const char * name ;
} ;
2014-07-03 18:29:05 +04:00
struct kvm_events_ops {
bool ( * is_begin_event ) ( struct perf_evsel * evsel ,
struct perf_sample * sample ,
struct event_key * key ) ;
bool ( * is_end_event ) ( struct perf_evsel * evsel ,
struct perf_sample * sample , struct event_key * key ) ;
2014-07-03 18:29:07 +04:00
struct child_event_ops * child_ops ;
2014-07-03 18:29:05 +04:00
void ( * decode_key ) ( struct perf_kvm_stat * kvm , struct event_key * key ,
char * decode ) ;
const char * name ;
} ;
struct exit_reasons_table {
unsigned long exit_code ;
const char * reason ;
} ;
# define EVENTS_BITS 12
# define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
struct perf_kvm_stat {
struct perf_tool tool ;
struct record_opts opts ;
struct perf_evlist * evlist ;
struct perf_session * session ;
const char * file_name ;
const char * report_event ;
const char * sort_key ;
int trace_vcpu ;
struct exit_reasons_table * exit_reasons ;
const char * exit_reasons_isa ;
struct kvm_events_ops * events_ops ;
key_cmp_fun compare ;
struct list_head kvm_events_cache [ EVENTS_CACHE_SIZE ] ;
u64 total_time ;
u64 total_count ;
u64 lost_events ;
u64 duration ;
struct intlist * pid_list ;
struct rb_root result ;
int timerfd ;
unsigned int display_time ;
bool live ;
perf kvm: Support using -f to override perf.data.guest file ownership
Enable perf kvm to use perf.data.guest when it is not owned by current
user or root.
Example:
# perf kvm stat record ls
# chown Yunlong.Song:Yunlong.Song perf.data.guest
# ls -al perf.data.guest
-rw------- 1 Yunlong.Song Yunlong.Song 4128937 Apr 2 11:05 perf.data.guest
# id
uid=0(root) gid=0(root) groups=0(root),64(pkcs11)
Before this patch:
# perf kvm stat report
File perf.data.guest not owned by current user or root (use -f to override)
Initializing perf session failed
# perf kvm stat report -f
Error: unknown switch `f'
usage: perf kvm stat report [<options>]
--event <report event>
event for reporting: vmexit, mmio (x86 only),
ioport (x86 only)
--vcpu <n> vcpu id to report
-k, --key <sort-key> key for sorting: sample(sort by samples
number) time (sort by avg time)
-p, --pid <pid> analyze events only for given process id(s)
As shown above, the -f option does not work at all.
After this patch:
# perf kvm stat report
File perf.data.guest not owned by current user or root (use -f to override)
Initializing perf session failed
# perf kvm stat report -f
Analyze events for all VMs, all VCPUs:
VM-EXIT Samples Samples% Time% Min Time Max Time Avg time
Total Samples:0, Total events handled time:0.00us.
As shown above, the -f option really works now. Since we have not
launched any KVM related process, the result shows 0 sample here.
Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1427982439-27388-5-git-send-email-yunlong.song@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-04-02 21:47:13 +08:00
bool force ;
2014-07-03 18:29:05 +04:00
} ;
struct kvm_reg_events_ops {
const char * name ;
struct kvm_events_ops * ops ;
} ;
void exit_event_get_key ( struct perf_evsel * evsel ,
struct perf_sample * sample ,
struct event_key * key ) ;
bool exit_event_begin ( struct perf_evsel * evsel ,
struct perf_sample * sample ,
struct event_key * key ) ;
bool exit_event_end ( struct perf_evsel * evsel ,
struct perf_sample * sample ,
struct event_key * key ) ;
void exit_event_decode_key ( struct perf_kvm_stat * kvm ,
struct event_key * key ,
char * decode ) ;
bool kvm_exit_event ( struct perf_evsel * evsel ) ;
bool kvm_entry_event ( struct perf_evsel * evsel ) ;
# define define_exit_reasons_table(name, symbols) \
static struct exit_reasons_table name [ ] = { \
symbols , { - 1 , NULL } \
}
/*
* arch specific callbacks and data structures
*/
int cpu_isa_init ( struct perf_kvm_stat * kvm , const char * cpuid ) ;
extern const char * const kvm_events_tp [ ] ;
extern struct kvm_reg_events_ops kvm_reg_events_ops [ ] ;
2014-07-03 18:29:06 +04:00
extern const char * const kvm_skip_events [ ] ;
2014-07-03 18:29:05 +04:00
# endif /* __PERF_KVM_STAT_H */