Skip to content

Commit 8542503

Browse files
Like Xubonzini
authored andcommitted
KVM: x86/pmu: Disable guest PEBS temporarily in two rare situations
The guest PEBS will be disabled when some users try to perf KVM and its user-space through the same PEBS facility OR when the host perf doesn't schedule the guest PEBS counter in a one-to-one mapping manner (neither of these are typical scenarios). The PEBS records in the guest DS buffer are still accurate and the above two restrictions will be checked before each vm-entry only if guest PEBS is deemed to be enabled. Suggested-by: Wei Wang <wei.w.wang@intel.com> Signed-off-by: Like Xu <like.xu@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Message-Id: <20220411101946.20262-15-likexu@tencent.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 63f21f3 commit 8542503

File tree

5 files changed

+43
-2
lines changed

5 files changed

+43
-2
lines changed

arch/x86/events/intel/core.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4048,8 +4048,15 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
40484048
.guest = pebs_mask & ~cpuc->intel_ctrl_host_mask,
40494049
};
40504050

4051-
/* Set hw GLOBAL_CTRL bits for PEBS counter when it runs for guest */
4052-
arr[0].guest |= arr[*nr].guest;
4051+
if (arr[pebs_enable].host) {
4052+
/* Disable guest PEBS if host PEBS is enabled. */
4053+
arr[pebs_enable].guest = 0;
4054+
} else {
4055+
/* Disable guest PEBS for cross-mapped PEBS counters. */
4056+
arr[pebs_enable].guest &= ~kvm_pmu->host_cross_mapped_mask;
4057+
/* Set hw GLOBAL_CTRL bits for PEBS counter when it runs for guest */
4058+
arr[global_ctrl].guest |= arr[pebs_enable].guest;
4059+
}
40534060

40544061
return arr;
40554062
}

arch/x86/include/asm/kvm_host.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,15 @@ struct kvm_pmu {
527527
u64 pebs_data_cfg;
528528
u64 pebs_data_cfg_mask;
529529

530+
/*
531+
* If a guest counter is cross-mapped to host counter with different
532+
* index, its PEBS capability will be temporarily disabled.
533+
*
534+
* The user should make sure that this mask is updated
535+
* after disabling interrupts and before perf_guest_get_msrs();
536+
*/
537+
u64 host_cross_mapped_mask;
538+
530539
/*
531540
* The gate to release perf_events not marked in
532541
* pmc_in_use only once in a vcpu time slice.

arch/x86/kvm/vmx/pmu_intel.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,26 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
786786
intel_pmu_release_guest_lbr_event(vcpu);
787787
}
788788

789+
void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu)
790+
{
791+
struct kvm_pmc *pmc = NULL;
792+
int bit;
793+
794+
for_each_set_bit(bit, (unsigned long *)&pmu->global_ctrl,
795+
X86_PMC_IDX_MAX) {
796+
pmc = intel_pmc_idx_to_pmc(pmu, bit);
797+
798+
if (!pmc || !pmc_speculative_in_use(pmc) ||
799+
!intel_pmc_is_enabled(pmc))
800+
continue;
801+
802+
if (pmc->perf_event && pmc->idx != pmc->perf_event->hw.idx) {
803+
pmu->host_cross_mapped_mask |=
804+
BIT_ULL(pmc->perf_event->hw.idx);
805+
}
806+
}
807+
}
808+
789809
struct kvm_pmu_ops intel_pmu_ops __initdata = {
790810
.pmc_perf_hw_id = intel_pmc_perf_hw_id,
791811
.pmc_is_enabled = intel_pmc_is_enabled,

arch/x86/kvm/vmx/vmx.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6796,6 +6796,10 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
67966796
struct perf_guest_switch_msr *msrs;
67976797
struct kvm_pmu *pmu = vcpu_to_pmu(&vmx->vcpu);
67986798

6799+
pmu->host_cross_mapped_mask = 0;
6800+
if (pmu->pebs_enable & pmu->global_ctrl)
6801+
intel_pmu_cross_mapped_check(pmu);
6802+
67996803
/* Note, nr_msrs may be garbage if perf_guest_get_msrs() returns NULL. */
68006804
msrs = perf_guest_get_msrs(&nr_msrs, (void *)pmu);
68016805
if (!msrs)

arch/x86/kvm/vmx/vmx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ union vmx_exit_reason {
9494
#define vcpu_to_lbr_desc(vcpu) (&to_vmx(vcpu)->lbr_desc)
9595
#define vcpu_to_lbr_records(vcpu) (&to_vmx(vcpu)->lbr_desc.records)
9696

97+
void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu);
9798
bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu);
9899
bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu);
99100

0 commit comments

Comments
 (0)