From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F4067191F84; Tue, 3 Mar 2026 00:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; cv=none; b=oOMfyptdjKeF7p9Hqzm6ogqw/wcAgATYUP45AsQaWTpUcL0xAS8AAO1AIgH71MAj7F3Y4ihTnp1RPta15Dr8qNDBVC6GWyYJWowlK/HC9DxKh6YsJDb3BhMKjTdYPOGLjliJ/y/M2j6NiFkU/3BaQMHRwyfpPRrc8dPAssiDKWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; c=relaxed/simple; bh=r3uyst2XvPutZGbquByoEiZKlWPLg+wME7+Xtx442m8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MrTL9k9llVJ6Rv/kn66yFvL6pSVhjE2kB0sZ9638p196AMjHj3Bk3DLNeEiwE8Mxne0obtcD5HrR4qVfT1x3hNQQcCSQ/zhjUFbzWvnJV+YYolVMghNB8PcYGMCElG9CsuQ4Pr0KsPSw0ajx7eEDCZoW2ci4wrxinJmRNXz1+os= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RZN0NjD6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RZN0NjD6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 985FDC2BC86; Tue, 3 Mar 2026 00:34:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498071; bh=r3uyst2XvPutZGbquByoEiZKlWPLg+wME7+Xtx442m8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RZN0NjD6Nlv+t54IfI4pkwAjAEdS3Ox4SQtQ8bSFedQuhsyYF1jxmqGKmC6OjrKts CDag9+lMR/1Z+adjsC1KQBZIS7N9FkxIHUEP9gbsXTuCXgCYg+kTJByjoYv0SRXosH sch5pErh0d2L7LjcWvQQjFifGuhsn4iERO85/3sdBujf0AuU9iAr0QVBh5GJy6VVJu NRRyJfDCfcS32T/qemJ+CBNz59+tctBLsDvc7nJogjrEdMIJpeSUh+pPZ2kToUZU3t eaK6sgIr4gUC81tmrNjXF2365USmjh40BPdByg94RpSxs6857npU/jZu6z9Q1P7lgq sKYMNB8XR4fXw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 01/26] KVM: nSVM: Avoid clearing VMCB_LBR in vmcb12 Date: Tue, 3 Mar 2026 00:33:55 +0000 Message-ID: <20260303003421.2185681-2-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" svm_copy_lbrs() always marks VMCB_LBR dirty in the destination VMCB. However, nested_svm_vmexit() uses it to copy LBRs to vmcb12, and clearing clean bits in vmcb12 is not architecturally defined. Move vmcb_mark_dirty() to callers and drop it for vmcb12. This also facilitates incoming refactoring that does not pass the entire VMCB to svm_copy_lbrs(). Fixes: d20c796ca370 ("KVM: x86: nSVM: implement nested LBR virtualization") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 7 +++++-- arch/x86/kvm/svm/svm.c | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index de90b104a0dd5..a31f3be1e16ec 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -714,6 +714,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm = *svm, struct vmcb *vmcb12 } else { svm_copy_lbrs(vmcb02, vmcb01); } + vmcb_mark_dirty(vmcb02, VMCB_LBR); svm_update_lbrv(&svm->vcpu); } =20 @@ -1232,10 +1233,12 @@ int nested_svm_vmexit(struct vcpu_svm *svm) kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); =20 if (unlikely(guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && - (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) + (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { svm_copy_lbrs(vmcb12, vmcb02); - else + } else { svm_copy_lbrs(vmcb01, vmcb02); + vmcb_mark_dirty(vmcb01, VMCB_LBR); + } =20 svm_update_lbrv(vcpu); =20 diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 8f8bc863e2143..a2452b8ec49db 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -848,8 +848,6 @@ void svm_copy_lbrs(struct vmcb *to_vmcb, struct vmcb *f= rom_vmcb) to_vmcb->save.br_to =3D from_vmcb->save.br_to; to_vmcb->save.last_excp_from =3D from_vmcb->save.last_excp_from; to_vmcb->save.last_excp_to =3D from_vmcb->save.last_excp_to; - - vmcb_mark_dirty(to_vmcb, VMCB_LBR); } =20 static void __svm_enable_lbrv(struct kvm_vcpu *vcpu) --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98FFB21883E; Tue, 3 Mar 2026 00:34:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; cv=none; b=Epn4kZ40+xLAX90d7URngoCvqvqPfJAWToq3eF3NFf6n7mKAXDq1bSqT9HZLR7KK+6gQwV+YmvRzbkvVA5b3iQ7MsSIEC4P02Wq/grFjrud3uvugZq5Mb6Akr+tRvflSO5wIA6rAGrhudCA9uVP8dG3MbxENJ46YFHFnNb8x1iw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; c=relaxed/simple; bh=wtmh9IxPpm9GtrspXY0nCDingbw85AxM/W+Q+IOm3VM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lTOEm+/m/EixVwqwsFxVI1BDCWgJ25OGxOit5i6LD68D6A6dGvWpo406ucj7xsC0T7KoQJR6iVtQ5FamkkJrT2R1NKcrG+O1OxfQIW7N2V9b7JovqTI79UX3NC2yGsiyudZkW6wfUwCqtauM/kdfFBUVy1qSBGG3Q4xzzLe8/yU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NuN8aMxw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NuN8aMxw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A09FC2BC9E; Tue, 3 Mar 2026 00:34:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498072; bh=wtmh9IxPpm9GtrspXY0nCDingbw85AxM/W+Q+IOm3VM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NuN8aMxwKLt+eWsh9H5mMM6FkvwRtRE0KayVGnP0edSIMftI+tS+KvovqFS4jEbPk HNlaarGWWghKTTVdMkDce/yhrCLHe8oJRgSnk1vEGEGMTAPHZuHOFEhQ3ogujnkrYJ z9x0op5I0Qv6nCIASREg73uCtnWFy74AWFrbA1JjqWIdTdT6cpkBRM9t/cZoitGCQ+ xz0dyMuSaDaX/gx9TL+FD9YIHrz3NPm9tK76Or59Gfqrj24R/zZntOMvWuWaVFRWIY S6PpC8ozmfOzsWWtVNIe//SrIYVYw+x9aUXm/nra1o8mz4m0mlPUSBnPlPLjlVra9y yk/V5CrDF69Qg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 02/26] KVM: SVM: Switch svm_copy_lbrs() to a macro Date: Tue, 3 Mar 2026 00:33:56 +0000 Message-ID: <20260303003421.2185681-3-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for using svm_copy_lbrs() with 'struct vmcb_save_area' without a containing 'struct vmcb', and later even 'struct vmcb_save_area_cached', make it a macro. Macros are generally not preferred compared to functions, mainly due to type-safety. However, in this case it seems like having a simple macro copying a few fields is better than copy-pasting the same 5 lines of code in different places. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 8 ++++---- arch/x86/kvm/svm/svm.c | 9 --------- arch/x86/kvm/svm/svm.h | 10 +++++++++- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index a31f3be1e16ec..f7d5db0af69ac 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -709,10 +709,10 @@ static void nested_vmcb02_prepare_save(struct vcpu_sv= m *svm, struct vmcb *vmcb12 * Reserved bits of DEBUGCTL are ignored. Be consistent with * svm_set_msr's definition of reserved bits. */ - svm_copy_lbrs(vmcb02, vmcb12); + svm_copy_lbrs(&vmcb02->save, &vmcb12->save); vmcb02->save.dbgctl &=3D ~DEBUGCTL_RESERVED_BITS; } else { - svm_copy_lbrs(vmcb02, vmcb01); + svm_copy_lbrs(&vmcb02->save, &vmcb01->save); } vmcb_mark_dirty(vmcb02, VMCB_LBR); svm_update_lbrv(&svm->vcpu); @@ -1234,9 +1234,9 @@ int nested_svm_vmexit(struct vcpu_svm *svm) =20 if (unlikely(guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { - svm_copy_lbrs(vmcb12, vmcb02); + svm_copy_lbrs(&vmcb12->save, &vmcb02->save); } else { - svm_copy_lbrs(vmcb01, vmcb02); + svm_copy_lbrs(&vmcb01->save, &vmcb02->save); vmcb_mark_dirty(vmcb01, VMCB_LBR); } =20 diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index a2452b8ec49db..f52e588317fcf 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -841,15 +841,6 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu = *vcpu) */ } =20 -void svm_copy_lbrs(struct vmcb *to_vmcb, struct vmcb *from_vmcb) -{ - to_vmcb->save.dbgctl =3D from_vmcb->save.dbgctl; - to_vmcb->save.br_from =3D from_vmcb->save.br_from; - to_vmcb->save.br_to =3D from_vmcb->save.br_to; - to_vmcb->save.last_excp_from =3D from_vmcb->save.last_excp_from; - to_vmcb->save.last_excp_to =3D from_vmcb->save.last_excp_to; -} - static void __svm_enable_lbrv(struct kvm_vcpu *vcpu) { to_svm(vcpu)->vmcb->control.virt_ext |=3D LBR_CTL_ENABLE_MASK; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index ebd7b36b1ceb9..44d767cd1d25a 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -713,8 +713,16 @@ static inline void *svm_vcpu_alloc_msrpm(void) return svm_alloc_permissions_map(MSRPM_SIZE, GFP_KERNEL_ACCOUNT); } =20 +#define svm_copy_lbrs(to, from) \ +do { \ + (to)->dbgctl =3D (from)->dbgctl; \ + (to)->br_from =3D (from)->br_from; \ + (to)->br_to =3D (from)->br_to; \ + (to)->last_excp_from =3D (from)->last_excp_from; \ + (to)->last_excp_to =3D (from)->last_excp_to; \ +} while (0) + void svm_vcpu_free_msrpm(void *msrpm); -void svm_copy_lbrs(struct vmcb *to_vmcb, struct vmcb *from_vmcb); void svm_enable_lbrv(struct kvm_vcpu *vcpu); void svm_update_lbrv(struct kvm_vcpu *vcpu); =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2701222599; Tue, 3 Mar 2026 00:34:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; cv=none; b=YkW9IL9zDDgRblYLiZ4YP18KldI60kBWd3ntFOj5P8/aVYNlFs1IMhhU9x8OAAkdOSbV+EfxtiILsD9a98nxYg63xfLsdUhHW2fis19/Zox8nqwXStFlI7yZZaQrDhwKPeJGVwueZGuW4Dc7p5oqI2hzJZF7BTmbnUu9MpWFAQU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498072; c=relaxed/simple; bh=bzvY4YRGMLfrodijPDFgV86Y9a5hYWOyqUPTjZ20rsE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rTBPmT2go8gE/SDsWwG9TyLNKk8yK/evkDKbH2XhDEwsfydzgRtS6a2RJaPv1q6hlTukbt75Bq4eZgRm0ROQhSdaJdxpQO01fJokymYlacaKt6hb9aYs0bWHtD7mG9OLp8fZyOfdWtBfwFGFPXfLvclfKftQOITSet0N69f+zTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l654d4/w; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l654d4/w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 706E7C2BCAF; Tue, 3 Mar 2026 00:34:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498072; bh=bzvY4YRGMLfrodijPDFgV86Y9a5hYWOyqUPTjZ20rsE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l654d4/wAl5yqVTdMpefI8/iCp5hW3OcSK4fsntbm/XeZQI+4gIFYuNCLq1gpu6eN gjPBRoctTJ3Ag4RjmawL/ZYNJ6wuzkldLzqWRwpYQyXlY6IcKFla92QrDAtBcx6bjX nqaTCt90Aa13gUaaKUNes4hdT5E59OauCEe0oIJFs9BZUjaTGA+fCG0OH53AHXdv9B SOI0/LVIGLzOGXdO5MKezyrk9U2mFibD5Mkj+AVv21DOgzn3AV7qWTVd2hCjJrOz3a /gRH3QJ0+Wq1kmH4SzPdEdaOetqt11lUvxAUqAuS/hEJfakA4z2ZYOn/951aHicxCh eOKLw9if3KvZQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org, Jim Mattson Subject: [PATCH v7 03/26] KVM: SVM: Add missing save/restore handling of LBR MSRs Date: Tue, 3 Mar 2026 00:33:57 +0000 Message-ID: <20260303003421.2185681-4-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" MSR_IA32_DEBUGCTLMSR and LBR MSRs are currently not enumerated by KVM_GET_MSR_INDEX_LIST, and LBR MSRs cannot be set with KVM_SET_MSRS. So save/restore is completely broken. Fix it by adding the MSRs to msrs_to_save_base, and allowing writes to LBR MSRs from userspace only (as they are read-only MSRs). Additionally, to correctly restore L1's LBRs while L2 is running, make sure the LBRs are copied from the captured VMCB01 save area in svm_copy_vmrun_state(). For VMX, this also adds save/restore handling of KVM_GET_MSR_INDEX_LIST. For unspported MSR_IA32_LAST* MSRs, kvm_do_msr_access() should 0 these MSRs on userspace reads, and ignore KVM_MSR_RET_UNSUPPORTED on userspace writes. Fixes: 24e09cbf480a ("KVM: SVM: enable LBR virtualization") Cc: stable@vger.kernel.org Reported-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 5 +++++ arch/x86/kvm/svm/svm.c | 24 ++++++++++++++++++++++++ arch/x86/kvm/x86.c | 3 +++ 3 files changed, 32 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f7d5db0af69ac..3bf758c9cb85c 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1100,6 +1100,11 @@ void svm_copy_vmrun_state(struct vmcb_save_area *to_= save, to_save->isst_addr =3D from_save->isst_addr; to_save->ssp =3D from_save->ssp; } + + if (lbrv) { + svm_copy_lbrs(to_save, from_save); + to_save->dbgctl &=3D ~DEBUGCTL_RESERVED_BITS; + } } =20 void svm_copy_vmloadsave_state(struct vmcb *to_vmcb, struct vmcb *from_vmc= b) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index f52e588317fcf..cb53174583a26 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3071,6 +3071,30 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct= msr_data *msr) vmcb_mark_dirty(svm->vmcb, VMCB_LBR); svm_update_lbrv(vcpu); break; + case MSR_IA32_LASTBRANCHFROMIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.br_from =3D data; + vmcb_mark_dirty(svm->vmcb, VMCB_LBR); + break; + case MSR_IA32_LASTBRANCHTOIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.br_to =3D data; + vmcb_mark_dirty(svm->vmcb, VMCB_LBR); + break; + case MSR_IA32_LASTINTFROMIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.last_excp_from =3D data; + vmcb_mark_dirty(svm->vmcb, VMCB_LBR); + break; + case MSR_IA32_LASTINTTOIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.last_excp_to =3D data; + vmcb_mark_dirty(svm->vmcb, VMCB_LBR); + break; case MSR_VM_HSAVE_PA: /* * Old kernels did not validate the value written to diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index db3f393192d94..416899b5dbe4d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -351,6 +351,9 @@ static const u32 msrs_to_save_base[] =3D { MSR_IA32_U_CET, MSR_IA32_S_CET, MSR_IA32_PL0_SSP, MSR_IA32_PL1_SSP, MSR_IA32_PL2_SSP, MSR_IA32_PL3_SSP, MSR_IA32_INT_SSP_TAB, + MSR_IA32_DEBUGCTLMSR, + MSR_IA32_LASTBRANCHFROMIP, MSR_IA32_LASTBRANCHTOIP, + MSR_IA32_LASTINTFROMIP, MSR_IA32_LASTINTTOIP, }; =20 static const u32 msrs_to_save_pmu[] =3D { --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49BB7237707; Tue, 3 Mar 2026 00:34:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498073; cv=none; b=T6hHvc1Y5bCe/f7HXxj9E3Gn/+moL5btPGsu8bkJ1qApCylUOr4Ug9OIkaKaJz9NDd/5hdjVBk7JirtfJkD/F+W8ZxSl6wo/eA/erQRp6OIqjE2lKHgxxtsRPhyF9i2r1JLeENDMkR+HCm287st+EG8+nSCR0dILFQCh9Gi/L08= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498073; c=relaxed/simple; bh=Ppt/tEFVP57TI65aOpNIHi11mVfA2f/wK0mP+p0lMVI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uP3hS4vfaSZMOvcird3QSbpXgb7AN3ARsQl0Hbae0s67Tt414vsFMO28FLAZ0wQHhC1zfeh9W96QYhs2JUheQShlDxdbXM6GKPIneLPCehdS6UdOv1LzLGwtjq0EnHV53OIZL3U1J/HaUdSHjjSNdBiJjV6VO7FfXgD7CKMir9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NVNTax0A; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NVNTax0A" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF537C4AF09; Tue, 3 Mar 2026 00:34:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498073; bh=Ppt/tEFVP57TI65aOpNIHi11mVfA2f/wK0mP+p0lMVI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NVNTax0A82oCelbkZGDWberlI1Qg3Z12IpJrCHhTGUGezvr1bOfQJ03MObAtdzmls hqVrslLkGFdfbIkKk7SCGOVN4MJq1C4bnSX4pxqF2VY7cCJsZYUP7GwaU4nn6rj0rI lvtU6l/znwqui9lsOLZ3GpO3We35OyYCN2+dc3HtQM9Eoq3Mj6PsVgh5HiAcAHb5nT SzjyU7z2QTe/ap+bEP1DRik2pEnMnmUWLwvnyhnNG+BW9smyrCdl+8ZBe8o23iTm6A Mkcy3th7AIjobIrhIJqOBwm3ATCNuzMQTATUjV/0QJO6+8OtiSNOC7iLIPm9foN5nX TW/4tJtQjYVig== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 04/26] KVM: selftests: Add a test for LBR save/restore (ft. nested) Date: Tue, 3 Mar 2026 00:33:58 +0000 Message-ID: <20260303003421.2185681-5-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a selftest exercising save/restore with usage of LBRs in both L1 and L2, and making sure all LBRs remain intact. Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 5 + .../selftests/kvm/x86/svm_lbr_nested_state.c | 145 ++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index fdec90e854671..36b48e766e499 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -112,6 +112,7 @@ TEST_GEN_PROGS_x86 +=3D x86/svm_vmcall_test TEST_GEN_PROGS_x86 +=3D x86/svm_int_ctl_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_soft_inject_test +TEST_GEN_PROGS_x86 +=3D x86/svm_lbr_nested_state TEST_GEN_PROGS_x86 +=3D x86/tsc_scaling_sync TEST_GEN_PROGS_x86 +=3D x86/sync_regs_test TEST_GEN_PROGS_x86 +=3D x86/ucna_injection_test diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 4ebae4269e681..db0171935197d 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1360,6 +1360,11 @@ static inline bool kvm_is_ignore_msrs(void) return get_kvm_param_bool("ignore_msrs"); } =20 +static inline bool kvm_is_lbrv_enabled(void) +{ + return !!get_kvm_amd_param_integer("lbrv"); +} + uint64_t *vm_get_pte(struct kvm_vm *vm, uint64_t vaddr); =20 uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, diff --git a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c b/tools= /testing/selftests/kvm/x86/svm_lbr_nested_state.c new file mode 100644 index 0000000000000..bf16abb1152e0 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026, Google, Inc. + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" + + +#define L2_GUEST_STACK_SIZE 64 + +#define DO_BRANCH() do { asm volatile("jmp 1f\n 1: nop"); } while (0) + +struct lbr_branch { + u64 from, to; +}; + +volatile struct lbr_branch l2_branch; + +#define RECORD_AND_CHECK_BRANCH(b) \ +do { \ + wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); \ + DO_BRANCH(); \ + (b)->from =3D rdmsr(MSR_IA32_LASTBRANCHFROMIP); \ + (b)->to =3D rdmsr(MSR_IA32_LASTBRANCHTOIP); \ + /* Disable LBR right after to avoid overriding the IPs */ \ + wrmsr(MSR_IA32_DEBUGCTLMSR, 0); \ + \ + GUEST_ASSERT_NE((b)->from, 0); \ + GUEST_ASSERT_NE((b)->to, 0); \ +} while (0) + +#define CHECK_BRANCH_MSRS(b) \ +do { \ + GUEST_ASSERT_EQ((b)->from, rdmsr(MSR_IA32_LASTBRANCHFROMIP)); \ + GUEST_ASSERT_EQ((b)->to, rdmsr(MSR_IA32_LASTBRANCHTOIP)); \ +} while (0) + +#define CHECK_BRANCH_VMCB(b, vmcb) \ +do { \ + GUEST_ASSERT_EQ((b)->from, vmcb->save.br_from); \ + GUEST_ASSERT_EQ((b)->to, vmcb->save.br_to); \ +} while (0) + +static void l2_guest_code(struct svm_test_data *svm) +{ + /* Record a branch, trigger save/restore, and make sure LBRs are intact */ + RECORD_AND_CHECK_BRANCH(&l2_branch); + GUEST_SYNC(true); + CHECK_BRANCH_MSRS(&l2_branch); + vmmcall(); +} + +static void l1_guest_code(struct svm_test_data *svm, bool nested_lbrv) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb =3D svm->vmcb; + struct lbr_branch l1_branch; + + /* Record a branch, trigger save/restore, and make sure LBRs are intact */ + RECORD_AND_CHECK_BRANCH(&l1_branch); + GUEST_SYNC(true); + CHECK_BRANCH_MSRS(&l1_branch); + + /* Run L2, which will also do the same */ + generic_svm_setup(svm, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + if (nested_lbrv) + vmcb->control.virt_ext =3D LBR_CTL_ENABLE_MASK; + else + vmcb->control.virt_ext &=3D ~LBR_CTL_ENABLE_MASK; + + run_guest(vmcb, svm->vmcb_gpa); + GUEST_ASSERT(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_VMMCALL); + + /* Trigger save/restore one more time before checking, just for kicks */ + GUEST_SYNC(true); + + /* + * If LBR_CTL_ENABLE is set, L1 and L2 should have separate LBR MSRs, so + * expect L1's LBRs to remain intact and L2 LBRs to be in the VMCB. + * Otherwise, the MSRs are shared between L1 & L2 so expect L2's LBRs. + */ + if (nested_lbrv) { + CHECK_BRANCH_MSRS(&l1_branch); + CHECK_BRANCH_VMCB(&l2_branch, vmcb); + } else { + CHECK_BRANCH_MSRS(&l2_branch); + } + GUEST_DONE(); +} + +void test_lbrv_nested_state(bool nested_lbrv) +{ + struct kvm_x86_state *state =3D NULL; + struct kvm_vcpu *vcpu; + vm_vaddr_t svm_gva; + struct kvm_vm *vm; + struct ucall uc; + + pr_info("Testing with nested LBRV %s\n", nested_lbrv ? "enabled" : "disab= led"); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vcpu_alloc_svm(vm, &svm_gva); + vcpu_args_set(vcpu, 2, svm_gva, nested_lbrv); + + for (;;) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + switch (get_ucall(vcpu, &uc)) { + case UCALL_SYNC: + /* Save the vCPU state and restore it in a new VM on sync */ + pr_info("Guest triggered save/restore.\n"); + state =3D vcpu_save_state(vcpu); + kvm_vm_release(vm); + vcpu =3D vm_recreate_with_one_vcpu(vm); + vcpu_load_state(vcpu, state); + kvm_x86_state_cleanup(state); + break; + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } +done: + kvm_vm_free(vm); +} + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + TEST_REQUIRE(kvm_is_lbrv_enabled()); + + test_lbrv_nested_state(/*nested_lbrv=3D*/false); + test_lbrv_nested_state(/*nested_lbrv=3D*/true); + + return 0; +} --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A75B6248861; Tue, 3 Mar 2026 00:34:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498073; cv=none; b=pMYLqG8oU+uiYINy3BBmi9cZdSZOnUNVpvPdRqKjgy/Kick/yHgLeC1itCi09XC5cNTsKKLhrxbGt2xJ2Bydx/Jj4tmkUp6lATjkCaLW6TECOW6D5HnY5jSJAYTDTtcIW54OFxE16ieKimByAmZJC0OR3m4sI9jYVqrnqN1tXQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498073; c=relaxed/simple; bh=f5x63EWl9Ak0ynSIx2o+WVCZCa048niPnvi+1XUeCCM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mweDhlMP/UlUr1hNhxMHY8BswPvc1oNhNPzj1vgP2dgqkd37dfbXrGPb9PWBtNQ10zO9TO2ORPGuh4QxyprnTl9EVVu4T3ReuZ9tJZ6WYCdrx2VsbIqjjsZFtGpAryI42USxhu2CDElgBCAq8WmpgOYpt70Yfy1+Sq9r4RCEiY4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QWS4FnHg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QWS4FnHg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C9B7C2BCB2; Tue, 3 Mar 2026 00:34:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498073; bh=f5x63EWl9Ak0ynSIx2o+WVCZCa048niPnvi+1XUeCCM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QWS4FnHgln9XDzgMfLOIFRGNJTsuEjCWkTXmc8i7xz+If/GTEWEAxs1MMzFLfnzg9 7w0s5lrouxgCAOHOAOU3gyBUApDO7BT63T7Ne3HEcoH3DSXOoSYN3G2qtH3DLXUuUE UhqsJD7jVctmsssWLsiFYFAe7MF+sR7otqAhuJ3k1UxSisTzP6ZnWPCLy6dabQw1u6 j3yMQcuq5jXCU1TimL9M2UIiX0wsqFGExRMmxYMbBz/UOlAHnGQ211O6xLUUUDb0It um1zp2UiJYmi6FpE0TCN2XNdjzWvoHxuo17boVbsx9S6/Vm7YI0qgBtRMJpQu67B1b IBhQEiA9XvFdA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 05/26] KVM: nSVM: Always inject a #GP if mapping VMCB12 fails on nested VMRUN Date: Tue, 3 Mar 2026 00:33:59 +0000 Message-ID: <20260303003421.2185681-6-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" nested_svm_vmrun() currently only injects a #GP if kvm_vcpu_map() fails with -EINVAL. But it could also fail with -EFAULT if creating a host mapping failed. Inject a #GP in all cases, no reason to treat failure modes differently. Fixes: 8c5fbf1a7231 ("KVM/nSVM: Use the new mapping API for mapping guest m= emory") CC: stable@vger.kernel.org Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 3bf758c9cb85c..25f769a0d9a0d 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1011,12 +1011,9 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) } =20 vmcb12_gpa =3D svm->vmcb->save.rax; - ret =3D kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map); - if (ret =3D=3D -EINVAL) { + if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { kvm_inject_gp(vcpu, 0); return 1; - } else if (ret) { - return kvm_skip_emulated_instruction(vcpu); } =20 ret =3D kvm_skip_emulated_instruction(vcpu); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5727E276041; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498074; cv=none; b=hSreQaAQNht8iP4Oq3yVjqHGjZK10tJvBi6kMQFRAc+SJBbF3lqX1G3xjeZbaTC320dVtaUGdTbCKlh7cqesWZFN22hYGJsFbnP0I051hvA4rf8HwU2rDc9KKszifSj4j7+TmhduEqhRMGsvu3Oc2xfz3VzZ7IDlXEseEPw2yaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498074; c=relaxed/simple; bh=Ah8N8t+zByEYmWJjcGNmQ4ocwVXaBIsh8l1+kytMLBU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SdFvnOqku1+jCeX0xJdwqUsBnlFZjrQLRlOfBnnNeXXBpeKdAjzG5D0XOuOwpuyMqW3GC7eH71n4Zg0U3KjOZYcQK2qUoeBWI2V0I1LmdRWb40ulAXguub14+mVfhoCXpDJBeB2VcFrYRNNkwcezW01IprwgYdzttAm3ngN9sqs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N+YGuNHC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N+YGuNHC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B415AC2BCB0; Tue, 3 Mar 2026 00:34:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498074; bh=Ah8N8t+zByEYmWJjcGNmQ4ocwVXaBIsh8l1+kytMLBU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N+YGuNHCUuLk7iih8ueuDehBdHzQmeJbNgMqI48x2+kJbNbkEQ38zCU4X4mOoHL5j pXEoZHpsXBQVimIwwC9izoFn9DYb3CnA64l3+6TTcZm8hg50cX7Dn5ErZI20VP+tEe lLVFlq4Nwb+kKQhyLqEYRad6pv/y5MQQrI9H/rdSkB1YgZjbGKHSrGAJTLp4pHauVv cxY9xhIQIOBSUSPLO/MQNHbCbcu2wupLMRysrZj/BasvAPAT3ZW1YFQ3WCgM7EmXJY oQ99uJyxRghswPTrIs68FgY73O7Iqi4CArDeBkhB59yk4qksu6to0I4Y/5EQyT9atr ckv5+2fXzoLrA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 06/26] KVM: nSVM: Refactor checking LBRV enablement in vmcb12 into a helper Date: Tue, 3 Mar 2026 00:34:00 +0000 Message-ID: <20260303003421.2185681-7-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor the vCPU cap and vmcb12 flag checks into a helper. The unlikely() annotation is dropped, it's unlikely (huh) to make a difference and the CPU will probably predict it better on its own. CC: stable@vger.kernel.org Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 25f769a0d9a0d..d84af051f65bc 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -639,6 +639,12 @@ void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm) svm->nested.vmcb02.ptr->save.g_pat =3D svm->vmcb01.ptr->save.g_pat; } =20 +static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu) +{ + return guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && + (to_svm(vcpu)->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK); +} + static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *= vmcb12) { bool new_vmcb12 =3D false; @@ -703,8 +709,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm = *svm, struct vmcb *vmcb12 vmcb_mark_dirty(vmcb02, VMCB_DR); } =20 - if (unlikely(guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && - (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { + if (nested_vmcb12_has_lbrv(vcpu)) { /* * Reserved bits of DEBUGCTL are ignored. Be consistent with * svm_set_msr's definition of reserved bits. @@ -1234,8 +1239,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) if (!nested_exit_on_intr(svm)) kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); =20 - if (unlikely(guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && - (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { + if (nested_vmcb12_has_lbrv(vcpu)) { svm_copy_lbrs(&vmcb12->save, &vmcb02->save); } else { svm_copy_lbrs(&vmcb01->save, &vmcb02->save); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81F3F28030E; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498074; cv=none; b=lNySvsH5+9Btjib3F1GJfkB6ppyQHMG7uHHvxx7YZRsFsHuZ553sRTJVFBTqr8NIj8I0pWpf7x9nDJYhZh6aU+G74CXDDWTlINwkmQeyHlaEsrr5MxZdwSvT4TINYIlwi6fO8rhxSqL0KRA6oFO8LnXj6+m60IEMxzwqo1NsT0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498074; c=relaxed/simple; bh=L61GK69gSANIjEbBYSDrtFGraWl/zccYBK9YL7ZW+Co=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o2iIacOZxt3KkPf1paM8tbyePyxZ4AAozt3CGaZ2cBEhUx5agdfcWhMhbgb1zIVryAIlN2hVRB6nLtCu8+d3JLp4cbZmGWpbxxr1oPzE/le9DHrNolW51kaMICpjtn49Kx+ptc4Scbh75rCjujePRuXjVqT55s94ye+BbOvnDxU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l28aBkZh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l28aBkZh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2599DC19423; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498074; bh=L61GK69gSANIjEbBYSDrtFGraWl/zccYBK9YL7ZW+Co=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l28aBkZh05RWk1S8bMutte38MJRFYC82VJ9njdcfujkvRLdTIJSWaf9BESBLokcIn VzTbfK8zjeLn5OehcJH4PrfBxyA0pVA7W6eDDj218rIsd+yxJulaKrjhukiCUCuPS+ BxXs78C0rDKvOWpYBBF5ow6PWiT1WWavHs68zp2F6O0D5SfTItx2iTraHIq/J2XrT9 UdA3g7NFq3OTkaY4FUsYIDOey0f8IUMrsHurJbLWX/f6uMahEx2LwDe4HFv6hE9d69 bAzT+tVuVdRp5T6JEVRjpAw+eTTS+XdHmo8PRXRdBL4UGLrl1NkYlh1GV87zFy5cTJ PDG5KKa9fRsMg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 07/26] KVM: nSVM: Refactor writing vmcb12 on nested #VMEXIT as a helper Date: Tue, 3 Mar 2026 00:34:01 +0000 Message-ID: <20260303003421.2185681-8-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move mapping vmcb12 and updating it out of nested_svm_vmexit() into a helper, no functional change intended. CC: stable@vger.kernel.org Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 77 ++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index d84af051f65bc..82a92501ee86a 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1125,36 +1125,20 @@ void svm_copy_vmloadsave_state(struct vmcb *to_vmcb= , struct vmcb *from_vmcb) to_vmcb->save.sysenter_eip =3D from_vmcb->save.sysenter_eip; } =20 -int nested_svm_vmexit(struct vcpu_svm *svm) +static int nested_svm_vmexit_update_vmcb12(struct kvm_vcpu *vcpu) { - struct kvm_vcpu *vcpu =3D &svm->vcpu; - struct vmcb *vmcb01 =3D svm->vmcb01.ptr; + struct vcpu_svm *svm =3D to_svm(vcpu); struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; - struct vmcb *vmcb12; struct kvm_host_map map; + struct vmcb *vmcb12; int rc; =20 rc =3D kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.vmcb12_gpa), &map); - if (rc) { - if (rc =3D=3D -EINVAL) - kvm_inject_gp(vcpu, 0); - return 1; - } + if (rc) + return rc; =20 vmcb12 =3D map.hva; =20 - /* Exit Guest-Mode */ - leave_guest_mode(vcpu); - svm->nested.vmcb12_gpa =3D 0; - WARN_ON_ONCE(svm->nested.nested_run_pending); - - kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); - - /* in case we halted in L2 */ - kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); - - /* Give the current vmcb to the guest */ - vmcb12->save.es =3D vmcb02->save.es; vmcb12->save.cs =3D vmcb02->save.cs; vmcb12->save.ss =3D vmcb02->save.ss; @@ -1191,10 +1175,48 @@ int nested_svm_vmexit(struct vcpu_svm *svm) if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS)) vmcb12->control.next_rip =3D vmcb02->control.next_rip; =20 + if (nested_vmcb12_has_lbrv(vcpu)) + svm_copy_lbrs(&vmcb12->save, &vmcb02->save); + vmcb12->control.int_ctl =3D svm->nested.ctl.int_ctl; vmcb12->control.event_inj =3D svm->nested.ctl.event_inj; vmcb12->control.event_inj_err =3D svm->nested.ctl.event_inj_err; =20 + trace_kvm_nested_vmexit_inject(vmcb12->control.exit_code, + vmcb12->control.exit_info_1, + vmcb12->control.exit_info_2, + vmcb12->control.exit_int_info, + vmcb12->control.exit_int_info_err, + KVM_ISA_SVM); + + kvm_vcpu_unmap(vcpu, &map); + return 0; +} + +int nested_svm_vmexit(struct vcpu_svm *svm) +{ + struct kvm_vcpu *vcpu =3D &svm->vcpu; + struct vmcb *vmcb01 =3D svm->vmcb01.ptr; + struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; + int rc; + + rc =3D nested_svm_vmexit_update_vmcb12(vcpu); + if (rc) { + if (rc =3D=3D -EINVAL) + kvm_inject_gp(vcpu, 0); + return 1; + } + + /* Exit Guest-Mode */ + leave_guest_mode(vcpu); + svm->nested.vmcb12_gpa =3D 0; + WARN_ON_ONCE(svm->nested.nested_run_pending); + + kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); + + /* in case we halted in L2 */ + kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); + if (!kvm_pause_in_guest(vcpu->kvm)) { vmcb01->control.pause_filter_count =3D vmcb02->control.pause_filter_coun= t; vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS); @@ -1239,9 +1261,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) if (!nested_exit_on_intr(svm)) kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); =20 - if (nested_vmcb12_has_lbrv(vcpu)) { - svm_copy_lbrs(&vmcb12->save, &vmcb02->save); - } else { + if (!nested_vmcb12_has_lbrv(vcpu)) { svm_copy_lbrs(&vmcb01->save, &vmcb02->save); vmcb_mark_dirty(vmcb01, VMCB_LBR); } @@ -1297,15 +1317,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm) svm->vcpu.arch.dr7 =3D DR7_FIXED_1; kvm_update_dr7(&svm->vcpu); =20 - trace_kvm_nested_vmexit_inject(vmcb12->control.exit_code, - vmcb12->control.exit_info_1, - vmcb12->control.exit_info_2, - vmcb12->control.exit_int_info, - vmcb12->control.exit_int_info_err, - KVM_ISA_SVM); - - kvm_vcpu_unmap(vcpu, &map); - nested_svm_transition_tlb_flush(vcpu); =20 nested_svm_uninit_mmu_context(vcpu); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E572031F9BA; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; cv=none; b=eS5I1YLZLebnCiR1F1FYzxfEWDmZl9OosE1xc1IANwClgM6ajBNM4dMonxV3GUszna7bl2h1pMXz3nTD1OVGT/CO4ZMGPASg41pYE9AzQVpphO4wfG4+AUD9SYqqHMhIOJXgT8VYvRILN9Ujz6rSDHpetGAadibefJP8ZXaM9aE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; c=relaxed/simple; bh=5AMx4cXBCnhrwKkrVFnaBuckFWwMy/Uk+j0dXdWnDBw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Sf7SmRMWqcY89MfHfLBy7DsOS+hAFMs9GUFyX7n4pfIZzOeVOpP3SC2k8hDh8VSQO7/dIYVuT47TY/zalZEv770OQShL1jsPR0TfXT9hFLsrEe78mT1V9tCOtkGwlDBp2FDIhqy+ESa08LKk1LJN2idr9lf/b772pPGcgxFP0RI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Stq6C2O6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Stq6C2O6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8B27CC2BCB0; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498074; bh=5AMx4cXBCnhrwKkrVFnaBuckFWwMy/Uk+j0dXdWnDBw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Stq6C2O6l+yInvuMbZ9z0t3K3hhe9GFDd4a6CUH/Hu/sOvAUN5L/tK8GQLR61Lx2I LgnbK1YXwKcez9QiFqHh1YR52KObEvT7uSXpgXxfcjfuBJIiLrwT4VJmCsaeCKK4wV LJIEGPsvPWVYByNM6eqZ+1qhUtdLOI9wjNrhVbwZdZvBEFvI+nL0M22foZH+a4dvJH 91sYKC54WLr02fK2Q01uGT19Rg9AxGqL5WiQlVi4JDQooEGCXTJzplWF5+m/6cGdey f64dYazkUT6r04NCu5yR8pEwrSwqPZoWC6if6gMYNXE4AOEQvNRbY//8EeJpSFwFjH y2aRpeM2iFmpA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 08/26] KVM: nSVM: Triple fault if mapping VMCB12 fails on nested #VMEXIT Date: Tue, 3 Mar 2026 00:34:02 +0000 Message-ID: <20260303003421.2185681-9-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" KVM currently injects a #GP and hopes for the best if mapping VMCB12 fails on nested #VMEXIT, and only if the failure mode is -EINVAL. Mapping the VMCB12 could also fail if creating host mappings fails. After the #GP is injected, nested_svm_vmexit() bails early, without cleaning up (e.g. KVM_REQ_GET_NESTED_STATE_PAGES is set, is_guest_mode() is true, etc). Instead of optionally injecting a #GP, triple fault the guest if mapping VMCB12 fails since KVM cannot make a sane recovery. The APM states that a #VMEXIT will triple fault if host state is illegal or an exception occurs while loading host state, so the behavior is not entirely made up. Do not return early from nested_svm_vmexit(), continue cleaning up the vCPU state (e.g. switch back to vmcb01), to handle the failure as gracefully as possible. Fixes: cf74a78b229d ("KVM: SVM: Add VMEXIT handler and intercepts") CC: stable@vger.kernel.org Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 82a92501ee86a..5ad0ac3680fdd 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1200,12 +1200,8 @@ int nested_svm_vmexit(struct vcpu_svm *svm) struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; int rc; =20 - rc =3D nested_svm_vmexit_update_vmcb12(vcpu); - if (rc) { - if (rc =3D=3D -EINVAL) - kvm_inject_gp(vcpu, 0); - return 1; - } + if (nested_svm_vmexit_update_vmcb12(vcpu)) + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); =20 /* Exit Guest-Mode */ leave_guest_mode(vcpu); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D43933F59B; Tue, 3 Mar 2026 00:34:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; cv=none; b=OGU3uwpXrqjWLeITcHCGWShTdKkaihMskS2Kpp9Sac7tcurlIUCVYprZwT0jciOdKVZ8/y9SBBKcFk63FHAkuuUITm9XFb4UOCNUo0aM0zhVntuH+j+9/KpuDGtpJVFj9a+NawdV7vXNbd72/5kGFMy8/l5ukzsiodVKnVM7SdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; c=relaxed/simple; bh=pfVYV6ekwPfSejRIqjGsbtiBVUUCU0z0cBXBBnz/UA4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SDh6K+sWb6AX0jyhfx4IP+ya0ImEis7Lw0KLQdcW7GYCBJ9UHzDqU/ClEAckjD6iOrCt894e+cNTe48nYcvnSpXHZ5RZOkuoZb9lZWYqyxTeAR1gMINrNu/YkDZJ51+/AnoDOzVuOS8C58CnNP0lInr+aV5pbZa8RFOgV2N6bCM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OsskKh9d; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OsskKh9d" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F0AE8C19423; Tue, 3 Mar 2026 00:34:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498075; bh=pfVYV6ekwPfSejRIqjGsbtiBVUUCU0z0cBXBBnz/UA4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OsskKh9dWKcobmwC3pFq0jOJyEg0ubGc213RZ6cMX8fXxa9mHNTEGGgSEWZpKkWpN aO7tmlAMAVOCB6JQeeHDVqW1M6OxkTYT/gy6Bf37dgXxaNepK2Chf7Q6nDiQI7c2jy grvofOn9DNvUF/iywpJnF7fPgTfiQQR9apyVPll3iGmUrdIPAfnSwzVJWKm6n/jR/J P4rUHgoCiz77Bxm/3TM5iYGU+AzS5bQ0RBnwq2vVuJ4Kvu2tt6dUml4Wv7aE5URXN9 fKdSxlgTXuEKEn1fdCRJvrW8Y5mDKRZP6hnILV1tNL78ceqqzJH9dYO5l2yOpCSQF2 Hpyex0GRhK7zw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 09/26] KVM: nSVM: Triple fault if restore host CR3 fails on nested #VMEXIT Date: Tue, 3 Mar 2026 00:34:03 +0000 Message-ID: <20260303003421.2185681-10-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If loading L1's CR3 fails on a nested #VMEXIT, nested_svm_vmexit() returns an error code that is ignored by most callers, and continues to run L1 with corrupted state. A sane recovery is not possible in this case, and HW behavior is to cause a shutdown. Inject a triple fault ,nstead, and do not return early from nested_svm_vmexit(). Continue cleaning up the vCPU state (e.g. clear pending exceptions), to handle the failure as gracefully as possible. From the APM: Upon #VMEXIT, the processor performs the following actions in order to return to the host execution context: ... if (illegal host state loaded, or exception while loading host state) shutdown else execute first host instruction following the VMRUN Remove the return value of nested_svm_vmexit(), which is mostly unchecked anyway. Fixes: d82aaef9c88a ("KVM: nSVM: use nested_svm_load_cr3() on guest->host s= witch") CC: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 10 +++------- arch/x86/kvm/svm/svm.c | 11 ++--------- arch/x86/kvm/svm/svm.h | 6 +++--- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 5ad0ac3680fdd..bb2cec5fd0434 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1193,12 +1193,11 @@ static int nested_svm_vmexit_update_vmcb12(struct k= vm_vcpu *vcpu) return 0; } =20 -int nested_svm_vmexit(struct vcpu_svm *svm) +void nested_svm_vmexit(struct vcpu_svm *svm) { struct kvm_vcpu *vcpu =3D &svm->vcpu; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; - int rc; =20 if (nested_svm_vmexit_update_vmcb12(vcpu)) kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); @@ -1317,9 +1316,8 @@ int nested_svm_vmexit(struct vcpu_svm *svm) =20 nested_svm_uninit_mmu_context(vcpu); =20 - rc =3D nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true); - if (rc) - return 1; + if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); =20 /* * Drop what we picked up for L2 via svm_complete_interrupts() so it @@ -1344,8 +1342,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm) */ if (kvm_apicv_activated(vcpu->kvm)) __kvm_vcpu_update_apicv(vcpu); - - return 0; } =20 static void nested_svm_triple_fault(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index cb53174583a26..1b31b033d79b0 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2234,13 +2234,9 @@ static int emulate_svm_instr(struct kvm_vcpu *vcpu, = int opcode) [SVM_INSTR_VMSAVE] =3D vmsave_interception, }; struct vcpu_svm *svm =3D to_svm(vcpu); - int ret; =20 if (is_guest_mode(vcpu)) { - /* Returns '1' or -errno on failure, '0' on success. */ - ret =3D nested_svm_simple_vmexit(svm, guest_mode_exit_codes[opcode]); - if (ret) - return ret; + nested_svm_simple_vmexit(svm, guest_mode_exit_codes[opcode]); return 1; } return svm_instr_handlers[opcode](vcpu); @@ -4796,7 +4792,6 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union= kvm_smram *smram) { struct vcpu_svm *svm =3D to_svm(vcpu); struct kvm_host_map map_save; - int ret; =20 if (!is_guest_mode(vcpu)) return 0; @@ -4816,9 +4811,7 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union= kvm_smram *smram) svm->vmcb->save.rsp =3D vcpu->arch.regs[VCPU_REGS_RSP]; svm->vmcb->save.rip =3D vcpu->arch.regs[VCPU_REGS_RIP]; =20 - ret =3D nested_svm_simple_vmexit(svm, SVM_EXIT_SW); - if (ret) - return ret; + nested_svm_simple_vmexit(svm, SVM_EXIT_SW); =20 /* * KVM uses VMCB01 to store L1 host state while L2 runs but diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 44d767cd1d25a..7629cb37c9302 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -793,14 +793,14 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu); void svm_copy_vmrun_state(struct vmcb_save_area *to_save, struct vmcb_save_area *from_save); void svm_copy_vmloadsave_state(struct vmcb *to_vmcb, struct vmcb *from_vmc= b); -int nested_svm_vmexit(struct vcpu_svm *svm); +void nested_svm_vmexit(struct vcpu_svm *svm); =20 -static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_= code) +static inline void nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit= _code) { svm->vmcb->control.exit_code =3D exit_code; svm->vmcb->control.exit_info_1 =3D 0; svm->vmcb->control.exit_info_2 =3D 0; - return nested_svm_vmexit(svm); + nested_svm_vmexit(svm); } =20 int nested_svm_exit_handled(struct vcpu_svm *svm); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C175734888F; Tue, 3 Mar 2026 00:34:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; cv=none; b=H2cdDByskqiolu+g25c/xAVhXztkua+OMiYkXc3l8rx3ZHChvOCcDWMv1URf9hjXQSo+oZ5BL4bVVBCCyHn9ZHD75oQxAgAWTRp8GOWK12zP8SBKntoEP/iIxB24HWutgQ1GPio42aia5u2xvU3EL1nTFjMUQoZrin1uEkDt25U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498075; c=relaxed/simple; bh=VkfpgkqyrVASRWFgTqoJ+zrG9g4hxcm1sZ6qMUOlIw8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LwWrLtdqYOlMyAu3Tyf9INSdvy00DsToFv7fSyLX/GdsEBBul2OG3xYsB3ethMqsqXr98kZwRluauj99sfbUiV+nWlAyW4GcF/I4aCfbaVMUAMJUE1NAfeNtIFmd3BquPaxFbQJdA6a6OuT4xJdy8zOwQ1m/2EyFw0svQmNCZXM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bPQ5YqMq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bPQ5YqMq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 634CBC2BC9E; Tue, 3 Mar 2026 00:34:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498075; bh=VkfpgkqyrVASRWFgTqoJ+zrG9g4hxcm1sZ6qMUOlIw8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bPQ5YqMq5kAVWLctOu4C7K/9R6VbenvpgTnHxVjVcCXBuLdifNOCQwq0Dz70sjp87 76jWeuT1xJmIkDo19oeYOcdnMBmKdql00vk3KYSyxoOCMgChxGbiyDHBhHCunSCBVx GHxIZS9/ZnltXRhX1ur8dzOjJAWbNSOqPU1eUDo4aSRR1jHI85lG4bhu5I4tsAJ0dC Cc5BngjJ4kvBvxjT76/3EhXQjrxNsfDuOQq6G6AChQ7AizNTPJvoAmTkDcpLLzjJKi McT+SE1I9b0B+N813G3P32lPOkPokc7aKJpsFYDwKmXuw03aG8YkaFBxiPQznebnqq cxOhn0ICQvkGg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 10/26] KVM: nSVM: Clear GIF on nested #VMEXIT(INVALID) Date: Tue, 3 Mar 2026 00:34:04 +0000 Message-ID: <20260303003421.2185681-11-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" According to the APM, GIF is set to 0 on any #VMEXIT, including an #VMEXIT(INVALID) due to failed consistency checks. Clear GIF on consistency check failures. Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index bb2cec5fd0434..04ccab887c5ec 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1036,6 +1036,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) vmcb12->control.exit_code =3D SVM_EXIT_ERR; vmcb12->control.exit_info_1 =3D 0; vmcb12->control.exit_info_2 =3D 0; + svm_set_gif(svm, false); goto out; } =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2EAF9214813; Tue, 3 Mar 2026 00:34:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498076; cv=none; b=JtcvHooXkyyvah8vaqNhen4e8/jOyzGLgxwGdfgnpm7T/7lvN8D2QmuNwzY+EFcpG04PR9mAgVAA6qTiJDbOQ6Yo/lhgruxoZLPIvdw0vkazs4DxRuW3SjdQglyY6bXm7vi05emaBIk1UQ+aEL1HWMwSt1rVxCO/AlhBkfg7leU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498076; c=relaxed/simple; bh=RVd07MvedhdIEW5JrYAtzB9IAWdTFtLD3Zt8Ivq+zBs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dokDEfbREL/ivorfZlLawEq20wtS33sjJtEzGy1d0DhROVpUDtIThpn9PkcvLQCHqOFpnqWLvwQ2dgjk/tvcQveTSwvtu749ipjAAc1GcqPtcIVRIa2eYzpCCBjJnov4ro1iFy6ZHWMyUSZqHZnG/+G8bIdU3457qQgaLZn6A0Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RKQ93PZU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RKQ93PZU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C863DC2BC86; Tue, 3 Mar 2026 00:34:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498076; bh=RVd07MvedhdIEW5JrYAtzB9IAWdTFtLD3Zt8Ivq+zBs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RKQ93PZU5kLqmJzX3yil87QdK6Ye+IdGZzTw8gWUTn8wV0DFl8GrXS1fwe6gPJLAc 7FPkGLed1Ehwrs7wm0BwQ6qskTAXr2YwDpNb2EV2jfEBCIfe3Y8weI5AJdOHw97Uxg XvGIevqogYN3rjTOPMU0mzaMiNLOyFl61V7gzB6d9O1WYH3q+tT93AVN4OSamGNCEn XMY8ZQr6pe52hgC1HirXWHtj+OK5G5pDxOlRrwi56lywUKmzWfJHtO+wAmsnkHY1WM lgT9W+2EVFP4ZwoJVbtwKUUsWmg4dX3eaDGbrkSte68Fpm26FnId8XjF9y5f1aNN+W SotJzmxKVb3Xg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 11/26] KVM: nSVM: Clear EVENTINJ fields in vmcb12 on nested #VMEXIT Date: Tue, 3 Mar 2026 00:34:05 +0000 Message-ID: <20260303003421.2185681-12-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" According to the APM, from the reference of the VMRUN instruction: Upon #VMEXIT, the processor performs the following actions in order to return to the host execution context: ... clear EVENTINJ field in VMCB KVM syncs EVENTINJ fields from vmcb02 to cached vmcb12 on every L2->L0 #VMEXIT. Since these fields are zeroed by the CPU on #VMEXIT, they will mostly be zeroed in vmcb12 on nested #VMEXIT by nested_svm_vmexit(). However, this is not the case when: 1. Consistency checks fail, as nested_svm_vmexit() is not called. 2. Entering guest mode fails before L2 runs (e.g. due to failed load of CR3). (2) was broken by commit 2d8a42be0e2b ("KVM: nSVM: synchronize VMCB controls updated by the processor on every vmexit"), as prior to that nested_svm_vmexit() always zeroed EVENTINJ fields. Explicitly clear the fields all nested #VMEXIT code paths. Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler") Fixes: 2d8a42be0e2b ("KVM: nSVM: synchronize VMCB controls updated by the p= rocessor on every vmexit") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 04ccab887c5ec..f0ed352a3e901 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1036,6 +1036,8 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) vmcb12->control.exit_code =3D SVM_EXIT_ERR; vmcb12->control.exit_info_1 =3D 0; vmcb12->control.exit_info_2 =3D 0; + vmcb12->control.event_inj =3D 0; + vmcb12->control.event_inj_err =3D 0; svm_set_gif(svm, false); goto out; } @@ -1179,9 +1181,9 @@ static int nested_svm_vmexit_update_vmcb12(struct kvm= _vcpu *vcpu) if (nested_vmcb12_has_lbrv(vcpu)) svm_copy_lbrs(&vmcb12->save, &vmcb02->save); =20 + vmcb12->control.event_inj =3D 0; + vmcb12->control.event_inj_err =3D 0; vmcb12->control.int_ctl =3D svm->nested.ctl.int_ctl; - vmcb12->control.event_inj =3D svm->nested.ctl.event_inj; - vmcb12->control.event_inj_err =3D svm->nested.ctl.event_inj_err; =20 trace_kvm_nested_vmexit_inject(vmcb12->control.exit_code, vmcb12->control.exit_info_1, --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3BCA3563FA; Tue, 3 Mar 2026 00:34:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498076; cv=none; b=MiYY+oyAD127tQnP2PfeFNvZ6oQ99nM+e/DdHPOBNS913fNKLq3vhQfOmjMiN4o5NGcNwD5sUnqhWD26eOdk8S8nUgdtiib+BddrOd81D1npZJYVUatKAf6WZsSnkvBUDm3yXmTc715bpb7yc5Yi5gzRIbsk+fJ9ZPeHan1+YFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498076; c=relaxed/simple; bh=JRTh4d4NiavCtUAPMWBR5Q7QKAgkkv2LsY9J4Zvx6kQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bdYHBIThpSCuuPd/VVjgAAqNmwZXEEVP9p0k/futyf/BqAnFS39yaEX/LXus19G9BXhl+tDOtDSLMslwfiyH4wN7npBewmaCuSbdc6GWP4bXgzrF8hkyzo3hhhVXOscTQiC3rdR773hSn3JmClfh+7KbZ/yOkrnildJOX38WssA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bU/ZXlHP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bU/ZXlHP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39AD7C2BC9E; Tue, 3 Mar 2026 00:34:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498076; bh=JRTh4d4NiavCtUAPMWBR5Q7QKAgkkv2LsY9J4Zvx6kQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bU/ZXlHP8nakl9RF1pU1UgGINXnaSRtiFO6wsI8P/v9jqN2yiFiNJxlLm+L/h2lOj txCAo8NbwbZg+G/lM2MCANT2YaJkXIe6HhJ7A73k2/Y6BO3bRrR7hJScnxgNeOhf8Z izvRPr3wfz4ftZVBnBdJyKhtzJTcguT0QttCMpRjZsufEIkKlShRuKT00haP5g2vHi rpdajO4FBtmy3QbPl3LmBLZ3CcQRxf711z50Dl75jnjw+PmBadUruIy+toqiTi1Ldp NcL59UJDkEfYObxJZuNN1XpuccrDvwp6hDEaqzTTCeAx1rvoUzBpXiRyCPhNqAMPJQ HJ3vJ1P1lGBgQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 12/26] KVM: nSVM: Clear tracking of L1->L2 NMI and soft IRQ on nested #VMEXIT Date: Tue, 3 Mar 2026 00:34:06 +0000 Message-ID: <20260303003421.2185681-13-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" KVM clears tracking of L1->L2 injected NMIs (i.e. nmi_l1_to_l2) and soft IRQs (i.e. soft_int_injected) on a synthesized #VMEXIT(INVALID) due to failed VMRUN. However, they are not explicitly cleared in other synthesized #VMEXITs. soft_int_injected is always cleared after the first VMRUN of L2 when completing interrupts, as any re-injection is then tracked by KVM (instead of purely in vmcb02). nmi_l1_to_l2 is not cleared after the first VMRUN if NMI injection failed, as KVM still needs to keep track that the NMI originated from L1 to avoid blocking NMIs for L1. It is only cleared when the NMI injection succeeds. KVM could synthesize a #VMEXIT to L1 before successfully injecting the NMI into L2 (e.g. due to a #NPF on L2's NMI handler in L1's NPTs). In this case, nmi_l1_to_l2 will remain true, and KVM may not correctly mask NMIs and intercept IRET when injecting an NMI into L1. Clear both nmi_l1_to_l2 and soft_int_injected in nested_svm_vmexit() to capture all #VMEXITs, except those that occur due to failed consistency checks, as those happen before nmi_l1_to_l2 or soft_int_injected are set. Fixes: 159fc6fa3b7d ("KVM: nSVM: Transparently handle L1 -> L2 NMI re-injec= tion") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f0ed352a3e901..b66bd9bfce9d8 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1065,8 +1065,6 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) =20 out_exit_err: svm->nested.nested_run_pending =3D 0; - svm->nmi_l1_to_l2 =3D false; - svm->soft_int_injected =3D false; =20 svm->vmcb->control.exit_code =3D SVM_EXIT_ERR; svm->vmcb->control.exit_info_1 =3D 0; @@ -1322,6 +1320,10 @@ void nested_svm_vmexit(struct vcpu_svm *svm) if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); =20 + /* Drop tracking for L1->L2 injected NMIs and soft IRQs */ + svm->nmi_l1_to_l2 =3D false; + svm->soft_int_injected =3D false; + /* * Drop what we picked up for L2 via svm_complete_interrupts() so it * doesn't end up in L1. --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D3A3359A68; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498077; cv=none; b=tTPBT7HNzHbsLOt8R3syPmu5l0mR9SZ1fRbLKeSrbhCEOHhHA37pE/Bmr+iVKhX/a0AvmRDzItCIWEAZhvJF1Pdw5SLlJ9upFUDhXinTRcH06E+PJrrOHUUqMZYiGnCqGaJNNLez5veKhmPztSmsdblj4+gyYwLiX2voo9a9Ad0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498077; c=relaxed/simple; bh=a3n687SEFo3mGCDwHQ3iI2OjGHE7+i7JTV7SzEfku0A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H/Ofpuxm3oghQgamsMsvDOzFdAyNJSuGF2hthWChAcQ3F/zO8THNohgzKjAbUwOeyiN2XhnD+I5J3UgF7zKd9qS5MeH1/0+I2xLcBt7ZpYkuY7rVSgt4wij5k2qXed7ZEOw8mI+9Hn/wKxLuLkfIN0acnrgGKB1Y+tj1JZAqpdM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=F59rAZ17; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="F59rAZ17" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9F206C2BCB0; Tue, 3 Mar 2026 00:34:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498076; bh=a3n687SEFo3mGCDwHQ3iI2OjGHE7+i7JTV7SzEfku0A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F59rAZ17Q6OEH7RnuJro9aRtyucDsDD/JvLNkW8oeeayY4RJtmKqTLnprOXTHGOgZ l8cJuba4821MRhxf59ePMRPuExtq71IWH/4/Q7fpIjoBaMqKcPf/ZD2+agpC/UI929 bHvQli9fHOnkyOPbOMxZQ7LeVJhuliV2Ri7RLNCQ46umL6wgz5VsLCYYqPeXmMhg3T /lcRxjV6ZJZSGUSHxQvCr9Y9uq7HqkBmBxk1IhemQf6QMryBZjSnic77LitQGeWzcE pCRozv4FkUuFXDvCioLCr+gWQvfbtsEamQCUbvNC1K7EFOgtj3nyqEip2ekMdJo+DL X6ngoy8pNHVCg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 13/26] KVM: nSVM: Drop nested_vmcb_check_{save/control}() wrappers Date: Tue, 3 Mar 2026 00:34:07 +0000 Message-ID: <20260303003421.2185681-14-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The wrappers provide little value and make it harder to see what KVM is checking in the normal flow. Drop them. Opportunistically fixup comments referring to the functions, adding '()' to make it clear it's a reference to a function. No functional change intended. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index b66bd9bfce9d8..21e1a43c91879 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -339,8 +339,8 @@ static bool nested_svm_check_bitmap_pa(struct kvm_vcpu = *vcpu, u64 pa, u32 size) kvm_vcpu_is_legal_gpa(vcpu, addr + size - 1); } =20 -static bool __nested_vmcb_check_controls(struct kvm_vcpu *vcpu, - struct vmcb_ctrl_area_cached *control) +static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu, + struct vmcb_ctrl_area_cached *control) { if (CC(!vmcb12_is_intercept(control, INTERCEPT_VMRUN))) return false; @@ -367,8 +367,8 @@ static bool __nested_vmcb_check_controls(struct kvm_vcp= u *vcpu, } =20 /* Common checks that apply to both L1 and L2 state. */ -static bool __nested_vmcb_check_save(struct kvm_vcpu *vcpu, - struct vmcb_save_area_cached *save) +static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu, + struct vmcb_save_area_cached *save) { if (CC(!(save->efer & EFER_SVME))) return false; @@ -402,22 +402,6 @@ static bool __nested_vmcb_check_save(struct kvm_vcpu *= vcpu, return true; } =20 -static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu) -{ - struct vcpu_svm *svm =3D to_svm(vcpu); - struct vmcb_save_area_cached *save =3D &svm->nested.save; - - return __nested_vmcb_check_save(vcpu, save); -} - -static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu) -{ - struct vcpu_svm *svm =3D to_svm(vcpu); - struct vmcb_ctrl_area_cached *ctl =3D &svm->nested.ctl; - - return __nested_vmcb_check_controls(vcpu, ctl); -} - /* * If a feature is not advertised to L1, clear the corresponding vmcb12 * intercept. @@ -469,7 +453,7 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, to->pause_filter_count =3D from->pause_filter_count; to->pause_filter_thresh =3D from->pause_filter_thresh; =20 - /* Copy asid here because nested_vmcb_check_controls will check it. */ + /* Copy asid here because nested_vmcb_check_controls() will check it */ to->asid =3D from->asid; to->msrpm_base_pa &=3D ~0x0fffULL; to->iopm_base_pa &=3D ~0x0fffULL; @@ -1031,8 +1015,8 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); =20 - if (!nested_vmcb_check_save(vcpu) || - !nested_vmcb_check_controls(vcpu)) { + if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) { vmcb12->control.exit_code =3D SVM_EXIT_ERR; vmcb12->control.exit_info_1 =3D 0; vmcb12->control.exit_info_2 =3D 0; @@ -1878,12 +1862,12 @@ static int svm_set_nested_state(struct kvm_vcpu *vc= pu, =20 ret =3D -EINVAL; __nested_copy_vmcb_control_to_cache(vcpu, &ctl_cached, ctl); - if (!__nested_vmcb_check_controls(vcpu, &ctl_cached)) + if (!nested_vmcb_check_controls(vcpu, &ctl_cached)) goto out_free; =20 /* * Processor state contains L2 state. Check that it is - * valid for guest mode (see nested_vmcb_check_save). + * valid for guest mode (see nested_vmcb_check_save()). */ cr0 =3D kvm_read_cr0(vcpu); if (((cr0 & X86_CR0_CD) =3D=3D 0) && (cr0 & X86_CR0_NW)) @@ -1897,7 +1881,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, if (!(save->cr0 & X86_CR0_PG) || !(save->cr0 & X86_CR0_PE) || (save->rflags & X86_EFLAGS_VM) || - !__nested_vmcb_check_save(vcpu, &save_cached)) + !nested_vmcb_check_save(vcpu, &save_cached)) goto out_free; =20 =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6927635BDCF; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498077; cv=none; b=kAGU/3kLKO59A39BsxCLtnhIsReMNc50QbHkFhEl+HRtpFSbfFEBJWYKCn6Fe4zt2msURSaGH2YN2BLWi4wUXi/OkNZbQ7KDzsNNfL/TYCwQtIuRcxoK5+44t1H4pIK1pIeipnab7Z8w8Gu9IG76OyX3mm78cZkzdyoxaarmMtg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498077; c=relaxed/simple; bh=olRAYun/Ux9B12Ks73aBoNVYZdrJiflf9wOE4eBtP24=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ds92JtQQI59XyP+F+y4OMEt8tskU9fvXadjRfnNQY3bkTKjabnPwzXQJkdi2dlFoh5p3TfISvBBpd4cbw5atjqS+VZPqk1wZs2ZLPotrQqtFTVF/DtVJ68+eJPWFeQ/DtGIDPuRsEUKh7C3MIXeXwONlWfaGbav22DPwhN/E5vE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ur1+s8dZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ur1+s8dZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 102F4C2BC9E; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498077; bh=olRAYun/Ux9B12Ks73aBoNVYZdrJiflf9wOE4eBtP24=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ur1+s8dZMQd/IcK0M9TZRBFKrcohsxNmVE9G4w2ICve2Y4wqvXtuogh9H8NXNlmwQ 6085XItScewKKQmag4O01FZMqcGv/HJ61BiNcFbjfAumQZ1EdmRZfkiqkfCwBlkvhZ 6iDZ1rY+OxfreuGZB/d3btx+/UafYY7UtY+Ovfp5dsp0Ab/v4JEZ6kQTgjrpH3idsJ qEUi1oLwMMHNfNgBOj1zJr7RuW/nTLiFLT1rZ/nC+2/MAg/i0yGoj12ZQQ3REsj/gE jqzTeGtaMZEz777mO0imqnVLm8m3R1gr1G7zzR5cgKqxMvIMXIx6ONakHLIHeBTy5Z 0EP+TeGH9BmtQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 14/26] KVM: nSVM: Drop the non-architectural consistency check for NP_ENABLE Date: Tue, 3 Mar 2026 00:34:08 +0000 Message-ID: <20260303003421.2185681-15-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" KVM currenty fails a nested VMRUN and injects VMEXIT_INVALID (aka SVM_EXIT_ERR) if L1 sets NP_ENABLE and the host does not support NPTs. On first glance, it seems like the check should actually be for guest_cpu_cap_has(X86_FEATURE_NPT) instead, as it is possible for the host to support NPTs but the guest CPUID to not advertise it. However, the consistency check is not architectural to begin with. The APM does not mention VMEXIT_INVALID if NP_ENABLE is set on a processor that does not have X86_FEATURE_NPT. Hence, NP_ENABLE should be ignored if X86_FEATURE_NPT is not available for L1, so sanitize it when copying from the VMCB12 to KVM's cache. Apart from the consistency check, NP_ENABLE in VMCB12 is currently ignored because the bit is actually copied from VMCB01 to VMCB02, not from VMCB12. Fixes: 4b16184c1cca ("KVM: SVM: Initialize Nested Nested MMU context on VMR= UN") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 21e1a43c91879..613d5e2e7c3d1 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -348,9 +348,6 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu = *vcpu, if (CC(control->asid =3D=3D 0)) return false; =20 - if (CC((control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) && !npt_enabled)) - return false; - if (CC(!nested_svm_check_bitmap_pa(vcpu, control->msrpm_base_pa, MSRPM_SIZE))) return false; @@ -431,6 +428,11 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vc= pu *vcpu, nested_svm_sanitize_intercept(vcpu, to, SKINIT); nested_svm_sanitize_intercept(vcpu, to, RDPRU); =20 + /* Always clear SVM_NESTED_CTL_NP_ENABLE if the guest cannot use NPTs */ + to->nested_ctl =3D from->nested_ctl; + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_NPT)) + to->nested_ctl &=3D ~SVM_NESTED_CTL_NP_ENABLE; + to->iopm_base_pa =3D from->iopm_base_pa; to->msrpm_base_pa =3D from->msrpm_base_pa; to->tsc_offset =3D from->tsc_offset; @@ -444,7 +446,6 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, to->exit_info_2 =3D from->exit_info_2; to->exit_int_info =3D from->exit_int_info; to->exit_int_info_err =3D from->exit_int_info_err; - to->nested_ctl =3D from->nested_ctl; to->event_inj =3D from->event_inj; to->event_inj_err =3D from->event_inj_err; to->next_rip =3D from->next_rip; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E71AA35F171; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; cv=none; b=X7zKLQayGq1txiz/VTIlrEddvMB8Pkp5TyE/rhAA1/23p4jAwcCuaRAIOqSG8kvz8NoYoeu04o57JWlkc1TxvT/tzELQZSGRhHC1duZQ8in00wHNEAW7ORzK/Z2Q0tgB+x0uwuUaflFkWcM8dGyDatdGme6lpOKhGmd/4A+rr2g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; c=relaxed/simple; bh=4yF4ObMkUIsa5S10Tx/7NPubGq6kLDk80Z+SpNKvNkI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IwxH/xw3vYKDSDTty77LKaTMRlqVc6MJHfKkKmoppYn9g1rCLYG/0rQTDI4V/4qyGl+y0RK97oxLCjv5Vh3K0t6f/M6mkejawHOX2GQvlAm6a3JWOZEgUCkY0yZQXSf0RqNm1V81mbkKo7VuAZg0vvt8asSLZ/DJwIaW2hAgMuo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=X5Qmc9Ii; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="X5Qmc9Ii" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75490C2BCB0; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498077; bh=4yF4ObMkUIsa5S10Tx/7NPubGq6kLDk80Z+SpNKvNkI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X5Qmc9Ii20cmtZR0kZRHCf2J3nrhhIeANVXWoTmRV+A0ujH3++pnqOFIXuzsB3uYp SI+3VQGG2xcZYI2TFJIo2p/tpF4TKzJldOjnD8y3VGkQLvlZc5Cyiuwk+hz/1TXK3B 7U44VvMKClHwhNN8sOgQ1iyAjQ3+4yCXCz6sHt8B9+R+2XK/GU4jBtKEU0sFVRJOo/ kQFIzlhk3bwtpX2j4WXTbve5axtL9P0NC1Pi1s1EPzXAS19fgs1E+gBzq8osoLhPto Wl/EXifzy4Gmf6VQbPaS6DM78dKBiJZ5bmhYTKbJQWXIJthYSdZn8DBAZ0OkN2GSXN V8opTrbYOx50g== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 15/26] KVM: nSVM: Add missing consistency check for nCR3 validity Date: Tue, 3 Mar 2026 00:34:09 +0000 Message-ID: <20260303003421.2185681-16-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From the APM Volume #2, 15.25.4 (24593=E2=80=94Rev. 3.42=E2=80=94March 2024= ): When VMRUN is executed with nested paging enabled (NP_ENABLE =3D 1), the following conditions are considered illegal state combinations, in addition to those mentioned in =E2=80=9CCanonicalization and Consistency Checks=E2=80=9D: =E2=80=A2 Any MBZ bit of nCR3 is set. =E2=80=A2 Any G_PAT.PA field has an unsupported type encoding or any reserved field in G_PAT has a nonzero value. Add the consistency check for nCR3 being a legal GPA with no MBZ bits set. The G_PAT.PA check was proposed separately [*]. [*]https://lore.kernel.org/kvm/20260205214326.1029278-3-jmattson@google.com/ Fixes: 4b16184c1cca ("KVM: SVM: Initialize Nested Nested MMU context on VMR= UN") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 613d5e2e7c3d1..3aaa4f0bb31ab 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -348,6 +348,11 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu= *vcpu, if (CC(control->asid =3D=3D 0)) return false; =20 + if (control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) { + if (CC(!kvm_vcpu_is_legal_gpa(vcpu, control->nested_cr3))) + return false; + } + if (CC(!nested_svm_check_bitmap_pa(vcpu, control->msrpm_base_pa, MSRPM_SIZE))) return false; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4376135F5ED; Tue, 3 Mar 2026 00:34:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; cv=none; b=rh4Xe+RNaEgK7suv996zR5px8R/DVxnTAF0NFu5MfaH5HpewIFV/RgNzWoS8ksMwEjOAgIp6Jpi3ZOQkgqGnUzV9q3JvjrLrnzOWlvzzqIEheHKoYpSklxd7jy7+iMPskw9DJjjzBGiuRLCELA5eTG+DFIpzE2nVqaAEib8Lvko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; c=relaxed/simple; bh=pIwNjczmYnEx1LxueriC9FIL1WKTRkr09sZcduektJA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hPHMgKzMK9Jh6yggkPVP0kpJdPMSUHDcrvPP16S16F9Wyfq6/+bnAKSUPK6Wg/lma2xfyUVLaRR6z5CSwJnL+enAQDbI9risEXBuNAKsa4WncHcowykwytbxAJzKF0etI7CkfQ8GcvZ9ZbjBeDVIMFBEb9H3yprx5pscW64DyVE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oW9FlGC4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oW9FlGC4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DA964C19423; Tue, 3 Mar 2026 00:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498078; bh=pIwNjczmYnEx1LxueriC9FIL1WKTRkr09sZcduektJA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oW9FlGC45PZpaXjlcsBV9FcMpSFQZSxalnO2HaEgzIaaOkPG4Si4VbqvsCt9Ef9s0 p3nKyxbGxl55hlY2yXrL6SpOAtcaztbk2NED1B4m/Lx8ixakAw50N0V6XtXAYSPQnF pOxR/8VyDA2pNOLaVcyh8vyzgCpinZw6pAZEZZmsr6tdmn/HJ07YfdN2Mt5YQUJBzE z7d0bBsS/l3PjmpnqZ9JmWKQWrJLBnE9WOel+5QBsEA9kFMEqYJpPOsVTvyyzlt8Oy +JaUSmrm1qeFUsnAajBUg2XhZJQnPjmkk/jhVUN3u8iXLv6TzCIn/OIPRHIHImgAL+ 6Y18w6a+nSSIQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 16/26] KVM: nSVM: Add missing consistency check for EFER, CR0, CR4, and CS Date: Tue, 3 Mar 2026 00:34:10 +0000 Message-ID: <20260303003421.2185681-17-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable According to the APM Volume #2, 15.5, Canonicalization and Consistency Checks (24593=E2=80=94Rev. 3.42=E2=80=94March 2024), the following conditio= n (among others) results in a #VMEXIT with VMEXIT_INVALID (aka SVM_EXIT_ERR): EFER.LME, CR0.PG, CR4.PAE, CS.L, and CS.D are all non-zero. In the list of consistency checks done when EFER.LME and CR0.PG are set, add a check that CS.L and CS.D are not both set, after the existing check that CR4.PAE is set. This is functionally a nop because the nested VMRUN results in SVM_EXIT_ERR in HW, which is forwarded to L1, but KVM makes all consistency checks before a VMRUN is actually attempted. Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler") Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 6 ++++++ arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 3aaa4f0bb31ab..93b3fab9b415d 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -392,6 +392,10 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vc= pu, CC(!(save->cr0 & X86_CR0_PE)) || CC(!kvm_vcpu_is_legal_cr3(vcpu, save->cr3))) return false; + + if (CC((save->cs.attrib & SVM_SELECTOR_L_MASK) && + (save->cs.attrib & SVM_SELECTOR_DB_MASK))) + return false; } =20 /* Note, SVM doesn't have any additional restrictions on CR4. */ @@ -487,6 +491,8 @@ static void __nested_copy_vmcb_save_to_cache(struct vmc= b_save_area_cached *to, * Copy only fields that are validated, as we need them * to avoid TOC/TOU races. */ + to->cs =3D from->cs; + to->efer =3D from->efer; to->cr0 =3D from->cr0; to->cr3 =3D from->cr3; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 7629cb37c9302..0a5d5a4453b7e 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -140,6 +140,7 @@ struct kvm_vmcb_info { }; =20 struct vmcb_save_area_cached { + struct vmcb_seg cs; u64 efer; u64 cr4; u64 cr3; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFF31361665; Tue, 3 Mar 2026 00:34:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; cv=none; b=N3VjLStFa8E8vzQQc1RjZuLdly5cEfgWOpEB7gy9e0e9XYC/b04/9/RxXWIWY9+LuMsasLJsPvfxp35lhb6meX7Hmhd3zlLN5HGxjGYTwLniGQnzm0u4MJtfcyQYtZcIq8YxOSN0YKG63sb8ES1NmgBQE4rmiYI4nhhLohXnJ88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498078; c=relaxed/simple; bh=+NotC64fi+InO3KYnZm6GKz1dnXRMKaYF+e8gDrnpC0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MOd/j1bJnBEdVEFtVBXkw5NlVDpwlWNf1BogX7OCCq2xTUwab/7avlddYt8XglR8foG8d67Qbw2sG9AWZFPmUOXAOTVIQnNpLC6aKQan2ErHwWqM+JeEvpUMoltJsjJRzuo28RvKdhF+itN3esbUGO+MwURFkNomT6p2K8Ru74w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pBkVVj7Y; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pBkVVj7Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C320C2BC86; Tue, 3 Mar 2026 00:34:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498078; bh=+NotC64fi+InO3KYnZm6GKz1dnXRMKaYF+e8gDrnpC0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pBkVVj7Yn8LeW/WCuO0TxQmSBDKkmwqPvyHfNz7ByCoSt4mWAbOrh3gquSPqEgbHD h4SdUHFhsP3UniBynOuudwAzUu54UkEaehD5QeA3Hl8mxuVBali4xviFvlU+WD0kb/ hYmFI/b3a7smE6GQ9h2JUT74bY7KLE3s8Urs5iPQnmClohYg3NY7AvIS0LtyyGCy7C K0iYeLJJGMQUSSu/NJqvlLW0myz/e26Q18FcE41q0k612erdjwVfhIikkWeWcOAHgX wKJafACbMH+q0yXQXwdrYR89+CJxz/i85MW4tHktCBAA/CtUEfD1FpwMukJeW/9gbr /Nl22OdcozeqQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v7 17/26] KVM: nSVM: Add missing consistency check for EVENTINJ Date: Tue, 3 Mar 2026 00:34:11 +0000 Message-ID: <20260303003421.2185681-18-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable According to the APM Volume #2, 15.20 (24593=E2=80=94Rev. 3.42=E2=80=94Marc= h 2024): VMRUN exits with VMEXIT_INVALID error code if either: =E2=80=A2 Reserved values of TYPE have been specified, or =E2=80=A2 TYPE =3D 3 (exception) has been specified with a vector that do= es not correspond to an exception (this includes vector 2, which is an NMI, not an exception). Add the missing consistency checks to KVM. For the second point, inject VMEXIT_INVALID if the vector is anything but the vectors defined by the APM for exceptions. Reserved vectors are also considered invalid, which matches the HW behavior. Vector 9 (i.e. #CSO) is considered invalid because it is reserved on modern CPUs, and according to LLMs no CPUs exist supporting SVM and producing #CSOs. Defined exceptions could be different between virtual CPUs as new CPUs define new vectors. In a best effort to dynamically define the valid vectors, make all currently defined vectors as valid except those obviously tied to a CPU feature: SHSTK -> #CP and SEV-ES -> #VC. As new vectors are defined, they can similarly be tied to corresponding CPU features. Invalid vectors on specific (e.g. old) CPUs that are missed by KVM should be rejected by HW anyway. Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler") CC: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 93b3fab9b415d..15f483fac28a0 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -339,6 +339,54 @@ static bool nested_svm_check_bitmap_pa(struct kvm_vcpu= *vcpu, u64 pa, u32 size) kvm_vcpu_is_legal_gpa(vcpu, addr + size - 1); } =20 +static bool nested_svm_event_inj_valid_exept(struct kvm_vcpu *vcpu, u8 vec= tor) +{ + /* + * Vectors that do not correspond to a defined exception are invalid + * (including #NMI and reserved vectors). In a best effort to define + * valid exceptions based on the virtual CPU, make all exceptions always + * valid except those obviously tied to a CPU feature. + */ + switch (vector) { + case DE_VECTOR: case DB_VECTOR: case BP_VECTOR: case OF_VECTOR: + case BR_VECTOR: case UD_VECTOR: case NM_VECTOR: case DF_VECTOR: + case TS_VECTOR: case NP_VECTOR: case SS_VECTOR: case GP_VECTOR: + case PF_VECTOR: case MF_VECTOR: case AC_VECTOR: case MC_VECTOR: + case XM_VECTOR: case HV_VECTOR: case SX_VECTOR: + return true; + case CP_VECTOR: + return guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK); + case VC_VECTOR: + return guest_cpu_cap_has(vcpu, X86_FEATURE_SEV_ES); + } + return false; +} + +/* + * According to the APM, VMRUN exits with SVM_EXIT_ERR if SVM_EVTINJ_VALID= is + * set and: + * - The type of event_inj is not one of the defined values. + * - The type is SVM_EVTINJ_TYPE_EXEPT, but the vector is not a valid exce= ption. + */ +static bool nested_svm_check_event_inj(struct kvm_vcpu *vcpu, u32 event_in= j) +{ + u32 type =3D event_inj & SVM_EVTINJ_TYPE_MASK; + u8 vector =3D event_inj & SVM_EVTINJ_VEC_MASK; + + if (!(event_inj & SVM_EVTINJ_VALID)) + return true; + + if (type !=3D SVM_EVTINJ_TYPE_INTR && type !=3D SVM_EVTINJ_TYPE_NMI && + type !=3D SVM_EVTINJ_TYPE_EXEPT && type !=3D SVM_EVTINJ_TYPE_SOFT) + return false; + + if (type =3D=3D SVM_EVTINJ_TYPE_EXEPT && + !nested_svm_event_inj_valid_exept(vcpu, vector)) + return false; + + return true; +} + static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu, struct vmcb_ctrl_area_cached *control) { @@ -365,6 +413,9 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu = *vcpu, return false; } =20 + if (CC(!nested_svm_check_event_inj(vcpu, control->event_inj))) + return false; + return true; } =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 169C0364936; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; cv=none; b=RS3kVfqjuuNo2nvl71Ol01j5ZZ1hoOSFWsTJnr38kA2JnOmazjROocrz9Fwn4YkozMR1MKrd6LgJh8qDdQJHhbAOW2I0/Qv5cNYXn1LFV89RDGOXVxBaJmpWMgbFEbA/yz+nNCWxzswUjqp78wN0TGuk1sofLT12DZkIb8X+R0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; c=relaxed/simple; bh=4qw1TlrWpsmd//UxHFjs6jBS8JsBWnD5WW9FNAzJsgI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C5FyhVsj2aCLIy3pjExaM+Wg5LjikMW7r3g67CkfG4TzkMjJvlhk1N3e0yXAkoW2GQtRyp5zd01HBjpgVJZaH7++uREPQ5fov30No44aWdEVKsK/d2KEkkbvF+W2uGHEcPzmalW7SPpDZu3bDqnGCRvf0ia2v43ZE6EnOG7Dsfs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EZ3eUU/M; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EZ3eUU/M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1714C2BC9E; Tue, 3 Mar 2026 00:34:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498078; bh=4qw1TlrWpsmd//UxHFjs6jBS8JsBWnD5WW9FNAzJsgI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EZ3eUU/M+8DJ1gBgZryyGM3bxUWed/MEbQHBL7jF3FZdHDHTYLv1GanJ+rDX7uxtW 33Vvap3oGcr3hvPq6REwrQkOOIB08CfFez/ym+86TtiZE6Z12FHL7NRqy9Q/eEAC6Y +rJ+qFV0dbKyd48e0VGTItDAZkAkA9yoBjKUmFrf+MsW4tXFwLVxWGc7Q7FYmFhtdV SDROuRAHRo5u2Ubk3epiMjdHRELlqP1EfHzPs+z95upNide8zqO9VYxudg1mmH9Pce w/a/TvHgrFa7hVg32aiuAGY42Ra9BnLmfCLy6Fme4PCqmd3ukUhnAnXgLLHkyCwwJC /s5TyiedC0VBg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 18/26] KVM: SVM: Rename vmcb->nested_ctl to vmcb->misc_ctl Date: Tue, 3 Mar 2026 00:34:12 +0000 Message-ID: <20260303003421.2185681-19-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The 'nested_ctl' field is misnamed. Although the first bit is for nested paging, the other defined bits are for SEV/SEV-ES. Other bits in the same field according to the APM (but not defined by KVM) include "Guest Mode Execution Trap", "Enable INVLPGB/TLBSYNC", and other control bits unrelated to 'nested'. There is nothing common among these bits, so just name the field misc_ctl. Also rename the flags accordingly. Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/svm.h | 8 ++++---- arch/x86/kvm/svm/nested.c | 14 +++++++------- arch/x86/kvm/svm/sev.c | 4 ++-- arch/x86/kvm/svm/svm.c | 4 ++-- arch/x86/kvm/svm/svm.h | 4 ++-- tools/testing/selftests/kvm/include/x86/svm.h | 6 +++--- tools/testing/selftests/kvm/lib/x86/svm.c | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index edde36097ddc3..983db6575141d 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -142,7 +142,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { u64 exit_info_2; u32 exit_int_info; u32 exit_int_info_err; - u64 nested_ctl; + u64 misc_ctl; u64 avic_vapic_bar; u64 ghcb_gpa; u32 event_inj; @@ -239,9 +239,9 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) =20 -#define SVM_NESTED_CTL_NP_ENABLE BIT(0) -#define SVM_NESTED_CTL_SEV_ENABLE BIT(1) -#define SVM_NESTED_CTL_SEV_ES_ENABLE BIT(2) +#define SVM_MISC_ENABLE_NP BIT(0) +#define SVM_MISC_ENABLE_SEV BIT(1) +#define SVM_MISC_ENABLE_SEV_ES BIT(2) =20 =20 #define SVM_TSC_RATIO_RSVD 0xffffff0000000000ULL diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 15f483fac28a0..2f84fca3df85a 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -396,7 +396,7 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu = *vcpu, if (CC(control->asid =3D=3D 0)) return false; =20 - if (control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) { + if (control->misc_ctl & SVM_MISC_ENABLE_NP) { if (CC(!kvm_vcpu_is_legal_gpa(vcpu, control->nested_cr3))) return false; } @@ -488,10 +488,10 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_v= cpu *vcpu, nested_svm_sanitize_intercept(vcpu, to, SKINIT); nested_svm_sanitize_intercept(vcpu, to, RDPRU); =20 - /* Always clear SVM_NESTED_CTL_NP_ENABLE if the guest cannot use NPTs */ - to->nested_ctl =3D from->nested_ctl; + /* Always clear SVM_MISC_ENABLE_NP if the guest cannot use NPTs */ + to->misc_ctl =3D from->misc_ctl; if (!guest_cpu_cap_has(vcpu, X86_FEATURE_NPT)) - to->nested_ctl &=3D ~SVM_NESTED_CTL_NP_ENABLE; + to->misc_ctl &=3D ~SVM_MISC_ENABLE_NP; =20 to->iopm_base_pa =3D from->iopm_base_pa; to->msrpm_base_pa =3D from->msrpm_base_pa; @@ -835,7 +835,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_s= vm *svm, } =20 /* Copied from vmcb01. msrpm_base can be overwritten later. */ - vmcb02->control.nested_ctl =3D vmcb01->control.nested_ctl; + vmcb02->control.misc_ctl =3D vmcb01->control.misc_ctl; vmcb02->control.iopm_base_pa =3D vmcb01->control.iopm_base_pa; vmcb02->control.msrpm_base_pa =3D vmcb01->control.msrpm_base_pa; vmcb_mark_dirty(vmcb02, VMCB_PERM_MAP); @@ -995,7 +995,7 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmc= b12_gpa, vmcb12->save.rip, vmcb12->control.int_ctl, vmcb12->control.event_inj, - vmcb12->control.nested_ctl, + vmcb12->control.misc_ctl, vmcb12->control.nested_cr3, vmcb12->save.cr3, KVM_ISA_SVM); @@ -1785,7 +1785,7 @@ static void nested_copy_vmcb_cache_to_control(struct = vmcb_control_area *dst, dst->exit_info_2 =3D from->exit_info_2; dst->exit_int_info =3D from->exit_int_info; dst->exit_int_info_err =3D from->exit_int_info_err; - dst->nested_ctl =3D from->nested_ctl; + dst->misc_ctl =3D from->misc_ctl; dst->event_inj =3D from->event_inj; dst->event_inj_err =3D from->event_inj_err; dst->next_rip =3D from->next_rip; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index ea515cf411686..0ed9cfed1cbcc 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -4599,7 +4599,7 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm, bo= ol init_event) struct kvm_sev_info *sev =3D to_kvm_sev_info(svm->vcpu.kvm); struct vmcb *vmcb =3D svm->vmcb01.ptr; =20 - svm->vmcb->control.nested_ctl |=3D SVM_NESTED_CTL_SEV_ES_ENABLE; + svm->vmcb->control.misc_ctl |=3D SVM_MISC_ENABLE_SEV_ES; =20 /* * An SEV-ES guest requires a VMSA area that is a separate from the @@ -4670,7 +4670,7 @@ void sev_init_vmcb(struct vcpu_svm *svm, bool init_ev= ent) { struct kvm_vcpu *vcpu =3D &svm->vcpu; =20 - svm->vmcb->control.nested_ctl |=3D SVM_NESTED_CTL_SEV_ENABLE; + svm->vmcb->control.misc_ctl |=3D SVM_MISC_ENABLE_SEV; clr_exception_intercept(svm, UD_VECTOR); =20 /* diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 1b31b033d79b0..7bc8b72fe5ad8 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1152,7 +1152,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool ini= t_event) =20 if (npt_enabled) { /* Setup VMCB for Nested Paging */ - control->nested_ctl |=3D SVM_NESTED_CTL_NP_ENABLE; + control->misc_ctl |=3D SVM_MISC_ENABLE_NP; svm_clr_intercept(svm, INTERCEPT_INVLPG); clr_exception_intercept(svm, PF_VECTOR); svm_clr_intercept(svm, INTERCEPT_CR3_READ); @@ -3362,7 +3362,7 @@ static void dump_vmcb(struct kvm_vcpu *vcpu) pr_err("%-20s%016llx\n", "exit_info2:", control->exit_info_2); pr_err("%-20s%08x\n", "exit_int_info:", control->exit_int_info); pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err); - pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl); + pr_err("%-20s%lld\n", "misc_ctl:", control->misc_ctl); pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3); pr_err("%-20s%016llx\n", "avic_vapic_bar:", control->avic_vapic_bar); pr_err("%-20s%016llx\n", "ghcb:", control->ghcb_gpa); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 0a5d5a4453b7e..f66e5c8565aad 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -167,7 +167,7 @@ struct vmcb_ctrl_area_cached { u64 exit_info_2; u32 exit_int_info; u32 exit_int_info_err; - u64 nested_ctl; + u64 misc_ctl; u32 event_inj; u32 event_inj_err; u64 next_rip; @@ -579,7 +579,7 @@ static inline bool gif_set(struct vcpu_svm *svm) =20 static inline bool nested_npt_enabled(struct vcpu_svm *svm) { - return svm->nested.ctl.nested_ctl & SVM_NESTED_CTL_NP_ENABLE; + return svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_NP; } =20 static inline bool nested_vnmi_enabled(struct vcpu_svm *svm) diff --git a/tools/testing/selftests/kvm/include/x86/svm.h b/tools/testing/= selftests/kvm/include/x86/svm.h index 10b30b38bb3fd..d81d8a9f5bfb6 100644 --- a/tools/testing/selftests/kvm/include/x86/svm.h +++ b/tools/testing/selftests/kvm/include/x86/svm.h @@ -97,7 +97,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { u64 exit_info_2; u32 exit_int_info; u32 exit_int_info_err; - u64 nested_ctl; + u64 misc_ctl; u64 avic_vapic_bar; u8 reserved_4[8]; u32 event_inj; @@ -175,8 +175,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define SVM_VM_CR_SVM_LOCK_MASK 0x0008ULL #define SVM_VM_CR_SVM_DIS_MASK 0x0010ULL =20 -#define SVM_NESTED_CTL_NP_ENABLE BIT(0) -#define SVM_NESTED_CTL_SEV_ENABLE BIT(1) +#define SVM_MISC_ENABLE_NP BIT(0) +#define SVM_MISC_ENABLE_SEV BIT(1) =20 struct __attribute__ ((__packed__)) vmcb_seg { u16 selector; diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 2e5c480c9afd4..eb20b00112c76 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -126,7 +126,7 @@ void generic_svm_setup(struct svm_test_data *svm, void = *guest_rip, void *guest_r guest_regs.rdi =3D (u64)svm; =20 if (svm->ncr3_gpa) { - ctrl->nested_ctl |=3D SVM_NESTED_CTL_NP_ENABLE; + ctrl->misc_ctl |=3D SVM_MISC_ENABLE_NP; ctrl->nested_cr3 =3D svm->ncr3_gpa; } } --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9AEAC36654B; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; cv=none; b=uVbykI1b4gJ6je7G3Z1v3JQ7cjNI+E4+e20g0uvlCp8OdMAegAmRnbwOdInrXDWqpsCawM/dLSF/MkpgBT0GrcaRPOVOkhOj4tyOo46z+Lax0D4hKM5XA2lv4vqtP5fFpGA/WrSqywFXkc+Eg0aYLf3QTt3io2dbD6P38KRnutg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; c=relaxed/simple; bh=lHsfF4Sr8Is/RN6rAX3qcLFjIb4PEZNKU9lIlDYTin4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XtjCcJsYMbYBDDxxt3P0EMp/j8K345ygJCHDM1V+UjJh+aG9jly39XdSC5HePx4+gYgZb6RAYO7rJvr/CDB7F8PnQS+jsvMDhYC7RuczUDzhGDOeNTUkIgBwm4tf5hwozBnwaHLMKmVX7rfLXUE1swuSiAAIOygEyYQ+oiAbbsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XoorKbzZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XoorKbzZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 19BCCC19423; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498079; bh=lHsfF4Sr8Is/RN6rAX3qcLFjIb4PEZNKU9lIlDYTin4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XoorKbzZSv3gGDCxhgx1d7nXoWJ5uQgC2BmlgsL3Rnw4imKDyzyt2CTWmvfwzTIEP XH0pw0pKzRL7lb4METytP1TYaBAtwiMP8GvlmTeGAzHlzOOpB1RrycoqBW7igt9oEg acEVdinnQ2YJP8+lLNODw7I4ezXrCsEyVpLd+2t5PBzaJa9NaFoTIOEFdLSxZTJOiS UnhFd1CGfRxUN1xu2PX0WF+WUaYMaJzl2/mNjaoEqwU1uqcTL0r2y1brQQYtmF/KW3 YulwGg8xq9e8y8Sws2ub6WeYTr6WGxs14KqxPXfzy/mzGhBK4Gf0oYFXAI4F3y26I2 5s9lOKHIPH+5w== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 19/26] KVM: SVM: Rename vmcb->virt_ext to vmcb->misc_ctl2 Date: Tue, 3 Mar 2026 00:34:13 +0000 Message-ID: <20260303003421.2185681-20-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 'virt' is confusing in the VMCB because it is relative and ambiguous. The 'virt_ext' field includes bits for LBR virtualization and VMSAVE/VMLOAD virtualization, so it's just another miscellaneous control field. Name it as such. While at it, move the definitions of the bits below those for 'misc_ctl' and rename them for consistency. Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/svm.h | 7 +++---- arch/x86/kvm/svm/nested.c | 16 +++++++-------- arch/x86/kvm/svm/svm.c | 20 +++++++++---------- arch/x86/kvm/svm/svm.h | 2 +- tools/testing/selftests/kvm/include/x86/svm.h | 8 ++++---- .../kvm/x86/nested_vmsave_vmload_test.c | 16 +++++++-------- .../selftests/kvm/x86/svm_lbr_nested_state.c | 4 ++-- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 983db6575141d..c169256c415fb 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -148,7 +148,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { u32 event_inj; u32 event_inj_err; u64 nested_cr3; - u64 virt_ext; + u64 misc_ctl2; u32 clean; u32 reserved_5; u64 next_rip; @@ -222,9 +222,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define X2APIC_MODE_SHIFT 30 #define X2APIC_MODE_MASK (1 << X2APIC_MODE_SHIFT) =20 -#define LBR_CTL_ENABLE_MASK BIT_ULL(0) -#define VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK BIT_ULL(1) - #define SVM_INTERRUPT_SHADOW_MASK BIT_ULL(0) #define SVM_GUEST_INTERRUPT_MASK BIT_ULL(1) =20 @@ -243,6 +240,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define SVM_MISC_ENABLE_SEV BIT(1) #define SVM_MISC_ENABLE_SEV_ES BIT(2) =20 +#define SVM_MISC2_ENABLE_V_LBR BIT_ULL(0) +#define SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE BIT_ULL(1) =20 #define SVM_TSC_RATIO_RSVD 0xffffff0000000000ULL #define SVM_TSC_RATIO_MIN 0x0000000000000001ULL diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 2f84fca3df85a..5994e309831d0 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -116,7 +116,7 @@ static bool nested_vmcb_needs_vls_intercept(struct vcpu= _svm *svm) if (!nested_npt_enabled(svm)) return true; =20 - if (!(svm->nested.ctl.virt_ext & VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK)) + if (!(svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE)) return true; =20 return false; @@ -179,7 +179,7 @@ void recalc_intercepts(struct vcpu_svm *svm) vmcb_set_intercept(c, INTERCEPT_VMLOAD); vmcb_set_intercept(c, INTERCEPT_VMSAVE); } else { - WARN_ON(!(c->virt_ext & VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK)); + WARN_ON(!(c->misc_ctl2 & SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE)); } } =20 @@ -510,7 +510,7 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, to->event_inj_err =3D from->event_inj_err; to->next_rip =3D from->next_rip; to->nested_cr3 =3D from->nested_cr3; - to->virt_ext =3D from->virt_ext; + to->misc_ctl2 =3D from->misc_ctl2; to->pause_filter_count =3D from->pause_filter_count; to->pause_filter_thresh =3D from->pause_filter_thresh; =20 @@ -689,7 +689,7 @@ void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm) static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu) { return guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && - (to_svm(vcpu)->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK); + (to_svm(vcpu)->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR); } =20 static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *= vmcb12) @@ -920,10 +920,10 @@ static void nested_vmcb02_prepare_control(struct vcpu= _svm *svm, svm->soft_int_next_rip =3D vmcb12_rip; } =20 - /* LBR_CTL_ENABLE_MASK is controlled by svm_update_lbrv() */ + /* SVM_MISC2_ENABLE_V_LBR is controlled by svm_update_lbrv() */ =20 if (!nested_vmcb_needs_vls_intercept(svm)) - vmcb02->control.virt_ext |=3D VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + vmcb02->control.misc_ctl2 |=3D SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; =20 if (guest_cpu_cap_has(vcpu, X86_FEATURE_PAUSEFILTER)) pause_count12 =3D svm->nested.ctl.pause_filter_count; @@ -1789,8 +1789,8 @@ static void nested_copy_vmcb_cache_to_control(struct = vmcb_control_area *dst, dst->event_inj =3D from->event_inj; dst->event_inj_err =3D from->event_inj_err; dst->next_rip =3D from->next_rip; - dst->nested_cr3 =3D from->nested_cr3; - dst->virt_ext =3D from->virt_ext; + dst->nested_cr3 =3D from->nested_cr3; + dst->misc_ctl2 =3D from->misc_ctl2; dst->pause_filter_count =3D from->pause_filter_count; dst->pause_filter_thresh =3D from->pause_filter_thresh; /* 'clean' and 'hv_enlightenments' are not changed by KVM */ diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 7bc8b72fe5ad8..94e14badddfa2 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -710,7 +710,7 @@ void *svm_alloc_permissions_map(unsigned long size, gfp= _t gfp_mask) static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); - bool intercept =3D !(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK); + bool intercept =3D !(svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LB= R); =20 if (intercept =3D=3D svm->lbr_msrs_intercepted) return; @@ -843,7 +843,7 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu *= vcpu) =20 static void __svm_enable_lbrv(struct kvm_vcpu *vcpu) { - to_svm(vcpu)->vmcb->control.virt_ext |=3D LBR_CTL_ENABLE_MASK; + to_svm(vcpu)->vmcb->control.misc_ctl2 |=3D SVM_MISC2_ENABLE_V_LBR; } =20 void svm_enable_lbrv(struct kvm_vcpu *vcpu) @@ -855,16 +855,16 @@ void svm_enable_lbrv(struct kvm_vcpu *vcpu) static void __svm_disable_lbrv(struct kvm_vcpu *vcpu) { KVM_BUG_ON(sev_es_guest(vcpu->kvm), vcpu->kvm); - to_svm(vcpu)->vmcb->control.virt_ext &=3D ~LBR_CTL_ENABLE_MASK; + to_svm(vcpu)->vmcb->control.misc_ctl2 &=3D ~SVM_MISC2_ENABLE_V_LBR; } =20 void svm_update_lbrv(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); - bool current_enable_lbrv =3D svm->vmcb->control.virt_ext & LBR_CTL_ENABLE= _MASK; + bool current_enable_lbrv =3D svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENA= BLE_V_LBR; bool enable_lbrv =3D (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR) || (is_guest_mode(vcpu) && guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && - (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK)); + (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR)); =20 if (enable_lbrv && !current_enable_lbrv) __svm_enable_lbrv(vcpu); @@ -1023,7 +1023,7 @@ static void svm_recalc_instruction_intercepts(struct = kvm_vcpu *vcpu) } =20 /* - * No need to toggle VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK here, it is + * No need to toggle SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE here, it is * always set if vls is enabled. If the intercepts are set, the bit is * meaningless anyway. */ @@ -1191,7 +1191,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool ini= t_event) } =20 if (vls) - svm->vmcb->control.virt_ext |=3D VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + svm->vmcb->control.misc_ctl2 |=3D SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; =20 if (vcpu->kvm->arch.bus_lock_detection_enabled) svm_set_intercept(svm, INTERCEPT_BUSLOCK); @@ -3368,7 +3368,7 @@ static void dump_vmcb(struct kvm_vcpu *vcpu) pr_err("%-20s%016llx\n", "ghcb:", control->ghcb_gpa); pr_err("%-20s%08x\n", "event_inj:", control->event_inj); pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err); - pr_err("%-20s%lld\n", "virt_ext:", control->virt_ext); + pr_err("%-20s%lld\n", "misc_ctl2:", control->misc_ctl2); pr_err("%-20s%016llx\n", "next_rip:", control->next_rip); pr_err("%-20s%016llx\n", "avic_backing_page:", control->avic_backing_page= ); pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id); @@ -4363,7 +4363,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_= vcpu *vcpu, u64 run_flags) * VM-Exit), as running with the host's DEBUGCTL can negatively affect * guest state and can even be fatal, e.g. due to Bus Lock Detect. */ - if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) && + if (!(svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR) && vcpu->arch.host_debugctl !=3D svm->vmcb->save.dbgctl) update_debugctlmsr(svm->vmcb->save.dbgctl); =20 @@ -4394,7 +4394,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_= vcpu *vcpu, u64 run_flags) if (unlikely(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_NMI)) kvm_before_interrupt(vcpu, KVM_HANDLING_NMI); =20 - if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) && + if (!(svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR) && vcpu->arch.host_debugctl !=3D svm->vmcb->save.dbgctl) update_debugctlmsr(vcpu->arch.host_debugctl); =20 diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index f66e5c8565aad..304328c33e960 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -172,7 +172,7 @@ struct vmcb_ctrl_area_cached { u32 event_inj_err; u64 next_rip; u64 nested_cr3; - u64 virt_ext; + u64 misc_ctl2; u32 clean; u64 bus_lock_rip; union { diff --git a/tools/testing/selftests/kvm/include/x86/svm.h b/tools/testing/= selftests/kvm/include/x86/svm.h index d81d8a9f5bfb6..c8539166270ea 100644 --- a/tools/testing/selftests/kvm/include/x86/svm.h +++ b/tools/testing/selftests/kvm/include/x86/svm.h @@ -103,7 +103,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { u32 event_inj; u32 event_inj_err; u64 nested_cr3; - u64 virt_ext; + u64 misc_ctl2; u32 clean; u32 reserved_5; u64 next_rip; @@ -155,9 +155,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define AVIC_ENABLE_SHIFT 31 #define AVIC_ENABLE_MASK (1 << AVIC_ENABLE_SHIFT) =20 -#define LBR_CTL_ENABLE_MASK BIT_ULL(0) -#define VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK BIT_ULL(1) - #define SVM_INTERRUPT_SHADOW_MASK 1 =20 #define SVM_IOIO_STR_SHIFT 2 @@ -178,6 +175,9 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define SVM_MISC_ENABLE_NP BIT(0) #define SVM_MISC_ENABLE_SEV BIT(1) =20 +#define SVM_MISC2_ENABLE_V_LBR BIT_ULL(0) +#define SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE BIT_ULL(1) + struct __attribute__ ((__packed__)) vmcb_seg { u16 selector; u16 attrib; diff --git a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c b/= tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c index 6764a48f9d4d9..71717118d6924 100644 --- a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c +++ b/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c @@ -79,8 +79,8 @@ static void l1_guest_code(struct svm_test_data *svm) svm->vmcb->control.intercept |=3D (BIT_ULL(INTERCEPT_VMSAVE) | BIT_ULL(INTERCEPT_VMLOAD)); =20 - /* ..VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK cleared.. */ - svm->vmcb->control.virt_ext &=3D ~VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + /* ..SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE cleared.. */ + svm->vmcb->control.misc_ctl2 &=3D ~SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; =20 svm->vmcb->save.rip =3D (u64)l2_guest_code_vmsave; run_guest(svm->vmcb, svm->vmcb_gpa); @@ -90,8 +90,8 @@ static void l1_guest_code(struct svm_test_data *svm) run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMLOAD); =20 - /* ..and VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK set */ - svm->vmcb->control.virt_ext |=3D VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + /* ..and SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE set */ + svm->vmcb->control.misc_ctl2 |=3D SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; =20 svm->vmcb->save.rip =3D (u64)l2_guest_code_vmsave; run_guest(svm->vmcb, svm->vmcb_gpa); @@ -106,20 +106,20 @@ static void l1_guest_code(struct svm_test_data *svm) BIT_ULL(INTERCEPT_VMLOAD)); =20 /* - * Without VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK, the GPA will be + * Without SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE, the GPA will be * interpreted as an L1 GPA, so VMCB0 should be used. */ svm->vmcb->save.rip =3D (u64)l2_guest_code_vmcb0; - svm->vmcb->control.virt_ext &=3D ~VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + svm->vmcb->control.misc_ctl2 &=3D ~SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL); =20 /* - * With VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK, the GPA will be interpeted as + * With SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE, the GPA will be interpeted as * an L2 GPA, and translated through the NPT to VMCB1. */ svm->vmcb->save.rip =3D (u64)l2_guest_code_vmcb1; - svm->vmcb->control.virt_ext |=3D VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; + svm->vmcb->control.misc_ctl2 |=3D SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE; run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL); =20 diff --git a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c b/tools= /testing/selftests/kvm/x86/svm_lbr_nested_state.c index bf16abb1152e0..ff99438824d3a 100644 --- a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c +++ b/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c @@ -69,9 +69,9 @@ static void l1_guest_code(struct svm_test_data *svm, bool= nested_lbrv) &l2_guest_stack[L2_GUEST_STACK_SIZE]); =20 if (nested_lbrv) - vmcb->control.virt_ext =3D LBR_CTL_ENABLE_MASK; + vmcb->control.misc_ctl2 =3D SVM_MISC2_ENABLE_V_LBR; else - vmcb->control.virt_ext &=3D ~LBR_CTL_ENABLE_MASK; + vmcb->control.misc_ctl2 &=3D ~SVM_MISC2_ENABLE_V_LBR; =20 run_guest(vmcb, svm->vmcb_gpa); GUEST_ASSERT(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_VMMCALL); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5B52366570; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; cv=none; b=G37UgX1MfmARWwhCzRYm817U9wxdcUR9HgS5g03jsvUi1GRjl3kWhPymWhfr/zcV9+rI9sLQl4eZYHFKNF2JgPwlOqDttqJJI8IAxVw/ES0AZ9kU04Wjf2G6d3nEbM+9g+zWinDxKfU9q1e2/mqxgQo5gZWtVWJs2YCYGeNZyK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498079; c=relaxed/simple; bh=iVkzc2Qb7bTJIvKcSCArEB8mpEt69UegMebDNgIwCYE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bBEVKacY4ycHuJSYdnyPmtuw32Ym3OtBjhuYzfu2Ij2YCs6OPwaoWYKKWvsk4HeW1ehDHjbbqaeyuJHkRM34qXCbGi6IRqZ+2X1mTEy2wBP/LYSuUMHus2kamlK4bMoz52hVnu2fO3DQ+m0UzLrG8Z4IOx5Z8oPX3sXy3M6VJTE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=awMYoRgp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="awMYoRgp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7674EC2BC86; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498079; bh=iVkzc2Qb7bTJIvKcSCArEB8mpEt69UegMebDNgIwCYE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=awMYoRgpDF3eEds0iqiGlCTaw6WYmpAU6tAPKUgSUs0TkrjDFzpwo2nnMIdXIGJsu nTdgR2cnCKmq7I7z9SyZWMVHsU4H4H4/IFq3PXMlZPdFeFWjpgcAYKe/IuUKVMAok3 fEy6MSDZ3W0Jbn7juz0nOX6vzgtM95UIwd4Iq4vuzW0JdQNqZQqOPn8VqDYCwIJB8b gHIzOUhBM+0wcR3vcZB8TsfAzGhfJjTZWkbO6z28BAZwQUldUGObobEXIEdhviXp6p 6s8uU/4Ilyt+F2uME2oO2K5qryXF/SJDAB+LDIZA3gwbWJBjgEzR78Y0xtFsryi1Fq 8FhhW1Ht5n1bQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 20/26] KVM: nSVM: Cache all used fields from VMCB12 Date: Tue, 3 Mar 2026 00:34:14 +0000 Message-ID: <20260303003421.2185681-21-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, most fields used from VMCB12 are cached in svm->nested.{ctl/save}. This is mainly to avoid TOC-TOU bugs. However, for the save area, only the fields used in the consistency checks (i.e. nested_vmcb_check_save()) were being cached. Other fields are read directly from guest memory in nested_vmcb02_prepare_save(). While probably benign, this still makes it possible for TOC-TOU bugs to happen. For example, RAX, RSP, and RIP are read twice, once to store in VMCB02, and once to store in vcpu->arch.regs. It is possible for the guest to modify the value between both reads, potentially causing nasty bugs. Harden against such bugs by caching everything in svm->nested.save. Cache all the needed fields, and keep all accesses to the VMCB12 strictly in nested_svm_vmrun() for caching and early error injection. Following changes will further limit the access to the VMCB12 in the nested VMRUN path. Introduce vmcb12_is_dirty() to use with the cached control fields instead of vmcb_is_dirty(), similar to vmcb12_is_intercept(). Opportunistically order the copies in __nested_copy_vmcb_save_to_cache() by the order in which the fields are defined in struct vmcb_save_area. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 118 ++++++++++++++++++++++---------------- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/svm/svm.h | 27 ++++++++- 3 files changed, 94 insertions(+), 53 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 5994e309831d0..f89040a467d4a 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -518,11 +518,11 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_v= cpu *vcpu, to->asid =3D from->asid; to->msrpm_base_pa &=3D ~0x0fffULL; to->iopm_base_pa &=3D ~0x0fffULL; + to->clean =3D from->clean; =20 #ifdef CONFIG_KVM_HYPERV /* Hyper-V extensions (Enlightened VMCB) */ if (kvm_hv_hypercall_enabled(vcpu)) { - to->clean =3D from->clean; memcpy(&to->hv_enlightenments, &from->hv_enlightenments, sizeof(to->hv_enlightenments)); } @@ -538,19 +538,34 @@ void nested_copy_vmcb_control_to_cache(struct vcpu_sv= m *svm, static void __nested_copy_vmcb_save_to_cache(struct vmcb_save_area_cached = *to, struct vmcb_save_area *from) { - /* - * Copy only fields that are validated, as we need them - * to avoid TOC/TOU races. - */ + to->es =3D from->es; to->cs =3D from->cs; + to->ss =3D from->ss; + to->ds =3D from->ds; + to->gdtr =3D from->gdtr; + to->idtr =3D from->idtr; + + to->cpl =3D from->cpl; =20 to->efer =3D from->efer; - to->cr0 =3D from->cr0; - to->cr3 =3D from->cr3; to->cr4 =3D from->cr4; - - to->dr6 =3D from->dr6; + to->cr3 =3D from->cr3; + to->cr0 =3D from->cr0; to->dr7 =3D from->dr7; + to->dr6 =3D from->dr6; + + to->rflags =3D from->rflags; + to->rip =3D from->rip; + to->rsp =3D from->rsp; + + to->s_cet =3D from->s_cet; + to->ssp =3D from->ssp; + to->isst_addr =3D from->isst_addr; + + to->rax =3D from->rax; + to->cr2 =3D from->cr2; + + svm_copy_lbrs(to, from); } =20 void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, @@ -692,8 +707,10 @@ static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vc= pu) (to_svm(vcpu)->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR); } =20 -static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *= vmcb12) +static void nested_vmcb02_prepare_save(struct vcpu_svm *svm) { + struct vmcb_ctrl_area_cached *control =3D &svm->nested.ctl; + struct vmcb_save_area_cached *save =3D &svm->nested.save; bool new_vmcb12 =3D false; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; @@ -709,48 +726,48 @@ static void nested_vmcb02_prepare_save(struct vcpu_sv= m *svm, struct vmcb *vmcb12 svm->nested.force_msr_bitmap_recalc =3D true; } =20 - if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_SEG))) { - vmcb02->save.es =3D vmcb12->save.es; - vmcb02->save.cs =3D vmcb12->save.cs; - vmcb02->save.ss =3D vmcb12->save.ss; - vmcb02->save.ds =3D vmcb12->save.ds; - vmcb02->save.cpl =3D vmcb12->save.cpl; + if (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_SEG))) { + vmcb02->save.es =3D save->es; + vmcb02->save.cs =3D save->cs; + vmcb02->save.ss =3D save->ss; + vmcb02->save.ds =3D save->ds; + vmcb02->save.cpl =3D save->cpl; vmcb_mark_dirty(vmcb02, VMCB_SEG); } =20 - if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_DT))) { - vmcb02->save.gdtr =3D vmcb12->save.gdtr; - vmcb02->save.idtr =3D vmcb12->save.idtr; + if (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_DT))) { + vmcb02->save.gdtr =3D save->gdtr; + vmcb02->save.idtr =3D save->idtr; vmcb_mark_dirty(vmcb02, VMCB_DT); } =20 if (guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && - (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_CET)))) { - vmcb02->save.s_cet =3D vmcb12->save.s_cet; - vmcb02->save.isst_addr =3D vmcb12->save.isst_addr; - vmcb02->save.ssp =3D vmcb12->save.ssp; + (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_CET)))) { + vmcb02->save.s_cet =3D save->s_cet; + vmcb02->save.isst_addr =3D save->isst_addr; + vmcb02->save.ssp =3D save->ssp; vmcb_mark_dirty(vmcb02, VMCB_CET); } =20 - kvm_set_rflags(vcpu, vmcb12->save.rflags | X86_EFLAGS_FIXED); + kvm_set_rflags(vcpu, save->rflags | X86_EFLAGS_FIXED); =20 svm_set_efer(vcpu, svm->nested.save.efer); =20 svm_set_cr0(vcpu, svm->nested.save.cr0); svm_set_cr4(vcpu, svm->nested.save.cr4); =20 - svm->vcpu.arch.cr2 =3D vmcb12->save.cr2; + svm->vcpu.arch.cr2 =3D save->cr2; =20 - kvm_rax_write(vcpu, vmcb12->save.rax); - kvm_rsp_write(vcpu, vmcb12->save.rsp); - kvm_rip_write(vcpu, vmcb12->save.rip); + kvm_rax_write(vcpu, save->rax); + kvm_rsp_write(vcpu, save->rsp); + kvm_rip_write(vcpu, save->rip); =20 /* In case we don't even reach vcpu_run, the fields are not updated */ - vmcb02->save.rax =3D vmcb12->save.rax; - vmcb02->save.rsp =3D vmcb12->save.rsp; - vmcb02->save.rip =3D vmcb12->save.rip; + vmcb02->save.rax =3D save->rax; + vmcb02->save.rsp =3D save->rsp; + vmcb02->save.rip =3D save->rip; =20 - if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_DR))) { + if (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_DR))) { vmcb02->save.dr7 =3D svm->nested.save.dr7 | DR7_FIXED_1; svm->vcpu.arch.dr6 =3D svm->nested.save.dr6 | DR6_ACTIVE_LOW; vmcb_mark_dirty(vmcb02, VMCB_DR); @@ -761,7 +778,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm = *svm, struct vmcb *vmcb12 * Reserved bits of DEBUGCTL are ignored. Be consistent with * svm_set_msr's definition of reserved bits. */ - svm_copy_lbrs(&vmcb02->save, &vmcb12->save); + svm_copy_lbrs(&vmcb02->save, save); vmcb02->save.dbgctl &=3D ~DEBUGCTL_RESERVED_BITS; } else { svm_copy_lbrs(&vmcb02->save, &vmcb01->save); @@ -984,28 +1001,29 @@ static void nested_svm_copy_common_state(struct vmcb= *from_vmcb, struct vmcb *to to_vmcb->save.spec_ctrl =3D from_vmcb->save.spec_ctrl; } =20 -int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, - struct vmcb *vmcb12, bool from_vmrun) +int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, bool from_= vmrun) { struct vcpu_svm *svm =3D to_svm(vcpu); + struct vmcb_ctrl_area_cached *control =3D &svm->nested.ctl; + struct vmcb_save_area_cached *save =3D &svm->nested.save; int ret; =20 trace_kvm_nested_vmenter(svm->vmcb->save.rip, vmcb12_gpa, - vmcb12->save.rip, - vmcb12->control.int_ctl, - vmcb12->control.event_inj, - vmcb12->control.misc_ctl, - vmcb12->control.nested_cr3, - vmcb12->save.cr3, + save->rip, + control->int_ctl, + control->event_inj, + control->misc_ctl, + control->nested_cr3, + save->cr3, KVM_ISA_SVM); =20 - trace_kvm_nested_intercepts(vmcb12->control.intercepts[INTERCEPT_CR] & 0x= ffff, - vmcb12->control.intercepts[INTERCEPT_CR] >> 16, - vmcb12->control.intercepts[INTERCEPT_EXCEPTION], - vmcb12->control.intercepts[INTERCEPT_WORD3], - vmcb12->control.intercepts[INTERCEPT_WORD4], - vmcb12->control.intercepts[INTERCEPT_WORD5]); + trace_kvm_nested_intercepts(control->intercepts[INTERCEPT_CR] & 0xffff, + control->intercepts[INTERCEPT_CR] >> 16, + control->intercepts[INTERCEPT_EXCEPTION], + control->intercepts[INTERCEPT_WORD3], + control->intercepts[INTERCEPT_WORD4], + control->intercepts[INTERCEPT_WORD5]); =20 =20 svm->nested.vmcb12_gpa =3D vmcb12_gpa; @@ -1015,8 +1033,8 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 v= mcb12_gpa, nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); =20 svm_switch_vmcb(svm, &svm->nested.vmcb02); - nested_vmcb02_prepare_control(svm, vmcb12->save.rip, vmcb12->save.cs.base= ); - nested_vmcb02_prepare_save(svm, vmcb12); + nested_vmcb02_prepare_control(svm, save->rip, save->cs.base); + nested_vmcb02_prepare_save(svm); =20 ret =3D nested_svm_load_cr3(&svm->vcpu, svm->nested.save.cr3, nested_npt_enabled(svm), from_vmrun); @@ -1104,7 +1122,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) =20 svm->nested.nested_run_pending =3D 1; =20 - if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, true)) + if (enter_svm_guest_mode(vcpu, vmcb12_gpa, true)) goto out_exit_err; =20 if (nested_svm_merge_msrpm(vcpu)) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 94e14badddfa2..19112ec48c0f7 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4885,7 +4885,7 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const= union kvm_smram *smram) vmcb12 =3D map.hva; nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); - ret =3D enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, vmcb12, f= alse); + ret =3D enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, false); =20 if (ret) goto unmap_save; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 304328c33e960..388aaa5d63d29 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -140,13 +140,32 @@ struct kvm_vmcb_info { }; =20 struct vmcb_save_area_cached { + struct vmcb_seg es; struct vmcb_seg cs; + struct vmcb_seg ss; + struct vmcb_seg ds; + struct vmcb_seg gdtr; + struct vmcb_seg idtr; + u8 cpl; u64 efer; u64 cr4; u64 cr3; u64 cr0; u64 dr7; u64 dr6; + u64 rflags; + u64 rip; + u64 rsp; + u64 s_cet; + u64 ssp; + u64 isst_addr; + u64 rax; + u64 cr2; + u64 dbgctl; + u64 br_from; + u64 br_to; + u64 last_excp_from; + u64 last_excp_to; }; =20 struct vmcb_ctrl_area_cached { @@ -421,6 +440,11 @@ static inline bool vmcb_is_dirty(struct vmcb *vmcb, in= t bit) return !test_bit(bit, (unsigned long *)&vmcb->control.clean); } =20 +static inline bool vmcb12_is_dirty(struct vmcb_ctrl_area_cached *control, = int bit) +{ + return !test_bit(bit, (unsigned long *)&control->clean); +} + static __always_inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) { return container_of(vcpu, struct vcpu_svm, vcpu); @@ -785,8 +809,7 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *= svm) =20 int __init nested_svm_init_msrpm_merge_offsets(void); =20 -int enter_svm_guest_mode(struct kvm_vcpu *vcpu, - u64 vmcb_gpa, struct vmcb *vmcb12, bool from_vmrun); +int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb_gpa, bool from_vm= run); void svm_leave_nested(struct kvm_vcpu *vcpu); void svm_free_nested(struct vcpu_svm *svm); int svm_allocate_nested(struct vcpu_svm *svm); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F594367F3C; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; cv=none; b=uEuarOU7VOPsc45h7D4lcUdSvl8lhaYoqPXul0pXcurd8zaNaAOn6i0yfTDT9EuPe6IIcJqXCy0rGz5uO1zmLKg7tjrVqK/qrJIMOCIlflzicloYkeALBZHGblvrHgh8BzwSdvUGGPUjV/3gs/V2rKdJeAgIVdp/Ssnv4w6JSdk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; c=relaxed/simple; bh=t6T5p2jEtoStZk2ZCNurG/WhOCqTBgnABKrBRmfK3Vs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W3G2Zbpttr934YBHrPMFstOJfWaUEAdZ8OasyNiVmsYcREFSJ7oXBZB05PJRHF3EWEjJZMgv5Cz1eatgx5oiGD+/vGtEIiZJZiXi44iq4oTzYCS3HR3oTRTzddm7E4d4tGSFZh2y4H2A5KG0Pe2CiuF59a0+6RN8SrCNQ+7TKSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WiveKnAA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WiveKnAA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2C8EC19423; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498080; bh=t6T5p2jEtoStZk2ZCNurG/WhOCqTBgnABKrBRmfK3Vs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WiveKnAAkAzfOFda66zzm2IoS1jhljqRP0atuS/SODnFiCj/IQBiNaftOtNrV5ocH Cx0T7IkDz+KcUSGib0XvdATUQd5A8a3uGtsGBgEVvONp69AVEMf8i7GQ6y5oZ13Vyo JpF+eN+FMKYJTZJiRiaAJq4qOzIp8FsmEcppn1S3NqUlX2d8nhIgPgAGCQT/qClBwW KHIuE/JQMweotwcF/wrrM6scu5IOAOxCkUsKU/aGBD8rLPLpflSPlyvQfhDs3QM0Zk NIAN2R1BYkmxLhvdDPnY+C5hdzV4VtGMTTOJ4lINxJdk5QIfwRugnUyFe9nz9LyYH6 uG9gDLLeEH7PQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 21/26] KVM: nSVM: Restrict mapping vmcb12 on nested VMRUN Date: Tue, 3 Mar 2026 00:34:15 +0000 Message-ID: <20260303003421.2185681-22-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" All accesses to the vmcb12 in the guest memory on nested VMRUN are limited to nested_svm_vmrun() copying vmcb12 fields and writing them on failed consistency checks. However, vmcb12 remains mapped throughout nested_svm_vmrun(). Mapping and unmapping around usages is possible, but it becomes easy-ish to introduce bugs where 'vmcb12' is used after being unmapped. Move reading the vmcb12, copying to cache, and consistency checks from nested_svm_vmrun() into a new helper, nested_svm_copy_vmcb12_to_cache() to limit the scope of the mapping. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 89 ++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f89040a467d4a..0151354b2ef01 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1054,12 +1054,39 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64= vmcb12_gpa, bool from_vmrun) return 0; } =20 -int nested_svm_vmrun(struct kvm_vcpu *vcpu) +static int nested_svm_copy_vmcb12_to_cache(struct kvm_vcpu *vcpu, u64 vmcb= 12_gpa) { struct vcpu_svm *svm =3D to_svm(vcpu); - int ret; - struct vmcb *vmcb12; struct kvm_host_map map; + struct vmcb *vmcb12; + int r =3D 0; + + if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) + return -EFAULT; + + vmcb12 =3D map.hva; + nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); + nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); + + if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) { + vmcb12->control.exit_code =3D SVM_EXIT_ERR; + vmcb12->control.exit_info_1 =3D 0; + vmcb12->control.exit_info_2 =3D 0; + vmcb12->control.event_inj =3D 0; + vmcb12->control.event_inj_err =3D 0; + svm_set_gif(svm, false); + r =3D -EINVAL; + } + + kvm_vcpu_unmap(vcpu, &map); + return r; +} + +int nested_svm_vmrun(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + int ret, err; u64 vmcb12_gpa; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; =20 @@ -1080,32 +1107,23 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return ret; } =20 + if (WARN_ON_ONCE(!svm->nested.initialized)) + return -EINVAL; + vmcb12_gpa =3D svm->vmcb->save.rax; - if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { + err =3D nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa); + if (err =3D=3D -EFAULT) { kvm_inject_gp(vcpu, 0); return 1; } =20 + /* + * Advance RIP if #GP or #UD are not injected, but otherwise stop if + * copying and checking vmcb12 failed. + */ ret =3D kvm_skip_emulated_instruction(vcpu); - - vmcb12 =3D map.hva; - - if (WARN_ON_ONCE(!svm->nested.initialized)) - return -EINVAL; - - nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); - nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); - - if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || - !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) { - vmcb12->control.exit_code =3D SVM_EXIT_ERR; - vmcb12->control.exit_info_1 =3D 0; - vmcb12->control.exit_info_2 =3D 0; - vmcb12->control.event_inj =3D 0; - vmcb12->control.event_inj_err =3D 0; - svm_set_gif(svm, false); - goto out; - } + if (err) + return ret; =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1122,23 +1140,18 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) =20 svm->nested.nested_run_pending =3D 1; =20 - if (enter_svm_guest_mode(vcpu, vmcb12_gpa, true)) - goto out_exit_err; - - if (nested_svm_merge_msrpm(vcpu)) - goto out; - -out_exit_err: - svm->nested.nested_run_pending =3D 0; - - svm->vmcb->control.exit_code =3D SVM_EXIT_ERR; - svm->vmcb->control.exit_info_1 =3D 0; - svm->vmcb->control.exit_info_2 =3D 0; + if (enter_svm_guest_mode(vcpu, vmcb12_gpa, true) || + !nested_svm_merge_msrpm(vcpu)) { + svm->nested.nested_run_pending =3D 0; + svm->nmi_l1_to_l2 =3D false; + svm->soft_int_injected =3D false; =20 - nested_svm_vmexit(svm); + svm->vmcb->control.exit_code =3D SVM_EXIT_ERR; + svm->vmcb->control.exit_info_1 =3D 0; + svm->vmcb->control.exit_info_2 =3D 0; =20 -out: - kvm_vcpu_unmap(vcpu, &map); + nested_svm_vmexit(svm); + } =20 return ret; } --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF3682367DF; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; cv=none; b=K+OmMm4bsc3OL16+NKg5v3yjB280m37wCE8/6pdNJKMTIbsraGJstY2HcLPY0tuqL3OBa4QoLkqWhCSGQNk2x06Ih78iVPwa8UzmQIM82qaViLfQHe3y4wlsH2UbIVKUU3t3/Vv9+l4LsktBn2VIpLPY+bkQs/Mr2GHa/zqv1VY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; c=relaxed/simple; bh=fj6FLXq+xF1/WvdvmFuZXB1XYHfJzjPbj4Xu3XDLoxY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=clQ1qV/hw/Lgbs/P04VuiFInY6k8wVXreM5c1++YrwWFIn6uTnCfCZnZ3y5YxVBTuv69blF3Q+o5WpU+vgqgtYofD4taDePQ24QMV83Su1T5OR802U7MdAytKmI9cQ2NMPMDm7748zbgvvAKWu/o4LjsH/dsQb1YrLU0LCF48dc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rEM5J6YD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rEM5J6YD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4295CC2BC86; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498080; bh=fj6FLXq+xF1/WvdvmFuZXB1XYHfJzjPbj4Xu3XDLoxY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rEM5J6YDT1pPqvT1YX4cXLGiCYn8eASdYQIqSPWuFcMQe7ssaS9OYRjtvfWlp393G Vfpwa6ZZfZX/ioA7LwFzXr+m3VM4OdrLPD38gQFbMddftfO1uE8BO0meXhszEWXnz8 bsA6Gtwtgf6n57zwajyga7Y/PZCTA2CNjgqS1U5B4gO09GMnxu2fccAccSowLVzXR6 sUkX/6512XX3Fn4LC/EGn0JGtyVBJ1Y2s4k5XKwlHbNTF0EqTvILA3SKEv3p2w/pql iuEjImhEObs2OjGc8TOY/d2ruqVy0wg07VVyTNz2Key6mZcrQ/BiR/N2Z5go4vGm6A KW7Rwza2P8NBQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 22/26] KVM: nSVM: Use PAGE_MASK to drop lower bits of bitmap GPAs from vmcb12 Date: Tue, 3 Mar 2026 00:34:16 +0000 Message-ID: <20260303003421.2185681-23-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use PAGE_MASK to drop the lower bits from IOPM_BASE_PA and MSRPM_BASE_PA while copying them instead of dropping the bits afterward with a hardcoded mask. No functional change intended. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 0151354b2ef01..2d0c39fad2724 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -493,8 +493,8 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, if (!guest_cpu_cap_has(vcpu, X86_FEATURE_NPT)) to->misc_ctl &=3D ~SVM_MISC_ENABLE_NP; =20 - to->iopm_base_pa =3D from->iopm_base_pa; - to->msrpm_base_pa =3D from->msrpm_base_pa; + to->iopm_base_pa =3D from->iopm_base_pa & PAGE_MASK; + to->msrpm_base_pa =3D from->msrpm_base_pa & PAGE_MASK; to->tsc_offset =3D from->tsc_offset; to->tlb_ctl =3D from->tlb_ctl; to->erap_ctl =3D from->erap_ctl; @@ -516,8 +516,6 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, =20 /* Copy asid here because nested_vmcb_check_controls() will check it */ to->asid =3D from->asid; - to->msrpm_base_pa &=3D ~0x0fffULL; - to->iopm_base_pa &=3D ~0x0fffULL; to->clean =3D from->clean; =20 #ifdef CONFIG_KVM_HYPERV --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A8B736B05A; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; cv=none; b=SP90D3TYg6s+d9jn5V041LqfpYhndYc91WxTA/T7t90zMCZ5YIgPMuo+AEN5ootaYOpKNo8usbuh4MI7utoxEwzYtlLOV3Lj2Cp9QVBnYmx7pTKliQcajexnVO58plfPpG7ORgL5GIMCoQFgmm17CAEChm4ZxpW4Ta/pWWWX0vM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; c=relaxed/simple; bh=95wwBjlq/N/L6+wVJriKShJaYwctfh7q+1J/sfqEdnI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jPi53/P8i2gP1O7x+RnWUxIT3Ifsg/UzWRHbsxshw3rXMhoJR7WF8Y+KpSxjmZ8yQ+nlkSQEQpN+k22TwUUFl/+mSs8MK236RaA98M+O2bk0MxbCxk6DrmotwSRJ/yeUclW+uHLigUrO6gRXkJQHlQWlrCwwL1kGBrAuwqlJrkw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XfLrPqjp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XfLrPqjp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9F155C2BCAF; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498080; bh=95wwBjlq/N/L6+wVJriKShJaYwctfh7q+1J/sfqEdnI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XfLrPqjpji/7NrxOFl3FYamBPJ03rHL4Rza14X+NkxnjeiXQnKy1e+YmcCGF15Dtu gcFQOgVtvu20b4OSNmEfDL+UB7yBTiDXrzMp7Pd59kxqKlHOkK55AgCbhpXpOdu7S8 nK7dk+tEm4Mp7gZV2PfVoPEyTUTR3Ro0cVPHEDHBw1bMwEpkmhTZrGlCwZXr9gJaEr nRjOxjVDEBXN9mROqiFH+bUgYeGcEioeefduEorVghSlt27AWi9OkYdsMdOYgo/kC4 3+lT2K9Lpje3pHBFzY0eOA3o+Ecnyl4zwaZ1Wv0FA3sgT3kFAEw5ostdMOvl2c4l2T hlaQTKj90D8sA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 23/26] KVM: nSVM: Sanitize TLB_CONTROL field when copying from vmcb12 Date: Tue, 3 Mar 2026 00:34:17 +0000 Message-ID: <20260303003421.2185681-24-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The APM defines possible values for TLB_CONTROL as 0, 1, 3, and 7 -- all of which are always allowed for KVM guests as KVM always supports X86_FEATURE_FLUSHBYASID. Only copy bits 0 to 2 from vmcb12's TLB_CONTROL, such that no unhandled or reserved bits end up in vmcb02. Note that TLB_CONTROL in vmcb12 is currently ignored by KVM, as it nukes the TLB on nested transitions anyway (see nested_svm_transition_tlb_flush()). However, such sanitization will be needed once the TODOs there are addressed, and it's minimal churn to add it now. Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/svm.h | 2 ++ arch/x86/kvm/svm/nested.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index c169256c415fb..16cf4f435aebd 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -182,6 +182,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define TLB_CONTROL_FLUSH_ASID 3 #define TLB_CONTROL_FLUSH_ASID_LOCAL 7 =20 +#define TLB_CONTROL_MASK GENMASK(2, 0) + #define ERAP_CONTROL_ALLOW_LARGER_RAP BIT(0) #define ERAP_CONTROL_CLEAR_RAP BIT(1) =20 diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 2d0c39fad2724..97439d0f5c49c 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -496,7 +496,7 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcp= u *vcpu, to->iopm_base_pa =3D from->iopm_base_pa & PAGE_MASK; to->msrpm_base_pa =3D from->msrpm_base_pa & PAGE_MASK; to->tsc_offset =3D from->tsc_offset; - to->tlb_ctl =3D from->tlb_ctl; + to->tlb_ctl =3D from->tlb_ctl & TLB_CONTROL_MASK; to->erap_ctl =3D from->erap_ctl; to->int_ctl =3D from->int_ctl; to->int_vector =3D from->int_vector; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 639AD239E6F; Tue, 3 Mar 2026 00:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; cv=none; b=SGDGwFMkPVsBEhSzmnRb+62sO+KC8ykgGLaLJe2F4NsJoSQx+ZBlVq/2DgLK6IoNpQWGRC4y+96w6Ug/AhAL84dYbMgs5Wvvt/tMz9r4szHDOCD9tcy+tHFZMGXaZUvVSyUuKqDlihDLVgVXbqNZlaats7rUWqDYgBUHyowWvp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; c=relaxed/simple; bh=nPB4lBnddVtLuKN1hae5RkAGRjj+yIg3+qfdTZt0tr4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NCortz/4g40dyrZ/S5m7PGyONeeBTIZyDdPAXKgHjiX3N86z9NwwYsZMQXe3CCQs0uuCGIZCcfiOSuTw/p+J1oa1N6Be9MB9/1kcJ2tfDRT92lO3j8kLnwLUeTdrZRjOpvPq77D02y/zqGgw+WfZ2fwnGFJAzyIHB7GrJwzDKRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BEfoLaqv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BEfoLaqv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0746CC2BC86; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498081; bh=nPB4lBnddVtLuKN1hae5RkAGRjj+yIg3+qfdTZt0tr4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BEfoLaqvY+IRd4lSHp/Gs5oiCl9on1w5wxUDi/YSmdez39v5zukg+QrAGAl6VZoPw tGUFNU+W2eikOkoegVveLSWrswYtNrG57fxRDmK2PUYhZrOzkq8fQ0Gg5men2fNMrA A/XatRBsyDL+y0yHTBQgdXPTiQ8v8vikYFyR/Ew7U1KqcA6t9JyfLC6Z8YRhVuo8Ba 1Wfzndr1QR4BUdWFqhnYcBRJKc+TphCz+C3es3o6CPXCVBNye7d5ZzxMi7uDbgtjag A4xKu5cPZqzMzGd/luiiQvijYk+7v06B/wiwAUISHpVVayT5M0qdEe8tIsiH1f/q5I w8Wc45182yVEw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , Jim Mattson Subject: [PATCH v7 24/26] KVM: nSVM: Sanitize INT/EVENTINJ fields when copying from vmcb12 Date: Tue, 3 Mar 2026 00:34:18 +0000 Message-ID: <20260303003421.2185681-25-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Make sure all fields used from vmcb12 in creating the vmcb02 are sanitized, such that no unhandled or reserved bits end up in the vmcb02. The following control fields are read from vmcb12 and have bits that are either reserved or not handled/advertised by KVM: tlb_ctl, int_ctl, int_state, int_vector, event_inj, misc_ctl, and misc_ctl2. The following fields do not require any extra sanitizing: - tlb_ctl: already being sanitized. - int_ctl: bits from vmcb12 are copied bit-by-bit as needed. - misc_ctl: only used in consistency checks (particularly NP_ENABLE). - misc_ctl2: bits from vmcb12 are copied bit-by-bit as needed. For the remaining fields (int_vector, int_state, and event_inj), make sure only defined bits are copied from L1's vmcb12 into KVM'cache by defining appropriate masks where needed. Suggested-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/svm.h | 5 +++++ arch/x86/kvm/svm/nested.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 16cf4f435aebd..bcfeb5e7c0edf 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -224,6 +224,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define X2APIC_MODE_SHIFT 30 #define X2APIC_MODE_MASK (1 << X2APIC_MODE_SHIFT) =20 +#define SVM_INT_VECTOR_MASK GENMASK(7, 0) + #define SVM_INTERRUPT_SHADOW_MASK BIT_ULL(0) #define SVM_GUEST_INTERRUPT_MASK BIT_ULL(1) =20 @@ -637,6 +639,9 @@ static inline void __unused_size_checks(void) #define SVM_EVTINJ_VALID (1 << 31) #define SVM_EVTINJ_VALID_ERR (1 << 11) =20 +#define SVM_EVTINJ_RESERVED_BITS ~(SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_M= ASK | \ + SVM_EVTINJ_VALID_ERR | SVM_EVTINJ_VALID) + #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK #define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK =20 diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 97439d0f5c49c..7ae62f04667cc 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -499,18 +499,18 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_v= cpu *vcpu, to->tlb_ctl =3D from->tlb_ctl & TLB_CONTROL_MASK; to->erap_ctl =3D from->erap_ctl; to->int_ctl =3D from->int_ctl; - to->int_vector =3D from->int_vector; - to->int_state =3D from->int_state; + to->int_vector =3D from->int_vector & SVM_INT_VECTOR_MASK; + to->int_state =3D from->int_state & SVM_INTERRUPT_SHADOW_MASK; to->exit_code =3D from->exit_code; to->exit_info_1 =3D from->exit_info_1; to->exit_info_2 =3D from->exit_info_2; to->exit_int_info =3D from->exit_int_info; to->exit_int_info_err =3D from->exit_int_info_err; - to->event_inj =3D from->event_inj; + to->event_inj =3D from->event_inj & ~SVM_EVTINJ_RESERVED_BITS; to->event_inj_err =3D from->event_inj_err; to->next_rip =3D from->next_rip; to->nested_cr3 =3D from->nested_cr3; - to->misc_ctl2 =3D from->misc_ctl2; + to->misc_ctl2 =3D from->misc_ctl2; to->pause_filter_count =3D from->pause_filter_count; to->pause_filter_thresh =3D from->pause_filter_thresh; =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C971137186C; Tue, 3 Mar 2026 00:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; cv=none; b=BC7lENYGcF0WkVNIrzRNJ8SPn7ezoFWLKA8Qy7pHErgwHt7lV4ZXz1G7NrrhdurNcxl+oGHY2IYwIXPLJ6l3LbpdLh0LmcI/yyNa/B8HRM4XTWZEr8aIPenrzKrV86FBfTwaYzdOtuemNihAheSSaoc4XDAaz7X1Tz0o1Q9lpfw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498081; c=relaxed/simple; bh=E41yJLQJa1kqF9bhFB8S8YwPtajDsxHNIvscFJFH2Eg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z3oy/7mXE32BglFCOYg9OCJmb+clPRRXAJWdNHGw75fyWN/pEWU96FUOntuaHijFkBa7D6ob/bwDa9V+SAg4jroi03ZXGXpQirjMMAog0sP0tTVufeMXOOOLv2tkRwVCp8ypr9ObEXbHG1UhML/P3DY0opuVe9T2dtRm1AdchAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BUV7gj7L; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BUV7gj7L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6CCC2C2BC9E; Tue, 3 Mar 2026 00:34:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498081; bh=E41yJLQJa1kqF9bhFB8S8YwPtajDsxHNIvscFJFH2Eg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BUV7gj7LSCeT9sZJ27VEjZkN2odTwwLll/wOpGYnCLe1rjYJwZ5uwoypLJE+dfz04 L/Vcvdgy/1q7g8DizK2+xf89YFNofT84PmBEEjOhOC9rcqWqQT+qbuPxMSA8hByOzJ 4Xlhxu1KG5vuRkjIyRTr+websArHuXbUTItbcR2JlyQNmzG712zsq/bXm2JqdsoH5w mX1JnJpNgUtLGvW98d9zF5Gx21mky/zRfdaXjKL+i8lbhKHVY5c6JaRpIi5sowPKWw 6rNnGgU91ZhkJEoOWfcz/QJNfzeUYzzUHhGZ3UilV4sv+1HjKSaOB8zMAMY7wm3Ayp vf+lT8xsGcqjg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , Jim Mattson Subject: [PATCH v7 25/26] KVM: nSVM: Only copy SVM_MISC_ENABLE_NP from VMCB01's misc_ctl Date: Tue, 3 Mar 2026 00:34:19 +0000 Message-ID: <20260303003421.2185681-26-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The 'misc_ctl' field in VMCB02 is taken as-is from VMCB01. However, the only bit that needs to copied is SVM_MISC_ENABLE_NP, as all other known bits in misc_ctl are related to SEV guests, and KVM doesn't support nested virtualization for SEV guests. Only copy SVM_MISC_ENABLE_NP to harden against future bugs if/when other bits are set for L1 but should not be set for L2. Opportunistically add a comment explaining why SVM_MISC_ENABLE_NP is taken from VMCB01 and not VMCB02. Suggested-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 7ae62f04667cc..fd1fc2d67bd33 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -849,8 +849,16 @@ static void nested_vmcb02_prepare_control(struct vcpu_= svm *svm, V_NMI_BLOCKING_MASK); } =20 - /* Copied from vmcb01. msrpm_base can be overwritten later. */ - vmcb02->control.misc_ctl =3D vmcb01->control.misc_ctl; + /* + * Copied from vmcb01. msrpm_base can be overwritten later. + * + * SVM_MISC_ENABLE_NP in vmcb12 is only used for consistency checks. If + * L1 enables NPTs, KVM shadows L1's NPTs and uses those to run L2. If + * L1 disables NPT, KVM runs L2 with the same NPTs used to run L1. For + * the latter, L1 runs L2 with shadow page tables that translate L2 GVAs + * to L1 GPAs, so the same NPTs can be used for L1 and L2. + */ + vmcb02->control.misc_ctl =3D vmcb01->control.misc_ctl & SVM_MISC_ENABLE_N= P; vmcb02->control.iopm_base_pa =3D vmcb01->control.iopm_base_pa; vmcb02->control.msrpm_base_pa =3D vmcb01->control.msrpm_base_pa; vmcb_mark_dirty(vmcb02, VMCB_PERM_MAP); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 2 06:08:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B046371CF0; Tue, 3 Mar 2026 00:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498082; cv=none; b=dE/paUQ5Jaw+xYhMSl3oZVTpfEh5hzTJXpHGcVEvdNz4BaumZXMDnUA9KNs8A+wigmv8jMk2zjGpsEg6YZlqOK77OH/vrftRlthqHejUm4cG6HemnwZfqlty7ViJ0B1bkazWLzKShh2a7bEchP2N2e7XF67KilNjV5Zc6VSnOsk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498082; c=relaxed/simple; bh=xZkALjitzazcpl0Fnsnu/oouWxj8iyjzP/CRxFDvIq4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=op5v0vfg1cZ1znXfk1fbbgebhqXHYOazq3NpwYDJECQLC/AMO2uoq9lFd10LfEO0tgD0KEKV6KVuk67NEjVeR2MwMKENK8O8wF0+9W8JMeKcU1/9gxjFPhy/J6i87hl1jjtcwfMKXNU0Hf7NhSh46etPK8ZvmLyD3Xvx7AmhdM0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jFIySHI9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jFIySHI9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2156C2BC86; Tue, 3 Mar 2026 00:34:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498082; bh=xZkALjitzazcpl0Fnsnu/oouWxj8iyjzP/CRxFDvIq4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jFIySHI9g/hS/LXcSBJEJYAkdQCg5Qior+YCxYMqAO6gKRoN5CKa8ULu17hLl+jKy VGZientHWvmPyVGH8f8/N+MtLRrBBttjh6dbp/ISFi+XuIjEMu957L40vsiASrDARr uAdOSMe5DpYD2TdegumOOyshuXrcKJoDbNWmjwCzh4A7nm3rt1uL2YPKC64p8ecjvX EOL1WzTIMi7KuwpVmCKGSuxljTuTaHEUcT6VFo5kco2rgf37illu6h/XGtaSULDuNK jFVfgFM5+S0+aWPflrZpCoWIvJ7gcCNJVjCo4fRdnWhxLxizLLYmOgF6HUmLtVXZs4 fF4pO0CA3q6SA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 26/26] KVM: selftest: Add a selftest for VMRUN/#VMEXIT with unmappable vmcb12 Date: Tue, 3 Mar 2026 00:34:20 +0000 Message-ID: <20260303003421.2185681-27-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test that verifies that KVM correctly injects a #GP for nested VMRUN and a shutdown for nested #VMEXIT, if the GPA of vmcb12 cannot be mapped. Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../kvm/x86/svm_nested_invalid_vmcb12_gpa.c | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb= 12_gpa.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 36b48e766e499..f12e7c17d379d 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -110,6 +110,7 @@ TEST_GEN_PROGS_x86 +=3D x86/state_test TEST_GEN_PROGS_x86 +=3D x86/vmx_preemption_timer_test TEST_GEN_PROGS_x86 +=3D x86/svm_vmcall_test TEST_GEN_PROGS_x86 +=3D x86/svm_int_ctl_test +TEST_GEN_PROGS_x86 +=3D x86/svm_nested_invalid_vmcb12_gpa TEST_GEN_PROGS_x86 +=3D x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_soft_inject_test TEST_GEN_PROGS_x86 +=3D x86/svm_lbr_nested_state diff --git a/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.= c b/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.c new file mode 100644 index 0000000000000..c6d5f712120d1 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026, Google LLC. + */ +#include "kvm_util.h" +#include "vmx.h" +#include "svm_util.h" +#include "kselftest.h" + + +#define L2_GUEST_STACK_SIZE 64 + +#define SYNC_GP 101 +#define SYNC_L2_STARTED 102 + +u64 valid_vmcb12_gpa; +int gp_triggered; + +static void guest_gp_handler(struct ex_regs *regs) +{ + GUEST_ASSERT(!gp_triggered); + GUEST_SYNC(SYNC_GP); + gp_triggered =3D 1; + regs->rax =3D valid_vmcb12_gpa; +} + +static void l2_guest_code(void) +{ + GUEST_SYNC(SYNC_L2_STARTED); + vmcall(); +} + +static void l1_guest_code(struct svm_test_data *svm, u64 invalid_vmcb12_gp= a) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + + generic_svm_setup(svm, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + valid_vmcb12_gpa =3D svm->vmcb_gpa; + + run_guest(svm->vmcb, invalid_vmcb12_gpa); /* #GP */ + + /* GP handler should jump here */ + GUEST_ASSERT(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_VMMCALL); + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + struct kvm_x86_state *state; + vm_vaddr_t nested_gva =3D 0; + struct kvm_vcpu *vcpu; + uint32_t maxphyaddr; + u64 max_legal_gpa; + struct kvm_vm *vm; + struct ucall uc; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vm_install_exception_handler(vcpu->vm, GP_VECTOR, guest_gp_handler); + + /* + * Find the max legal GPA that is not backed by a memslot (i.e. cannot + * be mapped by KVM). + */ + maxphyaddr =3D kvm_cpuid_property(vcpu->cpuid, X86_PROPERTY_MAX_PHY_ADDR); + max_legal_gpa =3D BIT_ULL(maxphyaddr) - PAGE_SIZE; + vcpu_alloc_svm(vm, &nested_gva); + vcpu_args_set(vcpu, 2, nested_gva, max_legal_gpa); + + /* VMRUN with max_legal_gpa, KVM injects a #GP */ + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], SYNC_GP); + + /* + * Enter L2 (with a legit vmcb12 GPA), then overwrite vmcb12 GPA with + * max_legal_gpa. KVM will fail to map vmcb12 on nested VM-Exit and + * cause a shutdown. + */ + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], SYNC_L2_STARTED); + + state =3D vcpu_save_state(vcpu); + state->nested.hdr.svm.vmcb_pa =3D max_legal_gpa; + vcpu_load_state(vcpu, state); + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); + + kvm_x86_state_cleanup(state); + kvm_vm_free(vm); + return 0; +} --=20 2.53.0.473.g4a7958ca14-goog