Skip to content

Commit c59a1f1

Browse files
Like Xubonzini
Like Xu
authored andcommitted
KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS
If IA32_PERF_CAPABILITIES.PEBS_BASELINE [bit 14] is set, the IA32_PEBS_ENABLE MSR exists and all architecturally enumerated fixed and general-purpose counters have corresponding bits in IA32_PEBS_ENABLE that enable generation of PEBS records. The general-purpose counter bits start at bit IA32_PEBS_ENABLE[0], and the fixed counter bits start at bit IA32_PEBS_ENABLE[32]. When guest PEBS is enabled, the IA32_PEBS_ENABLE MSR will be added to the perf_guest_switch_msr() and atomically switched during the VMX transitions just like CORE_PERF_GLOBAL_CTRL MSR. Based on whether the platform supports x86_pmu.pebs_ept, it has also refactored the way to add more msrs to arr[] in intel_guest_get_msrs() for extensibility. Originally-by: Andi Kleen <[email protected]> Co-developed-by: Kan Liang <[email protected]> Signed-off-by: Kan Liang <[email protected]> Co-developed-by: Luwei Kang <[email protected]> Signed-off-by: Luwei Kang <[email protected]> Signed-off-by: Like Xu <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 0d23dc3 commit c59a1f1

File tree

5 files changed

+98
-18
lines changed

5 files changed

+98
-18
lines changed

arch/x86/events/intel/core.c

+57-18
Original file line numberDiff line numberDiff line change
@@ -3969,33 +3969,72 @@ static int intel_pmu_hw_config(struct perf_event *event)
39693969
return 0;
39703970
}
39713971

