linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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 ++++++++++++++++++++++++++++++++-
 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(-)

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);
 
diff --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)
diff --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 ++++++++++++++++++++++++++++++++-
 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(-)

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);
 
diff --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)
diff --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).