From nobody Sat Feb 7 11:31:11 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (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 643FA42883F for ; Fri, 6 Feb 2026 19:09:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404951; cv=none; b=algog17TzKECtk9kXuxVgtWSzZ4W0Ner6eQhbjTs/4oqnq1eXy/iqETQQ/NkqNZ+GIVX9OaNwrj30mXjNCRrPaPfP10GK2KRWZNNirxTsT8Y4ekaYX7TZEP4tsB5dxVpvNWlKJx3Mz2d5xcef9y0uJR3ib4Hmc3LjtpguxzeJNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404951; c=relaxed/simple; bh=Kmr1cFOljWw2hgaMq50BmZqyywx7sk43KBMKDj7eJu4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k356Me+4YMn9b0K/YMIttviY5yOVm362D6PgUYB1m/2Te8dVWtQszxtBDLdb4KwzT0mqJmU9Ym3kXXyMerYa6T11KT6dOtNno33UuyUEZ91X5jjLCEnQyDokLdYGwf4kQYZdCwsc7saGuR6Zt3QY7V9gYfRzMV789HjCWtodWQ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=b6CxSVCo; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="b6CxSVCo" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404949; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aWtD9FCS1AgrEOXeXG6aQzMP8BhNwBCqOc4fqV1JL44=; b=b6CxSVCojNDocHy3aD1EJ7m7RUHzPNwC70DmUS2Ncu9Ekl6oCKFKBCWllkgQUD9yBMg3mB oIbLHstgrX63A8rWFCmCNbBoNfheup5Oq/X1Pi//qgV0AeM0vE1j1wVOn7U0cH/THAFsJE Os2NP6gYEwMTE09DKM0sIiOjmE++N7w= 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 v5 01/26] KVM: nSVM: Avoid clearing VMCB_LBR in vmcb12 Date: Fri, 6 Feb 2026 19:08:26 +0000 Message-ID: <20260206190851.860662-2-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 de90b104a0dd..a31f3be1e16e 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 5f0136dbdde6..98cbd7c7beed 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (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 111BA428849; Fri, 6 Feb 2026 19:09:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404953; cv=none; b=tO38odeFUMRsFgow2G65dcAO44s3xrdP85PGcP/gftFzX9R4CVkO4DhTqfxbfupHp0d8+F1/2ok05XBbvCGbeM+XkkVTkdO9z/M4SeZ+xHAbwzE/2vyDCOiW+r0yJsRbqto78H2OnLdDGImPLFhxy6K9KL9DNgMEKFNiSzBP/u8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404953; c=relaxed/simple; bh=jI/gSwWMQ9StivbdaamvYHJefB/eGDkVK85zxxekHKs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QsdSdxNbfWSM7hTINWOZbGBOnUA550oV+4+c0FLHu0XmvRg0vJHtRVFhno3T22l9dCM0eWuQrHt9k38jdZ9YsWVDuLQCocMEPPEk7vfK4Nfusu1ks5/IGxGfvwE2qS+7lmBvQecMx7SqgEQPAVGLTYY8YyX8kRDN1OxrnBUCneU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=cAqVjA83; arc=none smtp.client-ip=91.218.175.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="cAqVjA83" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404951; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xkoeMVQBPtbUztRZ+o14K0G1l1ptUD5ctfFp1SATztU=; b=cAqVjA83XzCr89dULnBmzUTcUn31qnXkOyqf5eD3Q12kh/BHyYWqW2E34+IVdxWYxaNITH HyRgZfn9Fg5Ppt+9blxGmsoOR2t+5orhvCHxorn3VadVhrObAki8B7dOEeseTMX5yBL622 FgJAbBeRpz5hDyn6ZcIkLIkZ9iIbE4w= 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 v5 02/26] KVM: SVM: Switch svm_copy_lbrs() to a macro Date: Fri, 6 Feb 2026 19:08:27 +0000 Message-ID: <20260206190851.860662-3-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 a31f3be1e16e..f7d5db0af69a 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 98cbd7c7beed..798f2c84d80b 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 ebd7b36b1ceb..44d767cd1d25 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-189.mta0.migadu.com (out-189.mta0.migadu.com [91.218.175.189]) (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 38FD7429809 for ; Fri, 6 Feb 2026 19:09:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.189 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404955; cv=none; b=TKuCfiZvSXAzHFZzQDr92iQWy+qCxEWB/RgFJJ3FqhMbxAXeef4v1G9F6fr+p+864xWJ0QRLWhvTguh2DV0dWPwLdeOwgwTG1ZyD8pDdbAJaM7cOEAxCUfr3rRpFwOrleWAwbBIQBQDRkXrZNHtruK8jMS2TaoyTrd3QgzgtzJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404955; c=relaxed/simple; bh=isGG8ianhv/yw+W1p+iiSxxVnSDJaWSOJuSdJgsuuCc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SdB7KOszpN3ULA2NyuJbab8R/rfdicFmMMnObREgTC5bY/9j1rBcX8LiGDax9x3LaEjwQEE0n7YARtq0y4Q3dZWG5mlulWIRJJ1mU9vwvaT0Blnupgxvh+2L7fA+2W+HRPrerwpcBBgRze379RQuGvx0DPnxRjqwVZiI6Kv81qA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=v3Rhvqa/; arc=none smtp.client-ip=91.218.175.189 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="v3Rhvqa/" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404953; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OFoKAHgIstDnIh2zPPIUgBzptuNqEXzOrzi2QTRbj4g=; b=v3Rhvqa/PVNH75m1jAFzLyTvMKU89UEF90/zZ4+PvZeBtNokN6DLesI9RsvNdrIw2gIKoI ROb1kNVmEeF8EYMPOY8hD1pztEm2zcf+a1UxxR1Rm8jUyN8sZJ0fKfuxDmWXJGr/cideW+ hhcKB+J6jekE5ckRBiknnQLQRs0hKOc= 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 v5 03/26] KVM: SVM: Add missing save/restore handling of LBR MSRs Date: Fri, 6 Feb 2026 19:08:28 +0000 Message-ID: <20260206190851.860662-4-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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(). 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 | 3 +++ arch/x86/kvm/svm/svm.c | 20 ++++++++++++++++++++ arch/x86/kvm/x86.c | 3 +++ 3 files changed, 26 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f7d5db0af69a..52d853684592 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1100,6 +1100,9 @@ void svm_copy_vmrun_state(struct vmcb_save_area *to_s= ave, 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); } =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 798f2c84d80b..d93414db6559 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3071,6 +3071,26 @@ 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; + break; + case MSR_IA32_LASTBRANCHTOIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.br_to =3D data; + break; + case MSR_IA32_LASTINTFROMIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.last_excp_from =3D data; + break; + case MSR_IA32_LASTINTTOIP: + if (!msr->host_initiated) + return 1; + svm->vmcb->save.last_excp_to =3D data; + 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 db3f393192d9..416899b5dbe4 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (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 5615742884D for ; Fri, 6 Feb 2026 19:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404956; cv=none; b=JRRNyaIgUzZBbOIAvT2OOqjVlooE8ALe9z+mVhfIn6SkjcyFv3uheuogGQiuGWQpSJhNb/WRKNu/feniFGjLJvHa6BO2tMpMdEQbhfnr8cV670MT9HWE1dhF/4D5667H2IKOBBNWTiCOYx6cjzZRzCPzIoF3qz9nMLdBt292atw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404956; c=relaxed/simple; bh=F9dZRsnyxRXWTRB7obIOuB4MUPqlW49vwnA1iHjR1Zg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KRS4iePWEt17zfDnovpaEB7IsAfCp9dcGvnI+eEPKckk4Qibc7B7n3khNBLAnECYOQNiz5e+AuD/oh1ewJ3pDMrfl7LAPAaD2X2lST4O0VU9kwo8jGjOHsB7bPudJN9O1Kq22XXzc/eDDz9fhn4fb15eewvaCQ30iz8bHMywx7A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=VE/DXPPR; arc=none smtp.client-ip=91.218.175.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="VE/DXPPR" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404955; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7NIvn4eC5R359Z5KTSY9RaVtvmEanE1nmyKVWvi5ZPU=; b=VE/DXPPRraC2Q6IytJi4MsoyDNfSIEFGunIKUZ+ecj9qC22kQuKGyHip/soe2ZAQ92wMzC BB75XDXU0GZJ9KYguHGJ7XZFkX8A5F53GEEbAOwvu26cr+pNd05NDDF8+yimIRxgt9Z+AW s+xKkG91Eh8sizDQnMw7V5xi802zrcc= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v5 04/26] KVM: selftests: Add a test for LBR save/restore (ft. nested) Date: Fri, 6 Feb 2026 19:08:29 +0000 Message-ID: <20260206190851.860662-5-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 | 146 ++++++++++++++++++ 3 files changed, 152 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 58eee0474db6..7810f9db5f77 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 4ebae4269e68..db0171935197 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 000000000000..0a17a2c71634 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c @@ -0,0 +1,146 @@ +// 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); \ + /* Disabe 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); + break; + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } +done: + if (state) + kvm_x86_state_cleanup(state); + 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (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 3DBE042EEA1 for ; Fri, 6 Feb 2026 19:09:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404962; cv=none; b=PpWwOKD8ht4/k6plwOdClDhx8Tzr0xdW4DYobwwH+uvhgEDe/DwTu63KkpJApnHPRrrTeKyClu2osBI+/i2sgZXOHB+KXN+7EGkq/LqZQ/aw7CtpCNYTTtAx+macUyMDrWa+eswO1yx7566coTNI9ltsmtBuJTGeIre6Y2fY6E8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404962; c=relaxed/simple; bh=lDWNpXDb4MOO/xKVjHxm1R134Ur2HHc/wXn7xLhN3ws=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tL3lhtvQmLiwqntKoDCAV+eYFVqX6MWg26uuAJ3RC3/0uDnAKpWQjr2w8Qk3RxyxXjEZBkbl2Nuivd5dI9Plk1ge64FbT714xK1GyjU4A35V3Pt7ut2NC5wl87aXgfFFj/5YvUUH0G5OcxiAvhI78hKIi7QrIcfDevlZ9iVSIMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=YBcr/SUu; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="YBcr/SUu" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404956; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FVsc5iL18GRJ+T1NB2HjC0Vm7twsC38I9OcGa98pL9g=; b=YBcr/SUucO/uFFFIfCUalpFWdljivMTRhTvAVDuaCnq1hkDMGmuPSe77LKWZl6HdWNrj/p C7yQKYVpoZLb+SLh1tVfMeUzTIMZrqmto5oPCFkQRgIGtAkIDog3fAevZbg0DeOdLfLgXu vxLTh/6dnhTNeSpq3vPhaWsHOoxVJAc= 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 v5 05/26] KVM: nSVM: Always inject a #GP if mapping VMCB12 fails on nested VMRUN Date: Fri, 6 Feb 2026 19:08:30 +0000 Message-ID: <20260206190851.860662-6-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 52d853684592..fab0d3d5baa2 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (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 D8985428845 for ; Fri, 6 Feb 2026 19:09:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404960; cv=none; b=f7zc3yN1p2KhZS15yyEuUab4QKP18PkoNbnWF3wyctjPQ0Dv/cQZ0JXNXcdaDKNzqRldXlvRXBQ2LEdPnzsLnEWtXCPtEvHRSj/u1Of/L1HutSQodsor1tEy8PrF27j2klFcFqWT959pBlARqgpAZi5EnUa99e8pUsRwWPt2lVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404960; c=relaxed/simple; bh=Uul8kI2RxcPnhJaSXw4jvPJlHmrZxMybTonVAnUSJqQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lW5skuZtIlK+DR6S1KdeLujPXAFEyiN9+h6/otXh6f1erYoK3oXIHgee2sQoOhqvh7OyvL1koNOMQFupZD21cIQEacojkxs7mDx1kPl4v5+JhPwSZ89ZWhK5SuxFO2ukzgRj2Lr2Ia7ZoWhB/BNOh9t7nz4ltYWvrIkHJsVcz/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=vaod6+qk; arc=none smtp.client-ip=91.218.175.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="vaod6+qk" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404958; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1U7vm49UR6+uOywZi/EV8GxihCiORkBtPEhghinikMI=; b=vaod6+qkxWj+w5+abRj1eQBn0Xg7VnhWRpl8N7URouVGC7VAD/xl2+c//pexPwNNARlaDp spuqnT0QmoKNj/MlM0tODQr6hXiX4kz7ma0lZEgPBtOR66lgMS7Y3gYihXv2nXklgymaws 8E1VQiUHHywZfvEC9SbiU8iTnas5fS0= 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 v5 06/26] KVM: nSVM: Triple fault if mapping VMCB12 fails on nested #VMEXIT Date: Fri, 6 Feb 2026 19:08:31 +0000 Message-ID: <20260206190851.860662-7-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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). Move mapping VMCB12 a bit later, after leaving guest mode and clearing KVM_REQ_GET_NESTED_STATE_PAGES, right before the VMCB12 is actually used. 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. Also update the WARN_ON() in svm_get_nested_state_pages() to WARN_ON_ONCE() to avoid future user-triggeable bugs spamming kernel logs and potentially causing issues. 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 | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index fab0d3d5baa2..830341b0e1f8 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1121,24 +1121,14 @@ void svm_copy_vmloadsave_state(struct vmcb *to_vmcb= , struct vmcb *from_vmcb) int nested_svm_vmexit(struct vcpu_svm *svm) { struct kvm_vcpu *vcpu =3D &svm->vcpu; + gpa_t vmcb12_gpa =3D svm->nested.vmcb12_gpa; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; struct vmcb *vmcb12; struct kvm_host_map map; - int rc; - - 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; - } - - 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); =20 kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); @@ -1146,8 +1136,16 @@ int nested_svm_vmexit(struct vcpu_svm *svm) /* in case we halted in L2 */ kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); =20 + svm->nested.vmcb12_gpa =3D 0; + + if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return 1; + } + /* Give the current vmcb to the guest */ =20 + vmcb12 =3D map.hva; vmcb12->save.es =3D vmcb02->save.es; vmcb12->save.cs =3D vmcb02->save.cs; vmcb12->save.ss =3D vmcb02->save.ss; @@ -1304,8 +1302,7 @@ 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) + if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) return 1; =20 /* @@ -1936,7 +1933,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, =20 static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu) { - if (WARN_ON(!is_guest_mode(vcpu))) + if (WARN_ON_ONCE(!is_guest_mode(vcpu))) return true; =20 if (!vcpu->arch.pdptrs_from_userspace && --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (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 D1816428846 for ; Fri, 6 Feb 2026 19:09:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404962; cv=none; b=GTQanKtuXQBZbjaqLPqgNZnBEeKlDX4brsvyjJlpiR29PS+TTetRYv50/GL5GOnu7tWdCGOKqy8qaLs8P83Y1qjiIQ4M/IHrxTLUZ618qcKQv37imCmR9liYwreG510fGmrrYmzXtvPxwzTmDMbczUUaQ+mD8+zQ5yaIRk6WONo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404962; c=relaxed/simple; bh=C1p3AS10bD2YZcL4D4GSYH8HHE9oRzO3xY0/ZBrpO8Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=befwdgxjoB8aUcKOEzgB4qwjR42Om0VvqSIxapAwP22LqB7llr/65vqyeoLDsYGnQl7fUBFf5SkCi9pyRk7VGeqTPR1hloXn7Z7eqW+ONu/ZGmSWrDrhf9Zi+6U2cOR1p/D3Jm2nE11+AOZAd7EsBuM4MeU5ZUAPKOKjYZFq4D8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=JvWNnrHU; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="JvWNnrHU" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404960; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ISg/b9mfa1uKSqpI8riZeaTxNIhO0uVtXR2GrmQhhSI=; b=JvWNnrHULM1ItCiAxXfGGn4yl/lzvJ5htbmBoxoks6glRX7gkeAKrdY4LZFxv6ZnaeOczM KzfcCc5sh9TaHOP8zGXqD/2OoLcpodQxUzPfy7iEplqTFFXt0sWU0UOGu++bYE3I1u9E/5 5PXZlBN7Sj+mFrH8s6CqMzcFkyxQFtQ= 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 v5 07/26] KVM: nSVM: Triple fault if restore host CR3 fails on nested #VMEXIT Date: Fri, 6 Feb 2026 19:08:32 +0000 Message-ID: <20260206190851.860662-8-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 instead. 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 | 12 ++++++------ arch/x86/kvm/svm/svm.c | 11 ++--------- arch/x86/kvm/svm/svm.h | 6 +++--- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 830341b0e1f8..33e6e1e77aac 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1118,7 +1118,7 @@ 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) +void nested_svm_vmexit(struct vcpu_svm *svm) { struct kvm_vcpu *vcpu =3D &svm->vcpu; gpa_t vmcb12_gpa =3D svm->nested.vmcb12_gpa; @@ -1140,7 +1140,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) =20 if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); - return 1; + return; } =20 /* Give the current vmcb to the guest */ @@ -1302,8 +1302,10 @@ int nested_svm_vmexit(struct vcpu_svm *svm) =20 nested_svm_uninit_mmu_context(vcpu); =20 - if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) - return 1; + if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) { + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return; + } =20 /* * Drop what we picked up for L2 via svm_complete_interrupts() so it @@ -1328,8 +1330,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 d93414db6559..a534c08fbe61 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); @@ -4792,7 +4788,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; @@ -4812,9 +4807,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 44d767cd1d25..7629cb37c930 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (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 D980342EEC1 for ; Fri, 6 Feb 2026 19:09:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404965; cv=none; b=trNlc813qd+1jsPUixL1M2bQ1JHVYYcE5lzI+6A8hbhFycLJDUgjwpRKuWxdhXldNprukcmqKVsqnRmdsyD0tIsrHQq3yrVMyCaFkOPLJVY2jNCG3tUAMB5k5ZQUce40NJtzSV+w8usgSJdEId7nOhET+rLDI04cex/9gdvJQ50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404965; c=relaxed/simple; bh=DkuRNSVbONxPMIEkcXv5LQ08XVA29Y5ZCcMxfYvXlOA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XwDl344Ea0LSWdLw+I3Zn94YlkpJ/fBKXkb5jaJknUeIh8px6PnEUUp1fa/jbWXbdAlzSbtfW6nnrQKeos91FK1OBFHPaYOF4NpQpxujLlGcTPQ6RG4JsLCJej8sqVB6y/Mwig2/XicnHibh5mYq27nFH56o63jhuRhNaQW7by8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=MOp1tIha; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="MOp1tIha" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404961; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AnBafR6PTCAPYshR7TLUsu64uvZgQsjYrHI1Jx1JcDc=; b=MOp1tIha81mh5lbhcPQkZqpZ7l7kiTe/L+KmUylsafbZV/gAQph4f7RxAWhMZXuTLGp94J 17TswEjnPSG8O7Cc8w5kz1ADoIvJQxEuStW6CsZQtbjh7m9czsuXg2KLkAwIyCeROhN8KV MvLsUU7gA/GMQhShUswD0/xcWBP+x8U= 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 v5 08/26] KVM: nSVM: Drop nested_vmcb_check_{save/control}() wrappers Date: Fri, 6 Feb 2026 19:08:33 +0000 Message-ID: <20260206190851.860662-9-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 33e6e1e77aac..29069fc5e8cb 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; @@ -1026,8 +1010,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; @@ -1861,12 +1845,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)) @@ -1880,7 +1864,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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (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 0825842885A for ; Fri, 6 Feb 2026 19:09:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404965; cv=none; b=TSKF33rSh+xNZalWb4vjZbPblUQzEeih5pxgK8jpEkl0hGY7cOmYnh+6BZMtxqgOHsehVYvArZU8yY0wbr4H7vhtfRG1x0aN3TpqyvwV5Hny5ANoAJgkpOUf+DyVLgKd25mcLrv4R82jYuwW4IL6vbrf0AlZ2H5ZKLrNkIcVaJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404965; c=relaxed/simple; bh=aFbbE1mXIIfwFOvI+A1BZSivVcixs1P5aMa3QZelj1Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QFqhNBq1wG711/osSh5snTf6LNVM6ZUNqKxH0sABwwczVs8/ZQ4JgIcDwjvzpb7IqnmzB85pCHxk31K1EkoHoexbs1Lmc6eTbnRu4JxaXmWUJ6y6MdiI91m63w0WuafrGeoQsxURPFakz+laaNwtXVHnr+iOIcRovFc2dkdQOe8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=a4gul3kQ; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="a4gul3kQ" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404963; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2eFD0yh8gByHsKvBqdBWwO0lKqyxFdc3ADbFbDOMW+c=; b=a4gul3kQEYygRMo6Z2mkbFDspLs3RN7nVa5IMWp7D/upcAodgiyc8wGyCAQNLzc4X5IFrW wlAijZpez8mo1FcPRVr2VhZTm08ICjLi1DNRUgLs5heabWWc9Ra7yKU0purgX8nTbScGVa jMPf3zKHFSXrkkw6bV7ZgOrNMUiZLHg= 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 v5 09/26] KVM: nSVM: Call enter_guest_mode() before switching to VMCB02 Date: Fri, 6 Feb 2026 19:08:34 +0000 Message-ID: <20260206190851.860662-10-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for moving more changes that rely on is_guest_mode() before switching to VMCB02, move entering guest mode a bit earlier. Nothing between the new callsite(s) and the old ones rely on is_guest_mode(), so this should be safe. No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 29069fc5e8cb..607d99172e2b 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -741,9 +741,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_s= vm *svm, =20 nested_svm_transition_tlb_flush(vcpu); =20 - /* Enter Guest-Mode */ - enter_guest_mode(vcpu); - /* * Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info, * exit_int_info_err, next_rip, insn_len, insn_bytes. @@ -944,6 +941,8 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmc= b12_gpa, =20 WARN_ON(svm->vmcb =3D=3D svm->nested.vmcb02.ptr); =20 + enter_guest_mode(vcpu); + nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); =20 svm_switch_vmcb(svm, &svm->nested.vmcb02); @@ -1890,6 +1889,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, svm_copy_vmrun_state(&svm->vmcb01.ptr->save, save); nested_copy_vmcb_control_to_cache(svm, ctl); =20 + enter_guest_mode(vcpu); svm_switch_vmcb(svm, &svm->nested.vmcb02); nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); =20 --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-183.mta0.migadu.com (out-183.mta0.migadu.com [91.218.175.183]) (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 CB450428846 for ; Fri, 6 Feb 2026 19:09:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.183 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404967; cv=none; b=Cqm0JntH7Mb0s45mhGJ2d7CRaaQ5z6qsujcRcuCKvpNfa2+WDm5K7M98Cpb0zR6lfq6iLUrtDrp8pA9mjGJDehB29nXDA4dbLPgzWhhg3yO+UXdAjQnh3/upqFYLXoKxG6KK+IFeTFzwEmjS+wngBKjo6SzJJcJFEBnkn1v5ZE4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404967; c=relaxed/simple; bh=2vnKk/0j7NLk9BjwTNt9Niw69jc7ATz5F/Nd5t15a4o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fqRHOhpdUdLyHBnJvCqwgrbPI7VFkX4BEDwNNTo3Kj6HV5F3CjDEHGIqlaPoqYY9sEnhwtRfWWV5qpafiaw/ipIJnrpDyNNsq+B5gdvvUnkbIhEFyOb5WFDfMamrKUMGNQHGQt5Driy/wbq1cbhfX4dFVjb2Wfck3qtupN9gwmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Fm7BGsTf; arc=none smtp.client-ip=91.218.175.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Fm7BGsTf" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404965; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c6WQRdiodBhsWPUMc6qwrczfvDz8gYzPH1Tbgvdt5pE=; b=Fm7BGsTfRWg1kE4MkhV9dsmaUgDzTexuDMoiPg/81KrQ+WMa0qMQJfYBVSSs1u7fqoPCW/ GHUZTvFPgN0g2Q6HhWiY90t7Nu9xmUA3+yYu/vJ/QRR96FP/wV2nA0JiQcSY9gOkNbwNTe 46gbbZUCbLCGDpSW/zypISUEmBQPz98= 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 v5 10/26] KVM: nSVM: Make nested_svm_merge_msrpm() return an errno Date: Fri, 6 Feb 2026 19:08:35 +0000 Message-ID: <20260206190851.860662-11-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for moving nested_svm_merge_msrpm() within enter_svm_guest_mode(), which returns an errno, return an errno from nested_svm_merge_msrpm(). No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 607d99172e2b..6e7238fed7ab 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -276,7 +276,7 @@ int __init nested_svm_init_msrpm_merge_offsets(void) * is optimized in that it only merges the parts where KVM MSR permission = bitmap * may contain zero bits. */ -static bool nested_svm_merge_msrpm(struct kvm_vcpu *vcpu) +static int nested_svm_merge_msrpm(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); nsvm_msrpm_merge_t *msrpm02 =3D svm->nested.msrpm; @@ -303,17 +303,19 @@ static bool nested_svm_merge_msrpm(struct kvm_vcpu *v= cpu) #endif =20 if (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))) - return true; + return 0; =20 for (i =3D 0; i < nested_svm_nr_msrpm_merge_offsets; i++) { const int p =3D nested_svm_msrpm_merge_offsets[i]; nsvm_msrpm_merge_t l1_val; gpa_t gpa; + int r; =20 gpa =3D svm->nested.ctl.msrpm_base_pa + (p * sizeof(l1_val)); =20 - if (kvm_vcpu_read_guest(vcpu, gpa, &l1_val, sizeof(l1_val))) - return false; + r =3D kvm_vcpu_read_guest(vcpu, gpa, &l1_val, sizeof(l1_val)); + if (r) + return r; =20 msrpm02[p] =3D msrpm01[p] | l1_val; } @@ -325,7 +327,7 @@ static bool nested_svm_merge_msrpm(struct kvm_vcpu *vcp= u) #endif svm->vmcb->control.msrpm_base_pa =3D __sme_set(__pa(svm->nested.msrpm)); =20 - return true; + return 0; } =20 /* @@ -1035,7 +1037,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, true)) goto out_exit_err; =20 - if (nested_svm_merge_msrpm(vcpu)) + if (!nested_svm_merge_msrpm(vcpu)) goto out; =20 out_exit_err: @@ -1930,7 +1932,7 @@ static bool svm_get_nested_state_pages(struct kvm_vcp= u *vcpu) if (CC(!load_pdptrs(vcpu, vcpu->arch.cr3))) return false; =20 - if (!nested_svm_merge_msrpm(vcpu)) { + if (nested_svm_merge_msrpm(vcpu)) { vcpu->run->exit_reason =3D KVM_EXIT_INTERNAL_ERROR; vcpu->run->internal.suberror =3D KVM_INTERNAL_ERROR_EMULATION; --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (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 76A3D43C067 for ; Fri, 6 Feb 2026 19:09:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404968; cv=none; b=POWinoqiYy6s86tmkMMz55WYnccpr+DesirhId/YKQNfiF5JTKLkAJq88KsUvdy9BNZKryF8uRpzcYJJqqcO6z49qGJ2AMfEy5fhxV2BTQGRnFR5olhxMD+ZgATDCAUhdh1iCMGh2EKevZx+7lu0+SzAq4dSjfifndlc/haew2k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404968; c=relaxed/simple; bh=ODb2/IeBwTyKMp4WD85zCZj6S9Ai9FchMpNcAg0S+no=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WZ642jaL8IaoBLLPYGtgl+Dqrj3BD7kFfiXh+T3Mvm6toMvGMCoeVkkHXbt87BzmGC2gqdgtp3kYlinE9f3TXhx5tgrwFYFR+HOp2vz8ewdkxGPxclHfsUW+Gn6E6qXasqPu9z0aEAGJngSsJ1DGDMPD6gQCfwNVbJOOncnUYq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=cYkUgsYk; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="cYkUgsYk" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404967; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iUgewoR9hSRJHPl5m11yn7PrfmFETAQcerjNyaq/Mfs=; b=cYkUgsYkjTu4mizejs2EwuPQugsVehayIX12RSQc1G2FjrUPlGmMglVDBoxIVQgJWdOwkh ZGPbabTcSAbIEZiCFOyNX8DDLTNftsppEW5nmSsgEfApvnZ0+nUSdgfGNKU+gRyEzziZPS ZCeV9/r70YY/lGXbMu6MwlnBqemATh8= 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 v5 11/26] KVM: nSVM: Call nested_svm_merge_msrpm() from enter_svm_guest_mode() Date: Fri, 6 Feb 2026 19:08:36 +0000 Message-ID: <20260206190851.860662-12-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for unifying the VMRUN failure code paths, move calling nested_svm_merge_msrpm() into enter_svm_guest_mode() next to the nested_svm_load_cr3() call (the other failure path in enter_svm_guest_mode()). Adding more uses of the from_vmrun parameter is not pretty, but it is plumbed all the way to nested_svm_load_cr3() so it's not going away soon anyway. No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 6e7238fed7ab..c16b68a07369 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -956,6 +956,12 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vm= cb12_gpa, if (ret) return ret; =20 + if (from_vmrun) { + ret =3D nested_svm_merge_msrpm(vcpu); + if (ret) + return ret; + } + if (!from_vmrun) kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); =20 @@ -1034,22 +1040,17 @@ 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)) - goto out_exit_err; - - if (!nested_svm_merge_msrpm(vcpu)) - goto out; - -out_exit_err: - svm->nested.nested_run_pending =3D 0; - svm->nmi_l1_to_l2 =3D false; - svm->soft_int_injected =3D false; + if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, true)) { + 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; - svm->vmcb->control.exit_info_2 =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; =20 - nested_svm_vmexit(svm); + nested_svm_vmexit(svm); + } =20 out: kvm_vcpu_unmap(vcpu, &map); --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (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 2EE5543CED7 for ; Fri, 6 Feb 2026 19:09:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404970; cv=none; b=fiS8mgD9P/kxbOJV3Uygc1aV3Gv5ICbnSiUoRcPVtSFPsRtuy75xTdWSfElYsi//oVN2g2dM7vrYXeUbVTcH4QBTPgwmvhH/cmOGlsB65Jx+olXNUUJ4/WtqgdsXi30fyawdwkck6WEP6TbLgi4kIidCzjU5F7nf5SuMcIFtw1Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404970; c=relaxed/simple; bh=LBmchytedw8fx4u5UhBQyRuvwF45htId9tkKO/LIPg4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FHI75ctsPaV4kzpeFeqXknrYHGESMHptGO7ps2d8tMEypu1smRsHCxHPgdFoQXL+Ox5Qd8MENJBBzRHjFUbT4dXtTRuGrLLGM8LhGLZD4wlMQP+UV+zrwQ3D2zNG7s0WPHl48mJNhsSgsAHgkLwzdooItfzruimLHywbo3SfARk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=YiXZ2o/w; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="YiXZ2o/w" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404968; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bEnWTOPvdqvemtyagr/QRJYM/xqwakpjIKYmfE9kKs0=; b=YiXZ2o/wpRhck7FpoMwL1kCrsVQpm+X1iNFEEeDv3rmTTmQPjzSawY7rZRPd1WfC9hzmf4 2O7y1yNy1FHe9N0he801jeALuF+X2vYWufyLXM4DwUtZOBhP4zBpKzrjJxpSvzb94TwkcL 5k7G8Ro9DF0wiMS4CplUmgBwO05hfzE= 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 v5 12/26] KVM: nSVM: Call nested_svm_init_mmu_context() before switching to VMCB02 Date: Fri, 6 Feb 2026 19:08:37 +0000 Message-ID: <20260206190851.860662-13-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for moving more code that depends on nested_svm_init_mmu_context() before switching to VMCB02, move the call outside of nested_vmcb02_prepare_control() into callers, a bit earlier. nested_svm_init_mmu_context() needs to be called after enter_guest_mode(), but not after switching to VMCB02. No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index c16b68a07369..77cb98e39fb3 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -803,10 +803,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_= svm *svm, /* Also overwritten later if necessary. */ vmcb02->control.tlb_ctl =3D TLB_CONTROL_DO_NOTHING; =20 - /* nested_cr3. */ - if (nested_npt_enabled(svm)) - nested_svm_init_mmu_context(vcpu); - vcpu->arch.tsc_offset =3D kvm_calc_nested_tsc_offset( vcpu->arch.l1_tsc_offset, svm->nested.ctl.tsc_offset, @@ -945,6 +941,9 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmc= b12_gpa, =20 enter_guest_mode(vcpu); =20 + if (nested_npt_enabled(svm)) + nested_svm_init_mmu_context(vcpu); + nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); =20 svm_switch_vmcb(svm, &svm->nested.vmcb02); @@ -1893,6 +1892,10 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, nested_copy_vmcb_control_to_cache(svm, ctl); =20 enter_guest_mode(vcpu); + + if (nested_npt_enabled(svm)) + nested_svm_init_mmu_context(vcpu); + svm_switch_vmcb(svm, &svm->nested.vmcb02); nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); =20 --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-171.mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (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 2625143D4E3; Fri, 6 Feb 2026 19:09:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404972; cv=none; b=W3HOxYAT/zW0Diwi4ptRve4nWH6SSGjLdgiWF+tmYsfmaOwqpmkDgyX8XaYydnMWpBmFfjuptLTKaTyHGxZq9gEg5rTMfRPFj528CAQt9kaU67j2mIv19TyggtFON5im8z081NeRrtryjQIQ5yhAObkP8gzzQA28gaYfCNzXeJg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404972; c=relaxed/simple; bh=iHRA+CY3G4sfkkjtab8WHpN/rU+K6k4ITce+YB/0thQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LJj6zdxtQZbnCE59Hx4Y+rZ0A0NH3/ftVarhdCqnSoaHIWzGowInFMK6wiygSwS9+R68aQZwNaUMcEYPHz3vnElkIsvm/QciJp9XVTdsNw/DQfKh+eu4dXGH/KcSw5ll+DzQGLc5Ud6QhqN9N46VO8tJAhBVRaWSisC1OW/t9BQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=KCyDsvnf; arc=none smtp.client-ip=91.218.175.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="KCyDsvnf" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404970; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5F/2K7Th5J9MsJE8ZyTAj5AnPleeJatK++yTTaOysm8=; b=KCyDsvnf7kkaocwaUwznotSB7h8GUdWWH6alrYHAyKPUtrSOick1p/HSufsG74mLaXHtB2 MsWD7FojC3Q0LevHDiCZD7AmOD7J4ngUJlVglabQx2tRb49F7CQ8EPRG5c7stuTTYqs/QH 0db80kGF7lvM6Rqvsu02nVL3XG8ptlU= 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 v5 13/26] KVM: nSVM: Refactor minimal #VMEXIT handling out of nested_svm_vmexit() Date: Fri, 6 Feb 2026 19:08:38 +0000 Message-ID: <20260206190851.860662-14-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for having a separate minimal #VMEXIT path for handling failed VMRUNs, move the minimal logic out of nested_svm_vmexit() into a helper. This includes clearing the GIF, handling single-stepping on VMRUN, and a few data structure cleanups. Basically, everything that is required by the architecture (or KVM) on a #VMEXIT where L2 never actually ran. Additionally move uninitializing the nested MMU and reloading host CR3 to the new helper. It is not required at this point, but following changes will require it. No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 61 ++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 77cb98e39fb3..a852508d7419 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -974,6 +974,34 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vm= cb12_gpa, return 0; } =20 +static void __nested_svm_vmexit(struct vcpu_svm *svm) +{ + struct vmcb *vmcb01 =3D svm->vmcb01.ptr; + struct kvm_vcpu *vcpu =3D &svm->vcpu; + + svm->nested.vmcb12_gpa =3D 0; + svm->nested.ctl.nested_cr3 =3D 0; + + /* GIF is cleared on #VMEXIT, no event can be injected in L1 */ + svm_set_gif(svm, false); + vmcb01->control.exit_int_info =3D 0; + + nested_svm_uninit_mmu_context(vcpu); + if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) { + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return; + } + + /* + * If we are here following the completion of a VMRUN that + * is being single-stepped, queue the pending #DB intercept + * right now so that it an be accounted for before we execute + * L1's next instruction. + */ + if (unlikely(vmcb01->save.rflags & X86_EFLAGS_TF)) + kvm_queue_exception(vcpu, DB_VECTOR); +} + int nested_svm_vmrun(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); @@ -1121,8 +1149,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) /* in case we halted in L2 */ kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); =20 - svm->nested.vmcb12_gpa =3D 0; - if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); return; @@ -1239,13 +1265,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) } } =20 - /* - * On vmexit the GIF is set to false and - * no event can be injected in L1. - */ - svm_set_gif(svm, false); - vmcb01->control.exit_int_info =3D 0; - svm->vcpu.arch.tsc_offset =3D svm->vcpu.arch.l1_tsc_offset; if (vmcb01->control.tsc_offset !=3D svm->vcpu.arch.tsc_offset) { vmcb01->control.tsc_offset =3D svm->vcpu.arch.tsc_offset; @@ -1258,8 +1277,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) svm_write_tsc_multiplier(vcpu); } =20 - svm->nested.ctl.nested_cr3 =3D 0; - /* * Restore processor state that had been saved in vmcb01 */ @@ -1285,13 +1302,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) =20 nested_svm_transition_tlb_flush(vcpu); =20 - nested_svm_uninit_mmu_context(vcpu); - - if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) { - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); - return; - } - /* * Drop what we picked up for L2 via svm_complete_interrupts() so it * doesn't end up in L1. @@ -1300,21 +1310,18 @@ void nested_svm_vmexit(struct vcpu_svm *svm) kvm_clear_exception_queue(vcpu); kvm_clear_interrupt_queue(vcpu); =20 - /* - * If we are here following the completion of a VMRUN that - * is being single-stepped, queue the pending #DB intercept - * right now so that it an be accounted for before we execute - * L1's next instruction. - */ - if (unlikely(vmcb01->save.rflags & X86_EFLAGS_TF)) - kvm_queue_exception(&(svm->vcpu), DB_VECTOR); - /* * Un-inhibit the AVIC right away, so that other vCPUs can start * to benefit from it right away. */ if (kvm_apicv_activated(vcpu->kvm)) __kvm_vcpu_update_apicv(vcpu); + + /* + * Potentially queues an exception, so it needs to be after + * kvm_clear_exception_queue() is called above. + */ + __nested_svm_vmexit(svm); } =20 static void nested_svm_triple_fault(struct kvm_vcpu *vcpu) --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-181.mta0.migadu.com (out-181.mta0.migadu.com [91.218.175.181]) (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 A6F8943D504 for ; Fri, 6 Feb 2026 19:09:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404973; cv=none; b=HSugMF4584QmBWvGdLgY9xaMq94SgeEhV45xrK0xqkj9i2d/lUg6E+3+lSRuOCHsVLK7IZnR/DQxKh7aL/L7v8HLtPoJ3b+wtUgx0adOBdcfz65iI6zDIMML2TLiSRdTlkoaM64t9o7xxgIhA8ov4CJcozDkvEvyx/qF26qY/ec= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404973; c=relaxed/simple; bh=qfymSp5sdM5UdXIapZ0krZEloaywrLeuhrSrgLX05Tg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o8VGvsYbjpujrMoGEB3ATLCTuJFQx7hjOMpcLKdS+W55t1Ri+uaFnGhbxfHlrZn0RBY+SW/RYs4QPCw96VgsU7b7SsePs+WppvZh1zvykmGRDZEmvHr6U6XYMFMdcfzIvmaogSMuILT6MVO0LyNA2/m1QvcK7WRr0uNhOeaR9oM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=gYWX9Ki9; arc=none smtp.client-ip=91.218.175.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="gYWX9Ki9" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404972; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=A61MjfomSxxuJgw3g4fkU+eGDEdvm0za4xW5Q7zFG64=; b=gYWX9Ki9iMCvKkkGqBgqTl36povFos+FqtRT0t177HxzSTDBDYwVlf8d5B4G47YzcIp4Xk +Zf2hlCKwG0dmYlKGCeBltS8E/69J+9RzP5jjIMS0eRLcFDwcaHwD9kLO+ZJ3wOlD7+gsP ccXg19xy0+Ba8Vo3pEXd/h46QVpTlD8= 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 v5 14/26] KVM: nSVM: Unify handling of VMRUN failures with proper cleanup Date: Fri, 6 Feb 2026 19:08:39 +0000 Message-ID: <20260206190851.860662-15-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" There are currently two possible causes of VMRUN failures emulated by KVM: 1) Consistency checks failures. In this case, KVM updates the exit code in the mapped VMCB12 and exits early in nested_svm_vmrun(). This causes a few problems: A) KVM does not clear the GIF if the early consistency checks fail (because nested_svm_vmexit() is not called). Nothing requires GIF=3D0 before a VMRUN, from the APM: It is assumed that VMM software cleared GIF some time before executing the VMRUN instruction, to ensure an atomic state switch. So an early #VMEXIT from early consistency checks could leave the GIF set. B) svm_leave_smm() is missing consistency checks on the newly loaded guest state, because the checks aren't performed by enter_svm_guest_mode(). 2) Failure to load L2's CR3 or merge the MSR bitmaps. In this case, a fully-fledged #VMEXIT injection is performed as VMCB02 is already prepared. Arguably all VMRUN failures should be handled before the VMCB02 is prepared, but with proper cleanup (e.g. clear the GIF). Move all the potential failure checks inside enter_svm_guest_mode() before switching to VMCB02. On failure of any of these checks, nested_svm_vmrun() synthesizes a minimal #VMEXIT through the new nested_svm_failed_vmrun() helper. __nested_svm_vmexit() already performs the necessary cleanup for a failed VMRUN, including uninitializing the nested MMU and reloading L1's CR3. This ensures that consistency check failures do proper necessary cleanup, while other failures do not doo too much cleanup. It also leaves a unified path for handling VMRUN failures. Cc: stable@vger.kernel.org Fixes: 52c65a30a5c6 ("KVM: SVM: Check for nested vmrun intercept before emu= lating vmrun") Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 66 +++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index a852508d7419..918f6a6eaf56 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -934,22 +934,19 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 v= mcb12_gpa, vmcb12->control.intercepts[INTERCEPT_WORD4], vmcb12->control.intercepts[INTERCEPT_WORD5]); =20 - svm->nested.vmcb12_gpa =3D vmcb12_gpa; =20 WARN_ON(svm->vmcb =3D=3D svm->nested.vmcb02.ptr); =20 enter_guest_mode(vcpu); =20 + if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) + return -EINVAL; + if (nested_npt_enabled(svm)) nested_svm_init_mmu_context(vcpu); =20 - nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); - - 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); - ret =3D nested_svm_load_cr3(&svm->vcpu, svm->nested.save.cr3, nested_npt_enabled(svm), from_vmrun); if (ret) @@ -961,6 +958,17 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vm= cb12_gpa, return ret; } =20 + /* + * Any VMRUN failure needs to happen before this point, such that the + * nested #VMEXIT is injected properly by nested_svm_vmrun_error_vmexit(). + */ + + nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); + + 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); + if (!from_vmrun) kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); =20 @@ -979,6 +987,8 @@ static void __nested_svm_vmexit(struct vcpu_svm *svm) struct vmcb *vmcb01 =3D svm->vmcb01.ptr; struct kvm_vcpu *vcpu =3D &svm->vcpu; =20 + WARN_ON_ONCE(is_guest_mode(vcpu)); + svm->nested.vmcb12_gpa =3D 0; svm->nested.ctl.nested_cr3 =3D 0; =20 @@ -1002,6 +1012,20 @@ static void __nested_svm_vmexit(struct vcpu_svm *svm) kvm_queue_exception(vcpu, DB_VECTOR); } =20 +static void nested_svm_vmrun_error_vmexit(struct kvm_vcpu *vcpu, struct vm= cb *vmcb12) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + + WARN_ON_ONCE(svm->vmcb =3D=3D svm->nested.vmcb02.ptr); + + leave_guest_mode(vcpu); + + vmcb12->control.exit_code =3D SVM_EXIT_ERR; + vmcb12->control.exit_info_1 =3D 0; + vmcb12->control.exit_info_2 =3D 0; + __nested_svm_vmexit(svm); +} + int nested_svm_vmrun(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); @@ -1044,14 +1068,6 @@ 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, &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; - goto out; - } - /* * Since vmcb01 is not in use, we can use it to store some of the L1 * state. @@ -1072,14 +1088,9 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) 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; - svm->vmcb->control.exit_info_2 =3D 0; - - nested_svm_vmexit(svm); + nested_svm_vmrun_error_vmexit(vcpu, vmcb12); } =20 -out: kvm_vcpu_unmap(vcpu, &map); =20 return ret; @@ -1217,6 +1228,13 @@ void nested_svm_vmexit(struct vcpu_svm *svm) if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS)) vmcb01->control.erap_ctl |=3D ERAP_CONTROL_CLEAR_RAP; =20 + /* + * nested_svm_vmexit() is intended for use only when KVM is synthesizing + * a #VMEXIT after a successful nested VMRUN. All VMRUN consistency + * checks must be performed before loading guest state, and so should + * use __nested_svm_vmexit(). + */ + WARN_ON_ONCE(svm->vmcb !=3D svm->nested.vmcb02.ptr); svm_switch_vmcb(svm, &svm->vmcb01); =20 /* @@ -1903,9 +1921,6 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, if (nested_npt_enabled(svm)) nested_svm_init_mmu_context(vcpu); =20 - svm_switch_vmcb(svm, &svm->nested.vmcb02); - nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); - /* * While the nested guest CR3 is already checked and set by * KVM_SET_SREGS, it was set when nested state was yet loaded, @@ -1917,6 +1932,9 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, if (ret) goto out_free; =20 + svm_switch_vmcb(svm, &svm->nested.vmcb02); + nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); + svm->nested.force_msr_bitmap_recalc =3D true; =20 kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-172.mta0.migadu.com (out-172.mta0.migadu.com [91.218.175.172]) (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 4629742981E for ; Fri, 6 Feb 2026 19:09:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404975; cv=none; b=lekL2EFJVNFxHE5z8sVlFTcUBs9jSxvhDT6k6EniYt7lFvcrImNQhNViN0bV55iDGgxywHb8joAc0oovMtMfiZja4a2UV8snBffPonvPqneXia8Id5Wd+X/ZaAUC8nIQGV+f0mr5FSNXSafNNFrYxWtkWUHRiD/A9Ll/qR8rqWE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404975; c=relaxed/simple; bh=2GCFQgDIIXc/4F8yoRTg5mJZlXIwfwKXQX8YO7VOUEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s0aGc+zOGulIqGtk5HqwnrjbAoAEpVEc5jBzJSGnz9C56VVPcmVqZBtH4jB/DOmKDctWbfr+d5PHS6+H4G+TQz0YZYmSKtnjaPPX0QeDHuRJ7zZXGGQxO7NyCTC3JfVpKHPM4XiJwyWKYXkwmH0vAxFdTXZUpX0vo4dLD1FWUGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=L3/uBPc2; arc=none smtp.client-ip=91.218.175.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="L3/uBPc2" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404973; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iK+en+N3Sh3Cz5P9nnp8aY0rKVsI9XKonHalz8PlHgA=; b=L3/uBPc2nVHFs3EYCLKt03ZD5Dg1VB8G++tKvueTGgC/JbkdGYq2Knrr4SaflXTPJ082iM CLXGJnATsmGKIPJamXyvhTTKm4jFjP6Zu4RL/GgYdSFhgS6CYoi1cRLsYGRSkDj7EfHaE8 7ahOPYlLBK1a0TxGpyj1FVZLGx09YWE= 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 v5 15/26] KVM: nSVM: Clear EVENTINJ field in VMCB12 on nested #VMEXIT Date: Fri, 6 Feb 2026 19:08:40 +0000 Message-ID: <20260206190851.860662-16-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 correctly cleared EVENTINJ (i.e. event_inj and event_inj_err) on nested #VMEXIT before commit 2d8a42be0e2b ("KVM: nSVM: synchronize VMCB controls updated by the processor on every vmexit"). That commit made sure the fields are synchronized between VMCB02 and KVM's cached VMCB12 on every L2->L0 #VMEXIT, such that they are serialized correctly on save/restore. However, the commit also incorrectly copied the fields from KVM's cached VMCB12 to L1's VMCB12 on nested #VMEXIT. Go back to clearing the fields, and so in __nested_svm_vmexit() instead of nested_svm_vmexit(), such that it also applies to #VMEXITs caused by a failed VMRUN. 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 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 918f6a6eaf56..2f43b70930a8 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -982,7 +982,7 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmc= b12_gpa, return 0; } =20 -static void __nested_svm_vmexit(struct vcpu_svm *svm) +static void __nested_svm_vmexit(struct vcpu_svm *svm, struct vmcb *vmcb12) { struct vmcb *vmcb01 =3D svm->vmcb01.ptr; struct kvm_vcpu *vcpu =3D &svm->vcpu; @@ -996,6 +996,10 @@ static void __nested_svm_vmexit(struct vcpu_svm *svm) svm_set_gif(svm, false); vmcb01->control.exit_int_info =3D 0; =20 + /* event_inj is cleared on #VMEXIT */ + vmcb12->control.event_inj =3D 0; + vmcb12->control.event_inj_err =3D 0; + nested_svm_uninit_mmu_context(vcpu); if (nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true)) { kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); @@ -1023,7 +1027,7 @@ static void nested_svm_vmrun_error_vmexit(struct kvm_= vcpu *vcpu, struct vmcb *vm vmcb12->control.exit_code =3D SVM_EXIT_ERR; vmcb12->control.exit_info_1 =3D 0; vmcb12->control.exit_info_2 =3D 0; - __nested_svm_vmexit(svm); + __nested_svm_vmexit(svm, vmcb12); } =20 int nested_svm_vmrun(struct kvm_vcpu *vcpu) @@ -1205,8 +1209,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) vmcb12->control.next_rip =3D vmcb02->control.next_rip; =20 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 if (!kvm_pause_in_guest(vcpu->kvm)) { vmcb01->control.pause_filter_count =3D vmcb02->control.pause_filter_coun= t; @@ -1316,8 +1318,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm) vmcb12->control.exit_int_info_err, KVM_ISA_SVM); =20 - kvm_vcpu_unmap(vcpu, &map); - nested_svm_transition_tlb_flush(vcpu); =20 /* @@ -1339,7 +1339,9 @@ void nested_svm_vmexit(struct vcpu_svm *svm) * Potentially queues an exception, so it needs to be after * kvm_clear_exception_queue() is called above. */ - __nested_svm_vmexit(svm); + __nested_svm_vmexit(svm, vmcb12); + + kvm_vcpu_unmap(vcpu, &map); } =20 static void nested_svm_triple_fault(struct kvm_vcpu *vcpu) --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (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 15B4943DA54 for ; Fri, 6 Feb 2026 19:09:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404977; cv=none; b=h6UBJzocg+FALqUp5rlkljiGjpTHjdlJD7ZytkJmi2DoUdTc5IdkvzuqQVTB1vBNm3WoBlbC5swsl4b5RBIzN+Al3C2ySndYSqJFHCQzP1Y4xIHEhm9mS6C6xEBdTqMJc3xtar2Lj8j1dpC3YcVilIHGmZ1ff6y1PQXzP3iR2/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404977; c=relaxed/simple; bh=rR9dAFfPMHmMulmPHmShmExNZnbbQjgQSPTy19JJlAQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CHw/io8hNAOYXA5hCTOFBBqru3uj5B1Gt6gcfFbYbN+4cGfu1cwLKMZ6gJ7tHqgSD3zb0FYSDvIPBWcUKW9IYTXdmtujOObZ8dN5wG+V99Gx7a1qmLLyKX+fRtbgScpLWiEmusfCyrUa4dK3qqq228gwprh6ZhqVUry4JedO7UQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Y73cGMhW; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Y73cGMhW" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tEqM3TO0SlxQ/S7xbx4vbL2+pEkeHcTx11OiYE4X5s0=; b=Y73cGMhWE0n1h2ti/oiu7P1tD2VrKME2AgW/W1e1x3rzPigI+XYEKzpsv9fuVtYzXgHX7i pcq7al8r7cLMk08MUCdSFy6D8CT5R9b+kmfTuQgRGI6pOLAhnht26mEQltjJjoNHXkMUuF oY3qmPxwOvF8tXoTjEIPbPVvTQ0RRyU= 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 v5 16/26] KVM: nSVM: Drop the non-architectural consistency check for NP_ENABLE Date: Fri, 6 Feb 2026 19:08:41 +0000 Message-ID: <20260206190851.860662-17-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 2f43b70930a8..61359e64e8ed 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -350,9 +350,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; @@ -433,6 +430,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; @@ -446,7 +448,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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (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 DD50D43E48D for ; Fri, 6 Feb 2026 19:09:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404979; cv=none; b=ah+aOTJzOVl3FI5JaNNi3X0ruPAmScJoPUtxX655ZJdNInMSR7Ejih0BcrG8n1CA+AbGO2Y1F0wKnv4ttG4RYW/TCx0yB9K6BRI6+miMGt6tPhdLwCn/wS5eG0zkpPED16D1QVRBpv9EGUyzUugUForx7F11wROUKSpzrlzb+kg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404979; c=relaxed/simple; bh=5ctLhR0lS99QfPYOjSZ2IkQWT2BlNOBp2oflUMsiFx4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LCh036iUQgDt51VjKQI+Xni1i2FFjpswTDWR6csxxLnP5jB54Q4KBMpsy7YiW4zGLtrn/+u18Ovbxq57zavwDsLBks2Lh25N5N6SS/MUpBvS0HuXklMkxTycZ427WsFFSti+NVvdwFbZgNEH7bNY2yRV83VYLCngDUbiPEg+QgM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=OKw0yfia; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="OKw0yfia" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404977; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Man7fEjZ0MIzpTt04AlItBFOGG4+DdWyp2A674rOJMI=; b=OKw0yfiatGEkN4wNXvRjT/GnBUjGoe6FpxetSivKffMij18qIFwP87ui88gMQlB0nR5oZq mm7D5wZM1hHIPlo+4B2T+NhA4sNJlCdxenO5PrUh7qHHQTPuaEnuBwz27+LWLzjhDNMfkZ 4zR2uwoMnljEodYf1Rv+wz0XtC6DMUo= 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 v5 17/26] KVM: nSVM: Add missing consistency check for nCR3 validity Date: Fri, 6 Feb 2026 19:08:42 +0000 Message-ID: <20260206190851.860662-18-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 61359e64e8ed..a5a5ce060f47 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -350,6 +350,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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (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 D94E742EEA3 for ; Fri, 6 Feb 2026 19:09:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404981; cv=none; b=g7lb5QljP8jQYR/dq+60eZbmmJdzh4iS6aPBC06pp+2KQBRkOylNCwBjgU1UBf3bgE97Vq+3Wb0M0A5AxN2ptmJgVcIMtw5hX8HnNwuzSvZgn5LowJvvSLLqQ65az3t6Sexf6PKGqXXkcG96nOcv/HmyLpBUM08nMiK30mwNqls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404981; c=relaxed/simple; bh=Vtfsd92Nedk+qa5QTjaWDaB64PIzJ/VkPPqgqlm5874=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cPmBRcCfbKukvljE/7BYTVUpfDxScehSyEwSlOrC7BjWXoDDiFVQEJIQGWg3SPdtWfwy5yn2xe2lkvNexYkC4rnsv2rcOZ8vhc3s2pD9+vs++wC9zr3dBXKhODRjELWkujqkBsqCr3UIuB92uqldx4cSkLlp8Av/qtHWNHUFQR4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=HR0CrVbk; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="HR0CrVbk" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404979; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oBlYJPqz9gw2yBOyADq3T7jaA/xUIHeZ1woVZ8G8pf8=; b=HR0CrVbkX/z+cZlMDMrIH5jObvqLSGsXyvMVFBp5eMEqUSwiBu/RnxWRz+WnW8/495Xyx+ 951x2KsV+ZWh/F5xQ+YI/rP5GwD8sh33BhuQy80KvgLTjhtLWA27TOxHLwkRh7ckHIFhJD pKHggN2riJKQti0ktUIC4Bt5OlWne5o= 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 v5 18/26] KVM: nSVM: Add missing consistency check for hCR0.PG and NP_ENABLE Date: Fri, 6 Feb 2026 19:08:43 +0000 Message-ID: <20260206190851.860662-19-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT From the APM Volume #2, 15.25.3 (24593=E2=80=94Rev. 3.42=E2=80=94March 2024= ): If VMRUN is executed with hCR0.PG cleared to zero and NP_ENABLE set to 1 , VMRUN terminates with #VMEXIT(VMEXIT_INVALID). Add the consistency check by plumbing L1's CR0 to nested_vmcb_check_controls(). 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 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index a5a5ce060f47..ca2d1b1b8be6 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -342,7 +342,8 @@ static bool nested_svm_check_bitmap_pa(struct kvm_vcpu = *vcpu, u64 pa, u32 size) } =20 static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu, - struct vmcb_ctrl_area_cached *control) + struct vmcb_ctrl_area_cached *control, + unsigned long l1_cr0) { if (CC(!vmcb12_is_intercept(control, INTERCEPT_VMRUN))) return false; @@ -353,6 +354,8 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu = *vcpu, if (control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) { if (CC(!kvm_vcpu_is_legal_gpa(vcpu, control->nested_cr3))) return false; + if (CC(!(l1_cr0 & X86_CR0_PG))) + return false; } =20 if (CC(!nested_svm_check_bitmap_pa(vcpu, control->msrpm_base_pa, @@ -947,7 +950,8 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmc= b12_gpa, enter_guest_mode(vcpu); =20 if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || - !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) + !nested_vmcb_check_controls(vcpu, &svm->nested.ctl, + svm->vmcb01.ptr->save.cr0)) return -EINVAL; =20 if (nested_npt_enabled(svm)) @@ -1879,7 +1883,8 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, =20 ret =3D -EINVAL; __nested_copy_vmcb_control_to_cache(vcpu, &ctl_cached, ctl); - if (!nested_vmcb_check_controls(vcpu, &ctl_cached)) + /* 'save' contains L1 state saved from before VMRUN */ + if (!nested_vmcb_check_controls(vcpu, &ctl_cached, save->cr0)) goto out_free; =20 /* --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-181.mta0.migadu.com (out-181.mta0.migadu.com [91.218.175.181]) (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 03CF543E9CF for ; Fri, 6 Feb 2026 19:09:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404983; cv=none; b=VPd0trjiLuIpCdss+P63DKpUt8MpPO8288xVtXSikouNO7a8Tm63naQhLsuZFuOJkmlScaWzkp31nBTfKpY3fKhv3chdh95gFGJBgRlme4gmqA4CPxAMQhqrCAiUwtUkLmyVKos0b/r2YH51FNhPDm+V0tDd6YlRZ1HyZQ9q/sA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404983; c=relaxed/simple; bh=myzwwiuhbadCyZSw7HuAVfjih7JweD6SXt48MzjlC4A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UUaovniVhlLC0B8YVo/lBIwJ1S72tL034kovsx56EFL8RUwFJIQRkEiPRc6XcWbne1HS7Umf3ougPO1CAo9QuKU0pByV5cpeN1RaJrEf5n10y1cDzVfCGoXztdJzv5+X2EDrqtOK4NCsy6umTI5RmYFqINdXKepnJxNNCZV1Ow4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=T7Rr8ibF; arc=none smtp.client-ip=91.218.175.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="T7Rr8ibF" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EG5LX6BdhVM8GYyf0Bk/7CQB4mY+IW3H5PUrABCxjTc=; b=T7Rr8ibFR44X8mefM5hzYRIf1QfZ6+9pXzWpwfKhwwuyixKX6SZ2VTGzIxHk8wUak6ldyU ogI9hmYe/L10uOredc20P1gcOjbtzhhOyXCrs0StSHCLVcNk84JWGe2Z/7LV/0zOerjDm7 x44zs1VO0SNT9y+UG3gp+Y2/TajFSpY= 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 v5 19/26] KVM: nSVM: Add missing consistency check for EFER, CR0, CR4, and CS Date: Fri, 6 Feb 2026 19:08:44 +0000 Message-ID: <20260206190851.860662-20-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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. Add the missing consistency check. 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 | 7 +++++++ arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index ca2d1b1b8be6..90942c8c9d9d 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -397,6 +397,11 @@ 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->cr4 & X86_CR4_PAE) && + (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. */ @@ -492,6 +497,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 7629cb37c930..0a5d5a4453b7 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (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 92387428852; Fri, 6 Feb 2026 19:09:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404984; cv=none; b=eebBjzC75VdGAoPRiY0NuZ43wIA87I7cwfG8SB8tP8TYAS2lURHKKqsQgsB5N8dkgy3pRczhVeQWrCP2a4CkuRDwJtOjZ03ZRCxV/6FVAJ8aq80YybLqRUwBNwlNrFmqMZKX3y7+aNpktnK1PLxCw7Loa2FrlfZZz62VsCaml3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404984; c=relaxed/simple; bh=xXJ1js8PVgxpZ9ffqHtCiNcemNKz4mzJwQqAywUpmtY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AlnNTYkI6rY0X5rQQIuRDjkpZ7O8DUgosq8jmjb5Y3XRqEk48j8VH9tpJ+lw1cKfrOJjUpnccsdn5wekqf9I0q+CVdUkaRnph+neYh6PyT/7fnxgGIElh//sNsIGPrWzPwKefciYzhkOKEuiCzFVTa/QTVbhaT1bgseLNkz5RAY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=mtOOP8Yg; arc=none smtp.client-ip=91.218.175.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="mtOOP8Yg" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QRdfCralJ8uAgraaBMtzVnH2mn82Aif+PEoIfxuLKoU=; b=mtOOP8YgWjniBg6c1JA3vbhX+xXd8tX+4++GfvRzOEhyldJOUfULKcjlDvqWKv0Ixd8tuw 85vnja0hsK9m9Rlnr+Xg3i6LB2lbSwnIrnUUZ34bYkL8CjGPDv8Z23ZFliMsbSTwticd4u I66SqgJXAOg4bKfMQU/BWlU5QpVghXg= 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 v5 20/26] KVM: nSVM: Add missing consistency check for event_inj Date: Fri, 6 Feb 2026 19:08:45 +0000 Message-ID: <20260206190851.860662-21-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 90942c8c9d9d..42f0dbd86a89 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -341,6 +341,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, unsigned long l1_cr0) @@ -370,6 +418,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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-184.mta0.migadu.com (out-184.mta0.migadu.com [91.218.175.184]) (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 2FC93441027 for ; Fri, 6 Feb 2026 19:09:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404986; cv=none; b=S8kXJAkRFO0AgogNKJTw6DiQYnjj4x+jb1lexFNFJIWk6HZ2cBKaDGvxVmC8od9764TJI6hkO7wXqB89xTdMcfemnpQDbvs49NEst5MwVM3TYR4SdvrlveczottVwRUuE+dXUXQ9SLNAvsp60aXtBn1cYDbePsW8yTeHLm22m/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404986; c=relaxed/simple; bh=JUDT+7Eh/cU+Y4SWZVSQLxL80w6YiNf4szRRp1A7WjE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tpmc2Gri/LTNrCrctE6sIO53HC5Vh13znDV74cqAyQwcYuTYRv349m1Unk2nbCc7YX3rn7tzwRq7oYt8HsrV/mi6O0jdkLOHLon3Wtt2TidFJwGUqB6tjpB0ruRe5pvkrCkQpukf9jVucT7qxEKq6rHPIhA/sKEBFHriYrCL89Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Pqyun2A5; arc=none smtp.client-ip=91.218.175.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Pqyun2A5" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404984; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j/tWCaP02zzkvXRIhMh2iPl6Wt9VXsdZeGUi4/BxY64=; b=Pqyun2A5z1wazY7AQjXzqRRD+3Hc+w8mq7Y8eO4QWhdgK0ObVra3MKD4Z+nYCZ6fpYRmos kstZdDb6qQBvOieLzkd20jHg4CASW3zM3G9ChViSnIANuuLKEZbOWyjWxIr2LWnJ5ZkAl5 Snp4f1IYc6fMfpQaIf3A7F+Jl88qGO0= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v5 21/26] KVM: SVM: Rename vmcb->nested_ctl to vmcb->misc_ctl Date: Fri, 6 Feb 2026 19:08:46 +0000 Message-ID: <20260206190851.860662-22-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 edde36097ddc..983db6575141 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 42f0dbd86a89..10673615ab39 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -399,7 +399,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; if (CC(!(l1_cr0 & X86_CR0_PG))) @@ -494,10 +494,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; @@ -833,7 +833,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); @@ -989,7 +989,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); @@ -1801,7 +1801,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 ea515cf41168..0ed9cfed1cbc 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 a534c08fbe61..c9120dc3d6ff 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); @@ -3358,7 +3358,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 0a5d5a4453b7..f66e5c8565aa 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 10b30b38bb3f..d81d8a9f5bfb 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 2e5c480c9afd..eb20b00112c7 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (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 A9590441024 for ; Fri, 6 Feb 2026 19:09:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404988; cv=none; b=ia/qfD2kde919kDYPYf0d2S9RH0GD/W/1dVaQPCkKjzQ3M7q0A6rsg1h6Qd7z1TQS0EOwzz3Qmf5w0WBNuo0OL58NgNkLxwLz11Q6ZYGF88xxG/1SQhKLc2L1OM3hIDSfjM7kYRnWQAPOqQPgyM8Y1vD2J5l1JK2YhWTlIoSowc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404988; c=relaxed/simple; bh=IE2LOMMVzzCq4n63t222erqdX3U+jtTSXvSNeqmRK7I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zi5jJlIpufLGA6Sl5QCHVVAMLJ1LFGewzyTUVsP/JMI9c/8PTCijVFG+Do+zlgFZJoh038F9m9gTIkU9prXKXiAuDOCQW+pktkZThIlEfm8aI2rA2uZJuhx1U4JMSYZguil1VcMj4SR272dWq0BuAnn/aNRUnlI58IbhHpAwZx0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=sc+HgOkd; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="sc+HgOkd" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+SRyW8PWhSIJQYz91UL9BaD05QehkW776cdUPG1w3Y4=; b=sc+HgOkdMhYz0Js6xfPj+Q/7JGe6wElOBVNS/tJL+EVJ0qhgdS3xKQJrsfUo/AuMPEPlGW LAmM8urq0+aRiYkARrOwtxADEIfgMU4oL9x6YjvQD1N6kByraWv09W0mratKYp04f+VcZa uyseFQTzU5lcRRAoRxQ4IxtSs3oMYZ0= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v5 22/26] KVM: SVM: Rename vmcb->virt_ext to vmcb->misc_ctl2 Date: Fri, 6 Feb 2026 19:08:47 +0000 Message-ID: <20260206190851.860662-23-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 | 18 ++++++++--------- 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, 37 insertions(+), 38 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 983db6575141..c169256c415f 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 10673615ab39..76118bfcb183 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 @@ -516,7 +516,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 @@ -757,7 +757,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm = *svm, struct vmcb *vmcb12 } =20 if (unlikely(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))) { /* * Reserved bits of DEBUGCTL are ignored. Be consistent with * svm_set_msr's definition of reserved bits. @@ -914,10 +914,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; @@ -1330,7 +1330,7 @@ void 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.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR))) { svm_copy_lbrs(&vmcb12->save, &vmcb02->save); } else { svm_copy_lbrs(&vmcb01->save, &vmcb02->save); @@ -1805,8 +1805,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 c9120dc3d6ff..0e197a2eb339 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); @@ -3364,7 +3364,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); @@ -4359,7 +4359,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 @@ -4390,7 +4390,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 f66e5c8565aa..304328c33e96 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 d81d8a9f5bfb..c8539166270e 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 6764a48f9d4d..71717118d692 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 0a17a2c71634..6c2988a14d1c 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (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 30030441050 for ; Fri, 6 Feb 2026 19:09:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404989; cv=none; b=QmBBrbj6ZAKmxUIbzpWq+kWzOTrdy5Juf+KIMsqNbvYTrnfEWSFFJXDQhv0DVB/caeu0tKTmjTC/ZtgW9e/uZ2nQXXypcu9pmKTfO7LivclG3pTuqB3eR1fZPAtwSXcGqJGlW0iOIa5jRR0fTP1HohL8gV0CpL1MM53iWLCYKZc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404989; c=relaxed/simple; bh=gleIQRw2r4X/Kz/Vfx/Tr5yKLD3hObEGC9AunVuekOY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RY0oGTSB3ahxDJ0lhjMTiptYQTAFVpdIkJkZuh95+r3V7t6vsQBMbV8yaN4Lz+c6xm5eXmOa1uPguo3xVeB/6dZjwwqknPkzPK94MFr9zjt8ctJjbfgDQZSNnIu67Yw5ZcGn75hvCxbahbPQNOUF7devILAVviPJUHdBQHTV8DQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=gETokG6l; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="gETokG6l" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404987; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6qhj1bqjZlmV/jHPCIYZDZlaIwD6o3RqMwKQ5tOk0gw=; b=gETokG6lkSibIqZkSHAu+kSG3fr9THNpEp8IjER1loTLa/NKKBAy/0edjja7gO1zQz2BGV jLWPxAmyEdkaXDhCiy/OwkicwQyfVQht5BwzS1Ox8o8YH1w+oCeylauMfw0C9zS1B39+FU M87OPTcJRFJQY1r5s8lH+42/DvqvE0g= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v5 23/26] KVM: nSVM: Cache all used fields from VMCB12 Date: Fri, 6 Feb 2026 19:08:48 +0000 Message-ID: <20260206190851.860662-24-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 | 116 ++++++++++++++++++++++---------------- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/svm/svm.h | 27 ++++++++- 3 files changed, 93 insertions(+), 52 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 76118bfcb183..b1f3e9df2cd5 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -544,19 +544,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 @@ 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 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); @@ -762,7 +779,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); @@ -978,28 +995,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 svm->nested.vmcb12_gpa =3D vmcb12_gpa; =20 @@ -1034,8 +1052,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 if (!from_vmrun) kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); @@ -1155,7 +1173,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)) { svm->nested.nested_run_pending =3D 0; svm->nmi_l1_to_l2 =3D false; svm->soft_int_injected =3D false; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 0e197a2eb339..364915f42e13 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4881,7 +4881,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 304328c33e96..388aaa5d63d2 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.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (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 C2BEA44104E for ; Fri, 6 Feb 2026 19:09:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404991; cv=none; b=Gr3omLXxFeV6IXij4txLtGpUX6U+eGxKeAA1i4qWDOiU7+mozSDsI9eBD63PFHwUyTu1JXhg7CZivk8ZkK4fFHVUa++lhdJVXUCP5BcjnB1kQuJIl2GXPOyx8giiTtUT7eGYMlZs8PNR1WyTAvgS1ZSUFaWSNnqe/rnu/6r7pxM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404991; c=relaxed/simple; bh=tChEFl18ibAzaJ2GEzMTWsWRSgUzH5SqTZHdeomPuqI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X7HSO5uQhMSrQt6GCLe0oY8dBYJAHxuDgmf/GdEDth3PuZ0mWLDH/36BcOPBdvr7j4w63nWvRFDmS1JZfO4Ft6+zKXVfFx3E+V98CYPkOJyvWphGgbKfKjAtUiUPTyoqpM8bgb1+ltXr4VegyT3rbpgA3NZ7Zcm9IavXYRexJV0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=NApjlN/g; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="NApjlN/g" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404989; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ogj2BvymrjP7EHk/aTikaXPciJhAL1YMt9xpscARaOc=; b=NApjlN/g4iu2vmC3mVXQ9kED1ZA00hE/9PL1K4n0pNqyysf1X6dKzzaWhn8MUir80BLGbP xOeGtC8zeJt9mleG1tbQRnVzPH5O3nQn6UD6UquVm8an1rDZFRCnOFGPQAIee3HTN/E3PD ggH3kA2/IK+QCoAAAAjllRFzUpQHGT4= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v5 24/26] KVM: nSVM: Restrict mapping VMCB12 on nested VMRUN Date: Fri, 6 Feb 2026 19:08:49 +0000 Message-ID: <20260206190851.860662-25-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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() and nested_svm_failed_vmrun(). However, the 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 and copying to cache from nested_svm_vmrun() into a new helper, nested_svm_copy_vmcb12_to_cache(), that maps the VMCB12, caches the needed fields, and unmaps it. Use kvm_vcpu_map_readonly() as only reading the VMCB12 is needed. Similarly, move mapping the VMCB12 on VMRUN failure into nested_svm_failed_vmrun(). Inject a triple fault if the mapping fails, similar to nested_svm_vmexit(). Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 53 ++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index b1f3e9df2cd5..0a7bb01f5404 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1102,26 +1102,56 @@ static void __nested_svm_vmexit(struct vcpu_svm *sv= m, struct vmcb *vmcb12) kvm_queue_exception(vcpu, DB_VECTOR); } =20 -static void nested_svm_vmrun_error_vmexit(struct kvm_vcpu *vcpu, struct vm= cb *vmcb12) +static void nested_svm_vmrun_error_vmexit(struct kvm_vcpu *vcpu, u64 vmcb1= 2_gpa) { struct vcpu_svm *svm =3D to_svm(vcpu); + struct kvm_host_map map; + struct vmcb *vmcb12; + int r; =20 WARN_ON_ONCE(svm->vmcb =3D=3D svm->nested.vmcb02.ptr); =20 leave_guest_mode(vcpu); =20 + r =3D kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map); + if (r) { + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return; + } + + vmcb12 =3D map.hva; vmcb12->control.exit_code =3D SVM_EXIT_ERR; vmcb12->control.exit_info_1 =3D 0; vmcb12->control.exit_info_2 =3D 0; __nested_svm_vmexit(svm, vmcb12); + + kvm_vcpu_unmap(vcpu, &map); +} + +static int nested_svm_copy_vmcb12_to_cache(struct kvm_vcpu *vcpu, u64 vmcb= 12_gpa) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + struct kvm_host_map map; + struct vmcb *vmcb12; + int r; + + r =3D kvm_vcpu_map_readonly(vcpu, gpa_to_gfn(vmcb12_gpa), &map); + if (r) + return r; + + vmcb12 =3D map.hva; + + nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); + nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); + + kvm_vcpu_unmap(vcpu, &map); + return 0; } =20 int nested_svm_vmrun(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); int ret; - struct vmcb *vmcb12; - struct kvm_host_map map; u64 vmcb12_gpa; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; =20 @@ -1142,22 +1172,17 @@ 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)) { + if (nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa)) { kvm_inject_gp(vcpu, 0); return 1; } =20 ret =3D kvm_skip_emulated_instruction(vcpu); =20 - 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); - /* * Since vmcb01 is not in use, we can use it to store some of the L1 * state. @@ -1178,11 +1203,9 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) svm->nmi_l1_to_l2 =3D false; svm->soft_int_injected =3D false; =20 - nested_svm_vmrun_error_vmexit(vcpu, vmcb12); + nested_svm_vmrun_error_vmexit(vcpu, vmcb12_gpa); } =20 - kvm_vcpu_unmap(vcpu, &map); - return ret; } =20 --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (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 73BCD4418E7 for ; Fri, 6 Feb 2026 19:09:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404992; cv=none; b=rmhSYBYEAYW7TUixu+uaMJcxS8S2q0EKb23pVLgOj2VuvIn2+c++rvfmHbFeWkSRrmPfpIhPwlzlBXikf76tSXUDnKhjTeuFGoJpHFELVh88GwzkUqsWUN2hqDwGTZ713Ptod229aa0VGaeMNHX1sYYhLH7LWu289emaHhcuG1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404992; c=relaxed/simple; bh=UR82i0rKsjMPvvFyaxQqjSxuopCoGUDmtDTfiU5AeG8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MVlxyhXHuY6bi8uiPF+RY3ror4k2ocpgkr6GnfS06ybGbI8j1kCHs4mm/1rhhhSor73ZDhABuoFoR3IfMNfGwEOMqV5mWtRcKQLxYHb7JM/ThdCKUCMaZyajTcTa73JfOEPSxcp6SlGgm93z7xq0FTHumQTt4wsT9x1Hg+le/+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=VLiu3UQw; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="VLiu3UQw" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404991; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=37/5OKaxAssey0ciUs5DRHclakNo+RTAWEaX8rkwNvA=; b=VLiu3UQwr/E35h50dD1s0hjJ2fDD3bvpKTPgyckyz4sCtzVGnBhp4cjjy4g52v11u366+l Go6kj3QBBqEEWIER2X3yEBoQ70mU3BCCvflcR8vKkTCdLWuVoxUDCZxIoW8sU7a1MMYgDK ug/eY3UjvYzi1Cb1IHIDX7x6KhtAIYg= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , Jim Mattson Subject: [PATCH v5 25/26] KVM: nSVM: Sanitize control fields copied from VMCB12 Date: Fri, 6 Feb 2026 19:08:50 +0000 Message-ID: <20260206190851.860662-26-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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: - 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, make sure only defined bits are copied from L1's VMCB12 into KVM'cache by defining appropriate masks where needed. The only exception is tlb_ctl, which is unused, so remove it. Opportunistically cleanup ignoring the lower bits of {io/msr}pm_base_pa in __nested_copy_vmcb_control_to_cache() by using PAGE_MASK. Also, move the ASID copying ahead with other special cases, and expand the comment about the ASID being copied only for consistency checks. Suggested-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/svm.h | 5 +++++ arch/x86/kvm/svm/nested.c | 28 +++++++++++++++------------- arch/x86/kvm/svm/svm.h | 1 - 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index c169256c415f..fe3b6d9cea31 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -222,6 +222,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 @@ -635,6 +637,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 0a7bb01f5404..c87738962970 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -499,32 +499,35 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_v= cpu *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; + /* + * Copy the ASID here because nested_vmcb_check_controls() will check + * it. The ASID could be invalid, or conflict with another VM's ASID , + * so it should never be used directly to run L2. + */ + to->asid =3D from->asid; + + /* Lower bits of IOPM_BASE_PA and MSRPM_BASE_PA are ignored */ + 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; 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 - /* 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; - #ifdef CONFIG_KVM_HYPERV /* Hyper-V extensions (Enlightened VMCB) */ if (kvm_hv_hypercall_enabled(vcpu)) { @@ -1832,7 +1835,6 @@ static void nested_copy_vmcb_cache_to_control(struct = vmcb_control_area *dst, dst->msrpm_base_pa =3D from->msrpm_base_pa; dst->tsc_offset =3D from->tsc_offset; dst->asid =3D from->asid; - dst->tlb_ctl =3D from->tlb_ctl; dst->erap_ctl =3D from->erap_ctl; dst->int_ctl =3D from->int_ctl; dst->int_vector =3D from->int_vector; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 388aaa5d63d2..0bb93879abfe 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -176,7 +176,6 @@ struct vmcb_ctrl_area_cached { u64 msrpm_base_pa; u64 tsc_offset; u32 asid; - u8 tlb_ctl; u8 erap_ctl; u32 int_ctl; u32 int_vector; --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sat Feb 7 11:31:11 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (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 417B542EECE for ; Fri, 6 Feb 2026 19:09:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404994; cv=none; b=OeMw5uPwVRs+mO1aQL/b60Ki/Z6X1LbwDm/5BQVMKlvd1/H2yYszCqQs5w6Ate7IalkY58Lw+lh9k9U4KQ7pyq6NZq2stEA00bZY/bMj9BknmdSgBd1Md73yigcpYUzNs+4LT9yaxhUoQCZKoDhJOc6+rcyxN45j6wbmbJNiOCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770404994; c=relaxed/simple; bh=YTcYKED/wvqngcm2f7lwHOcbYRZ3YkO3jVQI2neMGIQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I2+2nB7jBksTuEz0W0wra4hcLA5rhpyXZ/3OhN9SlQ2wAl53wwgwuHaXM9gn7GWATF8Phs1dl2CKpICchs+RtiRTFmCtS9eFZa/DU+yOoNReQwltdO0hWscReHfNvmVVoBkk4scS2kA2JuxuwMHOcCrCyN3eAW7DHlqpr508AS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=taJ4FaJn; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="taJ4FaJn" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770404992; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RK+d5ocqMQ7flxrKcmagDp5JVPOYd8dDWt+aOfINdHE=; b=taJ4FaJnhsdTtXwbeP7oPgjSfct0q4xMkHmi/QyP/1oYksNQ3BMdCEvUNgEFab1HgwEjrs 9IWaHHFORX47aM4TXl+sgWJD9NYH7VQ0T0KPu4MY/ShhWC7XzRJqMYBtwiSoFl49ybZEZx qs7kfAH2Rxaw5rg2OcLltsSfYEmLYmg= From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , Jim Mattson Subject: [PATCH v5 26/26] KVM: nSVM: Only copy SVM_MISC_ENABLE_NP from VMCB01's misc_ctl Date: Fri, 6 Feb 2026 19:08:51 +0000 Message-ID: <20260206190851.860662-27-yosry.ahmed@linux.dev> In-Reply-To: <20260206190851.860662-1-yosry.ahmed@linux.dev> References: <20260206190851.860662-1-yosry.ahmed@linux.dev> 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 X-Migadu-Flow: FLOW_OUT 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 c87738962970..d80b1bde6630 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -852,8 +852,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.rc2.204.g2597b5adb4-goog