Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp491488ybt; Wed, 8 Jul 2020 05:01:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxMfyCthuneM63P3t9Lrx9nepB1WPy/KR5YI5RXMip1hZbiVusK/GdfmRB0Bm2TOPivis2a X-Received: by 2002:a17:906:2714:: with SMTP id z20mr51522955ejc.469.1594209680521; Wed, 08 Jul 2020 05:01:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594209680; cv=none; d=google.com; s=arc-20160816; b=W+VaAX3Okpfac0e4u0bj/iif0f6PK43Fp0M+jXMGy7L/wgwEqvlJm9N6QxqAmQRPcI yyzKyftn+qG9KHcwhJMhMneFKWnKzenW8X+G1kDRfR2RSUCMt6AY4ok/00hlZiEE7e9a CzsrM3gVEZR1YLPQIbeIhMXwOamwFW3Lne8PsPs5brD8BCQYoTPNyn4LTQVn9LGKKBIM pDPi0cQaWtNJ8cBX9WAZ+He+Ao0GffX2NCD9rI2efcyq/v8SuAxnNo7yWD9YPse3pT74 l5wSGzMyoYXCpg0kULHrrh9P9XWtmgwX+ZhuYOg1O/7w55rmt4ifExP091s7Yd7y55wR HySA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=xxyPm+jDOr7wCv3oAZynzwxs2yrC7rLwPNCtJFDBYtU=; b=oAWGrklpnlgc54xJZaATES6xFqZW3rtsV0hlYDgVrtBDke+1dAsa701KjpXAl3b00W w9sE932U2+0+1cR+7hbbATTX+tmAFPqQsP7Xj200K63v53E5Y1ulYufumfHzqrXclXWl AiMpsExPGlQRorTMFxDn0qkYqEvDc4qBFhcJUUcWCZdMhGseD/YeujTkSK4t9j7iWG+u sB8HdksNZB7/VBVQ0Ftw7APkOrXRDaW8A8sYPNWxikEekBDbw4ZcgRK7XG6hNGlAp22F A2/JY+og2Rh9W5dd5CVGYD1kX8ACrLhuhNV0aAQ2peYOEuC2wWN5AR5AO+ykjq7KxnSU hRog== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=au1b5dUF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a16si16945007ejy.84.2020.07.08.05.00.56; Wed, 08 Jul 2020 05:01:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=au1b5dUF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728765AbgGHL5n (ORCPT + 99 others); Wed, 8 Jul 2020 07:57:43 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:33436 "EHLO us-smtp-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728592AbgGHL5n (ORCPT ); Wed, 8 Jul 2020 07:57:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594209461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xxyPm+jDOr7wCv3oAZynzwxs2yrC7rLwPNCtJFDBYtU=; b=au1b5dUFJgfJHnlkVvQh2HisqI41jmJrKWjgehrd6i56DhwJkz2H5mZ+/NWYYouy22afzm x4GkBF7wUt6Hluusk/Do2VK+kbpMdv+7YIRWVGCVfmgjEhQ9kdGGPYmB+yGwSoVEUfaBih oafj1ZSHAQaM8IgaKL/mxNkzVWUxrtQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-279-itPGOpVvOzyEQMgo2DBuUg-1; Wed, 08 Jul 2020 07:57:39 -0400 X-MC-Unique: itPGOpVvOzyEQMgo2DBuUg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 54F221902EA0; Wed, 8 Jul 2020 11:57:37 +0000 (UTC) Received: from starship.redhat.com (unknown [10.35.206.247]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9B60679247; Wed, 8 Jul 2020 11:57:32 +0000 (UTC) From: Maxim Levitsky To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ingo Molnar , Vitaly Kuznetsov , Jim Mattson , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)), Wanpeng Li , Joerg Roedel , "H. Peter Anvin" , Thomas Gleixner , Sean Christopherson , Borislav Petkov , Maxim Levitsky Subject: [PATCH] kvm: x86: replace kvm_spec_ctrl_test_value with runtime test on the host Date: Wed, 8 Jul 2020 14:57:31 +0300 Message-Id: <20200708115731.180097-1-mlevitsk@redhat.com> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To avoid complex and in some cases incorrect logic in kvm_spec_ctrl_test_value, just try the guest's given value on the host processor instead, and if it doesn't #GP, allow the guest to set it. One such case is when host CPU supports STIBP mitigation but doesn't support IBRS (as is the case with some Zen2 AMD cpus), and in this case we were giving guest #GP when it tried to use STIBP The reason why can can do the host test is that IA32_SPEC_CTRL msr is passed to the guest, after the guest sets it to a non zero value for the first time (due to performance reasons), and as as result of this, it is pointless to emulate #GP condition on this first access, in a different way than what the host CPU does. This is based on a patch from Sean Christopherson, who suggested this idea. Fixes: 6441fa6178f5 ("KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL") Suggested-by: Sean Christopherson Signed-off-by: Maxim Levitsky --- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/x86.c | 38 +++++++++++++++++++++----------------- arch/x86/kvm/x86.h | 2 +- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 74096aa72ad9..80421a72beb0 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2522,7 +2522,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) return 1; - if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1; svm->spec_ctrl = data; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 8187ca152ad2..01643893cf8e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2065,7 +2065,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) return 1; - if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1; vmx->spec_ctrl = data; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 09ee54f5e385..84da4d0cc05a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10706,28 +10706,32 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_arch_no_poll); -u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu) + +int kvm_spec_ctrl_test_value(u64 value) { - uint64_t bits = SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD; + /* + * test that setting IA32_SPEC_CTRL to given value + * is allowed by the host processor + */ + + u64 saved_value; + unsigned long flags; + int ret = 0; - /* The STIBP bit doesn't fault even if it's not advertised */ - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL) && - !boot_cpu_has(X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); + local_irq_save(flags); - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL_SSBD) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) && - !boot_cpu_has(X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; + if (rdmsrl_safe(MSR_IA32_SPEC_CTRL, &saved_value)) + ret = 1; + else if (wrmsrl_safe(MSR_IA32_SPEC_CTRL, value)) + ret = 1; + else + wrmsrl(MSR_IA32_SPEC_CTRL, saved_value); - return bits; + local_irq_restore(flags); + + return ret; } -EXPORT_SYMBOL_GPL(kvm_spec_ctrl_valid_bits); +EXPORT_SYMBOL_GPL(kvm_spec_ctrl_test_value); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 31928bf18ba5..73780a832691 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -368,7 +368,7 @@ static inline bool kvm_dr6_valid(u64 data) void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu); void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu); -u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu); +int kvm_spec_ctrl_test_value(u64 value); bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu); #define KVM_MSR_RET_INVALID 2 -- 2.25.4