KVM: x86/pmu: do not mask the value that is written to fixed PMUs [Linux 4.14.128]

KVM: x86/pmu: do not mask the value that is written to fixed PMUs [Linux 4.14.128]

This Linux kernel change "KVM: x86/pmu: do not mask the value that is written to fixed PMUs" is included in the Linux 4.14.128 release. This change is authored by Paolo Bonzini <pbonzini [at] redhat.com> on Mon May 20 17:34:30 2019 +0200. The commit for this change in Linux stable tree is 891bd1a (patch) which is from upstream commit 2924b52. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 2924b52.

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>

There are 13 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/x86/kvm/pmu_intel.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c
index 5ab4a36..2729131 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)

Leave a Reply

Your email address will not be published. Required fields are marked *