[PATCH v1 3/3] KVM: arm64: Add histogram stats for handling time of arch specific exit reasons

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



These logarithmic histogram stats are useful for monitoring performance
of handling for different kinds of VCPU exit reasons.

Signed-off-by: Jing Zhang <jingzhangos@xxxxxxxxxx>
---
 arch/arm64/include/asm/kvm_host.h | 36 ++++++++++++
 arch/arm64/kvm/arm.c              |  4 ++
 arch/arm64/kvm/guest.c            | 43 ++++++++++++++
 arch/arm64/kvm/handle_exit.c      | 95 +++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4d65de22add3..f1a29ca3d4f3 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -417,6 +417,9 @@ struct kvm_vcpu_arch {
 
 	/* Arch specific exit reason */
 	enum arm_exit_reason exit_reason;
+
+	/* The timestamp for the last VCPU exit */
+	u64 last_exit_time;
 };
 
 /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
@@ -605,6 +608,8 @@ struct kvm_vm_stat {
 	struct kvm_vm_stat_generic generic;
 };
 
+#define ARM_EXIT_HIST_CNT	64
+
 struct kvm_vcpu_stat {
 	struct kvm_vcpu_stat_generic generic;
 	u64 mmio_exit_user;
@@ -641,6 +646,36 @@ struct kvm_vcpu_stat {
 		u64 exit_fp_asimd;
 		u64 exit_pac;
 	};
+	/* Histogram stats for handling time of arch specific exit reasons */
+	struct {
+		u64 exit_unknown_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_irq_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_el1_serror_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_hyp_gone_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_il_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_wfi_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_wfe_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_cp15_32_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_cp15_64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_cp14_32_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_cp14_ls_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_cp14_64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_hvc32_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_smc32_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_hvc64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_smc64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_sys64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_sve_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_iabt_low_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_dabt_low_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_softstp_low_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_watchpt_low_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_breakpt_low_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_bkpt32_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_brk64_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_fp_asimd_hist[ARM_EXIT_HIST_CNT];
+		u64 exit_pac_hist[ARM_EXIT_HIST_CNT];
+	};
 };
 
 int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
@@ -715,6 +750,7 @@ void force_vm_exit(const cpumask_t *mask);
 
 int handle_exit(struct kvm_vcpu *vcpu, int exception_index);
 void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index);
+void update_hist_exit_stats(struct kvm_vcpu *vcpu);
 
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu);
 int kvm_handle_cp14_32(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index fe102cd2e518..156f80b699d3 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -795,6 +795,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 	ret = 1;
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	while (ret > 0) {
+		/* Update histogram stats for exit reasons */
+		update_hist_exit_stats(vcpu);
+
 		/*
 		 * Check conditions before entering the guest
 		 */
@@ -903,6 +906,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		 */
 		guest_exit();
 		trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
+		vcpu->arch.last_exit_time = ktime_to_ns(ktime_get());
 
 		/* Exit types that need handling before we can be preempted */
 		handle_exit_early(vcpu, ret);
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index abd9327d7110..bbf51578fdec 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -75,6 +75,49 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	STATS_DESC_COUNTER(VCPU, exit_brk64),
 	STATS_DESC_COUNTER(VCPU, exit_fp_asimd),
 	STATS_DESC_COUNTER(VCPU, exit_pac),
+	/* Histogram stats for handling time of arch specific exit reasons */
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_unknown_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_irq_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_el1_serror_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_hyp_gone_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_il_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_wfi_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_wfe_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_cp15_32_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_cp15_64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_cp14_32_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_cp14_ls_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_cp14_64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_hvc32_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_smc32_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_hvc64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_smc64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_sys64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_sve_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_iabt_low_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_dabt_low_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_softstp_low_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_watchpt_low_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_breakpt_low_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_bkpt32_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_brk64_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(
+			VCPU, exit_fp_asimd_hist, ARM_EXIT_HIST_CNT),
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU, exit_pac_hist, ARM_EXIT_HIST_CNT),
 };
 
 const struct kvm_stats_header kvm_vcpu_stats_header = {
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e83cd52078b2..5e642a6275c1 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -395,3 +395,98 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 	panic("HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%016lx\n",
 	      spsr, elr_virt, esr, far, hpfar, par, vcpu);
 }
+
+void update_hist_exit_stats(struct kvm_vcpu *vcpu)
+{
+	u64 val = ktime_to_ns(ktime_get()) - vcpu->arch.last_exit_time;
+
+	if (unlikely(!vcpu->arch.last_exit_time))
+		return;
+
+	switch (vcpu->arch.exit_reason) {
+	case ARM_EXIT_UNKNOWN:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_unknown_hist, val);
+		break;
+	case ARM_EXIT_IRQ:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_irq_hist, val);
+		break;
+	case ARM_EXIT_EL1_SERROR:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_el1_serror_hist, val);
+		break;
+	case ARM_EXIT_HYP_GONE:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_hyp_gone_hist, val);
+		break;
+	case ARM_EXIT_IL:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_il_hist, val);
+		break;
+	case ARM_EXIT_WFI:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_wfi_hist, val);
+		break;
+	case ARM_EXIT_WFE:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_wfe_hist, val);
+		break;
+	case ARM_EXIT_CP15_32:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_cp15_32_hist, val);
+		break;
+	case ARM_EXIT_CP15_64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_cp15_64_hist, val);
+		break;
+	case ARM_EXIT_CP14_32:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_cp14_32_hist, val);
+		break;
+	case ARM_EXIT_CP14_LS:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_cp14_ls_hist, val);
+		break;
+	case ARM_EXIT_CP14_64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_cp14_64_hist, val);
+		break;
+	case ARM_EXIT_HVC32:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_hvc32_hist, val);
+		break;
+	case ARM_EXIT_SMC32:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_smc32_hist, val);
+		break;
+	case ARM_EXIT_HVC64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_hvc64_hist, val);
+		break;
+	case ARM_EXIT_SMC64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_smc64_hist, val);
+		break;
+	case ARM_EXIT_SYS64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_sys64_hist, val);
+		break;
+	case ARM_EXIT_SVE:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_sve_hist, val);
+		break;
+	case ARM_EXIT_IABT_LOW:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_iabt_low_hist, val);
+		break;
+	case ARM_EXIT_DABT_LOW:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_dabt_low_hist, val);
+		break;
+	case ARM_EXIT_SOFTSTP_LOW:
+		KVM_STATS_LOG_HIST_UPDATE(
+				vcpu->stat.exit_softstp_low_hist, val);
+		break;
+	case ARM_EXIT_WATCHPT_LOW:
+		KVM_STATS_LOG_HIST_UPDATE(
+				vcpu->stat.exit_watchpt_low_hist, val);
+		break;
+	case ARM_EXIT_BREAKPT_LOW:
+		KVM_STATS_LOG_HIST_UPDATE(
+				vcpu->stat.exit_breakpt_low_hist, val);
+		break;
+	case ARM_EXIT_BKPT32:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_bkpt32_hist, val);
+		break;
+	case ARM_EXIT_BRK64:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_brk64_hist, val);
+		break;
+	case ARM_EXIT_FP_ASIMD:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_fp_asimd_hist, val);
+		break;
+	case ARM_EXIT_PAC:
+		KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.exit_pac_hist, val);
+		break;
+	}
+}
-- 
2.33.0.464.g1972c5931b-goog




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux