* [PATCH v8 0/3] KVM: perf: kvm events analysis tool
@ 2012-09-17 8:31 Dong Hao
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Dong Hao @ 2012-09-17 8:31 UTC (permalink / raw)
To: acme, dsahern, mtosatti, avi, mingo, linux-kernel, kvm
Cc: xiaoguangrong, runzhen
From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Changelog:
the changes from Avi's comments:
- move the definition of x86 fault vector to asm/kvm.h
- drop the second patch which introduced new tracpoints
the changes from David's comments:
- use scnprintf instead of snprintf
- drop exclusive check for '-a' and '-p', after this, we should
append -a to track all guest, -p to track the specified guest
- improve the help usage
- fix a possible memory leak
- some cleanups
the changes from Andrew Jones's comments:
- move stat related code to util/stat.c
Thank you very much for your patience!
This patchset introduces a perf-based tool (perf kvm stat record/report)
which can analyze kvm events more smartly. Below is the presentation slice
on 2012 Japan LinuxCon:
http://events.linuxfoundation.org/images/stories/pdf/lcjp2012_guangrong.pdf
You can get more details from it. If any questions/comments, please feel free
to let us know.
This patchset is based on Arnaldo's git tree perf/core branch.
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:
# pgrep qemu
13005
13059
total 2 guests are running on the host
Then, track the guest whose pid is 13059:
# ./perf kvm stat record -p 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:
# ./perf kvm stat report --event=vmexit
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:
# ./perf kvm stat report --event=mmio
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:
# ./perf kvm stat report --event=ioport
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:
# ./perf kvm stat report --event=vmexit --vcpu=0 --key=time
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.
Dong Hao (3):
KVM: x86: export svm/vmx exit code and vector code to userspace
perf: move stat related code to util/stat.c
KVM: perf: kvm events analysis tool
arch/x86/include/asm/kvm.h | 16 +
arch/x86/include/asm/kvm_host.h | 16 -
arch/x86/include/asm/svm.h | 205 +++++---
arch/x86/include/asm/vmx.h | 127 ++++--
arch/x86/kvm/trace.h | 89 ----
tools/perf/Documentation/perf-kvm.txt | 30 ++-
tools/perf/MANIFEST | 3 +
tools/perf/Makefile | 1 +
tools/perf/builtin-kvm.c | 840 ++++++++++++++++++++++++++++++++-
tools/perf/builtin-stat.c | 56 +---
tools/perf/util/header.c | 59 +++-
tools/perf/util/header.h | 1 +
tools/perf/util/stat.c | 57 +++
tools/perf/util/stat.h | 16 +
tools/perf/util/thread.h | 2 +
15 files changed, 1235 insertions(+), 283 deletions(-)
create mode 100644 tools/perf/util/stat.c
create mode 100644 tools/perf/util/stat.h
--
1.7.2.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace
2012-09-17 8:31 [PATCH v8 0/3] KVM: perf: kvm events analysis tool Dong Hao
@ 2012-09-17 8:31 ` Dong Hao
2012-09-17 14:58 ` Arnaldo Carvalho de Melo
2012-09-27 4:26 ` [tip:perf/core] KVM: x86: Export svm/ vmx " tip-bot for Xiao Guangrong
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
2012-09-17 8:31 ` [PATCH v8 3/3] KVM: perf: kvm events analysis tool Dong Hao
2 siblings, 2 replies; 14+ messages in thread
From: Dong Hao @ 2012-09-17 8:31 UTC (permalink / raw)
To: acme, dsahern, mtosatti, avi, mingo, linux-kernel, kvm
Cc: xiaoguangrong, runzhen
From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Exporting KVM exit information to userspace to be consumed by perf.
[ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
---
arch/x86/include/asm/kvm.h | 16 +++
arch/x86/include/asm/kvm_host.h | 16 ---
arch/x86/include/asm/svm.h | 205 +++++++++++++++++++++++++--------------
arch/x86/include/asm/vmx.h | 127 ++++++++++++++++--------
arch/x86/kvm/trace.h | 89 -----------------
5 files changed, 230 insertions(+), 223 deletions(-)
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index 246617e..41e08cb 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -9,6 +9,22 @@
#include <linux/types.h>
#include <linux/ioctl.h>
+#define DE_VECTOR 0
+#define DB_VECTOR 1
+#define BP_VECTOR 3
+#define OF_VECTOR 4
+#define BR_VECTOR 5
+#define UD_VECTOR 6
+#define NM_VECTOR 7
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+#define MF_VECTOR 16
+#define MC_VECTOR 18
+
/* Select x86 specific features in <linux/kvm.h> */
#define __KVM_HAVE_PIT
#define __KVM_HAVE_IOAPIC
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 09155d6..1eaa6b0 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -75,22 +75,6 @@
#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
-#define DE_VECTOR 0
-#define DB_VECTOR 1
-#define BP_VECTOR 3
-#define OF_VECTOR 4
-#define BR_VECTOR 5
-#define UD_VECTOR 6
-#define NM_VECTOR 7
-#define DF_VECTOR 8
-#define TS_VECTOR 10
-#define NP_VECTOR 11
-#define SS_VECTOR 12
-#define GP_VECTOR 13
-#define PF_VECTOR 14
-#define MF_VECTOR 16
-#define MC_VECTOR 18
-
#define SELECTOR_TI_MASK (1 << 2)
#define SELECTOR_RPL_MASK 0x03
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index f2b83bc..cdf5674 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -1,6 +1,135 @@
#ifndef __SVM_H
#define __SVM_H
+#define SVM_EXIT_READ_CR0 0x000
+#define SVM_EXIT_READ_CR3 0x003
+#define SVM_EXIT_READ_CR4 0x004
+#define SVM_EXIT_READ_CR8 0x008
+#define SVM_EXIT_WRITE_CR0 0x010
+#define SVM_EXIT_WRITE_CR3 0x013
+#define SVM_EXIT_WRITE_CR4 0x014
+#define SVM_EXIT_WRITE_CR8 0x018
+#define SVM_EXIT_READ_DR0 0x020
+#define SVM_EXIT_READ_DR1 0x021
+#define SVM_EXIT_READ_DR2 0x022
+#define SVM_EXIT_READ_DR3 0x023
+#define SVM_EXIT_READ_DR4 0x024
+#define SVM_EXIT_READ_DR5 0x025
+#define SVM_EXIT_READ_DR6 0x026
+#define SVM_EXIT_READ_DR7 0x027
+#define SVM_EXIT_WRITE_DR0 0x030
+#define SVM_EXIT_WRITE_DR1 0x031
+#define SVM_EXIT_WRITE_DR2 0x032
+#define SVM_EXIT_WRITE_DR3 0x033
+#define SVM_EXIT_WRITE_DR4 0x034
+#define SVM_EXIT_WRITE_DR5 0x035
+#define SVM_EXIT_WRITE_DR6 0x036
+#define SVM_EXIT_WRITE_DR7 0x037
+#define SVM_EXIT_EXCP_BASE 0x040
+#define SVM_EXIT_INTR 0x060
+#define SVM_EXIT_NMI 0x061
+#define SVM_EXIT_SMI 0x062
+#define SVM_EXIT_INIT 0x063
+#define SVM_EXIT_VINTR 0x064
+#define SVM_EXIT_CR0_SEL_WRITE 0x065
+#define SVM_EXIT_IDTR_READ 0x066
+#define SVM_EXIT_GDTR_READ 0x067
+#define SVM_EXIT_LDTR_READ 0x068
+#define SVM_EXIT_TR_READ 0x069
+#define SVM_EXIT_IDTR_WRITE 0x06a
+#define SVM_EXIT_GDTR_WRITE 0x06b
+#define SVM_EXIT_LDTR_WRITE 0x06c
+#define SVM_EXIT_TR_WRITE 0x06d
+#define SVM_EXIT_RDTSC 0x06e
+#define SVM_EXIT_RDPMC 0x06f
+#define SVM_EXIT_PUSHF 0x070
+#define SVM_EXIT_POPF 0x071
+#define SVM_EXIT_CPUID 0x072
+#define SVM_EXIT_RSM 0x073
+#define SVM_EXIT_IRET 0x074
+#define SVM_EXIT_SWINT 0x075
+#define SVM_EXIT_INVD 0x076
+#define SVM_EXIT_PAUSE 0x077
+#define SVM_EXIT_HLT 0x078
+#define SVM_EXIT_INVLPG 0x079
+#define SVM_EXIT_INVLPGA 0x07a
+#define SVM_EXIT_IOIO 0x07b
+#define SVM_EXIT_MSR 0x07c
+#define SVM_EXIT_TASK_SWITCH 0x07d
+#define SVM_EXIT_FERR_FREEZE 0x07e
+#define SVM_EXIT_SHUTDOWN 0x07f
+#define SVM_EXIT_VMRUN 0x080
+#define SVM_EXIT_VMMCALL 0x081
+#define SVM_EXIT_VMLOAD 0x082
+#define SVM_EXIT_VMSAVE 0x083
+#define SVM_EXIT_STGI 0x084
+#define SVM_EXIT_CLGI 0x085
+#define SVM_EXIT_SKINIT 0x086
+#define SVM_EXIT_RDTSCP 0x087
+#define SVM_EXIT_ICEBP 0x088
+#define SVM_EXIT_WBINVD 0x089
+#define SVM_EXIT_MONITOR 0x08a
+#define SVM_EXIT_MWAIT 0x08b
+#define SVM_EXIT_MWAIT_COND 0x08c
+#define SVM_EXIT_XSETBV 0x08d
+#define SVM_EXIT_NPF 0x400
+
+#define SVM_EXIT_ERR -1
+
+#define SVM_EXIT_REASONS \
+ { SVM_EXIT_READ_CR0, "read_cr0" }, \
+ { SVM_EXIT_READ_CR3, "read_cr3" }, \
+ { SVM_EXIT_READ_CR4, "read_cr4" }, \
+ { SVM_EXIT_READ_CR8, "read_cr8" }, \
+ { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
+ { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
+ { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
+ { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
+ { SVM_EXIT_READ_DR0, "read_dr0" }, \
+ { SVM_EXIT_READ_DR1, "read_dr1" }, \
+ { SVM_EXIT_READ_DR2, "read_dr2" }, \
+ { SVM_EXIT_READ_DR3, "read_dr3" }, \
+ { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
+ { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
+ { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
+ { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
+ { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
+ { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
+ { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
+ { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
+ { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
+ { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
+ { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
+ { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
+ { SVM_EXIT_INTR, "interrupt" }, \
+ { SVM_EXIT_NMI, "nmi" }, \
+ { SVM_EXIT_SMI, "smi" }, \
+ { SVM_EXIT_INIT, "init" }, \
+ { SVM_EXIT_VINTR, "vintr" }, \
+ { SVM_EXIT_CPUID, "cpuid" }, \
+ { SVM_EXIT_INVD, "invd" }, \
+ { SVM_EXIT_HLT, "hlt" }, \
+ { SVM_EXIT_INVLPG, "invlpg" }, \
+ { SVM_EXIT_INVLPGA, "invlpga" }, \
+ { SVM_EXIT_IOIO, "io" }, \
+ { SVM_EXIT_MSR, "msr" }, \
+ { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
+ { SVM_EXIT_SHUTDOWN, "shutdown" }, \
+ { SVM_EXIT_VMRUN, "vmrun" }, \
+ { SVM_EXIT_VMMCALL, "hypercall" }, \
+ { SVM_EXIT_VMLOAD, "vmload" }, \
+ { SVM_EXIT_VMSAVE, "vmsave" }, \
+ { SVM_EXIT_STGI, "stgi" }, \
+ { SVM_EXIT_CLGI, "clgi" }, \
+ { SVM_EXIT_SKINIT, "skinit" }, \
+ { SVM_EXIT_WBINVD, "wbinvd" }, \
+ { SVM_EXIT_MONITOR, "monitor" }, \
+ { SVM_EXIT_MWAIT, "mwait" }, \
+ { SVM_EXIT_XSETBV, "xsetbv" }, \
+ { SVM_EXIT_NPF, "npf" }
+
+#ifdef __KERNEL__
+
enum {
INTERCEPT_INTR,
INTERCEPT_NMI,
@@ -264,81 +393,6 @@ struct __attribute__ ((__packed__)) vmcb {
#define SVM_EXITINFO_REG_MASK 0x0F
-#define SVM_EXIT_READ_CR0 0x000
-#define SVM_EXIT_READ_CR3 0x003
-#define SVM_EXIT_READ_CR4 0x004
-#define SVM_EXIT_READ_CR8 0x008
-#define SVM_EXIT_WRITE_CR0 0x010
-#define SVM_EXIT_WRITE_CR3 0x013
-#define SVM_EXIT_WRITE_CR4 0x014
-#define SVM_EXIT_WRITE_CR8 0x018
-#define SVM_EXIT_READ_DR0 0x020
-#define SVM_EXIT_READ_DR1 0x021
-#define SVM_EXIT_READ_DR2 0x022
-#define SVM_EXIT_READ_DR3 0x023
-#define SVM_EXIT_READ_DR4 0x024
-#define SVM_EXIT_READ_DR5 0x025
-#define SVM_EXIT_READ_DR6 0x026
-#define SVM_EXIT_READ_DR7 0x027
-#define SVM_EXIT_WRITE_DR0 0x030
-#define SVM_EXIT_WRITE_DR1 0x031
-#define SVM_EXIT_WRITE_DR2 0x032
-#define SVM_EXIT_WRITE_DR3 0x033
-#define SVM_EXIT_WRITE_DR4 0x034
-#define SVM_EXIT_WRITE_DR5 0x035
-#define SVM_EXIT_WRITE_DR6 0x036
-#define SVM_EXIT_WRITE_DR7 0x037
-#define SVM_EXIT_EXCP_BASE 0x040
-#define SVM_EXIT_INTR 0x060
-#define SVM_EXIT_NMI 0x061
-#define SVM_EXIT_SMI 0x062
-#define SVM_EXIT_INIT 0x063
-#define SVM_EXIT_VINTR 0x064
-#define SVM_EXIT_CR0_SEL_WRITE 0x065
-#define SVM_EXIT_IDTR_READ 0x066
-#define SVM_EXIT_GDTR_READ 0x067
-#define SVM_EXIT_LDTR_READ 0x068
-#define SVM_EXIT_TR_READ 0x069
-#define SVM_EXIT_IDTR_WRITE 0x06a
-#define SVM_EXIT_GDTR_WRITE 0x06b
-#define SVM_EXIT_LDTR_WRITE 0x06c
-#define SVM_EXIT_TR_WRITE 0x06d
-#define SVM_EXIT_RDTSC 0x06e
-#define SVM_EXIT_RDPMC 0x06f
-#define SVM_EXIT_PUSHF 0x070
-#define SVM_EXIT_POPF 0x071
-#define SVM_EXIT_CPUID 0x072
-#define SVM_EXIT_RSM 0x073
-#define SVM_EXIT_IRET 0x074
-#define SVM_EXIT_SWINT 0x075
-#define SVM_EXIT_INVD 0x076
-#define SVM_EXIT_PAUSE 0x077
-#define SVM_EXIT_HLT 0x078
-#define SVM_EXIT_INVLPG 0x079
-#define SVM_EXIT_INVLPGA 0x07a
-#define SVM_EXIT_IOIO 0x07b
-#define SVM_EXIT_MSR 0x07c
-#define SVM_EXIT_TASK_SWITCH 0x07d
-#define SVM_EXIT_FERR_FREEZE 0x07e
-#define SVM_EXIT_SHUTDOWN 0x07f
-#define SVM_EXIT_VMRUN 0x080
-#define SVM_EXIT_VMMCALL 0x081
-#define SVM_EXIT_VMLOAD 0x082
-#define SVM_EXIT_VMSAVE 0x083
-#define SVM_EXIT_STGI 0x084
-#define SVM_EXIT_CLGI 0x085
-#define SVM_EXIT_SKINIT 0x086
-#define SVM_EXIT_RDTSCP 0x087
-#define SVM_EXIT_ICEBP 0x088
-#define SVM_EXIT_WBINVD 0x089
-#define SVM_EXIT_MONITOR 0x08a
-#define SVM_EXIT_MWAIT 0x08b
-#define SVM_EXIT_MWAIT_COND 0x08c
-#define SVM_EXIT_XSETBV 0x08d
-#define SVM_EXIT_NPF 0x400
-
-#define SVM_EXIT_ERR -1
-
#define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
@@ -350,3 +404,4 @@ struct __attribute__ ((__packed__)) vmcb {
#endif
+#endif
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 74fcb96..36ec21c 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -25,6 +25,88 @@
*
*/
+#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
+
+#define EXIT_REASON_EXCEPTION_NMI 0
+#define EXIT_REASON_EXTERNAL_INTERRUPT 1
+#define EXIT_REASON_TRIPLE_FAULT 2
+
+#define EXIT_REASON_PENDING_INTERRUPT 7
+#define EXIT_REASON_NMI_WINDOW 8
+#define EXIT_REASON_TASK_SWITCH 9
+#define EXIT_REASON_CPUID 10
+#define EXIT_REASON_HLT 12
+#define EXIT_REASON_INVD 13
+#define EXIT_REASON_INVLPG 14
+#define EXIT_REASON_RDPMC 15
+#define EXIT_REASON_RDTSC 16
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_VMCLEAR 19
+#define EXIT_REASON_VMLAUNCH 20
+#define EXIT_REASON_VMPTRLD 21
+#define EXIT_REASON_VMPTRST 22
+#define EXIT_REASON_VMREAD 23
+#define EXIT_REASON_VMRESUME 24
+#define EXIT_REASON_VMWRITE 25
+#define EXIT_REASON_VMOFF 26
+#define EXIT_REASON_VMON 27
+#define EXIT_REASON_CR_ACCESS 28
+#define EXIT_REASON_DR_ACCESS 29
+#define EXIT_REASON_IO_INSTRUCTION 30
+#define EXIT_REASON_MSR_READ 31
+#define EXIT_REASON_MSR_WRITE 32
+#define EXIT_REASON_INVALID_STATE 33
+#define EXIT_REASON_MWAIT_INSTRUCTION 36
+#define EXIT_REASON_MONITOR_INSTRUCTION 39
+#define EXIT_REASON_PAUSE_INSTRUCTION 40
+#define EXIT_REASON_MCE_DURING_VMENTRY 41
+#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
+#define EXIT_REASON_APIC_ACCESS 44
+#define EXIT_REASON_EPT_VIOLATION 48
+#define EXIT_REASON_EPT_MISCONFIG 49
+#define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
+#define EXIT_REASON_INVPCID 58
+
+#define VMX_EXIT_REASONS \
+ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
+ { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
+ { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
+ { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
+ { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
+ { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
+ { EXIT_REASON_CPUID, "CPUID" }, \
+ { EXIT_REASON_HLT, "HLT" }, \
+ { EXIT_REASON_INVLPG, "INVLPG" }, \
+ { EXIT_REASON_RDPMC, "RDPMC" }, \
+ { EXIT_REASON_RDTSC, "RDTSC" }, \
+ { EXIT_REASON_VMCALL, "VMCALL" }, \
+ { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
+ { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
+ { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
+ { EXIT_REASON_VMPTRST, "VMPTRST" }, \
+ { EXIT_REASON_VMREAD, "VMREAD" }, \
+ { EXIT_REASON_VMRESUME, "VMRESUME" }, \
+ { EXIT_REASON_VMWRITE, "VMWRITE" }, \
+ { EXIT_REASON_VMOFF, "VMOFF" }, \
+ { EXIT_REASON_VMON, "VMON" }, \
+ { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
+ { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
+ { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
+ { EXIT_REASON_MSR_READ, "MSR_READ" }, \
+ { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
+ { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
+ { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
+ { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
+ { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
+ { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
+ { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
+ { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
+ { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
+ { EXIT_REASON_WBINVD, "WBINVD" }
+
+#ifdef __KERNEL__
+
#include <linux/types.h>
/*
@@ -241,49 +323,6 @@ enum vmcs_field {
HOST_RIP = 0x00006c16,
};
-#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
-
-#define EXIT_REASON_EXCEPTION_NMI 0
-#define EXIT_REASON_EXTERNAL_INTERRUPT 1
-#define EXIT_REASON_TRIPLE_FAULT 2
-
-#define EXIT_REASON_PENDING_INTERRUPT 7
-#define EXIT_REASON_NMI_WINDOW 8
-#define EXIT_REASON_TASK_SWITCH 9
-#define EXIT_REASON_CPUID 10
-#define EXIT_REASON_HLT 12
-#define EXIT_REASON_INVD 13
-#define EXIT_REASON_INVLPG 14
-#define EXIT_REASON_RDPMC 15
-#define EXIT_REASON_RDTSC 16
-#define EXIT_REASON_VMCALL 18
-#define EXIT_REASON_VMCLEAR 19
-#define EXIT_REASON_VMLAUNCH 20
-#define EXIT_REASON_VMPTRLD 21
-#define EXIT_REASON_VMPTRST 22
-#define EXIT_REASON_VMREAD 23
-#define EXIT_REASON_VMRESUME 24
-#define EXIT_REASON_VMWRITE 25
-#define EXIT_REASON_VMOFF 26
-#define EXIT_REASON_VMON 27
-#define EXIT_REASON_CR_ACCESS 28
-#define EXIT_REASON_DR_ACCESS 29
-#define EXIT_REASON_IO_INSTRUCTION 30
-#define EXIT_REASON_MSR_READ 31
-#define EXIT_REASON_MSR_WRITE 32
-#define EXIT_REASON_INVALID_STATE 33
-#define EXIT_REASON_MWAIT_INSTRUCTION 36
-#define EXIT_REASON_MONITOR_INSTRUCTION 39
-#define EXIT_REASON_PAUSE_INSTRUCTION 40
-#define EXIT_REASON_MCE_DURING_VMENTRY 41
-#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
-#define EXIT_REASON_APIC_ACCESS 44
-#define EXIT_REASON_EPT_VIOLATION 48
-#define EXIT_REASON_EPT_MISCONFIG 49
-#define EXIT_REASON_WBINVD 54
-#define EXIT_REASON_XSETBV 55
-#define EXIT_REASON_INVPCID 58
-
/*
* Interruption-information format
*/
@@ -488,3 +527,5 @@ enum vm_instruction_error_number {
};
#endif
+
+#endif
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index a71faf7..bca63f0 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -183,95 +183,6 @@ TRACE_EVENT(kvm_apic,
#define KVM_ISA_VMX 1
#define KVM_ISA_SVM 2
-#define VMX_EXIT_REASONS \
- { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
- { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
- { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
- { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
- { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
- { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
- { EXIT_REASON_CPUID, "CPUID" }, \
- { EXIT_REASON_HLT, "HLT" }, \
- { EXIT_REASON_INVLPG, "INVLPG" }, \
- { EXIT_REASON_RDPMC, "RDPMC" }, \
- { EXIT_REASON_RDTSC, "RDTSC" }, \
- { EXIT_REASON_VMCALL, "VMCALL" }, \
- { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
- { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
- { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
- { EXIT_REASON_VMPTRST, "VMPTRST" }, \
- { EXIT_REASON_VMREAD, "VMREAD" }, \
- { EXIT_REASON_VMRESUME, "VMRESUME" }, \
- { EXIT_REASON_VMWRITE, "VMWRITE" }, \
- { EXIT_REASON_VMOFF, "VMOFF" }, \
- { EXIT_REASON_VMON, "VMON" }, \
- { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
- { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
- { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
- { EXIT_REASON_MSR_READ, "MSR_READ" }, \
- { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
- { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
- { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
- { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
- { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
- { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
- { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
- { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
- { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
- { EXIT_REASON_WBINVD, "WBINVD" }
-
-#define SVM_EXIT_REASONS \
- { SVM_EXIT_READ_CR0, "read_cr0" }, \
- { SVM_EXIT_READ_CR3, "read_cr3" }, \
- { SVM_EXIT_READ_CR4, "read_cr4" }, \
- { SVM_EXIT_READ_CR8, "read_cr8" }, \
- { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
- { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
- { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
- { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
- { SVM_EXIT_READ_DR0, "read_dr0" }, \
- { SVM_EXIT_READ_DR1, "read_dr1" }, \
- { SVM_EXIT_READ_DR2, "read_dr2" }, \
- { SVM_EXIT_READ_DR3, "read_dr3" }, \
- { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
- { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
- { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
- { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
- { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
- { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
- { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
- { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
- { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
- { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
- { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
- { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
- { SVM_EXIT_INTR, "interrupt" }, \
- { SVM_EXIT_NMI, "nmi" }, \
- { SVM_EXIT_SMI, "smi" }, \
- { SVM_EXIT_INIT, "init" }, \
- { SVM_EXIT_VINTR, "vintr" }, \
- { SVM_EXIT_CPUID, "cpuid" }, \
- { SVM_EXIT_INVD, "invd" }, \
- { SVM_EXIT_HLT, "hlt" }, \
- { SVM_EXIT_INVLPG, "invlpg" }, \
- { SVM_EXIT_INVLPGA, "invlpga" }, \
- { SVM_EXIT_IOIO, "io" }, \
- { SVM_EXIT_MSR, "msr" }, \
- { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
- { SVM_EXIT_SHUTDOWN, "shutdown" }, \
- { SVM_EXIT_VMRUN, "vmrun" }, \
- { SVM_EXIT_VMMCALL, "hypercall" }, \
- { SVM_EXIT_VMLOAD, "vmload" }, \
- { SVM_EXIT_VMSAVE, "vmsave" }, \
- { SVM_EXIT_STGI, "stgi" }, \
- { SVM_EXIT_CLGI, "clgi" }, \
- { SVM_EXIT_SKINIT, "skinit" }, \
- { SVM_EXIT_WBINVD, "wbinvd" }, \
- { SVM_EXIT_MONITOR, "monitor" }, \
- { SVM_EXIT_MWAIT, "mwait" }, \
- { SVM_EXIT_XSETBV, "xsetbv" }, \
- { SVM_EXIT_NPF, "npf" }
-
/*
* Tracepoint for kvm guest exit:
*/
--
1.7.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v8 2/3] perf: move stat related code to util/stat.c
2012-09-17 8:31 [PATCH v8 0/3] KVM: perf: kvm events analysis tool Dong Hao
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
@ 2012-09-17 8:31 ` Dong Hao
2012-09-18 14:01 ` David Ahern
` (2 more replies)
2012-09-17 8:31 ` [PATCH v8 3/3] KVM: perf: kvm events analysis tool Dong Hao
2 siblings, 3 replies; 14+ messages in thread
From: Dong Hao @ 2012-09-17 8:31 UTC (permalink / raw)
To: acme, dsahern, mtosatti, avi, mingo, linux-kernel, kvm
Cc: xiaoguangrong, runzhen
From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Then, the code can be shared between kvm events and perf stat
[ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
---
tools/perf/Makefile | 1 +
tools/perf/builtin-stat.c | 56 +------------------------------------------
tools/perf/util/stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/stat.h | 16 ++++++++++++
4 files changed, 76 insertions(+), 54 deletions(-)
create mode 100644 tools/perf/util/stat.c
create mode 100644 tools/perf/util/stat.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 209774b..5077f8e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -406,6 +406,7 @@ LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o
+LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/hist.o
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dab347d..3c43a35 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -51,13 +51,13 @@
#include "util/evsel.h"
#include "util/debug.h"
#include "util/color.h"
+#include "util/stat.h"
#include "util/header.h"
#include "util/cpumap.h"
#include "util/thread.h"
#include "util/thread_map.h"
#include <sys/prctl.h>
-#include <math.h>
#include <locale.h>
#define DEFAULT_SEPARATOR " "
@@ -199,11 +199,6 @@ static int output_fd;
static volatile int done = 0;
-struct stats
-{
- double n, mean, M2;
-};
-
struct perf_stat {
struct stats res_stats[3];
};
@@ -220,50 +215,6 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
evsel->priv = NULL;
}
-static void update_stats(struct stats *stats, u64 val)
-{
- double delta;
-
- stats->n++;
- delta = val - stats->mean;
- stats->mean += delta / stats->n;
- stats->M2 += delta*(val - stats->mean);
-}
-
-static double avg_stats(struct stats *stats)
-{
- return stats->mean;
-}
-
-/*
- * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
- *
- * (\Sum n_i^2) - ((\Sum n_i)^2)/n
- * s^2 = -------------------------------
- * n - 1
- *
- * http://en.wikipedia.org/wiki/Stddev
- *
- * The std dev of the mean is related to the std dev by:
- *
- * s
- * s_mean = -------
- * sqrt(n)
- *
- */
-static double stddev_stats(struct stats *stats)
-{
- double variance, variance_mean;
-
- if (!stats->n)
- return 0.0;
-
- variance = stats->M2 / (stats->n - 1);
- variance_mean = variance / stats->n;
-
- return sqrt(variance_mean);
-}
-
static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
@@ -559,10 +510,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
static void print_noise_pct(double total, double avg)
{
- double pct = 0.0;
-
- if (avg)
- pct = 100.0*total/avg;
+ double pct = rel_stddev_stats(total, avg);
if (csv_output)
fprintf(output, "%s%.2f%%", csv_sep, pct);
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
new file mode 100644
index 0000000..2374212
--- /dev/null
+++ b/tools/perf/util/stat.c
@@ -0,0 +1,57 @@
+#include <math.h>
+
+#include "stat.h"
+
+void update_stats(struct stats *stats, u64 val)
+{
+ double delta;
+
+ stats->n++;
+ delta = val - stats->mean;
+ stats->mean += delta / stats->n;
+ stats->M2 += delta*(val - stats->mean);
+}
+
+double avg_stats(struct stats *stats)
+{
+ return stats->mean;
+}
+
+/*
+ * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
+ *
+ * (\Sum n_i^2) - ((\Sum n_i)^2)/n
+ * s^2 = -------------------------------
+ * n - 1
+ *
+ * http://en.wikipedia.org/wiki/Stddev
+ *
+ * The std dev of the mean is related to the std dev by:
+ *
+ * s
+ * s_mean = -------
+ * sqrt(n)
+ *
+ */
+double stddev_stats(struct stats *stats)
+{
+ double variance, variance_mean;
+
+ if (!stats->n)
+ return 0.0;
+
+ variance = stats->M2 / (stats->n - 1);
+ variance_mean = variance / stats->n;
+
+ return sqrt(variance_mean);
+}
+
+double rel_stddev_stats(double stddev, double avg)
+{
+ double pct = 0.0;
+
+ if (avg)
+ pct = 100.0 * stddev/avg;
+
+ return pct;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
new file mode 100644
index 0000000..588367c
--- /dev/null
+++ b/tools/perf/util/stat.h
@@ -0,0 +1,16 @@
+#ifndef __PERF_STATS_H
+#define __PERF_STATS_H
+
+#include "types.h"
+
+struct stats
+{
+ double n, mean, M2;
+};
+
+void update_stats(struct stats *stats, u64 val);
+double avg_stats(struct stats *stats);
+double stddev_stats(struct stats *stats);
+double rel_stddev_stats(double stddev, double avg);
+
+#endif
--
1.7.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v8 3/3] KVM: perf: kvm events analysis tool
2012-09-17 8:31 [PATCH v8 0/3] KVM: perf: kvm events analysis tool Dong Hao
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
@ 2012-09-17 8:31 ` Dong Hao
2012-09-20 13:34 ` David Ahern
2012-09-27 4:27 ` [tip:perf/core] perf kvm: Events " tip-bot for Xiao Guangrong
2 siblings, 2 replies; 14+ messages in thread
From: Dong Hao @ 2012-09-17 8:31 UTC (permalink / raw)
To: acme, dsahern, mtosatti, avi, mingo, linux-kernel, kvm
Cc: xiaoguangrong, runzhen
From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
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:
# pgrep qemu
13005
13059
total 2 guests are running on the host
Then, track the guest whose pid is 13059:
# ./perf kvm stat record -p 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:
# ./perf kvm stat report --event=vmexit
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:
# ./perf kvm stat report --event=mmio
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:
# ./perf kvm stat report --event=ioport
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:
# ./perf kvm stat report --event=vmexit --vcpu=0 --key=time
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.
[ 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>
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
Signed-off-by: Runzhen Wang <runzhen@linux.vnet.ibm.com>
---
tools/perf/Documentation/perf-kvm.txt | 30 ++-
tools/perf/MANIFEST | 3 +
tools/perf/builtin-kvm.c | 840 ++++++++++++++++++++++++++++++++-
| 59 +++-
| 1 +
tools/perf/util/thread.h | 2 +
6 files changed, 929 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index dd84cb2..326f2cb 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -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]
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 0518079..80db3f4 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -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
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 4d2aa2c..1878947 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "perf.h"
+#include "util/evsel.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/symbol.h"
@@ -10,8 +11,10 @@
#include "util/parse-options.h"
#include "util/trace-event.h"
-
#include "util/debug.h"
+#include "util/debugfs.h"
+#include "util/tool.h"
+#include "util/stat.h"
#include <sys/prctl.h>
@@ -19,11 +22,840 @@
#include <pthread.h>
#include <math.h>
-static const char *file_name;
+#include "../../arch/x86/include/asm/svm.h"
+#include "../../arch/x86/include/asm/vmx.h"
+#include "../../arch/x86/include/asm/kvm.h"
+
+struct event_key {
+ #define INVALID_KEY (~0ULL)
+ u64 key;
+ int info;
+};
+
+struct kvm_events_ops {
+ bool (*is_begin_event)(struct event_format *event, void *data,
+ struct event_key *key);
+ bool (*is_end_event)(struct event_format *event, void *data,
+ struct event_key *key);
+ void (*decode_key)(struct event_key *key, char decode[20]);
+ const char *name;
+};
+
+static void exit_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->info = 0;
+ key->key = raw_field_value(event, "exit_reason", data);
+}
+
+static bool kvm_exit_event(struct event_format *event)
+{
+ return !strcmp(event->name, "kvm_exit");
+}
+
+static bool exit_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ if (kvm_exit_event(event)) {
+ exit_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool kvm_entry_event(struct event_format *event)
+{
+ return !strcmp(event->name, "kvm_entry");
+}
+
+static bool exit_event_end(struct event_format *event, void *data __maybe_unused,
+ struct event_key *key __maybe_unused)
+{
+ return kvm_entry_event(event);
+}
+
+struct exit_reasons_table {
+ unsigned long exit_code;
+ const char *reason;
+};
+
+struct exit_reasons_table vmx_exit_reasons[] = {
+ VMX_EXIT_REASONS
+};
+
+struct exit_reasons_table svm_exit_reasons[] = {
+ SVM_EXIT_REASONS
+};
+
+static int cpu_isa;
+
+static const char *get_exit_reason(u64 exit_code)
+{
+ int table_size = ARRAY_SIZE(svm_exit_reasons);
+ struct exit_reasons_table *table = svm_exit_reasons;
+
+ if (cpu_isa == 1) {
+ table = vmx_exit_reasons;
+ table_size = ARRAY_SIZE(vmx_exit_reasons);
+ }
+
+ while (table_size--) {
+ if (table->exit_code == exit_code)
+ return table->reason;
+ table++;
+ }
+
+ pr_err("unknown kvm exit code:%lld on %s\n",
+ (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM");
+ return "UNKNOWN";
+}
+
+static void exit_event_decode_key(struct event_key *key, char decode[20])
+{
+ const char *exit_reason = get_exit_reason(key->key);
+
+ scnprintf(decode, 20, "%s", exit_reason);
+}
+
+static struct kvm_events_ops exit_events = {
+ .is_begin_event = exit_event_begin,
+ .is_end_event = exit_event_end,
+ .decode_key = exit_event_decode_key,
+ .name = "VM-EXIT"
+};
+
+ /*
+ * For the mmio events, we treat:
+ * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
+ * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
+ */
+static void mmio_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->key = raw_field_value(event, "gpa", data);
+ key->info = raw_field_value(event, "type", data);
+}
+
+#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
+#define KVM_TRACE_MMIO_READ 1
+#define KVM_TRACE_MMIO_WRITE 2
+
+static bool mmio_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ /* MMIO read begin event in kernel. */
+ if (kvm_exit_event(event))
+ return true;
+
+ /* MMIO write begin event in kernel. */
+ if (!strcmp(event->name, "kvm_mmio") &&
+ raw_field_value(event, "type", data) == KVM_TRACE_MMIO_WRITE) {
+ mmio_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool mmio_event_end(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ /* MMIO write end event in kernel. */
+ if (kvm_entry_event(event))
+ return true;
+
+ /* MMIO read end event in kernel.*/
+ if (!strcmp(event->name, "kvm_mmio") &&
+ raw_field_value(event, "type", data) == KVM_TRACE_MMIO_READ) {
+ mmio_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static void mmio_event_decode_key(struct event_key *key, char decode[20])
+{
+ scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
+ key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
+}
+
+static struct kvm_events_ops mmio_events = {
+ .is_begin_event = mmio_event_begin,
+ .is_end_event = mmio_event_end,
+ .decode_key = mmio_event_decode_key,
+ .name = "MMIO Access"
+};
+
+ /* The time of emulation pio access is from kvm_pio to kvm_entry. */
+static void ioport_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->key = raw_field_value(event, "port", data);
+ key->info = raw_field_value(event, "rw", data);
+}
+
+static bool ioport_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ if (!strcmp(event->name, "kvm_pio")) {
+ ioport_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool ioport_event_end(struct event_format *event, void *data __maybe_unused,
+ struct event_key *key __maybe_unused)
+{
+ if (kvm_entry_event(event))
+ return true;
+
+ return false;
+}
+
+static void ioport_event_decode_key(struct event_key *key, char decode[20])
+{
+ scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
+ key->info ? "POUT" : "PIN");
+}
+
+static struct kvm_events_ops ioport_events = {
+ .is_begin_event = ioport_event_begin,
+ .is_end_event = ioport_event_end,
+ .decode_key = ioport_event_decode_key,
+ .name = "IO Port Access"
+};
+
+static const char *report_event = "vmexit";
+struct kvm_events_ops *events_ops;
+
+static bool register_kvm_events_ops(void)
+{
+ bool ret = true;
+
+ if (!strcmp(report_event, "vmexit"))
+ events_ops = &exit_events;
+ else if (!strcmp(report_event, "mmio"))
+ events_ops = &mmio_events;
+ else if (!strcmp(report_event, "ioport"))
+ events_ops = &ioport_events;
+ else {
+ pr_err("Unknown report event:%s\n", report_event);
+ ret = false;
+ }
+
+ return ret;
+}
+
+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;
+};
+
+struct vcpu_event_record {
+ int vcpu_id;
+ u64 start_time;
+ struct kvm_event *last_event;
+};
+
+#define EVENTS_BITS 12
+#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
+
+static u64 total_time;
+static u64 total_count;
+static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
+
+static void init_kvm_event_record(void)
+{
+ int i;
+
+ for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+ INIT_LIST_HEAD(&kvm_events_cache[i]);
+}
+
+static int kvm_events_hash_fn(u64 key)
+{
+ return key & (EVENTS_CACHE_SIZE - 1);
+}
+
+static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
+{
+ int old_max_vcpu = event->max_vcpu;
+
+ if (vcpu_id < event->max_vcpu)
+ return true;
+
+ while (event->max_vcpu <= vcpu_id)
+ event->max_vcpu += DEFAULT_VCPU_NUM;
+
+ event->vcpu = realloc(event->vcpu,
+ event->max_vcpu * sizeof(*event->vcpu));
+ if (!event->vcpu) {
+ pr_err("Not enough memory\n");
+ return false;
+ }
+
+ memset(event->vcpu + old_max_vcpu, 0,
+ (event->max_vcpu - old_max_vcpu) * sizeof(*event->vcpu));
+ return true;
+}
+
+static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
+{
+ struct kvm_event *event;
+
+ event = zalloc(sizeof(*event));
+ if (!event) {
+ pr_err("Not enough memory\n");
+ return NULL;
+ }
+
+ event->key = *key;
+ return event;
+}
+
+static struct kvm_event *find_create_kvm_event(struct event_key *key)
+{
+ struct kvm_event *event;
+ struct list_head *head;
+
+ BUG_ON(key->key == INVALID_KEY);
+
+ head = &kvm_events_cache[kvm_events_hash_fn(key->key)];
+ list_for_each_entry(event, head, hash_entry)
+ if (event->key.key == key->key && event->key.info == key->info)
+ return event;
+
+ event = kvm_alloc_init_event(key);
+ if (!event)
+ return NULL;
+
+ list_add(&event->hash_entry, head);
+ return event;
+}
+
+static bool handle_begin_event(struct vcpu_event_record *vcpu_record,
+ struct event_key *key, u64 timestamp)
+{
+ struct kvm_event *event = NULL;
+
+ if (key->key != INVALID_KEY)
+ event = find_create_kvm_event(key);
+
+ vcpu_record->last_event = event;
+ vcpu_record->start_time = timestamp;
+ return true;
+}
+
+static void
+kvm_update_event_stats(struct kvm_event_stats *kvm_stats, u64 time_diff)
+{
+ kvm_stats->time += time_diff;
+ update_stats(&kvm_stats->stats, time_diff);
+}
+
+static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
+{
+ struct kvm_event_stats *kvm_stats = &event->total;
+
+ if (vcpu_id != -1)
+ kvm_stats = &event->vcpu[vcpu_id];
+
+ return rel_stddev_stats(stddev_stats(&kvm_stats->stats),
+ avg_stats(&kvm_stats->stats));
+}
+
+static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
+ u64 time_diff)
+{
+ kvm_update_event_stats(&event->total, time_diff);
+
+ if (!kvm_event_expand(event, vcpu_id))
+ return false;
+
+ kvm_update_event_stats(&event->vcpu[vcpu_id], time_diff);
+ return true;
+}
+
+static bool handle_end_event(struct vcpu_event_record *vcpu_record,
+ struct event_key *key, u64 timestamp)
+{
+ struct kvm_event *event;
+ u64 time_begin, time_diff;
+
+ event = vcpu_record->last_event;
+ time_begin = vcpu_record->start_time;
+
+ /* The begin event is not caught. */
+ if (!time_begin)
+ return true;
+
+ /*
+ * In some case, the 'begin event' only records the start timestamp,
+ * the actual event is recognized in the 'end event' (e.g. mmio-event).
+ */
+
+ /* Both begin and end events did not get the key. */
+ if (!event && key->key == INVALID_KEY)
+ return true;
+
+ if (!event)
+ event = find_create_kvm_event(key);
+
+ if (!event)
+ return false;
+
+ vcpu_record->last_event = NULL;
+ vcpu_record->start_time = 0;
+
+ BUG_ON(timestamp < time_begin);
+
+ time_diff = timestamp - time_begin;
+ return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+}
+
+static struct vcpu_event_record
+*per_vcpu_record(struct thread *thread, struct event_format *event, void *data)
+{
+ /* Only kvm_entry records vcpu id. */
+ if (!thread->priv && kvm_entry_event(event)) {
+ struct vcpu_event_record *vcpu_record;
+
+ vcpu_record = zalloc(sizeof(struct vcpu_event_record));
+ if (!vcpu_record) {
+ pr_err("Not enough memory\n");
+ return NULL;
+ }
+
+ vcpu_record->vcpu_id = raw_field_value(event, "vcpu_id", data);
+ thread->priv = vcpu_record;
+ }
+
+ return (struct vcpu_event_record *)thread->priv;
+}
+
+static bool handle_kvm_event(struct thread *thread, struct event_format *event,
+ void *data, u64 timestamp)
+{
+ struct vcpu_event_record *vcpu_record;
+ struct event_key key = {.key = INVALID_KEY};
+
+ vcpu_record = per_vcpu_record(thread, event, data);
+ if (!vcpu_record)
+ return true;
+
+ if (events_ops->is_begin_event(event, data, &key))
+ return handle_begin_event(vcpu_record, &key, timestamp);
+
+ if (events_ops->is_end_event(event, data, &key))
+ return handle_end_event(vcpu_record, &key, timestamp);
+
+ return true;
+}
+
+typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
+struct kvm_event_key {
+ const char *name;
+ key_cmp_fun key;
+};
+
+static int trace_vcpu = -1;
+#define GET_EVENT_KEY(func, field) \
+static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
+{ \
+ if (vcpu == -1) \
+ return event->total.field; \
+ \
+ if (vcpu >= event->max_vcpu) \
+ return 0; \
+ \
+ return event->vcpu[vcpu].field; \
+}
+
+#define COMPARE_EVENT_KEY(func, field) \
+GET_EVENT_KEY(func, field) \
+static int compare_kvm_event_ ## func(struct kvm_event *one, \
+ struct kvm_event *two, int vcpu)\
+{ \
+ return get_event_ ##func(one, vcpu) > \
+ get_event_ ##func(two, vcpu); \
+}
+
+GET_EVENT_KEY(time, time);
+COMPARE_EVENT_KEY(count, stats.n);
+COMPARE_EVENT_KEY(mean, stats.mean);
+
+#define DEF_SORT_NAME_KEY(name, compare_key) \
+ { #name, compare_kvm_event_ ## compare_key }
+
+static struct kvm_event_key keys[] = {
+ DEF_SORT_NAME_KEY(sample, count),
+ DEF_SORT_NAME_KEY(time, mean),
+ { NULL, NULL }
+};
+
+static const char *sort_key = "sample";
+static key_cmp_fun compare;
+
+static bool select_key(void)
+{
+ int i;
+
+ for (i = 0; keys[i].name; i++) {
+ if (!strcmp(keys[i].name, sort_key)) {
+ compare = keys[i].key;
+ return true;
+ }
+ }
+
+ pr_err("Unknown compare key:%s\n", sort_key);
+ return false;
+}
+
+static struct rb_root result;
+static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
+ int vcpu)
+{
+ struct rb_node **rb = &result.rb_node;
+ struct rb_node *parent = NULL;
+ struct kvm_event *p;
+
+ while (*rb) {
+ p = container_of(*rb, struct kvm_event, rb);
+ parent = *rb;
+
+ if (bigger(event, p, vcpu))
+ rb = &(*rb)->rb_left;
+ else
+ rb = &(*rb)->rb_right;
+ }
+
+ rb_link_node(&event->rb, parent, rb);
+ rb_insert_color(&event->rb, &result);
+}
+
+static void update_total_count(struct kvm_event *event, int vcpu)
+{
+ total_count += get_event_count(event, vcpu);
+ total_time += get_event_time(event, vcpu);
+}
+
+static bool event_is_valid(struct kvm_event *event, int vcpu)
+{
+ return !!get_event_count(event, vcpu);
+}
+
+static void sort_result(int vcpu)
+{
+ unsigned int i;
+ struct kvm_event *event;
+
+ for (i = 0; i < EVENTS_CACHE_SIZE; i++)
+ list_for_each_entry(event, &kvm_events_cache[i], hash_entry)
+ if (event_is_valid(event, vcpu)) {
+ update_total_count(event, vcpu);
+ insert_to_result(event, compare, vcpu);
+ }
+}
+
+/* returns left most element of result, and erase it */
+static struct kvm_event *pop_from_result(void)
+{
+ struct rb_node *node = rb_first(&result);
+
+ if (!node)
+ return NULL;
+
+ rb_erase(node, &result);
+ return container_of(node, struct kvm_event, rb);
+}
+
+static void print_vcpu_info(int vcpu)
+{
+ pr_info("Analyze events for ");
+
+ if (vcpu == -1)
+ pr_info("all VCPUs:\n\n");
+ else
+ pr_info("VCPU %d:\n\n", vcpu);
+}
+
+static void print_result(int vcpu)
+{
+ char decode[20];
+ struct kvm_event *event;
+
+ pr_info("\n\n");
+ print_vcpu_info(vcpu);
+ pr_info("%20s ", events_ops->name);
+ pr_info("%10s ", "Samples");
+ pr_info("%9s ", "Samples%");
+
+ pr_info("%9s ", "Time%");
+ pr_info("%16s ", "Avg time");
+ pr_info("\n\n");
+
+ while ((event = pop_from_result())) {
+ u64 ecount, etime;
+
+ ecount = get_event_count(event, vcpu);
+ etime = get_event_time(event, vcpu);
+
+ events_ops->decode_key(&event->key, decode);
+ pr_info("%20s ", decode);
+ pr_info("%10llu ", (unsigned long long)ecount);
+ pr_info("%8.2f%% ", (double)ecount / total_count * 100);
+ pr_info("%8.2f%% ", (double)etime / total_time * 100);
+ pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
+ kvm_event_rel_stddev(vcpu, event));
+ pr_info("\n");
+ }
+
+ pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
+ (unsigned long long)total_count, total_time / 1e3);
+}
+
+static int process_sample_event(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
+{
+ struct thread *thread = machine__findnew_thread(machine, sample->tid);
+
+ if (thread == NULL) {
+ pr_debug("problem processing %d event, skipping it.\n",
+ event->header.type);
+ return -1;
+ }
+
+ if (!handle_kvm_event(thread, evsel->tp_format, sample->raw_data,
+ sample->time))
+ return -1;
+
+ return 0;
+}
+
+static struct perf_tool eops = {
+ .sample = process_sample_event,
+ .comm = perf_event__process_comm,
+ .ordered_samples = true,
+};
+
+static int get_cpu_isa(struct perf_session *session)
+{
+ char *cpuid;
+ int isa;
+
+ cpuid = perf_header__read_feature(session, HEADER_CPUID);
+
+ if (!cpuid) {
+ pr_err("read HEADER_CPUID failed.\n");
+ return -ENOTSUP;
+ }
+
+ if (strstr(cpuid, "Intel"))
+ isa = 1;
+ else if (strstr(cpuid, "AMD"))
+ isa = 0;
+ else {
+ pr_err("CPU %s is not supported.\n", cpuid);
+ isa = -ENOTSUP;
+ }
+
+ free(cpuid);
+ return isa;
+}
+
+static const char *file_name;
+
+static int read_events(void)
+{
+ struct perf_session *kvm_session;
+ int ret;
+
+ kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops);
+ if (!kvm_session) {
+ pr_err("Initializing perf session failed\n");
+ return -EINVAL;
+ }
+
+ if (!perf_session__has_traces(kvm_session, "kvm record"))
+ return -EINVAL;
+
+ /*
+ * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
+ * traced in the old kernel.
+ */
+ ret = get_cpu_isa(kvm_session);
+
+ if (ret < 0)
+ return ret;
+
+ cpu_isa = ret;
+
+ return perf_session__process_events(kvm_session, &eops);
+}
+
+static bool verify_vcpu(int vcpu)
+{
+ if (vcpu != -1 && vcpu < 0) {
+ pr_err("Invalid vcpu:%d.\n", vcpu);
+ return false;
+ }
+
+ return true;
+}
+
+static int kvm_events_report_vcpu(int vcpu)
+{
+ int ret = -EINVAL;
+
+ if (!verify_vcpu(vcpu))
+ goto exit;
+
+ if (!select_key())
+ goto exit;
+
+ if (!register_kvm_events_ops())
+ goto exit;
+
+ init_kvm_event_record();
+ setup_pager();
+
+ ret = read_events();
+ if (ret)
+ goto exit;
+
+ sort_result(vcpu);
+ print_result(vcpu);
+exit:
+ return ret;
+}
+
+static const char * const record_args[] = {
+ "record",
+ "-R",
+ "-f",
+ "-m", "1024",
+ "-c", "1",
+ "-e", "kvm:kvm_entry",
+ "-e", "kvm:kvm_exit",
+ "-e", "kvm:kvm_mmio",
+ "-e", "kvm:kvm_pio",
+};
+
+#define STRDUP_FAIL_EXIT(s) \
+ ({ char *_p; \
+ _p = strdup(s); \
+ if (!_p) \
+ return -ENOMEM; \
+ _p; \
+ })
+
+static int kvm_events_record(int argc, const char **argv)
+{
+ unsigned int rec_argc, i, j;
+ const char **rec_argv;
+
+ rec_argc = ARRAY_SIZE(record_args) + argc + 2;
+ rec_argv = calloc(rec_argc + 1, sizeof(char *));
+
+ if (rec_argv == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(record_args); i++)
+ rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
+
+ rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
+ rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
+
+ for (j = 1; j < (unsigned int)argc; j++, i++)
+ rec_argv[i] = argv[j];
+
+ return cmd_record(i, rec_argv, NULL);
+}
+
+static const char * const kvm_events_report_usage[] = {
+ "perf kvm stat report [<options>]",
+ NULL
+};
+
+static const struct option kvm_events_report_options[] = {
+ OPT_STRING(0, "event", &report_event, "report event",
+ "event for reporting: vmexit, mmio, ioport"),
+ OPT_INTEGER(0, "vcpu", &trace_vcpu,
+ "vcpu id to report"),
+ OPT_STRING('k', "key", &sort_key, "sort-key",
+ "key for sorting: sample(sort by samples number)"
+ " time (sort by avg time)"),
+ OPT_END()
+};
+
+static int kvm_events_report(int argc, const char **argv)
+{
+ symbol__init();
+
+ if (argc) {
+ argc = parse_options(argc, argv,
+ kvm_events_report_options,
+ kvm_events_report_usage, 0);
+ if (argc)
+ usage_with_options(kvm_events_report_usage,
+ kvm_events_report_options);
+ }
+
+ return kvm_events_report_vcpu(trace_vcpu);
+}
+
+static void print_kvm_stat_usage(void)
+{
+ printf("Usage: perf kvm stat <command>\n\n");
+
+ printf("# Available commands:\n");
+ printf("\trecord: record kvm events\n");
+ printf("\treport: report statistical data of kvm events\n");
+
+ printf("\nOtherwise, it is the alias of 'perf stat':\n");
+}
+
+static int kvm_cmd_stat(int argc, const char **argv)
+{
+ if (argc == 1) {
+ print_kvm_stat_usage();
+ goto perf_stat;
+ }
+
+ if (!strncmp(argv[1], "rec", 3))
+ return kvm_events_record(argc - 1, argv + 1);
+
+ if (!strncmp(argv[1], "rep", 3))
+ return kvm_events_report(argc - 1 , argv + 1);
+
+perf_stat:
+ return cmd_stat(argc, argv, NULL);
+}
+
static char name_buffer[256];
static const char * const kvm_usage[] = {
- "perf kvm [<options>] {top|record|report|diff|buildid-list}",
+ "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
NULL
};
@@ -135,6 +967,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
return cmd_top(argc, argv, NULL);
else if (!strncmp(argv[0], "buildid-list", 12))
return __cmd_buildid_list(argc, argv);
+ else if (!strncmp(argv[0], "stat", 4))
+ return kvm_cmd_stat(argc, argv);
else
usage_with_options(kvm_usage, kvm_options);
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index acbf633..ad72b28 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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)
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 209dad4..58de08b 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 70c2c13..f66610b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -16,6 +16,8 @@ struct thread {
bool comm_set;
char *comm;
int comm_len;
+
+ void *priv;
};
struct machine;
--
1.7.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
@ 2012-09-17 14:58 ` Arnaldo Carvalho de Melo
2012-09-20 12:51 ` Marcelo Tosatti
2012-09-27 4:26 ` [tip:perf/core] KVM: x86: Export svm/ vmx " tip-bot for Xiao Guangrong
1 sibling, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-09-17 14:58 UTC (permalink / raw)
To: Dong Hao
Cc: dsahern, mtosatti, avi, mingo, linux-kernel, kvm, xiaoguangrong, runzhen
Em Mon, Sep 17, 2012 at 04:31:13PM +0800, Dong Hao escreveu:
> From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
> Exporting KVM exit information to userspace to be consumed by perf.
>
> [ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
> Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
> Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Do we have acked/reviewed-by for this parth? Marcelo? Avi?
> arch/x86/include/asm/kvm.h | 16 +++
> arch/x86/include/asm/kvm_host.h | 16 ---
> arch/x86/include/asm/svm.h | 205 +++++++++++++++++++++++++--------------
> arch/x86/include/asm/vmx.h | 127 ++++++++++++++++--------
> arch/x86/kvm/trace.h | 89 -----------------
> 5 files changed, 230 insertions(+), 223 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
> index 246617e..41e08cb 100644
> --- a/arch/x86/include/asm/kvm.h
> +++ b/arch/x86/include/asm/kvm.h
> @@ -9,6 +9,22 @@
> #include <linux/types.h>
> #include <linux/ioctl.h>
>
> +#define DE_VECTOR 0
> +#define DB_VECTOR 1
> +#define BP_VECTOR 3
> +#define OF_VECTOR 4
> +#define BR_VECTOR 5
> +#define UD_VECTOR 6
> +#define NM_VECTOR 7
> +#define DF_VECTOR 8
> +#define TS_VECTOR 10
> +#define NP_VECTOR 11
> +#define SS_VECTOR 12
> +#define GP_VECTOR 13
> +#define PF_VECTOR 14
> +#define MF_VECTOR 16
> +#define MC_VECTOR 18
> +
> /* Select x86 specific features in <linux/kvm.h> */
> #define __KVM_HAVE_PIT
> #define __KVM_HAVE_IOAPIC
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 09155d6..1eaa6b0 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -75,22 +75,6 @@
> #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
> #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
>
> -#define DE_VECTOR 0
> -#define DB_VECTOR 1
> -#define BP_VECTOR 3
> -#define OF_VECTOR 4
> -#define BR_VECTOR 5
> -#define UD_VECTOR 6
> -#define NM_VECTOR 7
> -#define DF_VECTOR 8
> -#define TS_VECTOR 10
> -#define NP_VECTOR 11
> -#define SS_VECTOR 12
> -#define GP_VECTOR 13
> -#define PF_VECTOR 14
> -#define MF_VECTOR 16
> -#define MC_VECTOR 18
> -
> #define SELECTOR_TI_MASK (1 << 2)
> #define SELECTOR_RPL_MASK 0x03
>
> diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
> index f2b83bc..cdf5674 100644
> --- a/arch/x86/include/asm/svm.h
> +++ b/arch/x86/include/asm/svm.h
> @@ -1,6 +1,135 @@
> #ifndef __SVM_H
> #define __SVM_H
>
> +#define SVM_EXIT_READ_CR0 0x000
> +#define SVM_EXIT_READ_CR3 0x003
> +#define SVM_EXIT_READ_CR4 0x004
> +#define SVM_EXIT_READ_CR8 0x008
> +#define SVM_EXIT_WRITE_CR0 0x010
> +#define SVM_EXIT_WRITE_CR3 0x013
> +#define SVM_EXIT_WRITE_CR4 0x014
> +#define SVM_EXIT_WRITE_CR8 0x018
> +#define SVM_EXIT_READ_DR0 0x020
> +#define SVM_EXIT_READ_DR1 0x021
> +#define SVM_EXIT_READ_DR2 0x022
> +#define SVM_EXIT_READ_DR3 0x023
> +#define SVM_EXIT_READ_DR4 0x024
> +#define SVM_EXIT_READ_DR5 0x025
> +#define SVM_EXIT_READ_DR6 0x026
> +#define SVM_EXIT_READ_DR7 0x027
> +#define SVM_EXIT_WRITE_DR0 0x030
> +#define SVM_EXIT_WRITE_DR1 0x031
> +#define SVM_EXIT_WRITE_DR2 0x032
> +#define SVM_EXIT_WRITE_DR3 0x033
> +#define SVM_EXIT_WRITE_DR4 0x034
> +#define SVM_EXIT_WRITE_DR5 0x035
> +#define SVM_EXIT_WRITE_DR6 0x036
> +#define SVM_EXIT_WRITE_DR7 0x037
> +#define SVM_EXIT_EXCP_BASE 0x040
> +#define SVM_EXIT_INTR 0x060
> +#define SVM_EXIT_NMI 0x061
> +#define SVM_EXIT_SMI 0x062
> +#define SVM_EXIT_INIT 0x063
> +#define SVM_EXIT_VINTR 0x064
> +#define SVM_EXIT_CR0_SEL_WRITE 0x065
> +#define SVM_EXIT_IDTR_READ 0x066
> +#define SVM_EXIT_GDTR_READ 0x067
> +#define SVM_EXIT_LDTR_READ 0x068
> +#define SVM_EXIT_TR_READ 0x069
> +#define SVM_EXIT_IDTR_WRITE 0x06a
> +#define SVM_EXIT_GDTR_WRITE 0x06b
> +#define SVM_EXIT_LDTR_WRITE 0x06c
> +#define SVM_EXIT_TR_WRITE 0x06d
> +#define SVM_EXIT_RDTSC 0x06e
> +#define SVM_EXIT_RDPMC 0x06f
> +#define SVM_EXIT_PUSHF 0x070
> +#define SVM_EXIT_POPF 0x071
> +#define SVM_EXIT_CPUID 0x072
> +#define SVM_EXIT_RSM 0x073
> +#define SVM_EXIT_IRET 0x074
> +#define SVM_EXIT_SWINT 0x075
> +#define SVM_EXIT_INVD 0x076
> +#define SVM_EXIT_PAUSE 0x077
> +#define SVM_EXIT_HLT 0x078
> +#define SVM_EXIT_INVLPG 0x079
> +#define SVM_EXIT_INVLPGA 0x07a
> +#define SVM_EXIT_IOIO 0x07b
> +#define SVM_EXIT_MSR 0x07c
> +#define SVM_EXIT_TASK_SWITCH 0x07d
> +#define SVM_EXIT_FERR_FREEZE 0x07e
> +#define SVM_EXIT_SHUTDOWN 0x07f
> +#define SVM_EXIT_VMRUN 0x080
> +#define SVM_EXIT_VMMCALL 0x081
> +#define SVM_EXIT_VMLOAD 0x082
> +#define SVM_EXIT_VMSAVE 0x083
> +#define SVM_EXIT_STGI 0x084
> +#define SVM_EXIT_CLGI 0x085
> +#define SVM_EXIT_SKINIT 0x086
> +#define SVM_EXIT_RDTSCP 0x087
> +#define SVM_EXIT_ICEBP 0x088
> +#define SVM_EXIT_WBINVD 0x089
> +#define SVM_EXIT_MONITOR 0x08a
> +#define SVM_EXIT_MWAIT 0x08b
> +#define SVM_EXIT_MWAIT_COND 0x08c
> +#define SVM_EXIT_XSETBV 0x08d
> +#define SVM_EXIT_NPF 0x400
> +
> +#define SVM_EXIT_ERR -1
> +
> +#define SVM_EXIT_REASONS \
> + { SVM_EXIT_READ_CR0, "read_cr0" }, \
> + { SVM_EXIT_READ_CR3, "read_cr3" }, \
> + { SVM_EXIT_READ_CR4, "read_cr4" }, \
> + { SVM_EXIT_READ_CR8, "read_cr8" }, \
> + { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
> + { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
> + { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
> + { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
> + { SVM_EXIT_READ_DR0, "read_dr0" }, \
> + { SVM_EXIT_READ_DR1, "read_dr1" }, \
> + { SVM_EXIT_READ_DR2, "read_dr2" }, \
> + { SVM_EXIT_READ_DR3, "read_dr3" }, \
> + { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
> + { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
> + { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
> + { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
> + { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
> + { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
> + { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
> + { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
> + { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
> + { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
> + { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
> + { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
> + { SVM_EXIT_INTR, "interrupt" }, \
> + { SVM_EXIT_NMI, "nmi" }, \
> + { SVM_EXIT_SMI, "smi" }, \
> + { SVM_EXIT_INIT, "init" }, \
> + { SVM_EXIT_VINTR, "vintr" }, \
> + { SVM_EXIT_CPUID, "cpuid" }, \
> + { SVM_EXIT_INVD, "invd" }, \
> + { SVM_EXIT_HLT, "hlt" }, \
> + { SVM_EXIT_INVLPG, "invlpg" }, \
> + { SVM_EXIT_INVLPGA, "invlpga" }, \
> + { SVM_EXIT_IOIO, "io" }, \
> + { SVM_EXIT_MSR, "msr" }, \
> + { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
> + { SVM_EXIT_SHUTDOWN, "shutdown" }, \
> + { SVM_EXIT_VMRUN, "vmrun" }, \
> + { SVM_EXIT_VMMCALL, "hypercall" }, \
> + { SVM_EXIT_VMLOAD, "vmload" }, \
> + { SVM_EXIT_VMSAVE, "vmsave" }, \
> + { SVM_EXIT_STGI, "stgi" }, \
> + { SVM_EXIT_CLGI, "clgi" }, \
> + { SVM_EXIT_SKINIT, "skinit" }, \
> + { SVM_EXIT_WBINVD, "wbinvd" }, \
> + { SVM_EXIT_MONITOR, "monitor" }, \
> + { SVM_EXIT_MWAIT, "mwait" }, \
> + { SVM_EXIT_XSETBV, "xsetbv" }, \
> + { SVM_EXIT_NPF, "npf" }
> +
> +#ifdef __KERNEL__
> +
> enum {
> INTERCEPT_INTR,
> INTERCEPT_NMI,
> @@ -264,81 +393,6 @@ struct __attribute__ ((__packed__)) vmcb {
>
> #define SVM_EXITINFO_REG_MASK 0x0F
>
> -#define SVM_EXIT_READ_CR0 0x000
> -#define SVM_EXIT_READ_CR3 0x003
> -#define SVM_EXIT_READ_CR4 0x004
> -#define SVM_EXIT_READ_CR8 0x008
> -#define SVM_EXIT_WRITE_CR0 0x010
> -#define SVM_EXIT_WRITE_CR3 0x013
> -#define SVM_EXIT_WRITE_CR4 0x014
> -#define SVM_EXIT_WRITE_CR8 0x018
> -#define SVM_EXIT_READ_DR0 0x020
> -#define SVM_EXIT_READ_DR1 0x021
> -#define SVM_EXIT_READ_DR2 0x022
> -#define SVM_EXIT_READ_DR3 0x023
> -#define SVM_EXIT_READ_DR4 0x024
> -#define SVM_EXIT_READ_DR5 0x025
> -#define SVM_EXIT_READ_DR6 0x026
> -#define SVM_EXIT_READ_DR7 0x027
> -#define SVM_EXIT_WRITE_DR0 0x030
> -#define SVM_EXIT_WRITE_DR1 0x031
> -#define SVM_EXIT_WRITE_DR2 0x032
> -#define SVM_EXIT_WRITE_DR3 0x033
> -#define SVM_EXIT_WRITE_DR4 0x034
> -#define SVM_EXIT_WRITE_DR5 0x035
> -#define SVM_EXIT_WRITE_DR6 0x036
> -#define SVM_EXIT_WRITE_DR7 0x037
> -#define SVM_EXIT_EXCP_BASE 0x040
> -#define SVM_EXIT_INTR 0x060
> -#define SVM_EXIT_NMI 0x061
> -#define SVM_EXIT_SMI 0x062
> -#define SVM_EXIT_INIT 0x063
> -#define SVM_EXIT_VINTR 0x064
> -#define SVM_EXIT_CR0_SEL_WRITE 0x065
> -#define SVM_EXIT_IDTR_READ 0x066
> -#define SVM_EXIT_GDTR_READ 0x067
> -#define SVM_EXIT_LDTR_READ 0x068
> -#define SVM_EXIT_TR_READ 0x069
> -#define SVM_EXIT_IDTR_WRITE 0x06a
> -#define SVM_EXIT_GDTR_WRITE 0x06b
> -#define SVM_EXIT_LDTR_WRITE 0x06c
> -#define SVM_EXIT_TR_WRITE 0x06d
> -#define SVM_EXIT_RDTSC 0x06e
> -#define SVM_EXIT_RDPMC 0x06f
> -#define SVM_EXIT_PUSHF 0x070
> -#define SVM_EXIT_POPF 0x071
> -#define SVM_EXIT_CPUID 0x072
> -#define SVM_EXIT_RSM 0x073
> -#define SVM_EXIT_IRET 0x074
> -#define SVM_EXIT_SWINT 0x075
> -#define SVM_EXIT_INVD 0x076
> -#define SVM_EXIT_PAUSE 0x077
> -#define SVM_EXIT_HLT 0x078
> -#define SVM_EXIT_INVLPG 0x079
> -#define SVM_EXIT_INVLPGA 0x07a
> -#define SVM_EXIT_IOIO 0x07b
> -#define SVM_EXIT_MSR 0x07c
> -#define SVM_EXIT_TASK_SWITCH 0x07d
> -#define SVM_EXIT_FERR_FREEZE 0x07e
> -#define SVM_EXIT_SHUTDOWN 0x07f
> -#define SVM_EXIT_VMRUN 0x080
> -#define SVM_EXIT_VMMCALL 0x081
> -#define SVM_EXIT_VMLOAD 0x082
> -#define SVM_EXIT_VMSAVE 0x083
> -#define SVM_EXIT_STGI 0x084
> -#define SVM_EXIT_CLGI 0x085
> -#define SVM_EXIT_SKINIT 0x086
> -#define SVM_EXIT_RDTSCP 0x087
> -#define SVM_EXIT_ICEBP 0x088
> -#define SVM_EXIT_WBINVD 0x089
> -#define SVM_EXIT_MONITOR 0x08a
> -#define SVM_EXIT_MWAIT 0x08b
> -#define SVM_EXIT_MWAIT_COND 0x08c
> -#define SVM_EXIT_XSETBV 0x08d
> -#define SVM_EXIT_NPF 0x400
> -
> -#define SVM_EXIT_ERR -1
> -
> #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
>
> #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
> @@ -350,3 +404,4 @@ struct __attribute__ ((__packed__)) vmcb {
>
> #endif
>
> +#endif
> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
> index 74fcb96..36ec21c 100644
> --- a/arch/x86/include/asm/vmx.h
> +++ b/arch/x86/include/asm/vmx.h
> @@ -25,6 +25,88 @@
> *
> */
>
> +#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
> +
> +#define EXIT_REASON_EXCEPTION_NMI 0
> +#define EXIT_REASON_EXTERNAL_INTERRUPT 1
> +#define EXIT_REASON_TRIPLE_FAULT 2
> +
> +#define EXIT_REASON_PENDING_INTERRUPT 7
> +#define EXIT_REASON_NMI_WINDOW 8
> +#define EXIT_REASON_TASK_SWITCH 9
> +#define EXIT_REASON_CPUID 10
> +#define EXIT_REASON_HLT 12
> +#define EXIT_REASON_INVD 13
> +#define EXIT_REASON_INVLPG 14
> +#define EXIT_REASON_RDPMC 15
> +#define EXIT_REASON_RDTSC 16
> +#define EXIT_REASON_VMCALL 18
> +#define EXIT_REASON_VMCLEAR 19
> +#define EXIT_REASON_VMLAUNCH 20
> +#define EXIT_REASON_VMPTRLD 21
> +#define EXIT_REASON_VMPTRST 22
> +#define EXIT_REASON_VMREAD 23
> +#define EXIT_REASON_VMRESUME 24
> +#define EXIT_REASON_VMWRITE 25
> +#define EXIT_REASON_VMOFF 26
> +#define EXIT_REASON_VMON 27
> +#define EXIT_REASON_CR_ACCESS 28
> +#define EXIT_REASON_DR_ACCESS 29
> +#define EXIT_REASON_IO_INSTRUCTION 30
> +#define EXIT_REASON_MSR_READ 31
> +#define EXIT_REASON_MSR_WRITE 32
> +#define EXIT_REASON_INVALID_STATE 33
> +#define EXIT_REASON_MWAIT_INSTRUCTION 36
> +#define EXIT_REASON_MONITOR_INSTRUCTION 39
> +#define EXIT_REASON_PAUSE_INSTRUCTION 40
> +#define EXIT_REASON_MCE_DURING_VMENTRY 41
> +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
> +#define EXIT_REASON_APIC_ACCESS 44
> +#define EXIT_REASON_EPT_VIOLATION 48
> +#define EXIT_REASON_EPT_MISCONFIG 49
> +#define EXIT_REASON_WBINVD 54
> +#define EXIT_REASON_XSETBV 55
> +#define EXIT_REASON_INVPCID 58
> +
> +#define VMX_EXIT_REASONS \
> + { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
> + { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
> + { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
> + { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
> + { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
> + { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
> + { EXIT_REASON_CPUID, "CPUID" }, \
> + { EXIT_REASON_HLT, "HLT" }, \
> + { EXIT_REASON_INVLPG, "INVLPG" }, \
> + { EXIT_REASON_RDPMC, "RDPMC" }, \
> + { EXIT_REASON_RDTSC, "RDTSC" }, \
> + { EXIT_REASON_VMCALL, "VMCALL" }, \
> + { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
> + { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
> + { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
> + { EXIT_REASON_VMPTRST, "VMPTRST" }, \
> + { EXIT_REASON_VMREAD, "VMREAD" }, \
> + { EXIT_REASON_VMRESUME, "VMRESUME" }, \
> + { EXIT_REASON_VMWRITE, "VMWRITE" }, \
> + { EXIT_REASON_VMOFF, "VMOFF" }, \
> + { EXIT_REASON_VMON, "VMON" }, \
> + { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
> + { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
> + { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
> + { EXIT_REASON_MSR_READ, "MSR_READ" }, \
> + { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
> + { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
> + { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
> + { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
> + { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
> + { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
> + { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
> + { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
> + { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
> + { EXIT_REASON_WBINVD, "WBINVD" }
> +
> +#ifdef __KERNEL__
> +
> #include <linux/types.h>
>
> /*
> @@ -241,49 +323,6 @@ enum vmcs_field {
> HOST_RIP = 0x00006c16,
> };
>
> -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
> -
> -#define EXIT_REASON_EXCEPTION_NMI 0
> -#define EXIT_REASON_EXTERNAL_INTERRUPT 1
> -#define EXIT_REASON_TRIPLE_FAULT 2
> -
> -#define EXIT_REASON_PENDING_INTERRUPT 7
> -#define EXIT_REASON_NMI_WINDOW 8
> -#define EXIT_REASON_TASK_SWITCH 9
> -#define EXIT_REASON_CPUID 10
> -#define EXIT_REASON_HLT 12
> -#define EXIT_REASON_INVD 13
> -#define EXIT_REASON_INVLPG 14
> -#define EXIT_REASON_RDPMC 15
> -#define EXIT_REASON_RDTSC 16
> -#define EXIT_REASON_VMCALL 18
> -#define EXIT_REASON_VMCLEAR 19
> -#define EXIT_REASON_VMLAUNCH 20
> -#define EXIT_REASON_VMPTRLD 21
> -#define EXIT_REASON_VMPTRST 22
> -#define EXIT_REASON_VMREAD 23
> -#define EXIT_REASON_VMRESUME 24
> -#define EXIT_REASON_VMWRITE 25
> -#define EXIT_REASON_VMOFF 26
> -#define EXIT_REASON_VMON 27
> -#define EXIT_REASON_CR_ACCESS 28
> -#define EXIT_REASON_DR_ACCESS 29
> -#define EXIT_REASON_IO_INSTRUCTION 30
> -#define EXIT_REASON_MSR_READ 31
> -#define EXIT_REASON_MSR_WRITE 32
> -#define EXIT_REASON_INVALID_STATE 33
> -#define EXIT_REASON_MWAIT_INSTRUCTION 36
> -#define EXIT_REASON_MONITOR_INSTRUCTION 39
> -#define EXIT_REASON_PAUSE_INSTRUCTION 40
> -#define EXIT_REASON_MCE_DURING_VMENTRY 41
> -#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
> -#define EXIT_REASON_APIC_ACCESS 44
> -#define EXIT_REASON_EPT_VIOLATION 48
> -#define EXIT_REASON_EPT_MISCONFIG 49
> -#define EXIT_REASON_WBINVD 54
> -#define EXIT_REASON_XSETBV 55
> -#define EXIT_REASON_INVPCID 58
> -
> /*
> * Interruption-information format
> */
> @@ -488,3 +527,5 @@ enum vm_instruction_error_number {
> };
>
> #endif
> +
> +#endif
> diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
> index a71faf7..bca63f0 100644
> --- a/arch/x86/kvm/trace.h
> +++ b/arch/x86/kvm/trace.h
> @@ -183,95 +183,6 @@ TRACE_EVENT(kvm_apic,
> #define KVM_ISA_VMX 1
> #define KVM_ISA_SVM 2
>
> -#define VMX_EXIT_REASONS \
> - { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
> - { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
> - { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
> - { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
> - { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
> - { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
> - { EXIT_REASON_CPUID, "CPUID" }, \
> - { EXIT_REASON_HLT, "HLT" }, \
> - { EXIT_REASON_INVLPG, "INVLPG" }, \
> - { EXIT_REASON_RDPMC, "RDPMC" }, \
> - { EXIT_REASON_RDTSC, "RDTSC" }, \
> - { EXIT_REASON_VMCALL, "VMCALL" }, \
> - { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
> - { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
> - { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
> - { EXIT_REASON_VMPTRST, "VMPTRST" }, \
> - { EXIT_REASON_VMREAD, "VMREAD" }, \
> - { EXIT_REASON_VMRESUME, "VMRESUME" }, \
> - { EXIT_REASON_VMWRITE, "VMWRITE" }, \
> - { EXIT_REASON_VMOFF, "VMOFF" }, \
> - { EXIT_REASON_VMON, "VMON" }, \
> - { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
> - { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
> - { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
> - { EXIT_REASON_MSR_READ, "MSR_READ" }, \
> - { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
> - { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
> - { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
> - { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
> - { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
> - { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
> - { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
> - { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
> - { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
> - { EXIT_REASON_WBINVD, "WBINVD" }
> -
> -#define SVM_EXIT_REASONS \
> - { SVM_EXIT_READ_CR0, "read_cr0" }, \
> - { SVM_EXIT_READ_CR3, "read_cr3" }, \
> - { SVM_EXIT_READ_CR4, "read_cr4" }, \
> - { SVM_EXIT_READ_CR8, "read_cr8" }, \
> - { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
> - { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
> - { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
> - { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
> - { SVM_EXIT_READ_DR0, "read_dr0" }, \
> - { SVM_EXIT_READ_DR1, "read_dr1" }, \
> - { SVM_EXIT_READ_DR2, "read_dr2" }, \
> - { SVM_EXIT_READ_DR3, "read_dr3" }, \
> - { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
> - { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
> - { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
> - { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
> - { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
> - { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
> - { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
> - { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
> - { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
> - { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
> - { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
> - { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
> - { SVM_EXIT_INTR, "interrupt" }, \
> - { SVM_EXIT_NMI, "nmi" }, \
> - { SVM_EXIT_SMI, "smi" }, \
> - { SVM_EXIT_INIT, "init" }, \
> - { SVM_EXIT_VINTR, "vintr" }, \
> - { SVM_EXIT_CPUID, "cpuid" }, \
> - { SVM_EXIT_INVD, "invd" }, \
> - { SVM_EXIT_HLT, "hlt" }, \
> - { SVM_EXIT_INVLPG, "invlpg" }, \
> - { SVM_EXIT_INVLPGA, "invlpga" }, \
> - { SVM_EXIT_IOIO, "io" }, \
> - { SVM_EXIT_MSR, "msr" }, \
> - { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
> - { SVM_EXIT_SHUTDOWN, "shutdown" }, \
> - { SVM_EXIT_VMRUN, "vmrun" }, \
> - { SVM_EXIT_VMMCALL, "hypercall" }, \
> - { SVM_EXIT_VMLOAD, "vmload" }, \
> - { SVM_EXIT_VMSAVE, "vmsave" }, \
> - { SVM_EXIT_STGI, "stgi" }, \
> - { SVM_EXIT_CLGI, "clgi" }, \
> - { SVM_EXIT_SKINIT, "skinit" }, \
> - { SVM_EXIT_WBINVD, "wbinvd" }, \
> - { SVM_EXIT_MONITOR, "monitor" }, \
> - { SVM_EXIT_MWAIT, "mwait" }, \
> - { SVM_EXIT_XSETBV, "xsetbv" }, \
> - { SVM_EXIT_NPF, "npf" }
> -
> /*
> * Tracepoint for kvm guest exit:
> */
> --
> 1.7.2.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v8 2/3] perf: move stat related code to util/stat.c
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
@ 2012-09-18 14:01 ` David Ahern
2012-09-18 19:18 ` David Ahern
2012-09-19 15:18 ` [tip:perf/core] perf stat: Move stats " tip-bot for Xiao Guangrong
2 siblings, 0 replies; 14+ messages in thread
From: David Ahern @ 2012-09-18 14:01 UTC (permalink / raw)
To: Dong Hao
Cc: acme, mtosatti, avi, mingo, linux-kernel, kvm, xiaoguangrong, runzhen
On 9/17/12 2:31 AM, Dong Hao wrote:
> From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
> Then, the code can be shared between kvm events and perf stat
>
> [ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
> Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
> Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
> ---
> tools/perf/Makefile | 1 +
> tools/perf/builtin-stat.c | 56 +------------------------------------------
> tools/perf/util/stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/stat.h | 16 ++++++++++++
> 4 files changed, 76 insertions(+), 54 deletions(-)
> create mode 100644 tools/perf/util/stat.c
> create mode 100644 tools/perf/util/stat.h
>
> diff --git a/tools/perf/Makefile b/tools/perf/Makefile
> index 209774b..5077f8e 100644
> --- a/tools/perf/Makefile
> +++ b/tools/perf/Makefile
> @@ -406,6 +406,7 @@ LIB_OBJS += $(OUTPUT)util/target.o
> LIB_OBJS += $(OUTPUT)util/rblist.o
> LIB_OBJS += $(OUTPUT)util/intlist.o
> LIB_OBJS += $(OUTPUT)util/vdso.o
> +LIB_OBJS += $(OUTPUT)util/stat.o
>
> LIB_OBJS += $(OUTPUT)ui/helpline.o
> LIB_OBJS += $(OUTPUT)ui/hist.o
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index dab347d..3c43a35 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -51,13 +51,13 @@
> #include "util/evsel.h"
> #include "util/debug.h"
> #include "util/color.h"
> +#include "util/stat.h"
> #include "util/header.h"
> #include "util/cpumap.h"
> #include "util/thread.h"
> #include "util/thread_map.h"
>
> #include <sys/prctl.h>
> -#include <math.h>
> #include <locale.h>
>
> #define DEFAULT_SEPARATOR " "
> @@ -199,11 +199,6 @@ static int output_fd;
>
> static volatile int done = 0;
>
> -struct stats
> -{
> - double n, mean, M2;
> -};
> -
> struct perf_stat {
> struct stats res_stats[3];
> };
> @@ -220,50 +215,6 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
> evsel->priv = NULL;
> }
>
> -static void update_stats(struct stats *stats, u64 val)
> -{
> - double delta;
> -
> - stats->n++;
> - delta = val - stats->mean;
> - stats->mean += delta / stats->n;
> - stats->M2 += delta*(val - stats->mean);
> -}
> -
> -static double avg_stats(struct stats *stats)
> -{
> - return stats->mean;
> -}
> -
> -/*
> - * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
> - *
> - * (\Sum n_i^2) - ((\Sum n_i)^2)/n
> - * s^2 = -------------------------------
> - * n - 1
> - *
> - * http://en.wikipedia.org/wiki/Stddev
> - *
> - * The std dev of the mean is related to the std dev by:
> - *
> - * s
> - * s_mean = -------
> - * sqrt(n)
> - *
> - */
> -static double stddev_stats(struct stats *stats)
> -{
> - double variance, variance_mean;
> -
> - if (!stats->n)
> - return 0.0;
> -
> - variance = stats->M2 / (stats->n - 1);
> - variance_mean = variance / stats->n;
> -
> - return sqrt(variance_mean);
> -}
> -
> static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
> static struct stats runtime_cycles_stats[MAX_NR_CPUS];
> static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
> @@ -559,10 +510,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
>
> static void print_noise_pct(double total, double avg)
> {
> - double pct = 0.0;
> -
> - if (avg)
> - pct = 100.0*total/avg;
> + double pct = rel_stddev_stats(total, avg);
>
> if (csv_output)
> fprintf(output, "%s%.2f%%", csv_sep, pct);
> diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
> new file mode 100644
> index 0000000..2374212
> --- /dev/null
> +++ b/tools/perf/util/stat.c
> @@ -0,0 +1,57 @@
> +#include <math.h>
> +
> +#include "stat.h"
> +
> +void update_stats(struct stats *stats, u64 val)
> +{
> + double delta;
> +
> + stats->n++;
> + delta = val - stats->mean;
> + stats->mean += delta / stats->n;
> + stats->M2 += delta*(val - stats->mean);
> +}
> +
> +double avg_stats(struct stats *stats)
> +{
> + return stats->mean;
> +}
> +
> +/*
> + * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
> + *
> + * (\Sum n_i^2) - ((\Sum n_i)^2)/n
> + * s^2 = -------------------------------
> + * n - 1
> + *
> + * http://en.wikipedia.org/wiki/Stddev
> + *
> + * The std dev of the mean is related to the std dev by:
> + *
> + * s
> + * s_mean = -------
> + * sqrt(n)
> + *
> + */
> +double stddev_stats(struct stats *stats)
> +{
> + double variance, variance_mean;
> +
> + if (!stats->n)
> + return 0.0;
> +
> + variance = stats->M2 / (stats->n - 1);
> + variance_mean = variance / stats->n;
> +
> + return sqrt(variance_mean);
> +}
> +
> +double rel_stddev_stats(double stddev, double avg)
> +{
> + double pct = 0.0;
> +
> + if (avg)
> + pct = 100.0 * stddev/avg;
> +
> + return pct;
> +}
rel_stddev_stats should take the struct stats as an input and use
elements from it to compute the return value. perf-stat's relative
stddev sites can be fixed later.
> diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
> new file mode 100644
> index 0000000..588367c
> --- /dev/null
> +++ b/tools/perf/util/stat.h
> @@ -0,0 +1,16 @@
> +#ifndef __PERF_STATS_H
> +#define __PERF_STATS_H
> +
> +#include "types.h"
> +
> +struct stats
> +{
> + double n, mean, M2;
> +};
> +
> +void update_stats(struct stats *stats, u64 val);
> +double avg_stats(struct stats *stats);
> +double stddev_stats(struct stats *stats);
> +double rel_stddev_stats(double stddev, double avg);
> +
> +#endif
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v8 2/3] perf: move stat related code to util/stat.c
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
2012-09-18 14:01 ` David Ahern
@ 2012-09-18 19:18 ` David Ahern
2012-09-19 1:53 ` Xiao Guangrong
2012-09-19 15:18 ` [tip:perf/core] perf stat: Move stats " tip-bot for Xiao Guangrong
2 siblings, 1 reply; 14+ messages in thread
From: David Ahern @ 2012-09-18 19:18 UTC (permalink / raw)
To: Dong Hao
Cc: acme, mtosatti, avi, mingo, linux-kernel, kvm, xiaoguangrong, runzhen
On 9/17/12 2:31 AM, Dong Hao wrote:
> From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
> Then, the code can be shared between kvm events and perf stat
>
> [ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
> Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
> Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
> ---
> tools/perf/Makefile | 1 +
> tools/perf/builtin-stat.c | 56 +------------------------------------------
> tools/perf/util/stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/stat.h | 16 ++++++++++++
> 4 files changed, 76 insertions(+), 54 deletions(-)
> create mode 100644 tools/perf/util/stat.c
> create mode 100644 tools/perf/util/stat.h
Does not apply to Arnaldo's latest perf/core branch.
David
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v8 2/3] perf: move stat related code to util/stat.c
2012-09-18 19:18 ` David Ahern
@ 2012-09-19 1:53 ` Xiao Guangrong
2012-09-19 4:00 ` David Ahern
0 siblings, 1 reply; 14+ messages in thread
From: Xiao Guangrong @ 2012-09-19 1:53 UTC (permalink / raw)
To: David Ahern
Cc: Dong Hao, acme, mtosatti, avi, mingo, linux-kernel, kvm, runzhen
On 09/19/2012 03:18 AM, David Ahern wrote:
> On 9/17/12 2:31 AM, Dong Hao wrote:
>> From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>>
>> Then, the code can be shared between kvm events and perf stat
>>
>> [ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
>> Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>> Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
>> ---
>> tools/perf/Makefile | 1 +
>> tools/perf/builtin-stat.c | 56 +------------------------------------------
>> tools/perf/util/stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
>> tools/perf/util/stat.h | 16 ++++++++++++
>> 4 files changed, 76 insertions(+), 54 deletions(-)
>> create mode 100644 tools/perf/util/stat.c
>> create mode 100644 tools/perf/util/stat.h
>
> Does not apply to Arnaldo's latest perf/core branch.
The patch has already been applied to this branch:
http://git.kernel.org/?p=linux/kernel/git/acme/linux.git;a=commit;h=0007eceaceb11520071d053acfe06ee3326b1d13
You or we can improve rel_stddev_stats after perf-stat's code is fixed. :)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v8 2/3] perf: move stat related code to util/stat.c
2012-09-19 1:53 ` Xiao Guangrong
@ 2012-09-19 4:00 ` David Ahern
0 siblings, 0 replies; 14+ messages in thread
From: David Ahern @ 2012-09-19 4:00 UTC (permalink / raw)
To: Xiao Guangrong
Cc: Dong Hao, acme, mtosatti, avi, mingo, linux-kernel, kvm, runzhen
On 9/18/12 7:53 PM, Xiao Guangrong wrote:
>> Does not apply to Arnaldo's latest perf/core branch.
>
> The patch has already been applied to this branch:
> http://git.kernel.org/?p=linux/kernel/git/acme/linux.git;a=commit;h=0007eceaceb11520071d053acfe06ee3326b1d13
Did not expect that. ok. I'll try patch 3 tomorrow.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [tip:perf/core] perf stat: Move stats related code to util/stat.c
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
2012-09-18 14:01 ` David Ahern
2012-09-18 19:18 ` David Ahern
@ 2012-09-19 15:18 ` tip-bot for Xiao Guangrong
2 siblings, 0 replies; 14+ messages in thread
From: tip-bot for Xiao Guangrong @ 2012-09-19 15:18 UTC (permalink / raw)
To: linux-tip-commits
Cc: acme, linux-kernel, hpa, mingo, runzhen, xiaoguangrong, haodong,
mtosatti, dsahern, tglx, avi
Commit-ID: 0007eceaceb11520071d053acfe06ee3326b1d13
Gitweb: http://git.kernel.org/tip/0007eceaceb11520071d053acfe06ee3326b1d13
Author: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
AuthorDate: Mon, 17 Sep 2012 16:31:14 +0800
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Sep 2012 13:10:03 -0300
perf stat: Move stats related code to util/stat.c
Then, the code can be shared between kvm events and perf stat.
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
[ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: kvm@vger.kernel.org
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Runzhen Wang <runzhen@linux.vnet.ibm.com>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1347870675-31495-3-git-send-email-haodong@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/builtin-stat.c | 56 +------------------------------------------
tools/perf/util/stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/stat.h | 16 ++++++++++++
4 files changed, 76 insertions(+), 54 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 209774b..5077f8e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -406,6 +406,7 @@ LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o
+LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/hist.o
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dab347d..3c43a35 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -51,13 +51,13 @@
#include "util/evsel.h"
#include "util/debug.h"
#include "util/color.h"
+#include "util/stat.h"
#include "util/header.h"
#include "util/cpumap.h"
#include "util/thread.h"
#include "util/thread_map.h"
#include <sys/prctl.h>
-#include <math.h>
#include <locale.h>
#define DEFAULT_SEPARATOR " "
@@ -199,11 +199,6 @@ static int output_fd;
static volatile int done = 0;
-struct stats
-{
- double n, mean, M2;
-};
-
struct perf_stat {
struct stats res_stats[3];
};
@@ -220,50 +215,6 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
evsel->priv = NULL;
}
-static void update_stats(struct stats *stats, u64 val)
-{
- double delta;
-
- stats->n++;
- delta = val - stats->mean;
- stats->mean += delta / stats->n;
- stats->M2 += delta*(val - stats->mean);
-}
-
-static double avg_stats(struct stats *stats)
-{
- return stats->mean;
-}
-
-/*
- * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
- *
- * (\Sum n_i^2) - ((\Sum n_i)^2)/n
- * s^2 = -------------------------------
- * n - 1
- *
- * http://en.wikipedia.org/wiki/Stddev
- *
- * The std dev of the mean is related to the std dev by:
- *
- * s
- * s_mean = -------
- * sqrt(n)
- *
- */
-static double stddev_stats(struct stats *stats)
-{
- double variance, variance_mean;
-
- if (!stats->n)
- return 0.0;
-
- variance = stats->M2 / (stats->n - 1);
- variance_mean = variance / stats->n;
-
- return sqrt(variance_mean);
-}
-
static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
@@ -559,10 +510,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
static void print_noise_pct(double total, double avg)
{
- double pct = 0.0;
-
- if (avg)
- pct = 100.0*total/avg;
+ double pct = rel_stddev_stats(total, avg);
if (csv_output)
fprintf(output, "%s%.2f%%", csv_sep, pct);
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
new file mode 100644
index 0000000..2374212
--- /dev/null
+++ b/tools/perf/util/stat.c
@@ -0,0 +1,57 @@
+#include <math.h>
+
+#include "stat.h"
+
+void update_stats(struct stats *stats, u64 val)
+{
+ double delta;
+
+ stats->n++;
+ delta = val - stats->mean;
+ stats->mean += delta / stats->n;
+ stats->M2 += delta*(val - stats->mean);
+}
+
+double avg_stats(struct stats *stats)
+{
+ return stats->mean;
+}
+
+/*
+ * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
+ *
+ * (\Sum n_i^2) - ((\Sum n_i)^2)/n
+ * s^2 = -------------------------------
+ * n - 1
+ *
+ * http://en.wikipedia.org/wiki/Stddev
+ *
+ * The std dev of the mean is related to the std dev by:
+ *
+ * s
+ * s_mean = -------
+ * sqrt(n)
+ *
+ */
+double stddev_stats(struct stats *stats)
+{
+ double variance, variance_mean;
+
+ if (!stats->n)
+ return 0.0;
+
+ variance = stats->M2 / (stats->n - 1);
+ variance_mean = variance / stats->n;
+
+ return sqrt(variance_mean);
+}
+
+double rel_stddev_stats(double stddev, double avg)
+{
+ double pct = 0.0;
+
+ if (avg)
+ pct = 100.0 * stddev/avg;
+
+ return pct;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
new file mode 100644
index 0000000..588367c
--- /dev/null
+++ b/tools/perf/util/stat.h
@@ -0,0 +1,16 @@
+#ifndef __PERF_STATS_H
+#define __PERF_STATS_H
+
+#include "types.h"
+
+struct stats
+{
+ double n, mean, M2;
+};
+
+void update_stats(struct stats *stats, u64 val);
+double avg_stats(struct stats *stats);
+double stddev_stats(struct stats *stats);
+double rel_stddev_stats(double stddev, double avg);
+
+#endif
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace
2012-09-17 14:58 ` Arnaldo Carvalho de Melo
@ 2012-09-20 12:51 ` Marcelo Tosatti
0 siblings, 0 replies; 14+ messages in thread
From: Marcelo Tosatti @ 2012-09-20 12:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Avi Kivity
Cc: Dong Hao, dsahern, avi, mingo, linux-kernel, kvm, xiaoguangrong, runzhen
On Mon, Sep 17, 2012 at 07:58:57AM -0700, Arnaldo Carvalho de Melo wrote:
> Em Mon, Sep 17, 2012 at 04:31:13PM +0800, Dong Hao escreveu:
> > From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
> >
> > Exporting KVM exit information to userspace to be consumed by perf.
> >
> > [ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
> > Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
> > Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
> Do we have acked/reviewed-by for this parth? Marcelo? Avi?
Code move... ACK.
>
> > arch/x86/include/asm/kvm.h | 16 +++
> > arch/x86/include/asm/kvm_host.h | 16 ---
> > arch/x86/include/asm/svm.h | 205 +++++++++++++++++++++++++--------------
> > arch/x86/include/asm/vmx.h | 127 ++++++++++++++++--------
> > arch/x86/kvm/trace.h | 89 -----------------
> > 5 files changed, 230 insertions(+), 223 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
> > index 246617e..41e08cb 100644
> > --- a/arch/x86/include/asm/kvm.h
> > +++ b/arch/x86/include/asm/kvm.h
> > @@ -9,6 +9,22 @@
> > #include <linux/types.h>
> > #include <linux/ioctl.h>
> >
> > +#define DE_VECTOR 0
> > +#define DB_VECTOR 1
> > +#define BP_VECTOR 3
> > +#define OF_VECTOR 4
> > +#define BR_VECTOR 5
> > +#define UD_VECTOR 6
> > +#define NM_VECTOR 7
> > +#define DF_VECTOR 8
> > +#define TS_VECTOR 10
> > +#define NP_VECTOR 11
> > +#define SS_VECTOR 12
> > +#define GP_VECTOR 13
> > +#define PF_VECTOR 14
> > +#define MF_VECTOR 16
> > +#define MC_VECTOR 18
> > +
> > /* Select x86 specific features in <linux/kvm.h> */
> > #define __KVM_HAVE_PIT
> > #define __KVM_HAVE_IOAPIC
> > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> > index 09155d6..1eaa6b0 100644
> > --- a/arch/x86/include/asm/kvm_host.h
> > +++ b/arch/x86/include/asm/kvm_host.h
> > @@ -75,22 +75,6 @@
> > #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
> > #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
> >
> > -#define DE_VECTOR 0
> > -#define DB_VECTOR 1
> > -#define BP_VECTOR 3
> > -#define OF_VECTOR 4
> > -#define BR_VECTOR 5
> > -#define UD_VECTOR 6
> > -#define NM_VECTOR 7
> > -#define DF_VECTOR 8
> > -#define TS_VECTOR 10
> > -#define NP_VECTOR 11
> > -#define SS_VECTOR 12
> > -#define GP_VECTOR 13
> > -#define PF_VECTOR 14
> > -#define MF_VECTOR 16
> > -#define MC_VECTOR 18
> > -
> > #define SELECTOR_TI_MASK (1 << 2)
> > #define SELECTOR_RPL_MASK 0x03
> >
> > diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
> > index f2b83bc..cdf5674 100644
> > --- a/arch/x86/include/asm/svm.h
> > +++ b/arch/x86/include/asm/svm.h
> > @@ -1,6 +1,135 @@
> > #ifndef __SVM_H
> > #define __SVM_H
> >
> > +#define SVM_EXIT_READ_CR0 0x000
> > +#define SVM_EXIT_READ_CR3 0x003
> > +#define SVM_EXIT_READ_CR4 0x004
> > +#define SVM_EXIT_READ_CR8 0x008
> > +#define SVM_EXIT_WRITE_CR0 0x010
> > +#define SVM_EXIT_WRITE_CR3 0x013
> > +#define SVM_EXIT_WRITE_CR4 0x014
> > +#define SVM_EXIT_WRITE_CR8 0x018
> > +#define SVM_EXIT_READ_DR0 0x020
> > +#define SVM_EXIT_READ_DR1 0x021
> > +#define SVM_EXIT_READ_DR2 0x022
> > +#define SVM_EXIT_READ_DR3 0x023
> > +#define SVM_EXIT_READ_DR4 0x024
> > +#define SVM_EXIT_READ_DR5 0x025
> > +#define SVM_EXIT_READ_DR6 0x026
> > +#define SVM_EXIT_READ_DR7 0x027
> > +#define SVM_EXIT_WRITE_DR0 0x030
> > +#define SVM_EXIT_WRITE_DR1 0x031
> > +#define SVM_EXIT_WRITE_DR2 0x032
> > +#define SVM_EXIT_WRITE_DR3 0x033
> > +#define SVM_EXIT_WRITE_DR4 0x034
> > +#define SVM_EXIT_WRITE_DR5 0x035
> > +#define SVM_EXIT_WRITE_DR6 0x036
> > +#define SVM_EXIT_WRITE_DR7 0x037
> > +#define SVM_EXIT_EXCP_BASE 0x040
> > +#define SVM_EXIT_INTR 0x060
> > +#define SVM_EXIT_NMI 0x061
> > +#define SVM_EXIT_SMI 0x062
> > +#define SVM_EXIT_INIT 0x063
> > +#define SVM_EXIT_VINTR 0x064
> > +#define SVM_EXIT_CR0_SEL_WRITE 0x065
> > +#define SVM_EXIT_IDTR_READ 0x066
> > +#define SVM_EXIT_GDTR_READ 0x067
> > +#define SVM_EXIT_LDTR_READ 0x068
> > +#define SVM_EXIT_TR_READ 0x069
> > +#define SVM_EXIT_IDTR_WRITE 0x06a
> > +#define SVM_EXIT_GDTR_WRITE 0x06b
> > +#define SVM_EXIT_LDTR_WRITE 0x06c
> > +#define SVM_EXIT_TR_WRITE 0x06d
> > +#define SVM_EXIT_RDTSC 0x06e
> > +#define SVM_EXIT_RDPMC 0x06f
> > +#define SVM_EXIT_PUSHF 0x070
> > +#define SVM_EXIT_POPF 0x071
> > +#define SVM_EXIT_CPUID 0x072
> > +#define SVM_EXIT_RSM 0x073
> > +#define SVM_EXIT_IRET 0x074
> > +#define SVM_EXIT_SWINT 0x075
> > +#define SVM_EXIT_INVD 0x076
> > +#define SVM_EXIT_PAUSE 0x077
> > +#define SVM_EXIT_HLT 0x078
> > +#define SVM_EXIT_INVLPG 0x079
> > +#define SVM_EXIT_INVLPGA 0x07a
> > +#define SVM_EXIT_IOIO 0x07b
> > +#define SVM_EXIT_MSR 0x07c
> > +#define SVM_EXIT_TASK_SWITCH 0x07d
> > +#define SVM_EXIT_FERR_FREEZE 0x07e
> > +#define SVM_EXIT_SHUTDOWN 0x07f
> > +#define SVM_EXIT_VMRUN 0x080
> > +#define SVM_EXIT_VMMCALL 0x081
> > +#define SVM_EXIT_VMLOAD 0x082
> > +#define SVM_EXIT_VMSAVE 0x083
> > +#define SVM_EXIT_STGI 0x084
> > +#define SVM_EXIT_CLGI 0x085
> > +#define SVM_EXIT_SKINIT 0x086
> > +#define SVM_EXIT_RDTSCP 0x087
> > +#define SVM_EXIT_ICEBP 0x088
> > +#define SVM_EXIT_WBINVD 0x089
> > +#define SVM_EXIT_MONITOR 0x08a
> > +#define SVM_EXIT_MWAIT 0x08b
> > +#define SVM_EXIT_MWAIT_COND 0x08c
> > +#define SVM_EXIT_XSETBV 0x08d
> > +#define SVM_EXIT_NPF 0x400
> > +
> > +#define SVM_EXIT_ERR -1
> > +
> > +#define SVM_EXIT_REASONS \
> > + { SVM_EXIT_READ_CR0, "read_cr0" }, \
> > + { SVM_EXIT_READ_CR3, "read_cr3" }, \
> > + { SVM_EXIT_READ_CR4, "read_cr4" }, \
> > + { SVM_EXIT_READ_CR8, "read_cr8" }, \
> > + { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
> > + { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
> > + { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
> > + { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
> > + { SVM_EXIT_READ_DR0, "read_dr0" }, \
> > + { SVM_EXIT_READ_DR1, "read_dr1" }, \
> > + { SVM_EXIT_READ_DR2, "read_dr2" }, \
> > + { SVM_EXIT_READ_DR3, "read_dr3" }, \
> > + { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
> > + { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
> > + { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
> > + { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
> > + { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
> > + { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
> > + { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
> > + { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
> > + { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
> > + { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
> > + { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
> > + { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
> > + { SVM_EXIT_INTR, "interrupt" }, \
> > + { SVM_EXIT_NMI, "nmi" }, \
> > + { SVM_EXIT_SMI, "smi" }, \
> > + { SVM_EXIT_INIT, "init" }, \
> > + { SVM_EXIT_VINTR, "vintr" }, \
> > + { SVM_EXIT_CPUID, "cpuid" }, \
> > + { SVM_EXIT_INVD, "invd" }, \
> > + { SVM_EXIT_HLT, "hlt" }, \
> > + { SVM_EXIT_INVLPG, "invlpg" }, \
> > + { SVM_EXIT_INVLPGA, "invlpga" }, \
> > + { SVM_EXIT_IOIO, "io" }, \
> > + { SVM_EXIT_MSR, "msr" }, \
> > + { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
> > + { SVM_EXIT_SHUTDOWN, "shutdown" }, \
> > + { SVM_EXIT_VMRUN, "vmrun" }, \
> > + { SVM_EXIT_VMMCALL, "hypercall" }, \
> > + { SVM_EXIT_VMLOAD, "vmload" }, \
> > + { SVM_EXIT_VMSAVE, "vmsave" }, \
> > + { SVM_EXIT_STGI, "stgi" }, \
> > + { SVM_EXIT_CLGI, "clgi" }, \
> > + { SVM_EXIT_SKINIT, "skinit" }, \
> > + { SVM_EXIT_WBINVD, "wbinvd" }, \
> > + { SVM_EXIT_MONITOR, "monitor" }, \
> > + { SVM_EXIT_MWAIT, "mwait" }, \
> > + { SVM_EXIT_XSETBV, "xsetbv" }, \
> > + { SVM_EXIT_NPF, "npf" }
> > +
> > +#ifdef __KERNEL__
> > +
> > enum {
> > INTERCEPT_INTR,
> > INTERCEPT_NMI,
> > @@ -264,81 +393,6 @@ struct __attribute__ ((__packed__)) vmcb {
> >
> > #define SVM_EXITINFO_REG_MASK 0x0F
> >
> > -#define SVM_EXIT_READ_CR0 0x000
> > -#define SVM_EXIT_READ_CR3 0x003
> > -#define SVM_EXIT_READ_CR4 0x004
> > -#define SVM_EXIT_READ_CR8 0x008
> > -#define SVM_EXIT_WRITE_CR0 0x010
> > -#define SVM_EXIT_WRITE_CR3 0x013
> > -#define SVM_EXIT_WRITE_CR4 0x014
> > -#define SVM_EXIT_WRITE_CR8 0x018
> > -#define SVM_EXIT_READ_DR0 0x020
> > -#define SVM_EXIT_READ_DR1 0x021
> > -#define SVM_EXIT_READ_DR2 0x022
> > -#define SVM_EXIT_READ_DR3 0x023
> > -#define SVM_EXIT_READ_DR4 0x024
> > -#define SVM_EXIT_READ_DR5 0x025
> > -#define SVM_EXIT_READ_DR6 0x026
> > -#define SVM_EXIT_READ_DR7 0x027
> > -#define SVM_EXIT_WRITE_DR0 0x030
> > -#define SVM_EXIT_WRITE_DR1 0x031
> > -#define SVM_EXIT_WRITE_DR2 0x032
> > -#define SVM_EXIT_WRITE_DR3 0x033
> > -#define SVM_EXIT_WRITE_DR4 0x034
> > -#define SVM_EXIT_WRITE_DR5 0x035
> > -#define SVM_EXIT_WRITE_DR6 0x036
> > -#define SVM_EXIT_WRITE_DR7 0x037
> > -#define SVM_EXIT_EXCP_BASE 0x040
> > -#define SVM_EXIT_INTR 0x060
> > -#define SVM_EXIT_NMI 0x061
> > -#define SVM_EXIT_SMI 0x062
> > -#define SVM_EXIT_INIT 0x063
> > -#define SVM_EXIT_VINTR 0x064
> > -#define SVM_EXIT_CR0_SEL_WRITE 0x065
> > -#define SVM_EXIT_IDTR_READ 0x066
> > -#define SVM_EXIT_GDTR_READ 0x067
> > -#define SVM_EXIT_LDTR_READ 0x068
> > -#define SVM_EXIT_TR_READ 0x069
> > -#define SVM_EXIT_IDTR_WRITE 0x06a
> > -#define SVM_EXIT_GDTR_WRITE 0x06b
> > -#define SVM_EXIT_LDTR_WRITE 0x06c
> > -#define SVM_EXIT_TR_WRITE 0x06d
> > -#define SVM_EXIT_RDTSC 0x06e
> > -#define SVM_EXIT_RDPMC 0x06f
> > -#define SVM_EXIT_PUSHF 0x070
> > -#define SVM_EXIT_POPF 0x071
> > -#define SVM_EXIT_CPUID 0x072
> > -#define SVM_EXIT_RSM 0x073
> > -#define SVM_EXIT_IRET 0x074
> > -#define SVM_EXIT_SWINT 0x075
> > -#define SVM_EXIT_INVD 0x076
> > -#define SVM_EXIT_PAUSE 0x077
> > -#define SVM_EXIT_HLT 0x078
> > -#define SVM_EXIT_INVLPG 0x079
> > -#define SVM_EXIT_INVLPGA 0x07a
> > -#define SVM_EXIT_IOIO 0x07b
> > -#define SVM_EXIT_MSR 0x07c
> > -#define SVM_EXIT_TASK_SWITCH 0x07d
> > -#define SVM_EXIT_FERR_FREEZE 0x07e
> > -#define SVM_EXIT_SHUTDOWN 0x07f
> > -#define SVM_EXIT_VMRUN 0x080
> > -#define SVM_EXIT_VMMCALL 0x081
> > -#define SVM_EXIT_VMLOAD 0x082
> > -#define SVM_EXIT_VMSAVE 0x083
> > -#define SVM_EXIT_STGI 0x084
> > -#define SVM_EXIT_CLGI 0x085
> > -#define SVM_EXIT_SKINIT 0x086
> > -#define SVM_EXIT_RDTSCP 0x087
> > -#define SVM_EXIT_ICEBP 0x088
> > -#define SVM_EXIT_WBINVD 0x089
> > -#define SVM_EXIT_MONITOR 0x08a
> > -#define SVM_EXIT_MWAIT 0x08b
> > -#define SVM_EXIT_MWAIT_COND 0x08c
> > -#define SVM_EXIT_XSETBV 0x08d
> > -#define SVM_EXIT_NPF 0x400
> > -
> > -#define SVM_EXIT_ERR -1
> > -
> > #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
> >
> > #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
> > @@ -350,3 +404,4 @@ struct __attribute__ ((__packed__)) vmcb {
> >
> > #endif
> >
> > +#endif
> > diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
> > index 74fcb96..36ec21c 100644
> > --- a/arch/x86/include/asm/vmx.h
> > +++ b/arch/x86/include/asm/vmx.h
> > @@ -25,6 +25,88 @@
> > *
> > */
> >
> > +#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
> > +
> > +#define EXIT_REASON_EXCEPTION_NMI 0
> > +#define EXIT_REASON_EXTERNAL_INTERRUPT 1
> > +#define EXIT_REASON_TRIPLE_FAULT 2
> > +
> > +#define EXIT_REASON_PENDING_INTERRUPT 7
> > +#define EXIT_REASON_NMI_WINDOW 8
> > +#define EXIT_REASON_TASK_SWITCH 9
> > +#define EXIT_REASON_CPUID 10
> > +#define EXIT_REASON_HLT 12
> > +#define EXIT_REASON_INVD 13
> > +#define EXIT_REASON_INVLPG 14
> > +#define EXIT_REASON_RDPMC 15
> > +#define EXIT_REASON_RDTSC 16
> > +#define EXIT_REASON_VMCALL 18
> > +#define EXIT_REASON_VMCLEAR 19
> > +#define EXIT_REASON_VMLAUNCH 20
> > +#define EXIT_REASON_VMPTRLD 21
> > +#define EXIT_REASON_VMPTRST 22
> > +#define EXIT_REASON_VMREAD 23
> > +#define EXIT_REASON_VMRESUME 24
> > +#define EXIT_REASON_VMWRITE 25
> > +#define EXIT_REASON_VMOFF 26
> > +#define EXIT_REASON_VMON 27
> > +#define EXIT_REASON_CR_ACCESS 28
> > +#define EXIT_REASON_DR_ACCESS 29
> > +#define EXIT_REASON_IO_INSTRUCTION 30
> > +#define EXIT_REASON_MSR_READ 31
> > +#define EXIT_REASON_MSR_WRITE 32
> > +#define EXIT_REASON_INVALID_STATE 33
> > +#define EXIT_REASON_MWAIT_INSTRUCTION 36
> > +#define EXIT_REASON_MONITOR_INSTRUCTION 39
> > +#define EXIT_REASON_PAUSE_INSTRUCTION 40
> > +#define EXIT_REASON_MCE_DURING_VMENTRY 41
> > +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
> > +#define EXIT_REASON_APIC_ACCESS 44
> > +#define EXIT_REASON_EPT_VIOLATION 48
> > +#define EXIT_REASON_EPT_MISCONFIG 49
> > +#define EXIT_REASON_WBINVD 54
> > +#define EXIT_REASON_XSETBV 55
> > +#define EXIT_REASON_INVPCID 58
> > +
> > +#define VMX_EXIT_REASONS \
> > + { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
> > + { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
> > + { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
> > + { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
> > + { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
> > + { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
> > + { EXIT_REASON_CPUID, "CPUID" }, \
> > + { EXIT_REASON_HLT, "HLT" }, \
> > + { EXIT_REASON_INVLPG, "INVLPG" }, \
> > + { EXIT_REASON_RDPMC, "RDPMC" }, \
> > + { EXIT_REASON_RDTSC, "RDTSC" }, \
> > + { EXIT_REASON_VMCALL, "VMCALL" }, \
> > + { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
> > + { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
> > + { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
> > + { EXIT_REASON_VMPTRST, "VMPTRST" }, \
> > + { EXIT_REASON_VMREAD, "VMREAD" }, \
> > + { EXIT_REASON_VMRESUME, "VMRESUME" }, \
> > + { EXIT_REASON_VMWRITE, "VMWRITE" }, \
> > + { EXIT_REASON_VMOFF, "VMOFF" }, \
> > + { EXIT_REASON_VMON, "VMON" }, \
> > + { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
> > + { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
> > + { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
> > + { EXIT_REASON_MSR_READ, "MSR_READ" }, \
> > + { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
> > + { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
> > + { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
> > + { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
> > + { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
> > + { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
> > + { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
> > + { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
> > + { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
> > + { EXIT_REASON_WBINVD, "WBINVD" }
> > +
> > +#ifdef __KERNEL__
> > +
> > #include <linux/types.h>
> >
> > /*
> > @@ -241,49 +323,6 @@ enum vmcs_field {
> > HOST_RIP = 0x00006c16,
> > };
> >
> > -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
> > -
> > -#define EXIT_REASON_EXCEPTION_NMI 0
> > -#define EXIT_REASON_EXTERNAL_INTERRUPT 1
> > -#define EXIT_REASON_TRIPLE_FAULT 2
> > -
> > -#define EXIT_REASON_PENDING_INTERRUPT 7
> > -#define EXIT_REASON_NMI_WINDOW 8
> > -#define EXIT_REASON_TASK_SWITCH 9
> > -#define EXIT_REASON_CPUID 10
> > -#define EXIT_REASON_HLT 12
> > -#define EXIT_REASON_INVD 13
> > -#define EXIT_REASON_INVLPG 14
> > -#define EXIT_REASON_RDPMC 15
> > -#define EXIT_REASON_RDTSC 16
> > -#define EXIT_REASON_VMCALL 18
> > -#define EXIT_REASON_VMCLEAR 19
> > -#define EXIT_REASON_VMLAUNCH 20
> > -#define EXIT_REASON_VMPTRLD 21
> > -#define EXIT_REASON_VMPTRST 22
> > -#define EXIT_REASON_VMREAD 23
> > -#define EXIT_REASON_VMRESUME 24
> > -#define EXIT_REASON_VMWRITE 25
> > -#define EXIT_REASON_VMOFF 26
> > -#define EXIT_REASON_VMON 27
> > -#define EXIT_REASON_CR_ACCESS 28
> > -#define EXIT_REASON_DR_ACCESS 29
> > -#define EXIT_REASON_IO_INSTRUCTION 30
> > -#define EXIT_REASON_MSR_READ 31
> > -#define EXIT_REASON_MSR_WRITE 32
> > -#define EXIT_REASON_INVALID_STATE 33
> > -#define EXIT_REASON_MWAIT_INSTRUCTION 36
> > -#define EXIT_REASON_MONITOR_INSTRUCTION 39
> > -#define EXIT_REASON_PAUSE_INSTRUCTION 40
> > -#define EXIT_REASON_MCE_DURING_VMENTRY 41
> > -#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
> > -#define EXIT_REASON_APIC_ACCESS 44
> > -#define EXIT_REASON_EPT_VIOLATION 48
> > -#define EXIT_REASON_EPT_MISCONFIG 49
> > -#define EXIT_REASON_WBINVD 54
> > -#define EXIT_REASON_XSETBV 55
> > -#define EXIT_REASON_INVPCID 58
> > -
> > /*
> > * Interruption-information format
> > */
> > @@ -488,3 +527,5 @@ enum vm_instruction_error_number {
> > };
> >
> > #endif
> > +
> > +#endif
> > diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
> > index a71faf7..bca63f0 100644
> > --- a/arch/x86/kvm/trace.h
> > +++ b/arch/x86/kvm/trace.h
> > @@ -183,95 +183,6 @@ TRACE_EVENT(kvm_apic,
> > #define KVM_ISA_VMX 1
> > #define KVM_ISA_SVM 2
> >
> > -#define VMX_EXIT_REASONS \
> > - { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
> > - { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
> > - { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
> > - { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
> > - { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
> > - { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
> > - { EXIT_REASON_CPUID, "CPUID" }, \
> > - { EXIT_REASON_HLT, "HLT" }, \
> > - { EXIT_REASON_INVLPG, "INVLPG" }, \
> > - { EXIT_REASON_RDPMC, "RDPMC" }, \
> > - { EXIT_REASON_RDTSC, "RDTSC" }, \
> > - { EXIT_REASON_VMCALL, "VMCALL" }, \
> > - { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
> > - { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
> > - { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
> > - { EXIT_REASON_VMPTRST, "VMPTRST" }, \
> > - { EXIT_REASON_VMREAD, "VMREAD" }, \
> > - { EXIT_REASON_VMRESUME, "VMRESUME" }, \
> > - { EXIT_REASON_VMWRITE, "VMWRITE" }, \
> > - { EXIT_REASON_VMOFF, "VMOFF" }, \
> > - { EXIT_REASON_VMON, "VMON" }, \
> > - { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
> > - { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
> > - { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
> > - { EXIT_REASON_MSR_READ, "MSR_READ" }, \
> > - { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
> > - { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
> > - { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
> > - { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
> > - { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
> > - { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
> > - { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
> > - { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
> > - { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
> > - { EXIT_REASON_WBINVD, "WBINVD" }
> > -
> > -#define SVM_EXIT_REASONS \
> > - { SVM_EXIT_READ_CR0, "read_cr0" }, \
> > - { SVM_EXIT_READ_CR3, "read_cr3" }, \
> > - { SVM_EXIT_READ_CR4, "read_cr4" }, \
> > - { SVM_EXIT_READ_CR8, "read_cr8" }, \
> > - { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
> > - { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
> > - { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
> > - { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
> > - { SVM_EXIT_READ_DR0, "read_dr0" }, \
> > - { SVM_EXIT_READ_DR1, "read_dr1" }, \
> > - { SVM_EXIT_READ_DR2, "read_dr2" }, \
> > - { SVM_EXIT_READ_DR3, "read_dr3" }, \
> > - { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
> > - { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
> > - { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
> > - { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
> > - { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
> > - { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
> > - { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
> > - { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
> > - { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
> > - { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
> > - { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
> > - { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
> > - { SVM_EXIT_INTR, "interrupt" }, \
> > - { SVM_EXIT_NMI, "nmi" }, \
> > - { SVM_EXIT_SMI, "smi" }, \
> > - { SVM_EXIT_INIT, "init" }, \
> > - { SVM_EXIT_VINTR, "vintr" }, \
> > - { SVM_EXIT_CPUID, "cpuid" }, \
> > - { SVM_EXIT_INVD, "invd" }, \
> > - { SVM_EXIT_HLT, "hlt" }, \
> > - { SVM_EXIT_INVLPG, "invlpg" }, \
> > - { SVM_EXIT_INVLPGA, "invlpga" }, \
> > - { SVM_EXIT_IOIO, "io" }, \
> > - { SVM_EXIT_MSR, "msr" }, \
> > - { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
> > - { SVM_EXIT_SHUTDOWN, "shutdown" }, \
> > - { SVM_EXIT_VMRUN, "vmrun" }, \
> > - { SVM_EXIT_VMMCALL, "hypercall" }, \
> > - { SVM_EXIT_VMLOAD, "vmload" }, \
> > - { SVM_EXIT_VMSAVE, "vmsave" }, \
> > - { SVM_EXIT_STGI, "stgi" }, \
> > - { SVM_EXIT_CLGI, "clgi" }, \
> > - { SVM_EXIT_SKINIT, "skinit" }, \
> > - { SVM_EXIT_WBINVD, "wbinvd" }, \
> > - { SVM_EXIT_MONITOR, "monitor" }, \
> > - { SVM_EXIT_MWAIT, "mwait" }, \
> > - { SVM_EXIT_XSETBV, "xsetbv" }, \
> > - { SVM_EXIT_NPF, "npf" }
> > -
> > /*
> > * Tracepoint for kvm guest exit:
> > */
> > --
> > 1.7.2.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v8 3/3] KVM: perf: kvm events analysis tool
2012-09-17 8:31 ` [PATCH v8 3/3] KVM: perf: kvm events analysis tool Dong Hao
@ 2012-09-20 13:34 ` David Ahern
2012-09-27 4:27 ` [tip:perf/core] perf kvm: Events " tip-bot for Xiao Guangrong
1 sibling, 0 replies; 14+ messages in thread
From: David Ahern @ 2012-09-20 13:34 UTC (permalink / raw)
To: Dong Hao, acme
Cc: mtosatti, avi, mingo, linux-kernel, kvm, xiaoguangrong, runzhen
On 9/17/12 2:31 AM, Dong Hao wrote:
> From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
> 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:
> # pgrep qemu
> 13005
> 13059
>
> total 2 guests are running on the host
>
> Then, track the guest whose pid is 13059:
> # ./perf kvm stat record -p 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:
> # ./perf kvm stat report --event=vmexit
>
>
> 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:
> # ./perf kvm stat report --event=mmio
>
>
> 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:
> # ./perf kvm stat report --event=ioport
>
>
> 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:
> # ./perf kvm stat report --event=vmexit --vcpu=0 --key=time
>
>
> 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.
>
> [ 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>
> Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
> Signed-off-by: Runzhen Wang <runzhen@linux.vnet.ibm.com>
> ---
> tools/perf/Documentation/perf-kvm.txt | 30 ++-
> tools/perf/MANIFEST | 3 +
> tools/perf/builtin-kvm.c | 840 ++++++++++++++++++++++++++++++++-
> tools/perf/util/header.c | 59 +++-
> tools/perf/util/header.h | 1 +
> tools/perf/util/thread.h | 2 +
> 6 files changed, 929 insertions(+), 6 deletions(-)
>
Acked-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [tip:perf/core] KVM: x86: Export svm/ vmx exit code and vector code to userspace
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
2012-09-17 14:58 ` Arnaldo Carvalho de Melo
@ 2012-09-27 4:26 ` tip-bot for Xiao Guangrong
1 sibling, 0 replies; 14+ messages in thread
From: tip-bot for Xiao Guangrong @ 2012-09-27 4:26 UTC (permalink / raw)
To: linux-tip-commits
Cc: acme, linux-kernel, hpa, mingo, runzhen, xiaoguangrong, haodong,
mtosatti, dsahern, tglx, avi
Commit-ID: 26bf264e871a4b9a8ac09c21a2b518e7f23830d5
Gitweb: http://git.kernel.org/tip/26bf264e871a4b9a8ac09c21a2b518e7f23830d5
Author: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
AuthorDate: Mon, 17 Sep 2012 16:31:13 +0800
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 21 Sep 2012 12:48:09 -0300
KVM: x86: Export svm/vmx exit code and vector code to userspace
Exporting KVM exit information to userspace to be consumed by perf.
Signed-off-by: Dong Hao <haodong@linux.vnet.ibm.com>
[ Dong Hao <haodong@linux.vnet.ibm.com>: rebase it on acme's git tree ]
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Acked-by: Marcelo Tosatti <mtosatti@redhat.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-2-git-send-email-haodong@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
arch/x86/include/asm/kvm.h | 16 +++
arch/x86/include/asm/kvm_host.h | 16 ---
arch/x86/include/asm/svm.h | 205 +++++++++++++++++++++++++--------------
arch/x86/include/asm/vmx.h | 127 ++++++++++++++++--------
arch/x86/kvm/trace.h | 89 -----------------
5 files changed, 230 insertions(+), 223 deletions(-)
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index 246617e..41e08cb 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -9,6 +9,22 @@
#include <linux/types.h>
#include <linux/ioctl.h>
+#define DE_VECTOR 0
+#define DB_VECTOR 1
+#define BP_VECTOR 3
+#define OF_VECTOR 4
+#define BR_VECTOR 5
+#define UD_VECTOR 6
+#define NM_VECTOR 7
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+#define MF_VECTOR 16
+#define MC_VECTOR 18
+
/* Select x86 specific features in <linux/kvm.h> */
#define __KVM_HAVE_PIT
#define __KVM_HAVE_IOAPIC
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 09155d6..1eaa6b0 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -75,22 +75,6 @@
#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
-#define DE_VECTOR 0
-#define DB_VECTOR 1
-#define BP_VECTOR 3
-#define OF_VECTOR 4
-#define BR_VECTOR 5
-#define UD_VECTOR 6
-#define NM_VECTOR 7
-#define DF_VECTOR 8
-#define TS_VECTOR 10
-#define NP_VECTOR 11
-#define SS_VECTOR 12
-#define GP_VECTOR 13
-#define PF_VECTOR 14
-#define MF_VECTOR 16
-#define MC_VECTOR 18
-
#define SELECTOR_TI_MASK (1 << 2)
#define SELECTOR_RPL_MASK 0x03
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index f2b83bc..cdf5674 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -1,6 +1,135 @@
#ifndef __SVM_H
#define __SVM_H
+#define SVM_EXIT_READ_CR0 0x000
+#define SVM_EXIT_READ_CR3 0x003
+#define SVM_EXIT_READ_CR4 0x004
+#define SVM_EXIT_READ_CR8 0x008
+#define SVM_EXIT_WRITE_CR0 0x010
+#define SVM_EXIT_WRITE_CR3 0x013
+#define SVM_EXIT_WRITE_CR4 0x014
+#define SVM_EXIT_WRITE_CR8 0x018
+#define SVM_EXIT_READ_DR0 0x020
+#define SVM_EXIT_READ_DR1 0x021
+#define SVM_EXIT_READ_DR2 0x022
+#define SVM_EXIT_READ_DR3 0x023
+#define SVM_EXIT_READ_DR4 0x024
+#define SVM_EXIT_READ_DR5 0x025
+#define SVM_EXIT_READ_DR6 0x026
+#define SVM_EXIT_READ_DR7 0x027
+#define SVM_EXIT_WRITE_DR0 0x030
+#define SVM_EXIT_WRITE_DR1 0x031
+#define SVM_EXIT_WRITE_DR2 0x032
+#define SVM_EXIT_WRITE_DR3 0x033
+#define SVM_EXIT_WRITE_DR4 0x034
+#define SVM_EXIT_WRITE_DR5 0x035
+#define SVM_EXIT_WRITE_DR6 0x036
+#define SVM_EXIT_WRITE_DR7 0x037
+#define SVM_EXIT_EXCP_BASE 0x040
+#define SVM_EXIT_INTR 0x060
+#define SVM_EXIT_NMI 0x061
+#define SVM_EXIT_SMI 0x062
+#define SVM_EXIT_INIT 0x063
+#define SVM_EXIT_VINTR 0x064
+#define SVM_EXIT_CR0_SEL_WRITE 0x065
+#define SVM_EXIT_IDTR_READ 0x066
+#define SVM_EXIT_GDTR_READ 0x067
+#define SVM_EXIT_LDTR_READ 0x068
+#define SVM_EXIT_TR_READ 0x069
+#define SVM_EXIT_IDTR_WRITE 0x06a
+#define SVM_EXIT_GDTR_WRITE 0x06b
+#define SVM_EXIT_LDTR_WRITE 0x06c
+#define SVM_EXIT_TR_WRITE 0x06d
+#define SVM_EXIT_RDTSC 0x06e
+#define SVM_EXIT_RDPMC 0x06f
+#define SVM_EXIT_PUSHF 0x070
+#define SVM_EXIT_POPF 0x071
+#define SVM_EXIT_CPUID 0x072
+#define SVM_EXIT_RSM 0x073
+#define SVM_EXIT_IRET 0x074
+#define SVM_EXIT_SWINT 0x075
+#define SVM_EXIT_INVD 0x076
+#define SVM_EXIT_PAUSE 0x077
+#define SVM_EXIT_HLT 0x078
+#define SVM_EXIT_INVLPG 0x079
+#define SVM_EXIT_INVLPGA 0x07a
+#define SVM_EXIT_IOIO 0x07b
+#define SVM_EXIT_MSR 0x07c
+#define SVM_EXIT_TASK_SWITCH 0x07d
+#define SVM_EXIT_FERR_FREEZE 0x07e
+#define SVM_EXIT_SHUTDOWN 0x07f
+#define SVM_EXIT_VMRUN 0x080
+#define SVM_EXIT_VMMCALL 0x081
+#define SVM_EXIT_VMLOAD 0x082
+#define SVM_EXIT_VMSAVE 0x083
+#define SVM_EXIT_STGI 0x084
+#define SVM_EXIT_CLGI 0x085
+#define SVM_EXIT_SKINIT 0x086
+#define SVM_EXIT_RDTSCP 0x087
+#define SVM_EXIT_ICEBP 0x088
+#define SVM_EXIT_WBINVD 0x089
+#define SVM_EXIT_MONITOR 0x08a
+#define SVM_EXIT_MWAIT 0x08b
+#define SVM_EXIT_MWAIT_COND 0x08c
+#define SVM_EXIT_XSETBV 0x08d
+#define SVM_EXIT_NPF 0x400
+
+#define SVM_EXIT_ERR -1
+
+#define SVM_EXIT_REASONS \
+ { SVM_EXIT_READ_CR0, "read_cr0" }, \
+ { SVM_EXIT_READ_CR3, "read_cr3" }, \
+ { SVM_EXIT_READ_CR4, "read_cr4" }, \
+ { SVM_EXIT_READ_CR8, "read_cr8" }, \
+ { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
+ { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
+ { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
+ { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
+ { SVM_EXIT_READ_DR0, "read_dr0" }, \
+ { SVM_EXIT_READ_DR1, "read_dr1" }, \
+ { SVM_EXIT_READ_DR2, "read_dr2" }, \
+ { SVM_EXIT_READ_DR3, "read_dr3" }, \
+ { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
+ { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
+ { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
+ { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
+ { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
+ { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
+ { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
+ { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
+ { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
+ { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
+ { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
+ { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
+ { SVM_EXIT_INTR, "interrupt" }, \
+ { SVM_EXIT_NMI, "nmi" }, \
+ { SVM_EXIT_SMI, "smi" }, \
+ { SVM_EXIT_INIT, "init" }, \
+ { SVM_EXIT_VINTR, "vintr" }, \
+ { SVM_EXIT_CPUID, "cpuid" }, \
+ { SVM_EXIT_INVD, "invd" }, \
+ { SVM_EXIT_HLT, "hlt" }, \
+ { SVM_EXIT_INVLPG, "invlpg" }, \
+ { SVM_EXIT_INVLPGA, "invlpga" }, \
+ { SVM_EXIT_IOIO, "io" }, \
+ { SVM_EXIT_MSR, "msr" }, \
+ { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
+ { SVM_EXIT_SHUTDOWN, "shutdown" }, \
+ { SVM_EXIT_VMRUN, "vmrun" }, \
+ { SVM_EXIT_VMMCALL, "hypercall" }, \
+ { SVM_EXIT_VMLOAD, "vmload" }, \
+ { SVM_EXIT_VMSAVE, "vmsave" }, \
+ { SVM_EXIT_STGI, "stgi" }, \
+ { SVM_EXIT_CLGI, "clgi" }, \
+ { SVM_EXIT_SKINIT, "skinit" }, \
+ { SVM_EXIT_WBINVD, "wbinvd" }, \
+ { SVM_EXIT_MONITOR, "monitor" }, \
+ { SVM_EXIT_MWAIT, "mwait" }, \
+ { SVM_EXIT_XSETBV, "xsetbv" }, \
+ { SVM_EXIT_NPF, "npf" }
+
+#ifdef __KERNEL__
+
enum {
INTERCEPT_INTR,
INTERCEPT_NMI,
@@ -264,81 +393,6 @@ struct __attribute__ ((__packed__)) vmcb {
#define SVM_EXITINFO_REG_MASK 0x0F
-#define SVM_EXIT_READ_CR0 0x000
-#define SVM_EXIT_READ_CR3 0x003
-#define SVM_EXIT_READ_CR4 0x004
-#define SVM_EXIT_READ_CR8 0x008
-#define SVM_EXIT_WRITE_CR0 0x010
-#define SVM_EXIT_WRITE_CR3 0x013
-#define SVM_EXIT_WRITE_CR4 0x014
-#define SVM_EXIT_WRITE_CR8 0x018
-#define SVM_EXIT_READ_DR0 0x020
-#define SVM_EXIT_READ_DR1 0x021
-#define SVM_EXIT_READ_DR2 0x022
-#define SVM_EXIT_READ_DR3 0x023
-#define SVM_EXIT_READ_DR4 0x024
-#define SVM_EXIT_READ_DR5 0x025
-#define SVM_EXIT_READ_DR6 0x026
-#define SVM_EXIT_READ_DR7 0x027
-#define SVM_EXIT_WRITE_DR0 0x030
-#define SVM_EXIT_WRITE_DR1 0x031
-#define SVM_EXIT_WRITE_DR2 0x032
-#define SVM_EXIT_WRITE_DR3 0x033
-#define SVM_EXIT_WRITE_DR4 0x034
-#define SVM_EXIT_WRITE_DR5 0x035
-#define SVM_EXIT_WRITE_DR6 0x036
-#define SVM_EXIT_WRITE_DR7 0x037
-#define SVM_EXIT_EXCP_BASE 0x040
-#define SVM_EXIT_INTR 0x060
-#define SVM_EXIT_NMI 0x061
-#define SVM_EXIT_SMI 0x062
-#define SVM_EXIT_INIT 0x063
-#define SVM_EXIT_VINTR 0x064
-#define SVM_EXIT_CR0_SEL_WRITE 0x065
-#define SVM_EXIT_IDTR_READ 0x066
-#define SVM_EXIT_GDTR_READ 0x067
-#define SVM_EXIT_LDTR_READ 0x068
-#define SVM_EXIT_TR_READ 0x069
-#define SVM_EXIT_IDTR_WRITE 0x06a
-#define SVM_EXIT_GDTR_WRITE 0x06b
-#define SVM_EXIT_LDTR_WRITE 0x06c
-#define SVM_EXIT_TR_WRITE 0x06d
-#define SVM_EXIT_RDTSC 0x06e
-#define SVM_EXIT_RDPMC 0x06f
-#define SVM_EXIT_PUSHF 0x070
-#define SVM_EXIT_POPF 0x071
-#define SVM_EXIT_CPUID 0x072
-#define SVM_EXIT_RSM 0x073
-#define SVM_EXIT_IRET 0x074
-#define SVM_EXIT_SWINT 0x075
-#define SVM_EXIT_INVD 0x076
-#define SVM_EXIT_PAUSE 0x077
-#define SVM_EXIT_HLT 0x078
-#define SVM_EXIT_INVLPG 0x079
-#define SVM_EXIT_INVLPGA 0x07a
-#define SVM_EXIT_IOIO 0x07b
-#define SVM_EXIT_MSR 0x07c
-#define SVM_EXIT_TASK_SWITCH 0x07d
-#define SVM_EXIT_FERR_FREEZE 0x07e
-#define SVM_EXIT_SHUTDOWN 0x07f
-#define SVM_EXIT_VMRUN 0x080
-#define SVM_EXIT_VMMCALL 0x081
-#define SVM_EXIT_VMLOAD 0x082
-#define SVM_EXIT_VMSAVE 0x083
-#define SVM_EXIT_STGI 0x084
-#define SVM_EXIT_CLGI 0x085
-#define SVM_EXIT_SKINIT 0x086
-#define SVM_EXIT_RDTSCP 0x087
-#define SVM_EXIT_ICEBP 0x088
-#define SVM_EXIT_WBINVD 0x089
-#define SVM_EXIT_MONITOR 0x08a
-#define SVM_EXIT_MWAIT 0x08b
-#define SVM_EXIT_MWAIT_COND 0x08c
-#define SVM_EXIT_XSETBV 0x08d
-#define SVM_EXIT_NPF 0x400
-
-#define SVM_EXIT_ERR -1
-
#define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
@@ -350,3 +404,4 @@ struct __attribute__ ((__packed__)) vmcb {
#endif
+#endif
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 74fcb96..36ec21c 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -25,6 +25,88 @@
*
*/
+#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
+
+#define EXIT_REASON_EXCEPTION_NMI 0
+#define EXIT_REASON_EXTERNAL_INTERRUPT 1
+#define EXIT_REASON_TRIPLE_FAULT 2
+
+#define EXIT_REASON_PENDING_INTERRUPT 7
+#define EXIT_REASON_NMI_WINDOW 8
+#define EXIT_REASON_TASK_SWITCH 9
+#define EXIT_REASON_CPUID 10
+#define EXIT_REASON_HLT 12
+#define EXIT_REASON_INVD 13
+#define EXIT_REASON_INVLPG 14
+#define EXIT_REASON_RDPMC 15
+#define EXIT_REASON_RDTSC 16
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_VMCLEAR 19
+#define EXIT_REASON_VMLAUNCH 20
+#define EXIT_REASON_VMPTRLD 21
+#define EXIT_REASON_VMPTRST 22
+#define EXIT_REASON_VMREAD 23
+#define EXIT_REASON_VMRESUME 24
+#define EXIT_REASON_VMWRITE 25
+#define EXIT_REASON_VMOFF 26
+#define EXIT_REASON_VMON 27
+#define EXIT_REASON_CR_ACCESS 28
+#define EXIT_REASON_DR_ACCESS 29
+#define EXIT_REASON_IO_INSTRUCTION 30
+#define EXIT_REASON_MSR_READ 31
+#define EXIT_REASON_MSR_WRITE 32
+#define EXIT_REASON_INVALID_STATE 33
+#define EXIT_REASON_MWAIT_INSTRUCTION 36
+#define EXIT_REASON_MONITOR_INSTRUCTION 39
+#define EXIT_REASON_PAUSE_INSTRUCTION 40
+#define EXIT_REASON_MCE_DURING_VMENTRY 41
+#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
+#define EXIT_REASON_APIC_ACCESS 44
+#define EXIT_REASON_EPT_VIOLATION 48
+#define EXIT_REASON_EPT_MISCONFIG 49
+#define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
+#define EXIT_REASON_INVPCID 58
+
+#define VMX_EXIT_REASONS \
+ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
+ { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
+ { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
+ { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
+ { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
+ { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
+ { EXIT_REASON_CPUID, "CPUID" }, \
+ { EXIT_REASON_HLT, "HLT" }, \
+ { EXIT_REASON_INVLPG, "INVLPG" }, \
+ { EXIT_REASON_RDPMC, "RDPMC" }, \
+ { EXIT_REASON_RDTSC, "RDTSC" }, \
+ { EXIT_REASON_VMCALL, "VMCALL" }, \
+ { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
+ { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
+ { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
+ { EXIT_REASON_VMPTRST, "VMPTRST" }, \
+ { EXIT_REASON_VMREAD, "VMREAD" }, \
+ { EXIT_REASON_VMRESUME, "VMRESUME" }, \
+ { EXIT_REASON_VMWRITE, "VMWRITE" }, \
+ { EXIT_REASON_VMOFF, "VMOFF" }, \
+ { EXIT_REASON_VMON, "VMON" }, \
+ { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
+ { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
+ { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
+ { EXIT_REASON_MSR_READ, "MSR_READ" }, \
+ { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
+ { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
+ { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
+ { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
+ { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
+ { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
+ { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
+ { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
+ { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
+ { EXIT_REASON_WBINVD, "WBINVD" }
+
+#ifdef __KERNEL__
+
#include <linux/types.h>
/*
@@ -241,49 +323,6 @@ enum vmcs_field {
HOST_RIP = 0x00006c16,
};
-#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
-
-#define EXIT_REASON_EXCEPTION_NMI 0
-#define EXIT_REASON_EXTERNAL_INTERRUPT 1
-#define EXIT_REASON_TRIPLE_FAULT 2
-
-#define EXIT_REASON_PENDING_INTERRUPT 7
-#define EXIT_REASON_NMI_WINDOW 8
-#define EXIT_REASON_TASK_SWITCH 9
-#define EXIT_REASON_CPUID 10
-#define EXIT_REASON_HLT 12
-#define EXIT_REASON_INVD 13
-#define EXIT_REASON_INVLPG 14
-#define EXIT_REASON_RDPMC 15
-#define EXIT_REASON_RDTSC 16
-#define EXIT_REASON_VMCALL 18
-#define EXIT_REASON_VMCLEAR 19
-#define EXIT_REASON_VMLAUNCH 20
-#define EXIT_REASON_VMPTRLD 21
-#define EXIT_REASON_VMPTRST 22
-#define EXIT_REASON_VMREAD 23
-#define EXIT_REASON_VMRESUME 24
-#define EXIT_REASON_VMWRITE 25
-#define EXIT_REASON_VMOFF 26
-#define EXIT_REASON_VMON 27
-#define EXIT_REASON_CR_ACCESS 28
-#define EXIT_REASON_DR_ACCESS 29
-#define EXIT_REASON_IO_INSTRUCTION 30
-#define EXIT_REASON_MSR_READ 31
-#define EXIT_REASON_MSR_WRITE 32
-#define EXIT_REASON_INVALID_STATE 33
-#define EXIT_REASON_MWAIT_INSTRUCTION 36
-#define EXIT_REASON_MONITOR_INSTRUCTION 39
-#define EXIT_REASON_PAUSE_INSTRUCTION 40
-#define EXIT_REASON_MCE_DURING_VMENTRY 41
-#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
-#define EXIT_REASON_APIC_ACCESS 44
-#define EXIT_REASON_EPT_VIOLATION 48
-#define EXIT_REASON_EPT_MISCONFIG 49
-#define EXIT_REASON_WBINVD 54
-#define EXIT_REASON_XSETBV 55
-#define EXIT_REASON_INVPCID 58
-
/*
* Interruption-information format
*/
@@ -488,3 +527,5 @@ enum vm_instruction_error_number {
};
#endif
+
+#endif
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index a71faf7..bca63f0 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -183,95 +183,6 @@ TRACE_EVENT(kvm_apic,
#define KVM_ISA_VMX 1
#define KVM_ISA_SVM 2
-#define VMX_EXIT_REASONS \
- { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
- { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
- { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
- { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
- { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
- { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
- { EXIT_REASON_CPUID, "CPUID" }, \
- { EXIT_REASON_HLT, "HLT" }, \
- { EXIT_REASON_INVLPG, "INVLPG" }, \
- { EXIT_REASON_RDPMC, "RDPMC" }, \
- { EXIT_REASON_RDTSC, "RDTSC" }, \
- { EXIT_REASON_VMCALL, "VMCALL" }, \
- { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
- { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
- { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
- { EXIT_REASON_VMPTRST, "VMPTRST" }, \
- { EXIT_REASON_VMREAD, "VMREAD" }, \
- { EXIT_REASON_VMRESUME, "VMRESUME" }, \
- { EXIT_REASON_VMWRITE, "VMWRITE" }, \
- { EXIT_REASON_VMOFF, "VMOFF" }, \
- { EXIT_REASON_VMON, "VMON" }, \
- { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
- { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
- { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
- { EXIT_REASON_MSR_READ, "MSR_READ" }, \
- { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
- { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
- { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
- { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
- { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
- { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
- { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
- { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
- { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
- { EXIT_REASON_WBINVD, "WBINVD" }
-
-#define SVM_EXIT_REASONS \
- { SVM_EXIT_READ_CR0, "read_cr0" }, \
- { SVM_EXIT_READ_CR3, "read_cr3" }, \
- { SVM_EXIT_READ_CR4, "read_cr4" }, \
- { SVM_EXIT_READ_CR8, "read_cr8" }, \
- { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
- { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
- { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
- { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
- { SVM_EXIT_READ_DR0, "read_dr0" }, \
- { SVM_EXIT_READ_DR1, "read_dr1" }, \
- { SVM_EXIT_READ_DR2, "read_dr2" }, \
- { SVM_EXIT_READ_DR3, "read_dr3" }, \
- { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
- { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
- { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
- { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
- { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
- { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
- { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
- { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
- { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
- { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
- { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
- { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
- { SVM_EXIT_INTR, "interrupt" }, \
- { SVM_EXIT_NMI, "nmi" }, \
- { SVM_EXIT_SMI, "smi" }, \
- { SVM_EXIT_INIT, "init" }, \
- { SVM_EXIT_VINTR, "vintr" }, \
- { SVM_EXIT_CPUID, "cpuid" }, \
- { SVM_EXIT_INVD, "invd" }, \
- { SVM_EXIT_HLT, "hlt" }, \
- { SVM_EXIT_INVLPG, "invlpg" }, \
- { SVM_EXIT_INVLPGA, "invlpga" }, \
- { SVM_EXIT_IOIO, "io" }, \
- { SVM_EXIT_MSR, "msr" }, \
- { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
- { SVM_EXIT_SHUTDOWN, "shutdown" }, \
- { SVM_EXIT_VMRUN, "vmrun" }, \
- { SVM_EXIT_VMMCALL, "hypercall" }, \
- { SVM_EXIT_VMLOAD, "vmload" }, \
- { SVM_EXIT_VMSAVE, "vmsave" }, \
- { SVM_EXIT_STGI, "stgi" }, \
- { SVM_EXIT_CLGI, "clgi" }, \
- { SVM_EXIT_SKINIT, "skinit" }, \
- { SVM_EXIT_WBINVD, "wbinvd" }, \
- { SVM_EXIT_MONITOR, "monitor" }, \
- { SVM_EXIT_MWAIT, "mwait" }, \
- { SVM_EXIT_XSETBV, "xsetbv" }, \
- { SVM_EXIT_NPF, "npf" }
-
/*
* Tracepoint for kvm guest exit:
*/
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip:perf/core] perf kvm: Events analysis tool
2012-09-17 8:31 ` [PATCH v8 3/3] KVM: perf: kvm events analysis tool Dong Hao
2012-09-20 13:34 ` David Ahern
@ 2012-09-27 4:27 ` tip-bot for Xiao Guangrong
1 sibling, 0 replies; 14+ messages in thread
From: tip-bot for Xiao Guangrong @ 2012-09-27 4:27 UTC (permalink / raw)
To: linux-tip-commits
Cc: acme, linux-kernel, hpa, mingo, runzhen, xiaoguangrong, haodong,
mtosatti, dsahern, tglx, avi
Commit-ID: bcf6edcd6fdb8965290f0b635a530fa3c6c212e1
Gitweb: http://git.kernel.org/tip/bcf6edcd6fdb8965290f0b635a530fa3c6c212e1
Author: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
AuthorDate: Mon, 17 Sep 2012 16:31:15 +0800
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 21 Sep 2012 12:51:22 -0300
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>
---
tools/perf/Documentation/perf-kvm.txt | 30 ++-
tools/perf/MANIFEST | 3 +
tools/perf/builtin-kvm.c | 840 ++++++++++++++++++++++++++++++++-
| 59 +++-
| 1 +
tools/perf/util/thread.h | 2 +
6 files changed, 929 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index dd84cb2..326f2cb 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -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]
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 0518079..80db3f4 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -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
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 4d2aa2c..1878947 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "perf.h"
+#include "util/evsel.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/symbol.h"
@@ -10,8 +11,10 @@
#include "util/parse-options.h"
#include "util/trace-event.h"
-
#include "util/debug.h"
+#include "util/debugfs.h"
+#include "util/tool.h"
+#include "util/stat.h"
#include <sys/prctl.h>
@@ -19,11 +22,840 @@
#include <pthread.h>
#include <math.h>
-static const char *file_name;
+#include "../../arch/x86/include/asm/svm.h"
+#include "../../arch/x86/include/asm/vmx.h"
+#include "../../arch/x86/include/asm/kvm.h"
+
+struct event_key {
+ #define INVALID_KEY (~0ULL)
+ u64 key;
+ int info;
+};
+
+struct kvm_events_ops {
+ bool (*is_begin_event)(struct event_format *event, void *data,
+ struct event_key *key);
+ bool (*is_end_event)(struct event_format *event, void *data,
+ struct event_key *key);
+ void (*decode_key)(struct event_key *key, char decode[20]);
+ const char *name;
+};
+
+static void exit_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->info = 0;
+ key->key = raw_field_value(event, "exit_reason", data);
+}
+
+static bool kvm_exit_event(struct event_format *event)
+{
+ return !strcmp(event->name, "kvm_exit");
+}
+
+static bool exit_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ if (kvm_exit_event(event)) {
+ exit_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool kvm_entry_event(struct event_format *event)
+{
+ return !strcmp(event->name, "kvm_entry");
+}
+
+static bool exit_event_end(struct event_format *event, void *data __maybe_unused,
+ struct event_key *key __maybe_unused)
+{
+ return kvm_entry_event(event);
+}
+
+struct exit_reasons_table {
+ unsigned long exit_code;
+ const char *reason;
+};
+
+struct exit_reasons_table vmx_exit_reasons[] = {
+ VMX_EXIT_REASONS
+};
+
+struct exit_reasons_table svm_exit_reasons[] = {
+ SVM_EXIT_REASONS
+};
+
+static int cpu_isa;
+
+static const char *get_exit_reason(u64 exit_code)
+{
+ int table_size = ARRAY_SIZE(svm_exit_reasons);
+ struct exit_reasons_table *table = svm_exit_reasons;
+
+ if (cpu_isa == 1) {
+ table = vmx_exit_reasons;
+ table_size = ARRAY_SIZE(vmx_exit_reasons);
+ }
+
+ while (table_size--) {
+ if (table->exit_code == exit_code)
+ return table->reason;
+ table++;
+ }
+
+ pr_err("unknown kvm exit code:%lld on %s\n",
+ (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM");
+ return "UNKNOWN";
+}
+
+static void exit_event_decode_key(struct event_key *key, char decode[20])
+{
+ const char *exit_reason = get_exit_reason(key->key);
+
+ scnprintf(decode, 20, "%s", exit_reason);
+}
+
+static struct kvm_events_ops exit_events = {
+ .is_begin_event = exit_event_begin,
+ .is_end_event = exit_event_end,
+ .decode_key = exit_event_decode_key,
+ .name = "VM-EXIT"
+};
+
+ /*
+ * For the mmio events, we treat:
+ * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
+ * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
+ */
+static void mmio_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->key = raw_field_value(event, "gpa", data);
+ key->info = raw_field_value(event, "type", data);
+}
+
+#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
+#define KVM_TRACE_MMIO_READ 1
+#define KVM_TRACE_MMIO_WRITE 2
+
+static bool mmio_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ /* MMIO read begin event in kernel. */
+ if (kvm_exit_event(event))
+ return true;
+
+ /* MMIO write begin event in kernel. */
+ if (!strcmp(event->name, "kvm_mmio") &&
+ raw_field_value(event, "type", data) == KVM_TRACE_MMIO_WRITE) {
+ mmio_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool mmio_event_end(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ /* MMIO write end event in kernel. */
+ if (kvm_entry_event(event))
+ return true;
+
+ /* MMIO read end event in kernel.*/
+ if (!strcmp(event->name, "kvm_mmio") &&
+ raw_field_value(event, "type", data) == KVM_TRACE_MMIO_READ) {
+ mmio_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static void mmio_event_decode_key(struct event_key *key, char decode[20])
+{
+ scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
+ key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
+}
+
+static struct kvm_events_ops mmio_events = {
+ .is_begin_event = mmio_event_begin,
+ .is_end_event = mmio_event_end,
+ .decode_key = mmio_event_decode_key,
+ .name = "MMIO Access"
+};
+
+ /* The time of emulation pio access is from kvm_pio to kvm_entry. */
+static void ioport_event_get_key(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ key->key = raw_field_value(event, "port", data);
+ key->info = raw_field_value(event, "rw", data);
+}
+
+static bool ioport_event_begin(struct event_format *event, void *data,
+ struct event_key *key)
+{
+ if (!strcmp(event->name, "kvm_pio")) {
+ ioport_event_get_key(event, data, key);
+ return true;
+ }
+
+ return false;
+}
+
+static bool ioport_event_end(struct event_format *event, void *data __maybe_unused,
+ struct event_key *key __maybe_unused)
+{
+ if (kvm_entry_event(event))
+ return true;
+
+ return false;
+}
+
+static void ioport_event_decode_key(struct event_key *key, char decode[20])
+{
+ scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
+ key->info ? "POUT" : "PIN");
+}
+
+static struct kvm_events_ops ioport_events = {
+ .is_begin_event = ioport_event_begin,
+ .is_end_event = ioport_event_end,
+ .decode_key = ioport_event_decode_key,
+ .name = "IO Port Access"
+};
+
+static const char *report_event = "vmexit";
+struct kvm_events_ops *events_ops;
+
+static bool register_kvm_events_ops(void)
+{
+ bool ret = true;
+
+ if (!strcmp(report_event, "vmexit"))
+ events_ops = &exit_events;
+ else if (!strcmp(report_event, "mmio"))
+ events_ops = &mmio_events;
+ else if (!strcmp(report_event, "ioport"))
+ events_ops = &ioport_events;
+ else {
+ pr_err("Unknown report event:%s\n", report_event);
+ ret = false;
+ }
+
+ return ret;
+}
+
+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;
+};
+
+struct vcpu_event_record {
+ int vcpu_id;
+ u64 start_time;
+ struct kvm_event *last_event;
+};
+
+#define EVENTS_BITS 12
+#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
+
+static u64 total_time;
+static u64 total_count;
+static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
+
+static void init_kvm_event_record(void)
+{
+ int i;
+
+ for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+ INIT_LIST_HEAD(&kvm_events_cache[i]);
+}
+
+static int kvm_events_hash_fn(u64 key)
+{
+ return key & (EVENTS_CACHE_SIZE - 1);
+}
+
+static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
+{
+ int old_max_vcpu = event->max_vcpu;
+
+ if (vcpu_id < event->max_vcpu)
+ return true;
+
+ while (event->max_vcpu <= vcpu_id)
+ event->max_vcpu += DEFAULT_VCPU_NUM;
+
+ event->vcpu = realloc(event->vcpu,
+ event->max_vcpu * sizeof(*event->vcpu));
+ if (!event->vcpu) {
+ pr_err("Not enough memory\n");
+ return false;
+ }
+
+ memset(event->vcpu + old_max_vcpu, 0,
+ (event->max_vcpu - old_max_vcpu) * sizeof(*event->vcpu));
+ return true;
+}
+
+static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
+{
+ struct kvm_event *event;
+
+ event = zalloc(sizeof(*event));
+ if (!event) {
+ pr_err("Not enough memory\n");
+ return NULL;
+ }
+
+ event->key = *key;
+ return event;
+}
+
+static struct kvm_event *find_create_kvm_event(struct event_key *key)
+{
+ struct kvm_event *event;
+ struct list_head *head;
+
+ BUG_ON(key->key == INVALID_KEY);
+
+ head = &kvm_events_cache[kvm_events_hash_fn(key->key)];
+ list_for_each_entry(event, head, hash_entry)
+ if (event->key.key == key->key && event->key.info == key->info)
+ return event;
+
+ event = kvm_alloc_init_event(key);
+ if (!event)
+ return NULL;
+
+ list_add(&event->hash_entry, head);
+ return event;
+}
+
+static bool handle_begin_event(struct vcpu_event_record *vcpu_record,
+ struct event_key *key, u64 timestamp)
+{
+ struct kvm_event *event = NULL;
+
+ if (key->key != INVALID_KEY)
+ event = find_create_kvm_event(key);
+
+ vcpu_record->last_event = event;
+ vcpu_record->start_time = timestamp;
+ return true;
+}
+
+static void
+kvm_update_event_stats(struct kvm_event_stats *kvm_stats, u64 time_diff)
+{
+ kvm_stats->time += time_diff;
+ update_stats(&kvm_stats->stats, time_diff);
+}
+
+static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
+{
+ struct kvm_event_stats *kvm_stats = &event->total;
+
+ if (vcpu_id != -1)
+ kvm_stats = &event->vcpu[vcpu_id];
+
+ return rel_stddev_stats(stddev_stats(&kvm_stats->stats),
+ avg_stats(&kvm_stats->stats));
+}
+
+static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
+ u64 time_diff)
+{
+ kvm_update_event_stats(&event->total, time_diff);
+
+ if (!kvm_event_expand(event, vcpu_id))
+ return false;
+
+ kvm_update_event_stats(&event->vcpu[vcpu_id], time_diff);
+ return true;
+}
+
+static bool handle_end_event(struct vcpu_event_record *vcpu_record,
+ struct event_key *key, u64 timestamp)
+{
+ struct kvm_event *event;
+ u64 time_begin, time_diff;
+
+ event = vcpu_record->last_event;
+ time_begin = vcpu_record->start_time;
+
+ /* The begin event is not caught. */
+ if (!time_begin)
+ return true;
+
+ /*
+ * In some case, the 'begin event' only records the start timestamp,
+ * the actual event is recognized in the 'end event' (e.g. mmio-event).
+ */
+
+ /* Both begin and end events did not get the key. */
+ if (!event && key->key == INVALID_KEY)
+ return true;
+
+ if (!event)
+ event = find_create_kvm_event(key);
+
+ if (!event)
+ return false;
+
+ vcpu_record->last_event = NULL;
+ vcpu_record->start_time = 0;
+
+ BUG_ON(timestamp < time_begin);
+
+ time_diff = timestamp - time_begin;
+ return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+}
+
+static struct vcpu_event_record
+*per_vcpu_record(struct thread *thread, struct event_format *event, void *data)
+{
+ /* Only kvm_entry records vcpu id. */
+ if (!thread->priv && kvm_entry_event(event)) {
+ struct vcpu_event_record *vcpu_record;
+
+ vcpu_record = zalloc(sizeof(struct vcpu_event_record));
+ if (!vcpu_record) {
+ pr_err("Not enough memory\n");
+ return NULL;
+ }
+
+ vcpu_record->vcpu_id = raw_field_value(event, "vcpu_id", data);
+ thread->priv = vcpu_record;
+ }
+
+ return (struct vcpu_event_record *)thread->priv;
+}
+
+static bool handle_kvm_event(struct thread *thread, struct event_format *event,
+ void *data, u64 timestamp)
+{
+ struct vcpu_event_record *vcpu_record;
+ struct event_key key = {.key = INVALID_KEY};
+
+ vcpu_record = per_vcpu_record(thread, event, data);
+ if (!vcpu_record)
+ return true;
+
+ if (events_ops->is_begin_event(event, data, &key))
+ return handle_begin_event(vcpu_record, &key, timestamp);
+
+ if (events_ops->is_end_event(event, data, &key))
+ return handle_end_event(vcpu_record, &key, timestamp);
+
+ return true;
+}
+
+typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
+struct kvm_event_key {
+ const char *name;
+ key_cmp_fun key;
+};
+
+static int trace_vcpu = -1;
+#define GET_EVENT_KEY(func, field) \
+static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
+{ \
+ if (vcpu == -1) \
+ return event->total.field; \
+ \
+ if (vcpu >= event->max_vcpu) \
+ return 0; \
+ \
+ return event->vcpu[vcpu].field; \
+}
+
+#define COMPARE_EVENT_KEY(func, field) \
+GET_EVENT_KEY(func, field) \
+static int compare_kvm_event_ ## func(struct kvm_event *one, \
+ struct kvm_event *two, int vcpu)\
+{ \
+ return get_event_ ##func(one, vcpu) > \
+ get_event_ ##func(two, vcpu); \
+}
+
+GET_EVENT_KEY(time, time);
+COMPARE_EVENT_KEY(count, stats.n);
+COMPARE_EVENT_KEY(mean, stats.mean);
+
+#define DEF_SORT_NAME_KEY(name, compare_key) \
+ { #name, compare_kvm_event_ ## compare_key }
+
+static struct kvm_event_key keys[] = {
+ DEF_SORT_NAME_KEY(sample, count),
+ DEF_SORT_NAME_KEY(time, mean),
+ { NULL, NULL }
+};
+
+static const char *sort_key = "sample";
+static key_cmp_fun compare;
+
+static bool select_key(void)
+{
+ int i;
+
+ for (i = 0; keys[i].name; i++) {
+ if (!strcmp(keys[i].name, sort_key)) {
+ compare = keys[i].key;
+ return true;
+ }
+ }
+
+ pr_err("Unknown compare key:%s\n", sort_key);
+ return false;
+}
+
+static struct rb_root result;
+static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
+ int vcpu)
+{
+ struct rb_node **rb = &result.rb_node;
+ struct rb_node *parent = NULL;
+ struct kvm_event *p;
+
+ while (*rb) {
+ p = container_of(*rb, struct kvm_event, rb);
+ parent = *rb;
+
+ if (bigger(event, p, vcpu))
+ rb = &(*rb)->rb_left;
+ else
+ rb = &(*rb)->rb_right;
+ }
+
+ rb_link_node(&event->rb, parent, rb);
+ rb_insert_color(&event->rb, &result);
+}
+
+static void update_total_count(struct kvm_event *event, int vcpu)
+{
+ total_count += get_event_count(event, vcpu);
+ total_time += get_event_time(event, vcpu);
+}
+
+static bool event_is_valid(struct kvm_event *event, int vcpu)
+{
+ return !!get_event_count(event, vcpu);
+}
+
+static void sort_result(int vcpu)
+{
+ unsigned int i;
+ struct kvm_event *event;
+
+ for (i = 0; i < EVENTS_CACHE_SIZE; i++)
+ list_for_each_entry(event, &kvm_events_cache[i], hash_entry)
+ if (event_is_valid(event, vcpu)) {
+ update_total_count(event, vcpu);
+ insert_to_result(event, compare, vcpu);
+ }
+}
+
+/* returns left most element of result, and erase it */
+static struct kvm_event *pop_from_result(void)
+{
+ struct rb_node *node = rb_first(&result);
+
+ if (!node)
+ return NULL;
+
+ rb_erase(node, &result);
+ return container_of(node, struct kvm_event, rb);
+}
+
+static void print_vcpu_info(int vcpu)
+{
+ pr_info("Analyze events for ");
+
+ if (vcpu == -1)
+ pr_info("all VCPUs:\n\n");
+ else
+ pr_info("VCPU %d:\n\n", vcpu);
+}
+
+static void print_result(int vcpu)
+{
+ char decode[20];
+ struct kvm_event *event;
+
+ pr_info("\n\n");
+ print_vcpu_info(vcpu);
+ pr_info("%20s ", events_ops->name);
+ pr_info("%10s ", "Samples");
+ pr_info("%9s ", "Samples%");
+
+ pr_info("%9s ", "Time%");
+ pr_info("%16s ", "Avg time");
+ pr_info("\n\n");
+
+ while ((event = pop_from_result())) {
+ u64 ecount, etime;
+
+ ecount = get_event_count(event, vcpu);
+ etime = get_event_time(event, vcpu);
+
+ events_ops->decode_key(&event->key, decode);
+ pr_info("%20s ", decode);
+ pr_info("%10llu ", (unsigned long long)ecount);
+ pr_info("%8.2f%% ", (double)ecount / total_count * 100);
+ pr_info("%8.2f%% ", (double)etime / total_time * 100);
+ pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
+ kvm_event_rel_stddev(vcpu, event));
+ pr_info("\n");
+ }
+
+ pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
+ (unsigned long long)total_count, total_time / 1e3);
+}
+
+static int process_sample_event(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
+{
+ struct thread *thread = machine__findnew_thread(machine, sample->tid);
+
+ if (thread == NULL) {
+ pr_debug("problem processing %d event, skipping it.\n",
+ event->header.type);
+ return -1;
+ }
+
+ if (!handle_kvm_event(thread, evsel->tp_format, sample->raw_data,
+ sample->time))
+ return -1;
+
+ return 0;
+}
+
+static struct perf_tool eops = {
+ .sample = process_sample_event,
+ .comm = perf_event__process_comm,
+ .ordered_samples = true,
+};
+
+static int get_cpu_isa(struct perf_session *session)
+{
+ char *cpuid;
+ int isa;
+
+ cpuid = perf_header__read_feature(session, HEADER_CPUID);
+
+ if (!cpuid) {
+ pr_err("read HEADER_CPUID failed.\n");
+ return -ENOTSUP;
+ }
+
+ if (strstr(cpuid, "Intel"))
+ isa = 1;
+ else if (strstr(cpuid, "AMD"))
+ isa = 0;
+ else {
+ pr_err("CPU %s is not supported.\n", cpuid);
+ isa = -ENOTSUP;
+ }
+
+ free(cpuid);
+ return isa;
+}
+
+static const char *file_name;
+
+static int read_events(void)
+{
+ struct perf_session *kvm_session;
+ int ret;
+
+ kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops);
+ if (!kvm_session) {
+ pr_err("Initializing perf session failed\n");
+ return -EINVAL;
+ }
+
+ if (!perf_session__has_traces(kvm_session, "kvm record"))
+ return -EINVAL;
+
+ /*
+ * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
+ * traced in the old kernel.
+ */
+ ret = get_cpu_isa(kvm_session);
+
+ if (ret < 0)
+ return ret;
+
+ cpu_isa = ret;
+
+ return perf_session__process_events(kvm_session, &eops);
+}
+
+static bool verify_vcpu(int vcpu)
+{
+ if (vcpu != -1 && vcpu < 0) {
+ pr_err("Invalid vcpu:%d.\n", vcpu);
+ return false;
+ }
+
+ return true;
+}
+
+static int kvm_events_report_vcpu(int vcpu)
+{
+ int ret = -EINVAL;
+
+ if (!verify_vcpu(vcpu))
+ goto exit;
+
+ if (!select_key())
+ goto exit;
+
+ if (!register_kvm_events_ops())
+ goto exit;
+
+ init_kvm_event_record();
+ setup_pager();
+
+ ret = read_events();
+ if (ret)
+ goto exit;
+
+ sort_result(vcpu);
+ print_result(vcpu);
+exit:
+ return ret;
+}
+
+static const char * const record_args[] = {
+ "record",
+ "-R",
+ "-f",
+ "-m", "1024",
+ "-c", "1",
+ "-e", "kvm:kvm_entry",
+ "-e", "kvm:kvm_exit",
+ "-e", "kvm:kvm_mmio",
+ "-e", "kvm:kvm_pio",
+};
+
+#define STRDUP_FAIL_EXIT(s) \
+ ({ char *_p; \
+ _p = strdup(s); \
+ if (!_p) \
+ return -ENOMEM; \
+ _p; \
+ })
+
+static int kvm_events_record(int argc, const char **argv)
+{
+ unsigned int rec_argc, i, j;
+ const char **rec_argv;
+
+ rec_argc = ARRAY_SIZE(record_args) + argc + 2;
+ rec_argv = calloc(rec_argc + 1, sizeof(char *));
+
+ if (rec_argv == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(record_args); i++)
+ rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
+
+ rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
+ rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
+
+ for (j = 1; j < (unsigned int)argc; j++, i++)
+ rec_argv[i] = argv[j];
+
+ return cmd_record(i, rec_argv, NULL);
+}
+
+static const char * const kvm_events_report_usage[] = {
+ "perf kvm stat report [<options>]",
+ NULL
+};
+
+static const struct option kvm_events_report_options[] = {
+ OPT_STRING(0, "event", &report_event, "report event",
+ "event for reporting: vmexit, mmio, ioport"),
+ OPT_INTEGER(0, "vcpu", &trace_vcpu,
+ "vcpu id to report"),
+ OPT_STRING('k', "key", &sort_key, "sort-key",
+ "key for sorting: sample(sort by samples number)"
+ " time (sort by avg time)"),
+ OPT_END()
+};
+
+static int kvm_events_report(int argc, const char **argv)
+{
+ symbol__init();
+
+ if (argc) {
+ argc = parse_options(argc, argv,
+ kvm_events_report_options,
+ kvm_events_report_usage, 0);
+ if (argc)
+ usage_with_options(kvm_events_report_usage,
+ kvm_events_report_options);
+ }
+
+ return kvm_events_report_vcpu(trace_vcpu);
+}
+
+static void print_kvm_stat_usage(void)
+{
+ printf("Usage: perf kvm stat <command>\n\n");
+
+ printf("# Available commands:\n");
+ printf("\trecord: record kvm events\n");
+ printf("\treport: report statistical data of kvm events\n");
+
+ printf("\nOtherwise, it is the alias of 'perf stat':\n");
+}
+
+static int kvm_cmd_stat(int argc, const char **argv)
+{
+ if (argc == 1) {
+ print_kvm_stat_usage();
+ goto perf_stat;
+ }
+
+ if (!strncmp(argv[1], "rec", 3))
+ return kvm_events_record(argc - 1, argv + 1);
+
+ if (!strncmp(argv[1], "rep", 3))
+ return kvm_events_report(argc - 1 , argv + 1);
+
+perf_stat:
+ return cmd_stat(argc, argv, NULL);
+}
+
static char name_buffer[256];
static const char * const kvm_usage[] = {
- "perf kvm [<options>] {top|record|report|diff|buildid-list}",
+ "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
NULL
};
@@ -135,6 +967,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
return cmd_top(argc, argv, NULL);
else if (!strncmp(argv[0], "buildid-list", 12))
return __cmd_buildid_list(argc, argv);
+ else if (!strncmp(argv[0], "stat", 4))
+ return kvm_cmd_stat(argc, argv);
else
usage_with_options(kvm_usage, kvm_options);
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index acbf633..ad72b28 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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)
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 209dad4..58de08b 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 70c2c13..f66610b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -16,6 +16,8 @@ struct thread {
bool comm_set;
char *comm;
int comm_len;
+
+ void *priv;
};
struct machine;
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2012-09-27 4:29 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-17 8:31 [PATCH v8 0/3] KVM: perf: kvm events analysis tool Dong Hao
2012-09-17 8:31 ` [PATCH v8 1/3] KVM: x86: export svm/vmx exit code and vector code to userspace Dong Hao
2012-09-17 14:58 ` Arnaldo Carvalho de Melo
2012-09-20 12:51 ` Marcelo Tosatti
2012-09-27 4:26 ` [tip:perf/core] KVM: x86: Export svm/ vmx " tip-bot for Xiao Guangrong
2012-09-17 8:31 ` [PATCH v8 2/3] perf: move stat related code to util/stat.c Dong Hao
2012-09-18 14:01 ` David Ahern
2012-09-18 19:18 ` David Ahern
2012-09-19 1:53 ` Xiao Guangrong
2012-09-19 4:00 ` David Ahern
2012-09-19 15:18 ` [tip:perf/core] perf stat: Move stats " tip-bot for Xiao Guangrong
2012-09-17 8:31 ` [PATCH v8 3/3] KVM: perf: kvm events analysis tool Dong Hao
2012-09-20 13:34 ` David Ahern
2012-09-27 4:27 ` [tip:perf/core] perf kvm: Events " tip-bot for Xiao Guangrong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).