A successful VMRUN retires in guest mode and should be counted by the PMU as a guest instruction. However, __kvm_skip_emulated_instruction() is called before entering guest mode to advance L1's RIP to the instruction following VMRUN. This is needed as the RIP is saved in vmcb01 to be restored on VM-Exit. Since VMRUN emulation is the only caller of __kvm_skip_emulated_instruction(), move retiring instructions for PMU purposes to its wrapper, leaving __kvm_skip_emulated_instruction() as a transparent wrapper around the vendor-specific calls. Note that this is currently a noop because KVM does not virtualize Host-Only/Guest-Only PMC controls yet, so all instructions are counted regardless of the vCPU's host/guest state. But this change is needed for the incoming support for Host-Only/Guest-Only controls to count VMRUN correctly. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 9 ++++++++- arch/x86/kvm/x86.c | 11 +++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 0f6ea490d707b..58c78c889a812 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -30,6 +30,7 @@ #include "lapic.h" #include "svm.h" #include "hyperv.h" +#include "pmu.h" #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK @@ -1135,7 +1136,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return 0; if (ret) - return 1; + goto insn_retired; /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1165,6 +1166,12 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_svm_vmexit(svm); } +insn_retired: + /* + * A successful VMRUN is counted by the PMU in guest mode, so only + * retire the instruction after potentially entering guest mode. + */ + kvm_pmu_instruction_retired(vcpu); return 1; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 31dc48a8111e5..08be0a63b93bd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -9274,14 +9274,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu) int __kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) { - int r; - - r = kvm_x86_call(skip_emulated_instruction)(vcpu); - if (unlikely(!r)) - return 0; - - kvm_pmu_instruction_retired(vcpu); - return r; + return kvm_x86_call(skip_emulated_instruction)(vcpu); } EXPORT_SYMBOL_FOR_KVM_INTERNAL(__kvm_skip_emulated_instruction); @@ -9294,6 +9287,8 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) if (unlikely(!r)) return 0; + kvm_pmu_instruction_retired(vcpu); + /* * rflags is the old, "raw" value of the flags. The new value has * not been saved yet. -- 2.54.0.545.g6539524ca2-goog