]>
Commit | Line | Data |
---|---|---|
97c569a1 SL |
1 | From 1abdc7e52abb4227689ac20ac0eadff1b0454019 Mon Sep 17 00:00:00 2001 |
2 | From: Paolo Bonzini <pbonzini@redhat.com> | |
3 | Date: Mon, 20 May 2019 17:34:30 +0200 | |
4 | Subject: KVM: x86/pmu: do not mask the value that is written to fixed PMUs | |
5 | ||
6 | [ Upstream commit 2924b52117b2812e9633d5ea337333299166d373 ] | |
7 | ||
8 | According to the SDM, for MSR_IA32_PERFCTR0/1 "the lower-order 32 bits of | |
9 | each MSR may be written with any value, and the high-order 8 bits are | |
10 | sign-extended according to the value of bit 31", but the fixed counters | |
11 | in real hardware are limited to the width of the fixed counters ("bits | |
12 | beyond the width of the fixed-function counter are reserved and must be | |
13 | written as zeros"). Fix KVM to do the same. | |
14 | ||
15 | Reported-by: Nadav Amit <nadav.amit@gmail.com> | |
16 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | |
17 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
18 | --- | |
19 | arch/x86/kvm/pmu_intel.c | 13 ++++++++----- | |
20 | 1 file changed, 8 insertions(+), 5 deletions(-) | |
21 | ||
22 | diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c | |
23 | index 5ab4a364348e..2729131fe9bf 100644 | |
24 | --- a/arch/x86/kvm/pmu_intel.c | |
25 | +++ b/arch/x86/kvm/pmu_intel.c | |
26 | @@ -235,11 +235,14 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |
27 | } | |
28 | break; | |
29 | default: | |
30 | - if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || | |
31 | - (pmc = get_fixed_pmc(pmu, msr))) { | |
32 | - if (!msr_info->host_initiated) | |
33 | - data = (s64)(s32)data; | |
34 | - pmc->counter += data - pmc_read_counter(pmc); | |
35 | + if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) { | |
36 | + if (msr_info->host_initiated) | |
37 | + pmc->counter = data; | |
38 | + else | |
39 | + pmc->counter = (s32)data; | |
40 | + return 0; | |
41 | + } else if ((pmc = get_fixed_pmc(pmu, msr))) { | |
42 | + pmc->counter = data; | |
43 | return 0; | |
44 | } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { | |
45 | if (data == pmc->eventsel) | |
46 | -- | |
47 | 2.20.1 | |
48 |