mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-08-18 02:22:47 -07:00
perf kvm: Events analysis tool
Add 'perf kvm stat' support to analyze kvm vmexit/mmio/ioport smartly
Usage:
- kvm stat
run a command and gather performance counter statistics, it is the alias of
perf stat
- trace kvm events:
perf kvm stat record, or, if other tracepoints are interesting as well, we
can append the events like this:
perf kvm stat record -e timer:* -a
If many guests are running, we can track the specified guest by using -p or
--pid, -a is used to track events generated by all guests.
- show the result:
perf kvm stat report
The output example is following:
13005
13059
total 2 guests are running on the host
Then, track the guest whose pid is 13059:
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.253 MB perf.data.guest (~11065 samples) ]
See the vmexit events:
Analyze events for all VCPUs:
VM-EXIT Samples Samples% Time% Avg time
APIC_ACCESS 460 70.55% 0.01% 22.44us ( +- 1.75% )
HLT 93 14.26% 99.98% 832077.26us ( +- 10.42% )
EXTERNAL_INTERRUPT 64 9.82% 0.00% 35.35us ( +- 14.21% )
PENDING_INTERRUPT 24 3.68% 0.00% 9.29us ( +- 31.39% )
CR_ACCESS 7 1.07% 0.00% 8.12us ( +- 5.76% )
IO_INSTRUCTION 3 0.46% 0.00% 18.00us ( +- 11.79% )
EXCEPTION_NMI 1 0.15% 0.00% 5.83us ( +- -nan% )
Total Samples:652, Total events handled time:77396109.80us.
See the mmio events:
Analyze events for all VCPUs:
MMIO Access Samples Samples% Time% Avg time
0xfee00380:W 387 84.31% 79.28% 8.29us ( +- 3.32% )
0xfee00300:W 24 5.23% 9.96% 16.79us ( +- 1.97% )
0xfee00300:R 24 5.23% 7.83% 13.20us ( +- 3.00% )
0xfee00310:W 24 5.23% 2.93% 4.94us ( +- 3.84% )
Total Samples:459, Total events handled time:4044.59us.
See the ioport event:
Analyze events for all VCPUs:
IO Port Access Samples Samples% Time% Avg time
0xc050:POUT 3 100.00% 100.00% 13.75us ( +- 10.83% )
Total Samples:3, Total events handled time:41.26us.
And, --vcpu is used to track the specified vcpu and --key is used to sort the
result:
Analyze events for VCPU 0:
VM-EXIT Samples Samples% Time% Avg time
HLT 27 13.85% 99.97% 405790.24us ( +- 12.70% )
EXTERNAL_INTERRUPT 13 6.67% 0.00% 27.94us ( +- 22.26% )
APIC_ACCESS 146 74.87% 0.03% 21.69us ( +- 2.91% )
IO_INSTRUCTION 2 1.03% 0.00% 17.77us ( +- 20.56% )
CR_ACCESS 2 1.03% 0.00% 8.55us ( +- 6.47% )
PENDING_INTERRUPT 5 2.56% 0.00% 6.27us ( +- 3.94% )
Total Samples:195, Total events handled time:10959950.90us.
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
Signed-off-by: Runzhen Wang <runzhen@linux.vnet.ibm.com>
[ Dong Hao <haodong@linux.vnet.ibm.com>
Runzhen Wang <runzhen@linux.vnet.ibm.com>:
- rebase it on current acme's tree
- fix the compiling-error on i386 ]
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Acked-by: David Ahern <dsahern@gmail.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm@vger.kernel.org
Cc: Runzhen Wang <runzhen@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1347870675-31495-4-git-send-email-haodong@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
1 parent
26bf264e87
commit
bcf6edcd6f
6 files changed
+929
-6
No files matched your search
@@ -12,7 +12,7 @@ SYNOPSIS
|
||||
[--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]]
|
||||
{top|record|report|diff|buildid-list}
|
||||
'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path>
|
||||
| --guestvmlinux=<path>] {top|record|report|diff|buildid-list}
|
||||
| --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat}
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -38,6 +38,18 @@ There are a couple of variants of perf kvm:
|
||||
so that other tools can be used to fetch packages with matching symbol tables
|
||||
for use by perf report.
|
||||
|
||||
'perf kvm stat <command>' to run a command and gather performance counter
|
||||
statistics.
|
||||
Especially, perf 'kvm stat record/report' generates a statistical analysis
|
||||
of KVM events. Currently, vmexit, mmio and ioport events are supported.
|
||||
'perf kvm stat record <command>' records kvm events and the events between
|
||||
start and end <command>.
|
||||
And this command produces a file which contains tracing results of kvm
|
||||
events.
|
||||
|
||||
'perf kvm stat report' reports statistical data which includes events
|
||||
handled time, samples, and so on.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-i::
|
||||
@@ -68,7 +80,21 @@ OPTIONS
|
||||
--guestvmlinux=<path>::
|
||||
Guest os kernel vmlinux.
|
||||
|
||||
STAT REPORT OPTIONS
|
||||
-------------------
|
||||
--vcpu=<value>::
|
||||
analyze events which occures on this vcpu. (default: all vcpus)
|
||||
|
||||
--events=<value>::
|
||||
events to be analyzed. Possible values: vmexit, mmio, ioport.
|
||||
(default: vmexit)
|
||||
-k::
|
||||
--key=<value>::
|
||||
Sorting key. Possible values: sample (default, sort by samples
|
||||
number), time (sort by average time).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1],
|
||||
linkperf:perf-diff[1], linkperf:perf-buildid-list[1]
|
||||
linkperf:perf-diff[1], linkperf:perf-buildid-list[1],
|
||||
linkperf:perf-stat[1]
|
||||
@@ -16,3 +16,6 @@ arch/*/lib/memset*.S
|
||||
include/linux/poison.h
|
||||
include/linux/magic.h
|
||||
include/linux/hw_breakpoint.h
|
||||
arch/x86/include/asm/svm.h
|
||||
arch/x86/include/asm/vmx.h
|
||||
arch/x86/include/asm/kvm_host.h
|
||||
+837
-3
File diff suppressed because it is too large.
Load diff
@@ -1673,6 +1673,11 @@ static int process_build_id(struct perf_file_section *section,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *read_cpuid(struct perf_header *ph, int fd)
|
||||
{
|
||||
return do_read_string(fd, ph);
|
||||
}
|
||||
|
||||
static struct perf_evsel *
|
||||
perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
|
||||
{
|
||||
@@ -1726,6 +1731,7 @@ process_event_desc(struct perf_file_section *section __maybe_unused,
|
||||
struct feature_ops {
|
||||
int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
|
||||
void (*print)(struct perf_header *h, int fd, FILE *fp);
|
||||
char *(*read)(struct perf_header *h, int fd);
|
||||
int (*process)(struct perf_file_section *section,
|
||||
struct perf_header *h, int feat, int fd, void *data);
|
||||
const char *name;
|
||||
@@ -1740,6 +1746,9 @@ struct feature_ops {
|
||||
#define FEAT_OPF(n, func) \
|
||||
[n] = { .name = #n, .write = write_##func, .print = print_##func, \
|
||||
.full_only = true }
|
||||
#define FEAT_OPA_R(n, func) \
|
||||
[n] = { .name = #n, .write = write_##func, .print = print_##func, \
|
||||
.read = read_##func }
|
||||
|
||||
/* feature_ops not implemented: */
|
||||
#define print_tracing_data NULL
|
||||
@@ -1754,7 +1763,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
|
||||
FEAT_OPA(HEADER_ARCH, arch),
|
||||
FEAT_OPA(HEADER_NRCPUS, nrcpus),
|
||||
FEAT_OPA(HEADER_CPUDESC, cpudesc),
|
||||
FEAT_OPA(HEADER_CPUID, cpuid),
|
||||
FEAT_OPA_R(HEADER_CPUID, cpuid),
|
||||
FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
|
||||
FEAT_OPP(HEADER_EVENT_DESC, event_desc),
|
||||
FEAT_OPA(HEADER_CMDLINE, cmdline),
|
||||
@@ -1809,6 +1818,54 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct header_read_data {
|
||||
int feat;
|
||||
char *result;
|
||||
};
|
||||
|
||||
static int perf_file_section__read_feature(struct perf_file_section *section,
|
||||
struct perf_header *ph,
|
||||
int feat, int fd, void *data)
|
||||
{
|
||||
struct header_read_data *hd = data;
|
||||
|
||||
if (feat != hd->feat)
|
||||
return 0;
|
||||
|
||||
if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
|
||||
pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
|
||||
"%d, continuing...\n", section->offset, feat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (feat >= HEADER_LAST_FEATURE) {
|
||||
pr_warning("unknown feature %d\n", feat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!feat_ops[feat].read) {
|
||||
pr_warning("read is not supported for feature %d\n", feat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hd->result = feat_ops[feat].read(ph, fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *perf_header__read_feature(struct perf_session *session, int feat)
|
||||
{
|
||||
struct perf_header *header = &session->header;
|
||||
struct header_read_data hd;
|
||||
int fd = session->fd;
|
||||
|
||||
hd.feat = feat;
|
||||
hd.result = NULL;
|
||||
|
||||
perf_header__process_sections(header, fd, &hd,
|
||||
perf_file_section__read_feature);
|
||||
return hd.result;
|
||||
}
|
||||
|
||||
static int do_write_feat(int fd, struct perf_header *h, int type,
|
||||
struct perf_file_section **p,
|
||||
struct perf_evlist *evlist)
|
||||
|
||||
@@ -94,6 +94,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
|
||||
int feat, int fd, void *data));
|
||||
|
||||
int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
|
||||
char *perf_header__read_feature(struct perf_session *session, int feat);
|
||||
|
||||
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
|
||||
const char *name, bool is_kallsyms, bool is_vdso);
|
||||
|
||||
@@ -16,6 +16,8 @@ struct thread {
|
||||
bool comm_set;
|
||||
char *comm;
|
||||
int comm_len;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct machine;
|
||||
|
||||
Reference in new issue
Block a user