From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751946AbdLFLrS (ORCPT ); Wed, 6 Dec 2017 06:47:18 -0500 Received: from [195.214.232.25] ([195.214.232.25]:40772 "EHLO relay.sw.ru" rhost-flags-FAIL-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1751453AbdLFLrP (ORCPT ); Wed, 6 Dec 2017 06:47:15 -0500 From: Jan Dakinevich To: linux-kernel@vger.kernel.org Cc: Jan Dakinevich , "Denis V . Lunev" , Roman Kagan , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , "H. Peter Anvin" , x86@kernel.org, Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Andi Kleen , Kan Liang , Stephane Eranian , Colin King , Sebastian Andrzej Siewior , Jin Yao , kvm@vger.kernel.org Subject: [PATCH RFC 2/2] KVM: x86/vPMU: ignore access to LBR-related MSRs Date: Wed, 6 Dec 2017 14:43:03 +0300 Message-Id: <1512560585-27263-3-git-send-email-jan.dakinevich@virtuozzo.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1512560585-27263-1-git-send-email-jan.dakinevich@virtuozzo.com> References: <1512560585-27263-1-git-send-email-jan.dakinevich@virtuozzo.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Windows Server 2016 Essentials (for yet unknown reason) attempts to access MSR_LBR_TOS and other LBR-related registers at startup. These are not currently hadled by KVM so the guest gets #GP and crashes. To prevent that, identify LBR-related MSRs pertinent to the CPU model exposed to the guest, and dummy handle them (ignore writes and return zero on reads). Signed-off-by: Jan Dakinevich --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/pmu_intel.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 977de5f..04324dd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -34,6 +34,7 @@ #include #include #include +#include #define KVM_MAX_VCPUS 288 #define KVM_SOFT_MAX_VCPUS 240 @@ -416,6 +417,7 @@ struct kvm_pmu { struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED]; struct irq_work irq_work; u64 reprogram_pmi; + struct x86_pmu_lbr lbr; }; struct kvm_pmu_ops; diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c index 5ab4a36..7edf191 100644 --- a/arch/x86/kvm/pmu_intel.c +++ b/arch/x86/kvm/pmu_intel.c @@ -142,6 +142,24 @@ static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, return &counters[idx]; } +static bool intel_is_lbr_msr(struct kvm_vcpu *vcpu, u32 msr) +{ + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + struct x86_pmu_lbr *lbr = &pmu->lbr; + + if (!lbr->nr) + return false; + + if (msr == lbr->tos) + return true; + if (msr >= lbr->from && msr < lbr->from + lbr->nr) + return true; + if (msr >= lbr->to && msr < lbr->to + lbr->nr) + return true; + + return false; +} + static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -155,6 +173,10 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) ret = pmu->version > 1; break; default: + if (intel_is_lbr_msr(vcpu, msr)) { + ret = true; + break; + } ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) || get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) || get_fixed_pmc(pmu, msr); @@ -183,6 +205,10 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data) *data = pmu->global_ovf_ctrl; return 0; default: + if (intel_is_lbr_msr(vcpu, msr)) { + *data = 0; + return 0; + } if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_fixed_pmc(pmu, msr))) { *data = pmc_read_counter(pmc); @@ -235,6 +261,8 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } break; default: + if (intel_is_lbr_msr(vcpu, msr)) + return 0; if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_fixed_pmc(pmu, msr))) { if (!msr_info->host_initiated) @@ -303,6 +331,11 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) && (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED; + + entry = kvm_find_cpuid_entry(vcpu, 1, 0); + if (entry) + intel_pmu_lbr_fill(&pmu->lbr, + x86_family(entry->eax), x86_model(entry->eax)); } static void intel_pmu_init(struct kvm_vcpu *vcpu) -- 2.1.4