Exit statistics can be a very valuable information when looking at KVM performance. Expose them through debugfs. Signed-off-by: Marc Zyngier <marc.zyngier at arm.com> --- arch/arm/include/asm/kvm_host.h | 5 +++++ arch/arm/kvm/arm.c | 5 ++++- arch/arm/kvm/emulate.c | 1 + arch/arm/kvm/guest.c | 13 +++++++++++++ arch/arm/kvm/mmu.c | 8 ++++++++ 5 files changed, 31 insertions(+), 1 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index e6fd8ff..ffef12b 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -118,6 +118,11 @@ struct kvm_vm_stat { }; struct kvm_vcpu_stat { + u32 exits; + u32 mmio_exits; + u32 kmmio_exits; + u32 wfi_exits; + u32 irq_exits; u32 halt_wakeup; }; diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 7cd8190..86eca66 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -435,8 +435,10 @@ static inline int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, { unsigned long hsr_ec; - if (exception_index == ARM_EXCEPTION_IRQ) + if (exception_index == ARM_EXCEPTION_IRQ) { + vcpu->stat.irq_exits++; return 0; + } if (exception_index != ARM_EXCEPTION_HVC) { kvm_pr_unimpl("Unsupported exception type: %d", @@ -514,6 +516,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) kvm_vgic_sync_from_cpu(vcpu); vcpu->mode = OUTSIDE_GUEST_MODE; + vcpu->stat.exits++; kvm_guest_exit(); local_irq_enable(); diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index d810c30..3ceab47 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -443,6 +443,7 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run) { trace_kvm_wfi(vcpu->arch.regs.pc); + vcpu->stat.wfi_exits++; if (!vcpu->arch.irq_lines && !kvm_vgic_vcpu_pending_irq(vcpu)) vcpu->arch.wait_for_interrupts = 1; return 0; diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index c0adab0..d2ad91a 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -24,7 +24,20 @@ #include <asm/kvm_asm.h> #include <asm/kvm_emulate.h> +#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM } +#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU } + struct kvm_stats_debugfs_item debugfs_entries[] = { + /* vcpu stats */ + VCPU_STAT(exits), + VCPU_STAT(mmio_exits), + VCPU_STAT(kmmio_exits), + VCPU_STAT(wfi_exits), + VCPU_STAT(irq_exits), + VCPU_STAT(halt_wakeup), + + /* vm stats */ + VM_STAT(remote_tlb_flush), { NULL } }; diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 2d4fc68..04898d8 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -604,6 +604,14 @@ static int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, memcpy(run->mmio.data, vcpu_reg(vcpu, rd), len); run->exit_reason = vgic_handle_mmio(vcpu, run); + switch (run->exit_reason) { + case KVM_EXIT_MMIO: + vcpu->stat.mmio_exits++; + break; + case KVM_EXIT_UNKNOWN: + vcpu->stat.kmmio_exits++; + break; + } /* * The MMIO instruction is emulated and should not be re-executed -- 1.7.7.1