From nobody Mon Dec 15 22:06:12 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 0990526B942; Sun, 26 Oct 2025 20:20:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761510029; cv=none; b=kL/GriqYZwxhxJXUEj1f8N2YzA88k+ph0Pj+osXYwSeDH6vwZOBDUACcTpCu1/lnEv08EWTKn2wsEqpMiSbqAN3HgFcvAl309VOG9uPLdWqa8CVLgzFerj+Sz20b7uhb2PRQ7zfhcv7z5G5EBTLG/kjLdI0E3Mi8YVZuaTQ+FPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761510029; c=relaxed/simple; bh=kSZXk9B6dVsyYzgS5xh/mea/B39llGhjBgBKQtM6fDI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GsuEU/TlGDxcrmFJW/f3QeYXAPUc+2ynjAIMFU8e1Xq7sFCAW1XLbS4zb2GRql72B++rn3BO7Lu25DDn05JfnD1lkLtpCXdpZ7mIVwFJXaaI9tRN1fPA+giJzQqrxIWhjZN7v2GZqX7ARNB3/eWwf407E5oEUNlO5PaP6z4oPbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=tCl38Zhe; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="tCl38Zhe" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 59QKJBkO505258 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Sun, 26 Oct 2025 13:19:26 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 59QKJBkO505258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025102301; t=1761509966; bh=+AYoTKSGNUeP70NAIxa4bZWi9ub21GnOez55SMksxcY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tCl38Zhe5m2G/ZDZYEm5IR2iyyVlG8cPKAIgpfPaEA3OAIa4TZrRzVYKqQ7zGbgCV z3pPrb5i1CBH27ygWXJN4H5QqkXMBxC9EsDkliGkopNs5okL3WZWiccMTOYkpf3xwj djKZbxAgC4eGRzmX7NV2Q7LKHY8MTcjZt8obYqid6GEOxvo5HSKsJRoKjPGIuiJf3W agU64BcWiKnA3+VndG2sypwtuUSrOWVrVh5mANOVsa7n8gXxBYiIdR88mx9Vh35qYS EDRgKnWk6hE8iAFdxCnyKx95ymBFrdk8SguTJt61vyJ5CJywl4LIou504/FHw6gMPr nWW7Jap8ANLWA== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, corbet@lwn.net, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, luto@kernel.org, peterz@infradead.org, andrew.cooper3@citrix.com, chao.gao@intel.com, hch@infradead.org, sohil.mehta@intel.com Subject: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields Date: Sun, 26 Oct 2025 13:18:55 -0700 Message-ID: <20251026201911.505204-8-xin@zytor.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251026201911.505204-1-xin@zytor.com> References: <20251026201911.505204-1-xin@zytor.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Xin Li Initialize host VMCS FRED fields with host FRED MSRs' value and guest VMCS FRED fields to 0. FRED CPU state is managed in 9 new FRED MSRs: IA32_FRED_CONFIG, IA32_FRED_STKLVLS, IA32_FRED_RSP0, IA32_FRED_RSP1, IA32_FRED_RSP2, IA32_FRED_RSP3, IA32_FRED_SSP1, IA32_FRED_SSP2, IA32_FRED_SSP3, as well as a few existing CPU registers and MSRs: CR4.FRED, IA32_STAR, IA32_KERNEL_GS_BASE, IA32_PL0_SSP (also known as IA32_FRED_SSP0). CR4, IA32_KERNEL_GS_BASE and IA32_STAR are already well managed. Except IA32_FRED_RSP0 and IA32_FRED_SSP0, all other FRED CPU state MSRs have corresponding VMCS fields in both the host-state and guest-state areas. So KVM just needs to initialize them, and with proper VM entry/exit FRED controls, a FRED CPU will keep tracking host and guest FRED CPU state in VMCS automatically. Signed-off-by: Xin Li Signed-off-by: Xin Li (Intel) Tested-by: Shan Kang Tested-by: Xuelian Guo Reviewed-by: Chao Gao --- Change in v5: * Add TB from Xuelian Guo. Change in v4: * Initialize host SSP[1-3] to 0s in vmx_set_constant_host_state() because Linux doesn't support kernel shadow stacks (Chao Gao). Change in v3: * Use structure kvm_host_values to keep host fred config & stack levels (Sean Christopherson). Changes in v2: * Use kvm_cpu_cap_has() instead of cpu_feature_enabled() to decouple KVM's capability to virtualize a feature and host's enabling of a feature (Chao Gao). * Move guest FRED state init into __vmx_vcpu_reset() (Chao Gao). --- arch/x86/include/asm/vmx.h | 32 ++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmx.c | 36 ++++++++++++++++++++++++++++++++++++ arch/x86/kvm/x86.h | 3 +++ 3 files changed, 71 insertions(+) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index dd79d027ea70..6f8b8947c60c 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -293,12 +293,44 @@ enum vmcs_field { GUEST_BNDCFGS_HIGH =3D 0x00002813, GUEST_IA32_RTIT_CTL =3D 0x00002814, GUEST_IA32_RTIT_CTL_HIGH =3D 0x00002815, + GUEST_IA32_FRED_CONFIG =3D 0x0000281a, + GUEST_IA32_FRED_CONFIG_HIGH =3D 0x0000281b, + GUEST_IA32_FRED_RSP1 =3D 0x0000281c, + GUEST_IA32_FRED_RSP1_HIGH =3D 0x0000281d, + GUEST_IA32_FRED_RSP2 =3D 0x0000281e, + GUEST_IA32_FRED_RSP2_HIGH =3D 0x0000281f, + GUEST_IA32_FRED_RSP3 =3D 0x00002820, + GUEST_IA32_FRED_RSP3_HIGH =3D 0x00002821, + GUEST_IA32_FRED_STKLVLS =3D 0x00002822, + GUEST_IA32_FRED_STKLVLS_HIGH =3D 0x00002823, + GUEST_IA32_FRED_SSP1 =3D 0x00002824, + GUEST_IA32_FRED_SSP1_HIGH =3D 0x00002825, + GUEST_IA32_FRED_SSP2 =3D 0x00002826, + GUEST_IA32_FRED_SSP2_HIGH =3D 0x00002827, + GUEST_IA32_FRED_SSP3 =3D 0x00002828, + GUEST_IA32_FRED_SSP3_HIGH =3D 0x00002829, HOST_IA32_PAT =3D 0x00002c00, HOST_IA32_PAT_HIGH =3D 0x00002c01, HOST_IA32_EFER =3D 0x00002c02, HOST_IA32_EFER_HIGH =3D 0x00002c03, HOST_IA32_PERF_GLOBAL_CTRL =3D 0x00002c04, HOST_IA32_PERF_GLOBAL_CTRL_HIGH =3D 0x00002c05, + HOST_IA32_FRED_CONFIG =3D 0x00002c08, + HOST_IA32_FRED_CONFIG_HIGH =3D 0x00002c09, + HOST_IA32_FRED_RSP1 =3D 0x00002c0a, + HOST_IA32_FRED_RSP1_HIGH =3D 0x00002c0b, + HOST_IA32_FRED_RSP2 =3D 0x00002c0c, + HOST_IA32_FRED_RSP2_HIGH =3D 0x00002c0d, + HOST_IA32_FRED_RSP3 =3D 0x00002c0e, + HOST_IA32_FRED_RSP3_HIGH =3D 0x00002c0f, + HOST_IA32_FRED_STKLVLS =3D 0x00002c10, + HOST_IA32_FRED_STKLVLS_HIGH =3D 0x00002c11, + HOST_IA32_FRED_SSP1 =3D 0x00002c12, + HOST_IA32_FRED_SSP1_HIGH =3D 0x00002c13, + HOST_IA32_FRED_SSP2 =3D 0x00002c14, + HOST_IA32_FRED_SSP2_HIGH =3D 0x00002c15, + HOST_IA32_FRED_SSP3 =3D 0x00002c16, + HOST_IA32_FRED_SSP3_HIGH =3D 0x00002c17, PIN_BASED_VM_EXEC_CONTROL =3D 0x00004000, CPU_BASED_VM_EXEC_CONTROL =3D 0x00004002, EXCEPTION_BITMAP =3D 0x00004004, diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index fcfa99160018..c8b5359123bf 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1459,6 +1459,15 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int c= pu) (unsigned long)(cpu_entry_stack(cpu) + 1)); } =20 + /* Per-CPU FRED MSRs */ + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) { +#ifdef CONFIG_X86_64 + vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB)); + vmcs_write64(HOST_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI)); + vmcs_write64(HOST_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF)); +#endif + } + vmx->loaded_vmcs->cpu =3D cpu; } } @@ -4330,6 +4339,17 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vm= x) */ vmcs_write16(HOST_DS_SELECTOR, 0); vmcs_write16(HOST_ES_SELECTOR, 0); + + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) { + /* FRED CONFIG and STKLVLS are the same on all CPUs */ + vmcs_write64(HOST_IA32_FRED_CONFIG, kvm_host.fred_config); + vmcs_write64(HOST_IA32_FRED_STKLVLS, kvm_host.fred_stklvls); + + /* Linux doesn't support kernel shadow stacks, thus SSPs are 0s */ + vmcs_write64(HOST_IA32_FRED_SSP1, 0); + vmcs_write64(HOST_IA32_FRED_SSP2, 0); + vmcs_write64(HOST_IA32_FRED_SSP3, 0); + } #else vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ @@ -4841,6 +4861,17 @@ static void init_vmcs(struct vcpu_vmx *vmx) } =20 vmx_setup_uret_msrs(vmx); + + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) { + vmcs_write64(GUEST_IA32_FRED_CONFIG, 0); + vmcs_write64(GUEST_IA32_FRED_RSP1, 0); + vmcs_write64(GUEST_IA32_FRED_RSP2, 0); + vmcs_write64(GUEST_IA32_FRED_RSP3, 0); + vmcs_write64(GUEST_IA32_FRED_STKLVLS, 0); + vmcs_write64(GUEST_IA32_FRED_SSP1, 0); + vmcs_write64(GUEST_IA32_FRED_SSP2, 0); + vmcs_write64(GUEST_IA32_FRED_SSP3, 0); + } } =20 static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu) @@ -8717,6 +8748,11 @@ __init int vmx_hardware_setup(void) =20 kvm_caps.inapplicable_quirks &=3D ~KVM_X86_QUIRK_IGNORE_GUEST_PAT; =20 + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) { + rdmsrl(MSR_IA32_FRED_CONFIG, kvm_host.fred_config); + rdmsrl(MSR_IA32_FRED_STKLVLS, kvm_host.fred_stklvls); + } + return r; } =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index f3dc77f006f9..0c1fbf75442b 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -52,6 +52,9 @@ struct kvm_host_values { u64 xss; u64 s_cet; u64 arch_capabilities; + + u64 fred_config; + u64 fred_stklvls; }; =20 void kvm_spurious_fault(void); --=20 2.51.0