summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-05-20 17:34:30 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-22 08:18:23 +0200
commita1b9c6b4cba0e8ee069670e0185026859b6df361 (patch)
treec49c6146dfe76f5235aabde17ada347f6265db9a
parent7caddacf863f128e21a0ceb092dafa3801b95c20 (diff)
downloadlinux-stable-a1b9c6b4cba0e8ee069670e0185026859b6df361.tar.gz
linux-stable-a1b9c6b4cba0e8ee069670e0185026859b6df361.tar.bz2
linux-stable-a1b9c6b4cba0e8ee069670e0185026859b6df361.zip
KVM: x86/pmu: do not mask the value that is written to fixed PMUs
[ Upstream commit 2924b52117b2812e9633d5ea337333299166d373 ] According to the SDM, for MSR_IA32_PERFCTR0/1 "the lower-order 32 bits of each MSR may be written with any value, and the high-order 8 bits are sign-extended according to the value of bit 31", but the fixed counters in real hardware are limited to the width of the fixed counters ("bits beyond the width of the fixed-function counter are reserved and must be written as zeros"). Fix KVM to do the same. Reported-by: Nadav Amit <nadav.amit@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--arch/x86/kvm/pmu_intel.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c
index 23a7c7ba377a..8fc07ea23344 100644
--- a/arch/x86/kvm/pmu_intel.c
+++ b/arch/x86/kvm/pmu_intel.c
@@ -235,11 +235,14 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
}
break;
default:
- if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
- (pmc = get_fixed_pmc(pmu, msr))) {
- if (!msr_info->host_initiated)
- data = (s64)(s32)data;
- pmc->counter += data - pmc_read_counter(pmc);
+ if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) {
+ if (msr_info->host_initiated)
+ pmc->counter = data;
+ else
+ pmc->counter = (s32)data;
+ return 0;
+ } else if ((pmc = get_fixed_pmc(pmu, msr))) {
+ pmc->counter = data;
return 0;
} else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
if (data == pmc->eventsel)