Skip to content

Commit 7a0fc73

Browse files
committed
KVM: x86/pmu: Treat "fixed" PMU type in RDPMC as index as a value, not flag
Refactor KVM's handling of ECX for RDPMC to treat the FIXED modifier as an explicit value, not a flag (minus one wart). While non-architectural PMUs do use bit 31 as a flag (for "fast" reads), architectural PMUs use the upper half of ECX to encode the type. From the SDM: ECX[31:16] specifies type of PMC while ECX[15:0] specifies the index of the PMC to be read within that type Note, that the known supported types are 4000H and 2000H, i.e. look a lot like flags, doesn't contradict the above statement that ECX[31:16] holds the type, at least not by any sane reading of the SDM. Keep the explicitly clearing of the FIXED "flag", as KVM subtly relies on that behavior to disallow unsupported types while allowing the correct indices for fixed counters. This wart will be cleaned up in short order. Opportunistically grab the per-type bitmask in the if-else blocks to eliminate the one-off usage of the local "fixed" bool. Reported-by: Jim Mattson <jmattson@google.com> Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20240109230250.424295-11-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 5728a4a commit 7a0fc73

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

arch/x86/kvm/vmx/pmu_intel.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
*/
2929
#define INTEL_RDPMC_FIXED INTEL_PMC_FIXED_RDPMC_BASE
3030

31+
#define INTEL_RDPMC_TYPE_MASK GENMASK(31, 16)
32+
#define INTEL_RDPMC_INDEX_MASK GENMASK(15, 0)
33+
3134
#define MSR_PMC_FULL_WIDTH_BIT (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0)
3235

3336
static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
@@ -66,10 +69,11 @@ static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
6669
static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
6770
unsigned int idx, u64 *mask)
6871
{
72+
unsigned int type = idx & INTEL_RDPMC_TYPE_MASK;
6973
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
70-
bool fixed = idx & INTEL_RDPMC_FIXED;
7174
struct kvm_pmc *counters;
7275
unsigned int num_counters;
76+
u64 bitmask;
7377

7478
/*
7579
* The encoding of ECX for RDPMC is different for architectural versus
@@ -90,16 +94,20 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
9094
* i.e. let RDPMC fail due to accessing a non-existent counter.
9195
*/
9296
idx &= ~INTEL_RDPMC_FIXED;
93-
if (fixed) {
97+
if (type == INTEL_RDPMC_FIXED) {
9498
counters = pmu->fixed_counters;
9599
num_counters = pmu->nr_arch_fixed_counters;
100+
bitmask = pmu->counter_bitmask[KVM_PMC_FIXED];
96101
} else {
97102
counters = pmu->gp_counters;
98103
num_counters = pmu->nr_arch_gp_counters;
104+
bitmask = pmu->counter_bitmask[KVM_PMC_GP];
99105
}
106+
100107
if (idx >= num_counters)
101108
return NULL;
102-
*mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP];
109+
110+
*mask &= bitmask;
103111
return &counters[array_index_nospec(idx, num_counters)];
104112
}
105113

0 commit comments

Comments
 (0)