History

kvm: add halt-polling cpu usage stats

Two new stats for exposing halt-polling cpu usage: halt_poll_success_ns halt_poll_fail_ns Thus sum of these 2 stats is the total cpu time spent polling. "success" means the VCPU polled until a virtual interrupt was delivered. "fail" means the VCPU had to schedule out (either because the maximum poll time was reached or it needed to yield the CPU). To avoid touching every arch's kvm_vcpu_stat struct, only update and export halt-polling cpu usage stats if we're on x86. Exporting cpu usage as a u64 and in nanoseconds means we will overflow at ~500 years, which seems reasonably large. Signed-off-by: David Matlack <dmatlack@google.com> Signed-off-by: Jon Cargille <jcargill@google.com> Reviewed-by: Jim Mattson <jmattson@google.com>

David Matlack committed 6 years ago

Commit cb953121 parent 93dff2f10 files · +33 −3Browse files

Unified · Split

10 files
  1. arch/arm64/include/asm/kvm_host.h +2 −0
  2. arch/arm64/kvm/guest.c +2 −0
  3. arch/mips/include/asm/kvm_host.h +2 −0
  4. arch/mips/kvm/mips.c +2 −0
  5. arch/powerpc/kvm/booke.c +2 −0
  6. arch/s390/include/asm/kvm_host.h +2 −0
  7. arch/s390/kvm/kvm-s390.c +2 −0
  8. arch/x86/include/asm/kvm_host.h +2 −0
  9. arch/x86/kvm/x86.c +2 −0
  10. virt/kvm/kvm_main.c +15 −3
