Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp847623ybz; Fri, 1 May 2020 09:35:42 -0700 (PDT) X-Google-Smtp-Source: APiQypI91QxgjR6eV0Bt81GbqGUMWJKBSMOarSwoQUb6K0wBvENARTCXUuvURna5uTw5patuXYpP X-Received: by 2002:a17:906:a418:: with SMTP id l24mr4008659ejz.362.1588350941921; Fri, 01 May 2020 09:35:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588350941; cv=none; d=google.com; s=arc-20160816; b=Z3KGV0xEEqvg10veqOwvLuxeyhgp+Fx5Wn+Os2fFXs2hXf0mOugw+Cxk+5LaIWOE/w Ot937E9mFhxMrLlrZMAHYwJfSHlfzlXigGDt6NdOZDqSD4TcKfz7tE8BqpsrxArdRhpr sU0Uyn0OjrNcGbF0mP3uCyGeXIY8XAPB/jPmOlGDp9dOcunnCS/TL9nfaJXDNiwK6ILh MGNWj7tDtWAHzTvAaAOZiDYYkreafKz+8+r41OWnfRzk9y4d1aljFMa1vjK0FQVCLol2 uMxfxLMZpmH1bCOEZWnvAvEjKjK4viidjH3iMBvJOMFspQY/mG/+aMPLnsDEeC1NANSF E/Og== 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 :message-id:date:subject:cc:to:from:ironport-sdr:ironport-sdr; bh=JQA8mMGLWUtm5ppqfXhb++Mir0dlAGVkPj8LOOvTPXA=; b=knmsgC0+d1QRwWyHmGswA1ZEljVaVn9i2q2voQ2Y0oLaZP6w345IispHI/5kQNPGSP wOeSgM8DAheOrhsIHrn5XbJSCiD6+R/u0Z1vHvJxYetrsCRlr0bSX1m4n74TkEuhKKed kukGIbchr2UCYdNx40ZKL3D0wZOwHUNWZ6JB5GF5xkNbo9RSFhnEwqHC3qiSTuL439Kr 4VFk96xWJGwPtutdlu7mz4Q3WmWL3051XSgq3jSKPamOMc9LaFWr9uKrknRcj+dza+cD do6Gw6rGIxqb/HvHky02hM/4syVYaoA9q/v7psHGQsUbTHJIkdLszz2ff8HHSa3LQGp1 6CSg== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ly8si2270296ejb.254.2020.05.01.09.35.18; Fri, 01 May 2020 09:35:41 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729858AbgEAQbT (ORCPT + 99 others); Fri, 1 May 2020 12:31:19 -0400 Received: from mga18.intel.com ([134.134.136.126]:34079 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728443AbgEAQbT (ORCPT ); Fri, 1 May 2020 12:31:19 -0400 IronPort-SDR: W5sDEKIs7gx6q57Zw/agA/E19Qt/IYxLuPV/v/5g7tJu8TK7yAikEc/cBCkU16Ixkse2k/L4ih hEbd/uaK5roA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 May 2020 09:31:18 -0700 IronPort-SDR: cpEtsaaOrcMa0T8NEjZHyuf7OcEaONkNfLXa6DIHBYIQTqjUCVND3/OmJiIN40xVxl9pVTHgus 2PfpTHNI7yKw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,340,1583222400"; d="scan'208";a="262131602" Received: from sjchrist-coffee.jf.intel.com ([10.54.74.152]) by orsmga006.jf.intel.com with ESMTP; 01 May 2020 09:31:18 -0700 From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Graf , KarimAllah Raslan Subject: [PATCH v2] KVM: nVMX: Skip IBPB when switching between vmcs01 and vmcs02 Date: Fri, 1 May 2020 09:31:17 -0700 Message-Id: <20200501163117.4655-1-sean.j.christopherson@intel.com> X-Mailer: git-send-email 2.26.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Skip the Indirect Branch Prediction Barrier that is triggered on a VMCS switch when running with spectre_v2_user=on/auto if the switch is between two VMCSes in the same guest, i.e. between vmcs01 and vmcs02. The IBPB is intended to prevent one guest from attacking another, which is unnecessary in the nested case as it's the same guest from KVM's perspective. This all but eliminates the overhead observed for nested VMX transitions when running with CONFIG_RETPOLINE=y and spectre_v2_user=on/auto, which can be significant, e.g. roughly 3x on current systems. Reported-by: Alexander Graf Cc: KarimAllah Raslan Cc: stable@vger.kernel.org Fixes: 15d45071523d ("KVM/x86: Add IBPB support") Signed-off-by: Sean Christopherson --- v2: Pass a boolean to indicate a nested VMCS switch and instead WARN if the buddy VMCS is not already loaded. [Alex] Paolo, feel free to drop the WARN_ON_ONCE() if you think it's overkill. I'm 50/50 as to whether it's useful or just a waste of cycles. Figured it'd be easier for you to delete a line of code while applying than to add and test a new WARN. arch/x86/kvm/vmx/nested.c | 3 ++- arch/x86/kvm/vmx/vmx.c | 7 ++++--- arch/x86/kvm/vmx/vmx.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 2c36f3f53108..b57420f3dd8f 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -302,8 +302,9 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs) cpu = get_cpu(); prev = vmx->loaded_vmcs; + WARN_ON_ONCE(prev->cpu != cpu || prev->vmcs != per_cpu(current_vmcs, cpu)); vmx->loaded_vmcs = vmcs; - vmx_vcpu_load_vmcs(vcpu, cpu); + vmx_vcpu_load_vmcs(vcpu, cpu, true); vmx_sync_vmcs_host_state(vmx, prev); put_cpu(); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 3ab6ca6062ce..d3d57b7a67bd 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1311,7 +1311,7 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu) pi_set_on(pi_desc); } -void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu) +void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu, bool nested_switch) { struct vcpu_vmx *vmx = to_vmx(vcpu); bool already_loaded = vmx->loaded_vmcs->cpu == cpu; @@ -1336,7 +1336,8 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu) if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) { per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs; vmcs_load(vmx->loaded_vmcs->vmcs); - indirect_branch_prediction_barrier(); + if (!nested_switch) + indirect_branch_prediction_barrier(); } if (!already_loaded) { @@ -1377,7 +1378,7 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); - vmx_vcpu_load_vmcs(vcpu, cpu); + vmx_vcpu_load_vmcs(vcpu, cpu, false); vmx_vcpu_pi_load(vcpu, cpu); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index b5e773267abe..fa61dc802183 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -320,7 +320,7 @@ struct kvm_vmx { }; bool nested_vmx_allowed(struct kvm_vcpu *vcpu); -void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu); +void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu, bool nested_switch); void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu); int allocate_vpid(void); void free_vpid(int vpid); -- 2.26.0