3972+
/*
3973+
* Currently, the only caller of this function is the atomic_switch_perf_msrs().
3974+
* The host perf conext helps to prepare the values of the real hardware for
3975+
* a set of msrs that need to be switched atomically in a vmx transaction.
3976+
*
3977+
* For example, the pseudocode needed to add a new msr should look like:
3978+
*
3979+
* arr[(*nr)++] = (struct perf_guest_switch_msr){
3980+
* .msr = the hardware msr address,
3981+
* .host = the value the hardware has when it doesn't run a guest,
3982+
* .guest = the value the hardware has when it runs a guest,
3983+
* };
3984+
*
3985+
* These values have nothing to do with the emulated values the guest sees
3986+
* when it uses {RD,WR}MSR, which should be handled by the KVM context,
3987+
* specifically in the intel_pmu_{get,set}_msr().
3988+
*/
39723989
static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
39733990
{
39743991
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
39753992
struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
39763993
u64 intel_ctrl = hybrid(cpuc->pmu, intel_ctrl);
3994+
u64 pebs_mask = cpuc->pebs_enabled & x86_pmu.pebs_capable;
3995+
int global_ctrl, pebs_enable;
3996+
3997+
*nr = 0;
3998+
global_ctrl = (*nr)++;
3999+
arr[global_ctrl] = (struct perf_guest_switch_msr){
4000+
.msr = MSR_CORE_PERF_GLOBAL_CTRL,
4001+
.host = intel_ctrl & ~cpuc->intel_ctrl_guest_mask,
4002+
.guest = intel_ctrl & (~cpuc->intel_ctrl_host_mask | ~pebs_mask),
4003+
};
39774004

3978-
arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
3979-
arr[0].host = intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
3980-
arr[0].guest = intel_ctrl & ~cpuc->intel_ctrl_host_mask;
3981-
arr[0].guest &= ~(cpuc->pebs_enabled & x86_pmu.pebs_capable);
3982-
*nr = 1;
4005+
if (!x86_pmu.pebs)
4006+
return arr;
39834007

3984-
if (x86_pmu.pebs && x86_pmu.pebs_no_isolation) {
3985-
/*
3986-
* If PMU counter has PEBS enabled it is not enough to
3987-
* disable counter on a guest entry since PEBS memory
3988-
* write can overshoot guest entry and corrupt guest
3989-
* memory. Disabling PEBS solves the problem.
3990-
*
3991-
* Don't do this if the CPU already enforces it.
3992-
*/
3993-
arr[1].msr = MSR_IA32_PEBS_ENABLE;
3994-
arr[1].host = cpuc->pebs_enabled;
3995-
arr[1].guest = 0;
3996-
*nr = 2;
4008+
/*
4009+
* If PMU counter has PEBS enabled it is not enough to
4010+
* disable counter on a guest entry since PEBS memory
4011+
* write can overshoot guest entry and corrupt guest
4012+
* memory. Disabling PEBS solves the problem.
4013+
*
4014+
* Don't do this if the CPU already enforces it.
4015+
*/
4016+
if (x86_pmu.pebs_no_isolation) {
4017+
arr[(*nr)++] = (struct perf_guest_switch_msr){
4018+
.msr = MSR_IA32_PEBS_ENABLE,
4019+
.host = cpuc->pebs_enabled,
4020+
.guest = 0,
4021+
};
4022+
return arr;
39974023
}
39984024

4025+
if (!x86_pmu.pebs_ept)
4026+
return arr;
4027+
pebs_enable = (*nr)++;
4028+
4029+
arr[pebs_enable] = (struct perf_guest_switch_msr){
4030+
.msr = MSR_IA32_PEBS_ENABLE,
4031+
.host = cpuc->pebs_enabled & ~cpuc->intel_ctrl_guest_mask,
4032+
.guest = pebs_mask & ~cpuc->intel_ctrl_host_mask,
4033+
};
4034+
4035+
/* Set hw GLOBAL_CTRL bits for PEBS counter when it runs for guest */
4036+
arr[0].guest |= arr[*nr].guest;
4037+
39994038
return arr;
40004039
}
40014040

arch/x86/include/asm/kvm_host.h

+3
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ struct kvm_pmu {
521521
DECLARE_BITMAP(all_valid_pmc_idx, X86_PMC_IDX_MAX);
522522
DECLARE_BITMAP(pmc_in_use, X86_PMC_IDX_MAX);
523523

524+
u64 pebs_enable;
525+
u64 pebs_enable_mask;
526+
524527
/*
525528
* The gate to release perf_events not marked in
526529
* pmc_in_use only once in a vcpu time slice.

arch/x86/include/asm/msr-index.h

+6
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@
196196
#define PERF_CAP_PT_IDX 16
197197

198198
#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6
199+
#define PERF_CAP_PEBS_TRAP BIT_ULL(6)
200+
#define PERF_CAP_ARCH_REG BIT_ULL(7)
201+
#define PERF_CAP_PEBS_FORMAT 0xf00
202+
#define PERF_CAP_PEBS_BASELINE BIT_ULL(14)
203+
#define PERF_CAP_PEBS_MASK (PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \
204+
PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE)
199205

200206
#define MSR_IA32_RTIT_CTL 0x00000570
201207
#define RTIT_CTL_TRACEEN BIT(0)

arch/x86/kvm/vmx/pmu_intel.c

+31
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
214214
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
215215
ret = pmu->version > 1;
216216
break;
217+
case MSR_IA32_PEBS_ENABLE:
218+
ret = vcpu->arch.perf_capabilities & PERF_CAP_PEBS_FORMAT;
219+
break;
217220
default:
218221
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
219222
get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
@@ -361,6 +364,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
361364
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
362365
msr_info->data = 0;
363366
return 0;
367+
case MSR_IA32_PEBS_ENABLE:
368+
msr_info->data = pmu->pebs_enable;
369+
return 0;
364370
default:
365371
if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
366372
(pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -421,6 +427,14 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
421427
return 0;
422428
}
423429
break;
430+
case MSR_IA32_PEBS_ENABLE:
431+
if (pmu->pebs_enable == data)
432+
return 0;
433+
if (!(data & pmu->pebs_enable_mask)) {
434+
pmu->pebs_enable = data;
435+
return 0;
436+
}
437+
break;
424438
default:
425439
if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
426440
(pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -489,6 +503,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
489503
pmu->reserved_bits = 0xffffffff00200000ull;
490504
pmu->raw_event_mask = X86_RAW_EVENT_MASK;
491505
pmu->fixed_ctr_ctrl_mask = ~0ull;
506+
pmu->pebs_enable_mask = ~0ull;
492507

493508
entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
494509
if (!entry || !vcpu->kvm->arch.enable_pmu)
@@ -560,6 +575,22 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
560575

561576
if (lbr_desc->records.nr)
562577
bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);
578+
579+
if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_FORMAT) {
580+
if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_BASELINE) {
581+
pmu->pebs_enable_mask = ~pmu->global_ctrl;
582+
pmu->reserved_bits &= ~ICL_EVENTSEL_ADAPTIVE;
583+
for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
584+
pmu->fixed_ctr_ctrl_mask &=
585+
~(1ULL << (INTEL_PMC_IDX_FIXED + i * 4));
586+
}
587+
} else {
588+
pmu->pebs_enable_mask =
589+
~((1ull << pmu->nr_arch_gp_counters) - 1);
590+
}
591+
} else {
592+
vcpu->arch.perf_capabilities &= ~PERF_CAP_PEBS_MASK;
593+
}
563594
}
564595

565596
static void intel_pmu_init(struct kvm_vcpu *vcpu)

arch/x86/kvm/x86.c

+1
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,7 @@ static const u32 msrs_to_save_all[] = {
14481448
MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13,
14491449
MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15,
14501450
MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17,
1451+
MSR_IA32_PEBS_ENABLE,
14511452

14521453
MSR_K7_EVNTSEL0, MSR_K7_EVNTSEL1, MSR_K7_EVNTSEL2, MSR_K7_EVNTSEL3,
14531454
MSR_K7_PERFCTR0, MSR_K7_PERFCTR1, MSR_K7_PERFCTR2, MSR_K7_PERFCTR3,

0 commit comments

Comments
 (0)