arch/arm64/include/asm/kvm_host.h+2−0
@@ -415,6 +415,8 @@ struct kvm_vm_stat { · 414 unmodified lines
415struct kvm_vcpu_stat {415struct kvm_vcpu_stat {
416 u64 halt_successful_poll;416 u64 halt_successful_poll;
417 u64 halt_attempted_poll;417 u64 halt_attempted_poll;
418 u64 halt_poll_success_ns;
419 u64 halt_poll_fail_ns;
418 u64 halt_poll_invalid;420 u64 halt_poll_invalid;
419 u64 halt_wakeup;421 u64 halt_wakeup;
420 u64 hvc_exit_stat;422 u64 hvc_exit_stat;
arch/arm64/kvm/guest.c+2−0
@@ -40,6 +40,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { · 39 unmodified lines
40 VCPU_STAT("mmio_exit_user", mmio_exit_user),40 VCPU_STAT("mmio_exit_user", mmio_exit_user),
41 VCPU_STAT("mmio_exit_kernel", mmio_exit_kernel),41 VCPU_STAT("mmio_exit_kernel", mmio_exit_kernel),
42 VCPU_STAT("exits", exits),42 VCPU_STAT("exits", exits),
43 VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
44 VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
43 { NULL }45 { NULL }
44};46};
45 47
arch/mips/include/asm/kvm_host.h+2−0
@@ -174,6 +174,8 @@ struct kvm_vcpu_stat { · 173 unmodified lines
174#endif174#endif
175 u64 halt_successful_poll;175 u64 halt_successful_poll;
176 u64 halt_attempted_poll;176 u64 halt_attempted_poll;
177 u64 halt_poll_success_ns;
178 u64 halt_poll_fail_ns;
177 u64 halt_poll_invalid;179 u64 halt_poll_invalid;
178 u64 halt_wakeup;180 u64 halt_wakeup;
179};181};
arch/mips/kvm/mips.c+2−0
@@ -72,6 +72,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { · 71 unmodified lines
72 VCPU_STAT("halt_attempted_poll", halt_attempted_poll),72 VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
73 VCPU_STAT("halt_poll_invalid", halt_poll_invalid),73 VCPU_STAT("halt_poll_invalid", halt_poll_invalid),
74 VCPU_STAT("halt_wakeup", halt_wakeup),74 VCPU_STAT("halt_wakeup", halt_wakeup),
75 VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
76 VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
75 {NULL}77 {NULL}
76};78};
77 79
arch/powerpc/kvm/booke.c+2−0
@@ -54,6 +54,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { · 53 unmodified lines
54 VCPU_STAT("halt_wakeup", halt_wakeup),54 VCPU_STAT("halt_wakeup", halt_wakeup),
55 VCPU_STAT("doorbell", dbell_exits),55 VCPU_STAT("doorbell", dbell_exits),
56 VCPU_STAT("guest doorbell", gdbell_exits),56 VCPU_STAT("guest doorbell", gdbell_exits),
57 VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
58 VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
57 VM_STAT("remote_tlb_flush", remote_tlb_flush),59 VM_STAT("remote_tlb_flush", remote_tlb_flush),
58 { NULL }60 { NULL }
59};61};
arch/s390/include/asm/kvm_host.h+2−0
@@ -375,6 +375,8 @@ struct kvm_vcpu_stat { · 374 unmodified lines
375 u64 halt_poll_invalid;375 u64 halt_poll_invalid;
376 u64 halt_no_poll_steal;376 u64 halt_no_poll_steal;
377 u64 halt_wakeup;377 u64 halt_wakeup;
378 u64 halt_poll_success_ns;
379 u64 halt_poll_fail_ns;
378 u64 instruction_lctl;380 u64 instruction_lctl;
379 u64 instruction_lctlg;381 u64 instruction_lctlg;
380 u64 instruction_stctl;382 u64 instruction_stctl;
arch/s390/kvm/kvm-s390.c+2−0
@@ -75,6 +75,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { · 74 unmodified lines
75 VCPU_STAT("halt_poll_invalid", halt_poll_invalid),75 VCPU_STAT("halt_poll_invalid", halt_poll_invalid),
76 VCPU_STAT("halt_no_poll_steal", halt_no_poll_steal),76 VCPU_STAT("halt_no_poll_steal", halt_no_poll_steal),
77 VCPU_STAT("halt_wakeup", halt_wakeup),77 VCPU_STAT("halt_wakeup", halt_wakeup),
78 VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
79 VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
78 VCPU_STAT("instruction_lctlg", instruction_lctlg),80 VCPU_STAT("instruction_lctlg", instruction_lctlg),
79 VCPU_STAT("instruction_lctl", instruction_lctl),81 VCPU_STAT("instruction_lctl", instruction_lctl),
80 VCPU_STAT("instruction_stctl", instruction_stctl),82 VCPU_STAT("instruction_stctl", instruction_stctl),
arch/x86/include/asm/kvm_host.h+2−0
@@ -1031,6 +1031,8 @@ struct kvm_vcpu_stat { · 1030 unmodified lines
1031 u64 irq_injections;1031 u64 irq_injections;
1032 u64 nmi_injections;1032 u64 nmi_injections;
1033 u64 req_event;1033 u64 req_event;
1034 u64 halt_poll_success_ns;
1035 u64 halt_poll_fail_ns;
1034};1036};
1035 1037
1036struct x86_instruction_info;1038struct x86_instruction_info;
arch/x86/kvm/x86.c+2−0
@@ -217,6 +217,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { · 216 unmodified lines
217 VCPU_STAT("nmi_injections", nmi_injections),217 VCPU_STAT("nmi_injections", nmi_injections),
218 VCPU_STAT("req_event", req_event),218 VCPU_STAT("req_event", req_event),
219 VCPU_STAT("l1d_flush", l1d_flush),219 VCPU_STAT("l1d_flush", l1d_flush),
220 VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
221 VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
220 VM_STAT("mmu_shadow_zapped", mmu_shadow_zapped),222 VM_STAT("mmu_shadow_zapped", mmu_shadow_zapped),
221 VM_STAT("mmu_pte_write", mmu_pte_write),223 VM_STAT("mmu_pte_write", mmu_pte_write),
222 VM_STAT("mmu_pte_updated", mmu_pte_updated),224 VM_STAT("mmu_pte_updated", mmu_pte_updated),
virt/kvm/kvm_main.c+15−3
@@ -2667,18 +2667,27 @@ out: · 2666 unmodified lines
2667 return ret;2667 return ret;
2668}2668}
2669 2669
2670static inline void
2671update_halt_poll_stats(struct kvm_vcpu *vcpu, u64 poll_ns, bool waited)
2672{
2673 if (waited)
2674 vcpu->stat.halt_poll_fail_ns += poll_ns;
2675 else
2676 vcpu->stat.halt_poll_success_ns += poll_ns;
2677}
2678
2670/*2679/*
2671 * The vCPU has executed a HLT instruction with in-kernel mode enabled.2680 * The vCPU has executed a HLT instruction with in-kernel mode enabled.
2672 */2681 */
2673void kvm_vcpu_block(struct kvm_vcpu *vcpu)2682void kvm_vcpu_block(struct kvm_vcpu *vcpu)
2674{2683{
2675 ktime_t start, cur;2684 ktime_t start, cur, poll_end;
2676 bool waited = false;2685 bool waited = false;
2677 u64 block_ns;2686 u64 block_ns;
2678 2687
2679 kvm_arch_vcpu_blocking(vcpu);2688 kvm_arch_vcpu_blocking(vcpu);
2680 2689
2681 start = cur = ktime_get();2690 start = cur = poll_end = ktime_get();
2682 if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) {2691 if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) {
2683 ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);2692 ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
2684 2693
@@ -2694,7 +2703,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) · 9 unmodified lines
2694 ++vcpu->stat.halt_poll_invalid;2703 ++vcpu->stat.halt_poll_invalid;
2695 goto out;2704 goto out;
2696 }2705 }
2697 cur = ktime_get();2706 poll_end = cur = ktime_get();
2698 } while (single_task_running() && ktime_before(cur, stop));2707 } while (single_task_running() && ktime_before(cur, stop));
2699 }2708 }
2700 2709
@@ -2714,6 +2723,9 @@ out: · 13 unmodified lines
2714 kvm_arch_vcpu_unblocking(vcpu);2723 kvm_arch_vcpu_unblocking(vcpu);
2715 block_ns = ktime_to_ns(cur) - ktime_to_ns(start);2724 block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
2716 2725
2726 update_halt_poll_stats(
2727 vcpu, ktime_to_ns(ktime_sub(poll_end, start)), waited);
2728
2717 if (!kvm_arch_no_poll(vcpu)) {2729 if (!kvm_arch_no_poll(vcpu)) {
2718 if (!vcpu_valid_wakeup(vcpu)) {2730 if (!vcpu_valid_wakeup(vcpu)) {
2719 shrink_halt_poll_ns(vcpu);2731 shrink_halt_poll_ns(vcpu);