| From 5ba81ba53c59bbff18d1f40e05e292adf84213b0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 26 Feb 2022 15:41:31 -0800 |
| Subject: KVM: x86/svm: Clear reserved bits written to PerfEvtSeln MSRs |
| |
| From: Jim Mattson <jmattson@google.com> |
| |
| [ Upstream commit 9b026073db2f1ad0e4d8b61c83316c8497981037 ] |
| |
| AMD EPYC CPUs never raise a #GP for a WRMSR to a PerfEvtSeln MSR. Some |
| reserved bits are cleared, and some are not. Specifically, on |
| Zen3/Milan, bits 19 and 42 are not cleared. |
| |
| When emulating such a WRMSR, KVM should not synthesize a #GP, |
| regardless of which bits are set. However, undocumented bits should |
| not be passed through to the hardware MSR. So, rather than checking |
| for reserved bits and synthesizing a #GP, just clear the reserved |
| bits. |
| |
| This may seem pedantic, but since KVM currently does not support the |
| "Host/Guest Only" bits (41:40), it is necessary to clear these bits |
| rather than synthesizing #GP, because some popular guests (e.g Linux) |
| will set the "Host Only" bit even on CPUs that don't support |
| EFER.SVME, and they don't expect a #GP. |
| |
| For example, |
| |
| root@Ubuntu1804:~# perf stat -e r26 -a sleep 1 |
| |
| Performance counter stats for 'system wide': |
| |
| 0 r26 |
| |
| 1.001070977 seconds time elapsed |
| |
| Feb 23 03:59:58 Ubuntu1804 kernel: [ 405.379957] unchecked MSR access error: WRMSR to 0xc0010200 (tried to write 0x0000020000130026) at rIP: 0xffffffff9b276a28 (native_write_msr+0x8/0x30) |
| Feb 23 03:59:58 Ubuntu1804 kernel: [ 405.379958] Call Trace: |
| Feb 23 03:59:58 Ubuntu1804 kernel: [ 405.379963] amd_pmu_disable_event+0x27/0x90 |
| |
| Fixes: ca724305a2b0 ("KVM: x86/vPMU: Implement AMD vPMU code for KVM") |
| Reported-by: Lotus Fenn <lotusf@google.com> |
| Signed-off-by: Jim Mattson <jmattson@google.com> |
| Reviewed-by: Like Xu <likexu@tencent.com> |
| Reviewed-by: David Dunn <daviddunn@google.com> |
| Message-Id: <20220226234131.2167175-1-jmattson@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/kvm/svm/pmu.c | 8 +++----- |
| 1 file changed, 3 insertions(+), 5 deletions(-) |
| |
| diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c |
| index 04e483471dbb..39ee0e271d9c 100644 |
| --- a/arch/x86/kvm/svm/pmu.c |
| +++ b/arch/x86/kvm/svm/pmu.c |
| @@ -260,12 +260,10 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) |
| /* MSR_EVNTSELn */ |
| pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_EVNTSEL); |
| if (pmc) { |
| - if (data == pmc->eventsel) |
| - return 0; |
| - if (!(data & pmu->reserved_bits)) { |
| + data &= ~pmu->reserved_bits; |
| + if (data != pmc->eventsel) |
| reprogram_gp_counter(pmc, data); |
| - return 0; |
| - } |
| + return 0; |
| } |
| |
| return 1; |
| -- |
| 2.35.1 |
| |