To emulate PEBS facility, KVM may needs setup context such as guest DS PEBS fields correctly before vm-entry and this part will be implemented in the vmx handle_event() hook. When the cross-map happens to any enabled PEBS counter, it will make PMU request and exit to kvm_pmu_handle_event() for some rewrite stuff and then back to cross-map check again and finally to vm-entry. In this hook, KVM would rewrite the state for the guest and it won't move events, hence races with the NMI PMI are not a problem. Signed-off-by: Like Xu <like.xu@xxxxxxxxxxxxxxx> --- arch/x86/kvm/pmu.c | 3 +++ arch/x86/kvm/pmu.h | 1 + arch/x86/kvm/vmx/pmu_intel.c | 9 +++++++++ arch/x86/kvm/vmx/vmx.c | 3 --- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index a6c5951a5728..f87be3c2140e 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -339,6 +339,9 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu) */ if (unlikely(pmu->need_cleanup)) kvm_pmu_cleanup(vcpu); + + if (kvm_x86_ops.pmu_ops->handle_event) + kvm_x86_ops.pmu_ops->handle_event(vcpu); } /* check if idx is a valid index to access PMU */ diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index f5ec94e9a1dc..b1e52e33f08c 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -45,6 +45,7 @@ struct kvm_pmu_ops { void (*refresh)(struct kvm_vcpu *vcpu); void (*init)(struct kvm_vcpu *vcpu); void (*reset)(struct kvm_vcpu *vcpu); + void (*handle_event)(struct kvm_vcpu *vcpu); }; static inline u64 pmc_bitmask(struct kvm_pmc *pmc) diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 99d9453e0176..2917105e584e 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -491,6 +491,14 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu) pmu->global_ovf_ctrl = 0; } +void intel_pmu_handle_event(struct kvm_vcpu *vcpu) +{ + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + + if (!(pmu->global_ctrl & pmu->pebs_enable)) + return; +} + struct kvm_pmu_ops intel_pmu_ops = { .find_arch_event = intel_find_arch_event, .find_fixed_event = intel_find_fixed_event, @@ -505,4 +513,5 @@ struct kvm_pmu_ops intel_pmu_ops = { .refresh = intel_pmu_refresh, .init = intel_pmu_init, .reset = intel_pmu_reset, + .handle_event = intel_pmu_handle_event, }; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 302808ec9699..3b62907c8959 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6556,9 +6556,6 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx) if (!msrs) return; - if (pmu->counter_cross_mapped) - msrs[1].guest = 0; - if (nr_msrs > 2 && msrs[1].guest) { msrs[2].guest = pmu->ds_area; if (nr_msrs > 3) -- 2.21.3